• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/db-4.8.30/docs/programmer_reference/
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-&gt;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-&gt;datamember1=new-value1; 
101iterator-&gt;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 &amp;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-&gt;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-&gt;_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-&gt;_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-&gt;</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&amp;elem)
294{
295	memcpy(dest, &amp;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&amp; dest, const void *srcdata)
301{
302	memcpy(&amp;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&amp; 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&lt;ID&gt;::instance()-&gt;set_copy_function(copy_id);
317DbstlElemTraits&lt;ID&gt;::instance()-&gt;set_size_function(size_id);
318DbstlElemTraits&lt;ID&gt;::instance()-&gt;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