1<?xml version="1.0" encoding="UTF-8" standalone="no"?> 2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3<html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 6 <title>Dbstl persistence</title> 7 <link rel="stylesheet" href="gettingStarted.css" type="text/css" /> 8 <meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /> 9 <link rel="start" href="index.html" title="Berkeley DB Programmer's Reference Guide" /> 10 <link rel="up" href="stl.html" title="Chapter��7.��Standard Template Library API" /> 11 <link rel="prev" href="stl_complex_rw.html" title="Store and Retrieve data or objects of complex types" /> 12 <link rel="next" href="stl_container_specific.html" title="Dbstl container specific notes" /> 13 </head> 14 <body> 15 <div class="navheader"> 16 <table width="100%" summary="Navigation header"> 17 <tr> 18 <th colspan="3" align="center">Dbstl persistence</th> 19 </tr> 20 <tr> 21 <td width="20%" align="left"><a accesskey="p" href="stl_complex_rw.html">Prev</a>��</td> 22 <th width="60%" align="center">Chapter��7.��Standard Template Library API</th> 23 <td width="20%" align="right">��<a accesskey="n" href="stl_container_specific.html">Next</a></td> 24 </tr> 25 </table> 26 <hr /> 27 </div> 28 <div class="sect1" lang="en" xml:lang="en"> 29 <div class="titlepage"> 30 <div> 31 <div> 32 <h2 class="title" style="clear: both"><a id="stl_persistence"></a>Dbstl persistence</h2> 33 </div> 34 </div> 35 </div> 36 <div class="toc"> 37 <dl> 38 <dt> 39 <span class="sect2"> 40 <a href="stl_persistence.html#directdbget">Direct database get</a> 41 </span> 42 </dt> 43 <dt> 44 <span class="sect2"> 45 <a href="stl_persistence.html#chg_persistence">Change persistence</a> 46 </span> 47 </dt> 48 <dt> 49 <span class="sect2"> 50 <a href="stl_persistence.html#obj_life_persistence">Object life time and persistence </a> 51 </span> 52 </dt> 53 </dl> 54 </div> 55 <p> 56 The following sections provide information on how to achieve 57 persistence using dbstl. 58</p> 59 <div class="sect2" lang="en" xml:lang="en"> 60 <div class="titlepage"> 61 <div> 62 <div> 63 <h3 class="title"><a id="directdbget"></a>Direct database get</h3> 64 </div> 65 </div> 66 </div> 67 <p> 68 Each container has a <span class="bold"><strong>begin()</strong></span> method 69 which produces an iterator. These 70 <span class="bold"><strong>begin</strong></span> methods take a boolean parameter, 71 <span class="bold"><strong>directdb_get</strong></span>, which controls the 72 caching behavior of the iterator. The default value of this parameter 73 is <code class="literal">true</code>. 74</p> 75 <p> 76 If <span class="bold"><strong>directdb_get</strong></span> is 77 <code class="literal">true</code>, then the persistent object is fetched anew 78 from the database each time the iterator is dereferenced as a pointer 79 by use of the star-operator 80 (<span class="bold"><strong>*iterator</strong></span>) or by use of the arrow-operator 81 (<span class="bold"><strong>iterator->member</strong></span>). If 82 <span class="bold"><strong>directdb_get</strong></span> is <code class="literal">false</code>, then 83 the first dereferencing of the iterator fetches the object from the 84 database, but later dereferences can return cached data. 85</p> 86 <p> 87 With <span class="bold"><strong>directdb_get</strong></span> set to <code class="literal">true</code>, if you call: 88</p> 89 <pre class="programlisting">(*iterator).datamember1=new-value1; 90(*iterator).datamember2=new-value2; </pre> 91 <p> 92 then the assignment to <code class="literal">datamember1</code> will be lost, 93 because the second dereferencing of the iterator would cause the cached 94 copy of the object to be overwritten by the object's persistent data 95 from the database. 96</p> 97 <p> 98 You also can use the arrow operator like this: 99</p> 100 <pre class="programlisting">iterator->datamember1=new-value1; 101iterator->datamember2=new-value2; </pre> 102 <p> 103 This works exactly the same way as <span class="bold"><strong>iterator::operator*</strong></span>. 104 For this reason, the same caching rules apply to arrow operators as they do 105 for star operators. 106</p> 107 <p> 108 One way to avoid this problem is to create a reference to the object, 109 and use it to access the object: 110</p> 111 <pre class="programlisting">container::value_type &ref = *iterator; 112ref.datamember1=new-value1; 113ref.datamember2=new-value2; 114...// more member function calls and datamember assignments 115ref._DB_STL_StoreElement(); </pre> 116 <p> 117 The above code will not lose the newly assigned value of <code class="literal">ref.datamember1</code> 118 in the way that the previous example did. 119</p> 120 <p> 121 In order to avoid these complications, you can assign to the object 122 referenced by an iterator with another object of the same type like this: 123</p> 124 <pre class="programlisting">container::value_type obj2; 125obj2.datamember1 = new-value1; 126obj2.datamember2 = new-value2; 127*itr = obj2; </pre> 128 <p> 129 This code snippet causes the new values in <code class="literal">obj2</code> to 130 be stored into the underlying database. 131</p> 132 <p> 133 If you have two iterators going through the same container like this: 134</p> 135 <pre class="programlisting"> 136for (iterator1 = v.begin(), iterator2 = v.begin(); 137 iterator1 != v.end(); 138 ++iterator1, ++iterator2) { 139 *iterator1 = new_value; 140 print(*iterator2); 141} </pre> 142 <p> 143 then the printed value will depend on the value of 144 <span class="bold"><strong>directdb_get</strong></span> with which the 145 iterator had been created. If <span class="bold"><strong>directdb_get</strong></span> 146 is <code class="literal">false</code>, then the original, persistent value is 147 printed; otherwise the newly assigned value is returned from the 148 cache when <code class="literal">iterator2</code> is dereferenced. This 149 happens because each iterator has its own cached copy of the 150 persistent object, and the dereferencing of 151 <code class="literal">iterator2</code> refreshes 152 <code class="literal">iterator2</code>'s copy from the database, retrieving 153 the value stored by the assignment to 154 <code class="literal">*iterator1</code>. 155</p> 156 <p> 157 Alternatively, you can set <span class="bold"><strong>directdb_get 158 </strong></span> to <code class="literal">false</code> and call 159 <code class="methodname">iterator2->refresh()</code> immediately before 160 the dereferencing of <code class="literal">iterator2</code>, so that 161 <code class="literal">iterator2</code>'s cached value is refreshed. 162</p> 163 <p> 164 If <span class="bold"><strong>directdb_get</strong></span> is 165 <code class="literal">false</code>, a few of the tests in dbstl's test kit 166 will fail. This is because the above contrived case appears in 167 several of C++ STL tests. Consequently, the default value of the 168 <span class="bold"><strong>directdb_get</strong></span> parameter in the 169 <code class="methodname">container::begin()</code> methods is 170 <code class="literal">true</code>. If your use cases avoid such bizarre usage 171 of iterators, you can set it to <code class="literal">false</code>, which 172 makes the iterator read operation faster. 173</p> 174 </div> 175 <div class="sect2" lang="en" xml:lang="en"> 176 <div class="titlepage"> 177 <div> 178 <div> 179 <h3 class="title"><a id="chg_persistence"></a>Change persistence</h3> 180 </div> 181 </div> 182 </div> 183 <p> 184 If you modify the object to which an iterator refers by using one 185 of the following: 186</p> 187 <pre class="programlisting">(*iterator).member_function_call()</pre> 188 <p> 189 or 190</p> 191 <pre class="programlisting">(*iterator).data_member = new_value</pre> 192 <p> 193 then you should call 194 <code class="methodname">iterator->_DB_STL_StoreElement()</code> to 195 store the change. Otherwise the change is lost after the 196 iterator moves on to other elements. 197</p> 198 <p> 199 If you are storing a sequence, and you modified some part of it, you 200 should also call 201 <code class="methodname">iterator->_DB_STL_StoreElement()</code> 202 before moving the iterator. 203</p> 204 <p> 205 And in both cases, if <span class="bold"><strong>directdb_get</strong></span> 206 is <code class="literal">true</code> (this is the default value), you should 207 call <code class="methodname">_DB_STL_StoreElement()</code> after the 208 change and before the next iterator movement OR the next 209 dereferencing of the iterator by the star or arrow operators 210 (<code class="literal">iterator::operator*</code> or 211 <code class="literal">iterator::operator-></code>). Otherwise, you will 212 lose the change. 213</p> 214 <p> 215 If you update the element by assigning to a dereferenced iterator like 216 this: 217</p> 218 <pre class="programlisting">*iterator = new_element;</pre> 219 <p> 220 then you never have to call 221 <code class="methodname">_DB_STL_StoreElement()</code> because the change 222 is stored in the database automatically. 223</p> 224 </div> 225 <div class="sect2" lang="en" xml:lang="en"> 226 <div class="titlepage"> 227 <div> 228 <div> 229 <h3 class="title"><a id="obj_life_persistence"></a>Object life time and persistence </h3> 230 </div> 231 </div> 232 </div> 233 <p> 234 Dbstl is an interface to Berkeley DB, so it is used to store data 235 persistently. This is really a different purpose from that of 236 regular C++ STL. This difference in their goals has implications on 237 expected object lifetime: In standard STL, when you store an object 238 A of type ID into C++ stl vector V using V.push_back(A), if a 239 proper copy constructor is provided in A's class type, then the 240 copy of A (call it B) and everything in B, such as another object C 241 pointed to by B's data member B.c_ptr, will be stored in V and will 242 live as long as B is still in V and V is alive. B will be destroyed 243 when V is destroyed or B is erased from V. 244</p> 245 <p> 246 This is not true for dbstl, which will copy A's data and store it 247 in the underlying database. The copy is by default a shallow copy, 248 but users can register their object marshalling and unmarshalling 249 functions using the <code class="classname">DbstlElemTraits</code> class 250 template. So if A is passed to a <code class="classname">db_vector</code> 251 container, <code class="literal">dv</code>, by using 252 <code class="literal">dv.push_back(A)</code>, then dbstl copies A's data 253 using the registered functions, and stores data into the underlying 254 database. Consequently, A will be valid, even if the container is 255 destroyed, because it is stored into the database. 256</p> 257 <p> 258 If the copy is simply a shallow copy, and A is later destroyed, then 259 the pointer stored in the database will become invalid. The next time 260 we use the retrieved object, we will be using an invalid pointer, which 261 probably will result in errors. To avoid this, store the referred 262 object C rather than the pointer member A.c_ptr itself, by registering 263 the right marshalling/unmarshalling function with 264 <code class="classname">DbstlElemTraits</code>. 265</p> 266 <p> 267 For example, consider the following example class declaration: 268</p> 269 <pre class="programlisting">class ID 270{ 271public: 272 string Name; 273 int Score; 274}; </pre> 275 <p> 276 Here, the class ID has a data member <span class="bold"><strong>Name</strong></span>, which refers to a memory address of 277 the actual characters in the string. If we simply shallow copy an 278 object, <code class="literal">id</code>, of class ID to store it, then the 279 stored data, <code class="literal">idd</code>, is invalid when 280 <code class="literal">id</code> is destroyed. This is because 281 <code class="literal">idd</code> and <code class="literal">id</code> refer to a common 282 memory address which is the base address of the memory space storing 283 all characters in the string, and this memory space is released when 284 <code class="literal">id</code> is destroyed. So <code class="literal">idd</code> will be 285 referring to an invalid address. The next time we retrieve 286 <code class="literal">idd</code> and use it, there will probably be memory 287 corruption. 288</p> 289 <p> 290 The way to store <code class="literal">id</code> is to write a marshal/unmarshal 291 function pair like this: 292</p> 293 <pre class="programlisting">void copy_id(void *dest, const ID&elem) 294{ 295 memcpy(dest, &elem.Score, sizeof(elem.Score)); 296 char *p = ((char *)dest) + sizeof(elem.Score); 297 strcpy(p, elem.Name.c_str()); 298} 299 300void restore_id(ID& dest, const void *srcdata) 301{ 302 memcpy(&dest.Score, srcdata, sizeof(dest.Score)); 303 const char *p = ((char *)srcdata) + sizeof(dest.Score); 304 dest.Name = p; 305} 306 307size_t size_id(const ID& elem) 308{ 309 return sizeof(elem.Score) + elem.Name.size() + 310 1;// store the '\0' char. 311} </pre> 312 <p> 313 Then register the above functions before storing any instance of 314 <code class="classname">ID</code>: 315 </p> 316 <pre class="programlisting">DbstlElemTraits<ID>::instance()->set_copy_function(copy_id); 317DbstlElemTraits<ID>::instance()->set_size_function(size_id); 318DbstlElemTraits<ID>::instance()->set_restore_function(restore_id); </pre> 319 <p> 320 This way, the actual data of instances of ID are stored, and so the 321 data will persist even if the container itself is destroyed. 322 </p> 323 </div> 324 </div> 325 <div class="navfooter"> 326 <hr /> 327 <table width="100%" summary="Navigation footer"> 328 <tr> 329 <td width="40%" align="left"><a accesskey="p" href="stl_complex_rw.html">Prev</a>��</td> 330 <td width="20%" align="center"> 331 <a accesskey="u" href="stl.html">Up</a> 332 </td> 333 <td width="40%" align="right">��<a accesskey="n" href="stl_container_specific.html">Next</a></td> 334 </tr> 335 <tr> 336 <td width="40%" align="left" valign="top">Store and Retrieve data or objects of complex types ��</td> 337 <td width="20%" align="center"> 338 <a accesskey="h" href="index.html">Home</a> 339 </td> 340 <td width="40%" align="right" valign="top">��Dbstl container specific notes</td> 341 </tr> 342 </table> 343 </div> 344 </body> 345</html> 346