diff options
Diffstat (limited to 'docs/programmer_reference/stl_persistence.html')
| -rw-r--r-- | docs/programmer_reference/stl_persistence.html | 378 |
1 files changed, 200 insertions, 178 deletions
diff --git a/docs/programmer_reference/stl_persistence.html b/docs/programmer_reference/stl_persistence.html index 343923f5..32d99b5f 100644 --- a/docs/programmer_reference/stl_persistence.html +++ b/docs/programmer_reference/stl_persistence.html @@ -14,7 +14,7 @@ <body> <div xmlns="" class="navheader"> <div class="libver"> - <p>Library Version 11.2.5.3</p> + <p>Library Version 12.1.6.1</p> </div> <table width="100%" summary="Navigation header"> <tr> @@ -55,10 +55,10 @@ </dt> </dl> </div> - <p> - The following sections provide information on how to achieve - persistence using dbstl. -</p> + <p> + The following sections provide information on how to + achieve persistence using dbstl. + </p> <div class="sect2" lang="en" xml:lang="en"> <div class="titlepage"> <div> @@ -68,112 +68,121 @@ </div> </div> <p> - Each container has a <span class="bold"><strong>begin()</strong></span> method - which produces an iterator. These - <span class="bold"><strong>begin</strong></span> methods take a boolean parameter, - <span class="bold"><strong>directdb_get</strong></span>, which controls the - caching behavior of the iterator. The default value of this parameter - is <code class="literal">true</code>. -</p> - <p> - If <span class="bold"><strong>directdb_get</strong></span> is - <code class="literal">true</code>, then the persistent object is fetched anew - from the database each time the iterator is dereferenced as a pointer - by use of the star-operator - (<span class="bold"><strong>*iterator</strong></span>) or by use of the arrow-operator - (<span class="bold"><strong>iterator->member</strong></span>). If - <span class="bold"><strong>directdb_get</strong></span> is <code class="literal">false</code>, then - the first dereferencing of the iterator fetches the object from the - database, but later dereferences can return cached data. -</p> - <p> - With <span class="bold"><strong>directdb_get</strong></span> set to <code class="literal">true</code>, if you call: -</p> + Each container has a <span class="bold"><strong>begin()</strong></span> method + which produces an iterator. + These <span class="bold"><strong>begin</strong></span> methods take + a boolean parameter, <span class="bold"><strong>directdb_get</strong></span>, which + controls the caching behavior of the iterator. The default value of this + parameter is <code class="literal">true</code>. + </p> + <p> + If <span class="bold"><strong>directdb_get</strong></span> is + <code class="literal">true</code>, then the persistent object is + fetched anew from the database each time the iterator is + dereferenced as a pointer by use of the star-operator + (<span class="bold"><strong>*iterator</strong></span>) or by use + of the arrow-operator (<span class="bold"><strong>iterator->member</strong></span>). + If <span class="bold"><strong>directdb_get</strong></span> is + <code class="literal">false</code>, then the first dereferencing + of the iterator fetches the object from the database, but + later dereferences can return cached data. + </p> + <p> + With <span class="bold"><strong>directdb_get</strong></span> set + to <code class="literal">true</code>, if you call: + </p> <pre class="programlisting">(*iterator).datamember1=new-value1; (*iterator).datamember2=new-value2; </pre> <p> - then the assignment to <code class="literal">datamember1</code> will be lost, - because the second dereferencing of the iterator would cause the cached - copy of the object to be overwritten by the object's persistent data - from the database. -</p> + then the assignment to <code class="literal">datamember1</code> + will be lost, because the second dereferencing of the + iterator would cause the cached copy of the object to be + overwritten by the object's persistent data from the + database. + </p> <p> - You also can use the arrow operator like this: -</p> + You also can use the arrow operator like this: + </p> <pre class="programlisting">iterator->datamember1=new-value1; iterator->datamember2=new-value2; </pre> <p> - This works exactly the same way as <span class="bold"><strong>iterator::operator*</strong></span>. - For this reason, the same caching rules apply to arrow operators as they do - for star operators. -</p> - <p> - One way to avoid this problem is to create a reference to the object, - and use it to access the object: -</p> + This works exactly the same way as <span class="bold"><strong>iterator::operator*</strong></span>. For this + reason, the same caching rules apply to arrow operators as + they do for star operators. + </p> + <p> + One way to avoid this problem is to create a reference + to the object, and use it to access the object: + </p> <pre class="programlisting">container::value_type &ref = *iterator; ref.datamember1=new-value1; ref.datamember2=new-value2; ...// more member function calls and datamember assignments ref._DB_STL_StoreElement(); </pre> - <p> - The above code will not lose the newly assigned value of <code class="literal">ref.datamember1</code> - in the way that the previous example did. -</p> - <p> - In order to avoid these complications, you can assign to the object - referenced by an iterator with another object of the same type like this: -</p> + <p> + The above code will not lose the newly assigned value + of <code class="literal">ref.datamember1</code> in the way that the + previous example did. + </p> + <p> + In order to avoid these complications, you can assign + to the object referenced by an iterator with another + object of the same type like this: + </p> <pre class="programlisting">container::value_type obj2; obj2.datamember1 = new-value1; obj2.datamember2 = new-value2; *itr = obj2; </pre> <p> - This code snippet causes the new values in <code class="literal">obj2</code> to - be stored into the underlying database. -</p> - <p> - If you have two iterators going through the same container like this: -</p> - <pre class="programlisting"> -for (iterator1 = v.begin(), iterator2 = v.begin(); + This code snippet causes the new values in + <code class="literal">obj2</code> to be stored into the + underlying database. + </p> + <p> + If you have two iterators going through the same + container like this: + </p> + <pre class="programlisting">for (iterator1 = v.begin(), iterator2 = v.begin(); iterator1 != v.end(); ++iterator1, ++iterator2) { *iterator1 = new_value; print(*iterator2); } </pre> + <p> + then the printed value will depend on the value of + <span class="bold"><strong>directdb_get</strong></span> with + which the iterator had been created. If <span class="bold"><strong>directdb_get</strong></span> is + <code class="literal">false</code>, then the original, + persistent value is printed; otherwise the newly assigned + value is returned from the cache when + <code class="literal">iterator2</code> is dereferenced. This + happens because each iterator has its own cached copy of + the persistent object, and the dereferencing of + <code class="literal">iterator2</code> refreshes + <code class="literal">iterator2</code>'s copy from the database, + retrieving the value stored by the assignment to + <code class="literal">*iterator1</code>. + </p> <p> - then the printed value will depend on the value of - <span class="bold"><strong>directdb_get</strong></span> with which the - iterator had been created. If <span class="bold"><strong>directdb_get</strong></span> - is <code class="literal">false</code>, then the original, persistent value is - printed; otherwise the newly assigned value is returned from the - cache when <code class="literal">iterator2</code> is dereferenced. This - happens because each iterator has its own cached copy of the - persistent object, and the dereferencing of - <code class="literal">iterator2</code> refreshes - <code class="literal">iterator2</code>'s copy from the database, retrieving - the value stored by the assignment to - <code class="literal">*iterator1</code>. -</p> - <p> - Alternatively, you can set <span class="bold"><strong>directdb_get - </strong></span> to <code class="literal">false</code> and call - <code class="methodname">iterator2->refresh()</code> immediately before - the dereferencing of <code class="literal">iterator2</code>, so that - <code class="literal">iterator2</code>'s cached value is refreshed. -</p> - <p> - If <span class="bold"><strong>directdb_get</strong></span> is - <code class="literal">false</code>, a few of the tests in dbstl's test kit - will fail. This is because the above contrived case appears in - several of C++ STL tests. Consequently, the default value of the - <span class="bold"><strong>directdb_get</strong></span> parameter in the - <code class="methodname">container::begin()</code> methods is - <code class="literal">true</code>. If your use cases avoid such bizarre usage - of iterators, you can set it to <code class="literal">false</code>, which - makes the iterator read operation faster. -</p> + Alternatively, you can set <span class="bold"><strong>directdb_get </strong></span> to + <code class="literal">false</code> and call <code class="methodname">iterator2->refresh()</code> + immediately before the dereferencing of + <code class="literal">iterator2</code>, so that + <code class="literal">iterator2</code>'s cached value is + refreshed. + </p> + <p> + If <span class="bold"><strong>directdb_get</strong></span> is + <code class="literal">false</code>, a few of the tests in + dbstl's test kit will fail. This is because the above + contrived case appears in several of C++ STL tests. + Consequently, the default value of the <span class="bold"><strong>directdb_get</strong></span> parameter in the + <code class="methodname">container::begin()</code> methods is + <code class="literal">true</code>. If your use cases avoid such + bizarre usage of iterators, you can set it to + <code class="literal">false</code>, which makes the iterator + read operation faster. + </p> </div> <div class="sect2" lang="en" xml:lang="en"> <div class="titlepage"> @@ -184,46 +193,48 @@ for (iterator1 = v.begin(), iterator2 = v.begin(); </div> </div> <p> - If you modify the object to which an iterator refers by using one - of the following: -</p> + If you modify the object to which an iterator refers by + using one of the following: + </p> <pre class="programlisting">(*iterator).member_function_call()</pre> <p> - or -</p> + or + </p> <pre class="programlisting">(*iterator).data_member = new_value</pre> <p> - then you should call - <code class="methodname">iterator->_DB_STL_StoreElement()</code> to - store the change. Otherwise the change is lost after the - iterator moves on to other elements. -</p> - <p> - If you are storing a sequence, and you modified some part of it, you - should also call - <code class="methodname">iterator->_DB_STL_StoreElement()</code> - before moving the iterator. -</p> + then you should call + <code class="methodname">iterator->_DB_STL_StoreElement()</code> + to store the change. Otherwise the change is lost after + the iterator moves on to other elements. + </p> <p> - And in both cases, if <span class="bold"><strong>directdb_get</strong></span> - is <code class="literal">true</code> (this is the default value), you should - call <code class="methodname">_DB_STL_StoreElement()</code> after the - change and before the next iterator movement OR the next - dereferencing of the iterator by the star or arrow operators - (<code class="literal">iterator::operator*</code> or - <code class="literal">iterator::operator-></code>). Otherwise, you will - lose the change. -</p> + If you are storing a sequence, and you modified some + part of it, you should also call + <code class="methodname">iterator->_DB_STL_StoreElement()</code> + before moving the iterator. + </p> <p> - If you update the element by assigning to a dereferenced iterator like - this: -</p> + And in both cases, if <span class="bold"><strong>directdb_get</strong></span> is + <code class="literal">true</code> + (this is the default value), you should call + <code class="methodname">_DB_STL_StoreElement()</code> after + the change and before the next iterator movement OR the + next dereferencing of the iterator by the star or arrow + operators (<code class="literal">iterator::operator*</code> or + <code class="literal">iterator::operator-></code>). + Otherwise, you will lose the change. + </p> + <p> + If you update the element by assigning to a + dereferenced iterator like this: + </p> <pre class="programlisting">*iterator = new_element;</pre> <p> - then you never have to call - <code class="methodname">_DB_STL_StoreElement()</code> because the change - is stored in the database automatically. -</p> + then you never have to call + <code class="methodname">_DB_STL_StoreElement()</code> + because the change is stored in the database + automatically. + </p> </div> <div class="sect2" lang="en" xml:lang="en"> <div class="titlepage"> @@ -233,42 +244,48 @@ for (iterator1 = v.begin(), iterator2 = v.begin(); </div> </div> </div> + <p> + Dbstl is an interface to Berkeley DB, so it is used to + store data persistently. This is really a different + purpose from that of regular C++ STL. This difference in + their goals has implications on expected object lifetime: + In standard STL, when you store an object A of type ID + into C++ stl vector V using V.push_back(A), if a proper + copy constructor is provided in A's class type, then the + copy of A (call it B) and everything in B, such as another + object C pointed to by B's data member B.c_ptr, will be + stored in V and will live as long as B is still in V and V + is alive. B will be destroyed when V is destroyed or B is + erased from V. + </p> <p> - Dbstl is an interface to Berkeley DB, so it is used to store data - persistently. This is really a different purpose from that of - regular C++ STL. This difference in their goals has implications on - expected object lifetime: In standard STL, when you store an object - A of type ID into C++ stl vector V using V.push_back(A), if a - proper copy constructor is provided in A's class type, then the - copy of A (call it B) and everything in B, such as another object C - pointed to by B's data member B.c_ptr, will be stored in V and will - live as long as B is still in V and V is alive. B will be destroyed - when V is destroyed or B is erased from V. -</p> - <p> - This is not true for dbstl, which will copy A's data and store it - in the underlying database. The copy is by default a shallow copy, - but users can register their object marshalling and unmarshalling - functions using the <code class="classname">DbstlElemTraits</code> class - template. So if A is passed to a <code class="classname">db_vector</code> - container, <code class="literal">dv</code>, by using - <code class="literal">dv.push_back(A)</code>, then dbstl copies A's data - using the registered functions, and stores data into the underlying - database. Consequently, A will be valid, even if the container is - destroyed, because it is stored into the database. -</p> - <p> - If the copy is simply a shallow copy, and A is later destroyed, then - the pointer stored in the database will become invalid. The next time - we use the retrieved object, we will be using an invalid pointer, which - probably will result in errors. To avoid this, store the referred - object C rather than the pointer member A.c_ptr itself, by registering - the right marshalling/unmarshalling function with - <code class="classname">DbstlElemTraits</code>. -</p> + This is not true for dbstl, which will copy A's data + and store it in the underlying database. The copy is by + default a shallow copy, but users can register their + object marshalling and unmarshalling functions using the + <code class="classname">DbstlElemTraits</code> class template. + So if A is passed to a <code class="classname">db_vector</code> + container, <code class="literal">dv</code>, by using + <code class="literal">dv.push_back(A)</code>, then dbstl copies + A's data using the registered functions, and stores data + into the underlying database. Consequently, A will be + valid, even if the container is destroyed, because it is + stored into the database. + </p> + <p> + If the copy is simply a shallow copy, and A is later + destroyed, then the pointer stored in the database will + become invalid. The next time we use the retrieved object, + we will be using an invalid pointer, which probably will + result in errors. To avoid this, store the referred object + C rather than the pointer member A.c_ptr itself, by + registering the right marshalling/unmarshalling function + with <code class="classname">DbstlElemTraits</code>. + </p> <p> - For example, consider the following example class declaration: -</p> + For example, consider the following example class + declaration: + </p> <pre class="programlisting">class ID { public: @@ -276,23 +293,25 @@ public: int Score; }; </pre> <p> - Here, the class ID has a data member <span class="bold"><strong>Name</strong></span>, which refers to a memory address of - the actual characters in the string. If we simply shallow copy an - object, <code class="literal">id</code>, of class ID to store it, then the - stored data, <code class="literal">idd</code>, is invalid when - <code class="literal">id</code> is destroyed. This is because - <code class="literal">idd</code> and <code class="literal">id</code> refer to a common - memory address which is the base address of the memory space storing - all characters in the string, and this memory space is released when - <code class="literal">id</code> is destroyed. So <code class="literal">idd</code> will be - referring to an invalid address. The next time we retrieve - <code class="literal">idd</code> and use it, there will probably be memory - corruption. -</p> + Here, the class ID has a data member <span class="bold"><strong>Name</strong></span>, which refers to a memory + address of the actual characters in the string. If we + simply shallow copy an object, <code class="literal">id</code>, of + class ID to store it, then the stored data, + <code class="literal">idd</code>, is invalid when + <code class="literal">id</code> is destroyed. This is because + <code class="literal">idd</code> and <code class="literal">id</code> refer + to a common memory address which is the base address of + the memory space storing all characters in the string, and + this memory space is released when <code class="literal">id</code> + is destroyed. So <code class="literal">idd</code> will be referring + to an invalid address. The next time we retrieve + <code class="literal">idd</code> and use it, there will probably + be memory corruption. + </p> <p> - The way to store <code class="literal">id</code> is to write a marshal/unmarshal - function pair like this: -</p> + The way to store <code class="literal">id</code> is to write a + marshal/unmarshal function pair like this: + </p> <pre class="programlisting">void copy_id(void *dest, const ID&elem) { memcpy(dest, &elem.Score, sizeof(elem.Score)); @@ -313,16 +332,17 @@ size_t size_id(const ID& elem) 1;// store the '\0' char. } </pre> <p> - Then register the above functions before storing any instance of - <code class="classname">ID</code>: - </p> + Then register the above functions before storing any + instance of <code class="classname">ID</code>: + </p> <pre class="programlisting">DbstlElemTraits<ID>::instance()->set_copy_function(copy_id); DbstlElemTraits<ID>::instance()->set_size_function(size_id); DbstlElemTraits<ID>::instance()->set_restore_function(restore_id); </pre> <p> - This way, the actual data of instances of ID are stored, and so the - data will persist even if the container itself is destroyed. - </p> + This way, the actual data of instances of ID are + stored, and so the data will persist even if the container + itself is destroyed. + </p> </div> </div> <div class="navfooter"> @@ -336,11 +356,13 @@ DbstlElemTraits<ID>::instance()->set_restore_function(restore_id); </p <td width="40%" align="right"> <a accesskey="n" href="stl_container_specific.html">Next</a></td> </tr> <tr> - <td width="40%" align="left" valign="top">Store and Retrieve data or objects of complex types </td> + <td width="40%" align="left" valign="top">Store and Retrieve data or + objects of complex types </td> <td width="20%" align="center"> <a accesskey="h" href="index.html">Home</a> </td> - <td width="40%" align="right" valign="top"> Dbstl container specific notes</td> + <td width="40%" align="right" valign="top"> Dbstl container specific + notes</td> </tr> </table> </div> |
