• 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/gsg/CXX/
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>Database Usage Example</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="Getting Started with Berkeley DB" />
10    <link rel="up" href="DBEntry.html" title="Chapter��3.��Database Records" />
11    <link rel="prev" href="usingDbt.html" title="Reading and Writing Database Records" />
12    <link rel="next" href="Cursors.html" title="Chapter��4.��Using Cursors" />
13  </head>
14  <body>
15    <div class="navheader">
16      <table width="100%" summary="Navigation header">
17        <tr>
18          <th colspan="3" align="center">Database Usage Example</th>
19        </tr>
20        <tr>
21          <td width="20%" align="left"><a accesskey="p" href="usingDbt.html">Prev</a>��</td>
22          <th width="60%" align="center">Chapter��3.��Database Records</th>
23          <td width="20%" align="right">��<a accesskey="n" href="Cursors.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="DbCXXUsage"></a>Database Usage Example</h2>
33          </div>
34        </div>
35      </div>
36      <p>
37        In <a class="xref" href="CoreDbCXXUsage.html" title="Database Example">Database Example</a> we created 
38        a class that opens and closes a database for us.
39        We now make use of that class to load inventory data into
40        two databases that we will use for our inventory system.
41    </p>
42      <p>
43        Again, remember that you can find the complete implementation for these functions
44        in:
45    </p>
46      <pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_cxx/getting_started</pre>
47      <p>
48        where <code class="literal"><span class="emphasis"><em>DB_INSTALL</em></span></code> is the location where you
49        placed your DB distribution.
50    </p>
51      <div class="example">
52        <a id="VENDORCXXStruct"></a>
53        <p class="title">
54          <b>Example 3.1 VENDOR Structure</b>
55        </p>
56        <div class="example-contents">
57          <p>
58            We want to store data related to an inventory system. There are two
59            types of information that we want to manage: inventory data and related
60            vendor contact information. To manage this information, we could
61            have created a structure for each type of data, but to illustrate
62            storing mixed data without a structure we refrain from creating one
63            for the inventory data.
64        </p>
65          <p>
66            We now show the definition of the VENDOR structure.
67            Note that the VENDOR structure uses fixed-length fields. 
68            This is not necessary and in fact could
69            represent a waste of resources if the number of vendors stored in
70            our database scales to very large numbers. However, for simplicity we use
71            fixed-length fields anyway, especially 
72            given that our sample data contains so few vendor records.
73        </p>
74          <a id="cxx_dbt10"></a>
75          <pre class="programlisting">// File: gettingStartedCommon.hpp
76#define MAXFIELD 20
77typedef struct vendor {
78    char name[MAXFIELD];             // Vendor name
79    char street[MAXFIELD];           // Street name and number
80    char city[MAXFIELD];             // City
81    char state[3];                   // Two-digit US state code
82    char zipcode[6];                 // US zipcode
83    char phone_number[13];           // Vendor phone number
84    char sales_rep[MAXFIELD];        // Name of sales representative
85    char sales_rep_phone[MAXFIELD];  // Sales rep's phone number
86} VENDOR;</pre>
87        </div>
88      </div>
89      <br class="example-break" />
90      <div class="example">
91        <a id="InventoryData"></a>
92        <p class="title">
93          <b>Example 3.2 InventoryData Class</b>
94        </p>
95        <div class="example-contents">
96          <p>
97            In order to manage our actual inventory data, we create a class that
98            encapsulates the data that we want to store for each inventory
99            record. Beyond simple data encapsulation, this class is also capable
100            of marshaling the inventory data into a single contiguous buffer
101            for the purposes of storing in that data in a DB database.
102        </p>
103          <p>
104            We also provide two constructors for this class. The default
105            constructor simply initializes all our data members for us. A second
106            constructor is also provided that is capable of populating our data
107            members from a <code class="literal">void *</code>. This second constructor is
108            not really needed until the next chapter where we show how to read
109            data from the databases, but we include it here for the purpose of
110            completeness anyway.
111        </p>
112          <p>
113            To simplify things a bit, we include the entire implementation for this
114            class in <code class="filename">gettingStartedCommon.hpp</code> along with
115            our <code class="literal">VENDOR</code> structure definition.
116        </p>
117          <p>
118            To begin, we create the public getter and setter methods that we
119            use with our class' private members. We also show the implementation
120            of the method that we use to initialize all our private members.
121        </p>
122          <a id="cxx_dbt11"></a>
123          <pre class="programlisting">class InventoryData
124{
125public:
126    inline void setPrice(double price) {price_ = price;}
127    inline void setQuantity(long quantity) {quantity_ = quantity;}
128    inline void setCategory(std::string &amp;category) {category_ = category;}
129    inline void setName(std::string &amp;name) {name_ = name;}
130    inline void setVendor(std::string &amp;vendor) {vendor_ = vendor;}
131    inline void setSKU(std::string &amp;sku) {sku_ = sku;}
132                                                                                                                                    
133    inline double&amp; getPrice() {return(price_);}
134    inline long&amp; getQuantity() {return(quantity_);}
135    inline std::string&amp; getCategory() {return(category_);}
136    inline std::string&amp; getName() {return(name_);}
137    inline std::string&amp; getVendor() {return(vendor_);}
138    inline std::string&amp; getSKU() {return(sku_);}
139                                                                                                                                    
140    // Initialize our data members
141    void clear()
142    {
143        price_ = 0.0;
144        quantity_ = 0;
145        category_.clear();
146        name_.clear();
147        vendor_.clear();
148        sku_.clear();
149    } </pre>
150          <p>
151        Next we implement our constructors. The default constructor simply calls
152        the <code class="methodname">clear()</code>. The second constructor takes a
153        <code class="literal">void *</code> as an argument, which it then uses to
154        initialize the data members. Note, again, that we will not actually use
155        this second constructor in this chapter, but we show it here just to be
156        complete anyway.
157    </p>
158          <a id="cxx_dbt12"></a>
159          <pre class="programlisting">    // Default constructor
160    InventoryData() { clear(); }
161                                                                                                                                    
162    // Constructor from a void *
163    // For use with the data returned from a bdb get
164    InventoryData(void *buffer)
165    {
166        char *buf = (char *)buffer;
167                                                                                                                                    
168        price_ = *((double *)buf);
169        bufLen_ = sizeof(double);
170                                                                                                                                    
171        quantity_ = *((long *)(buf + bufLen_));
172        bufLen_ += sizeof(long);
173                                                                                                                                    
174        name_ = buf + bufLen_;
175        bufLen_ += name_.size() + 1;
176                                                                                                                                    
177        sku_ = buf + bufLen_;
178        bufLen_ += sku_.size() + 1;
179                                                                                                                                    
180        category_ = buf + bufLen_;
181        bufLen_ += category_.size() + 1;
182                                                                                                                                    
183        vendor_ = buf + bufLen_;
184        bufLen_ += vendor_.size() + 1;
185    } </pre>
186          <p>
187        Next we provide a couple of methods for returning the class' buffer and
188        the size of the buffer. These are used for actually storing the class'
189        data in a DB database.
190    </p>
191          <a id="cxx_dbt13"></a>
192          <pre class="programlisting">    // Marshalls this classes data members into a single
193    // contiguous memory location for the purpose of storing
194    // the data in a database.
195    char *
196    getBuffer()
197    {
198        // Zero out the buffer
199        memset(databuf_, 0, 500);
200        // Now pack the data into a single contiguous memory location for
201        // storage.
202        bufLen_ = 0;
203        int dataLen = 0;
204                                                                                                                                    
205        dataLen = sizeof(double);
206        memcpy(databuf_, &amp;price_, dataLen);
207        bufLen_ += dataLen;
208                                                                                                                                    
209        dataLen = sizeof(long);
210        memcpy(databuf_ + bufLen_, &amp;quantity_, dataLen);
211        bufLen_ += dataLen;
212                                                                                                                                    
213        packString(databuf_, name_);
214        packString(databuf_, sku_);
215        packString(databuf_, category_);
216        packString(databuf_, vendor_);
217                                                                                                                                    
218        return (databuf_);
219    }
220                                                                                                                                    
221    // Returns the size of the buffer. Used for storing
222    // the buffer in a database.
223    inline int getBufferSize() { return (bufLen_); } </pre>
224          <p>
225        Our last public method is a utility method that we use to get the class
226        to show itself.
227    </p>
228          <a id="cxx_dbt14"></a>
229          <pre class="programlisting">     // Utility function used to show the contents of this class
230    void
231    show() {
232        std::cout &lt;&lt; "\nName:         " &lt;&lt; name_ &lt;&lt; std::endl;
233        std::cout &lt;&lt; "    SKU:        " &lt;&lt; sku_ &lt;&lt; std::endl;
234        std::cout &lt;&lt; "    Price:      " &lt;&lt; price_ &lt;&lt; std::endl;
235        std::cout &lt;&lt; "    Quantity:   " &lt;&lt; quantity_ &lt;&lt; std::endl;
236        std::cout &lt;&lt; "    Category:   " &lt;&lt; category_ &lt;&lt; std::endl;
237        std::cout &lt;&lt; "    Vendor:     " &lt;&lt; vendor_ &lt;&lt; std::endl;
238    } </pre>
239          <p>
240        Finally, we provide a private method that is used to help us pack data
241        into our buffer, and we declare our private data members.
242    </p>
243          <a id="cxx_dbt15"></a>
244          <pre class="programlisting">private:
245
246    // Utility function that appends a char * to the end of
247    // the buffer.
248    void
249    packString(char *buffer, std::string &amp;theString)
250    {
251        int string_size = theString.size() + 1;
252        memcpy(buffer+bufLen_, theString.c_str(), string_size);
253        bufLen_ += string_size;
254    }
255
256    // Data members
257    std::string category_, name_, vendor_, sku_;
258    double price_;
259    long quantity_;
260    int bufLen_;
261    char databuf_[500];
262}; </pre>
263        </div>
264      </div>
265      <br class="example-break" />
266      <div class="example">
267        <a id="exampledbload-cxx"></a>
268        <p class="title">
269          <b>Example 3.3 example_database_load</b>
270        </p>
271        <div class="example-contents">
272          <p>
273            Our initial sample application loads database information from
274            several flat files. To save space, we won't show all the details of
275            this example program. However, as always you can find the complete
276            implementation for this program here:
277        </p>
278          <pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_cxx/getting_started</pre>
279          <p>
280        where <code class="literal"><span class="emphasis"><em>DB_INSTALL</em></span></code> is the location where you
281        placed your DB distribution.
282    </p>
283          <p>
284        We begin with the normal include directives and forward declarations:
285    </p>
286          <a id="cxx_dbt16"></a>
287          <pre class="programlisting">// File: example_database_load.cpp
288#include &lt;iostream&gt;
289#include &lt;fstream&gt;
290#include &lt;cstdlib&gt;
291                                                                                                                                    
292#include "MyDb.hpp"
293#include "gettingStartedCommon.hpp" 
294
295// Forward declarations
296void loadVendorDB(MyDb&amp;, std::string&amp;);
297void loadInventoryDB(MyDb&amp;, std::string&amp;);
298</pre>
299          <p>
300       Next we begin our <code class="function">main()</code> function with the variable
301       declarations and command line parsing that is normal for most command
302       line applications:  
303    </p>
304          <a id="cxx_dbt17"></a>
305          <pre class="programlisting">// Loads the contents of vendors.txt and inventory.txt into
306// Berkeley DB databases. 
307int
308main(int argc, char *argv[])
309{
310    // Initialize the path to the database files
311    std::string basename("./");
312    std::string databaseHome("./");
313                                                                                                                                    
314    // Database names
315    std::string vDbName("vendordb.db");
316    std::string iDbName("inventorydb.db");
317
318    // Parse the command line arguments here and determine 
319    // the location of the flat text files containing the 
320    // inventory data here. This step is omitted for clarity.
321
322    //  Identify the full name for our input files, which should
323    //  also include some path information.
324    std::string inventoryFile = basename + "inventory.txt";
325    std::string vendorFile = basename + "vendors.txt";
326                                                                                                                                    
327    try
328    {
329        // Open all databases.
330        MyDb inventoryDB(databaseHome, iDbName);
331        MyDb vendorDB(databaseHome, vDbName);
332                                                                                                                                    
333        // Load the vendor database
334        loadVendorDB(vendorDB, vendorFile);
335
336        // Load the inventory database
337        loadInventoryDB(inventoryDB, inventoryFile);
338    } catch(DbException &amp;e) {
339        std::cerr &lt;&lt; "Error loading databases. " &lt;&lt; std::endl;
340        std::cerr &lt;&lt; e.what() &lt;&lt; std::endl;
341        return(e.get_errno());
342    } catch(std::exception &amp;e) {
343        std::cerr &lt;&lt; "Error loading databases. " &lt;&lt; std::endl;
344        std::cerr &lt;&lt; e.what() &lt;&lt; std::endl;
345        return(-1);
346    }
347                                                                                                                                    
348    return(0);
349} // End main </pre>
350          <p>
351        Note that we do not explicitly close our databases here. This is because
352        the databases are encapsulated in <code class="classname">MyDb</code> class
353        objects, and those objects are on the stack. When they go out of scope,
354        their destructors will cause the database close to occur.
355    </p>
356          <p>
357        Notice that there is not a lot to this function because we have pushed
358        off all the database activity to other places.
359    </p>
360          <p>
361        Next we show the implementation of
362        <code class="function">loadVendorDB()</code>. We load this data by
363        scanning (line by line) the contents of the
364        <code class="filename">vendors.txt</code> file into a VENDOR structure. Once we have a
365        line scanned into the structure, we can store that structure into our
366        vendors database. 
367     </p>
368          <p>
369        Note that we use the vendor's name as the key here. In doing so, we
370        assume that the vendor's name is unique in our database. If it was not,
371        we would either have to select a different key, or architect our
372        application such that it could cope with multiple vendor records with
373        the same name.
374     </p>
375          <a id="cxx_dbt18"></a>
376          <pre class="programlisting">// Loads the contents of the vendors.txt file into a database
377void
378loadVendorDB(MyDb &amp;vendorDB, std::string &amp;vendorFile)
379{
380    std::ifstream inFile(vendorFile.c_str(), std::ios::in);
381    if ( !inFile )
382    {
383        std::cerr &lt;&lt; "Could not open file '" &lt;&lt; vendorFile
384                  &lt;&lt; "'. Giving up." &lt;&lt; std::endl;
385        throw std::exception();
386    }
387                                                                                                                                    
388    VENDOR my_vendor;
389    while (!inFile.eof())
390    {
391        std::string stringBuf;
392        std::getline(inFile, stringBuf);
393        memset(&amp;my_vendor, 0, sizeof(VENDOR));
394                                                                                                                                    
395        // Scan the line into the structure.
396        // Convenient, but not particularly safe.
397        // In a real program, there would be a lot more
398        // defensive code here.
399        sscanf(stringBuf.c_str(),
400          "%20[^#]#%20[^#]#%20[^#]#%3[^#]#%6[^#]#%13[^#]#%20[^#]#%20[^\n]",
401          my_vendor.name, my_vendor.street,
402          my_vendor.city, my_vendor.state,
403          my_vendor.zipcode, my_vendor.phone_number,
404          my_vendor.sales_rep, my_vendor.sales_rep_phone);
405                                                                                                                                    
406        Dbt key(my_vendor.name, strlen(my_vendor.name) + 1);
407        Dbt data(&amp;my_vendor, sizeof(VENDOR));
408                                                                                                                                    
409        vendorDB.getDb().put(NULL, &amp;key, &amp;data, 0);
410    }
411    inFile.close();
412} </pre>
413          <p>
414        Finally, we need to write the
415        <code class="function">loadInventoryDB()</code> function. To load the inventory information, 
416        we read in each line of the inventory.txt file, obtain each field from
417        it, then we load this data into an <code class="classname">InventoryData</code>
418        instance. 
419     </p>
420          <p>
421        To help us obtain the various fields from each line of input,
422        we also create a simple helper function that locates the position of the
423        first a field delimiter (a pound (#) sign) from a line of input.
424     </p>
425          <p>
426        Note that we could have simply decided to store our inventory data in a
427        structure very much like the VENDOR structure that we use above.
428        However, by storing this data in the
429        <code class="classname">InventoryData</code> class, which identifies the size of
430        the data that it contains, 
431        we can use the smallest amount of space possible for the data that we
432        are storing.  The result is that our cache can be smaller than it might
433        otherwise be and our database will take less space on disk than if we used
434        a structure with fixed-length fields.
435    </p>
436          <p>
437        For a trivial dataset such as what we use for these examples, these
438        resource savings are negligible. But if we were storing hundreds of
439        millions of records, then the cost savings may become significant.
440    </p>
441          <a id="cxx_dbt19"></a>
442          <pre class="programlisting">// Used to locate the first pound sign (a field delimiter)
443// in the input string.
444int
445getNextPound(std::string &amp;theString, std::string &amp;substring)
446{
447    int pos = theString.find("#");
448    substring.assign(theString, 0, pos);
449    theString.assign(theString, pos + 1, theString.size());
450    return (pos);
451}
452                                                                                                                                    
453                                                                                                                                    
454// Loads the contents of the inventory.txt file into a database
455void
456loadInventoryDB(MyDb &amp;inventoryDB, std::string &amp;inventoryFile)
457{
458    InventoryData inventoryData;
459    std::string substring;
460    int nextPound;
461                                                                                                                                    
462    std::ifstream inFile(inventoryFile.c_str(), std::ios::in);
463    if (!inFile)
464    {
465        std::cerr &lt;&lt; "Could not open file '" &lt;&lt; inventoryFile
466                  &lt;&lt; "'. Giving up." &lt;&lt; std::endl;
467        throw std::exception();
468    }
469                                                                                                                                    
470    while (!inFile.eof())
471    {
472        inventoryData.clear();
473        std::string stringBuf;
474        std::getline(inFile, stringBuf);
475                                                                                                                                    
476        // Now parse the line
477        if (!stringBuf.empty())
478        {
479            nextPound = getNextPound(stringBuf, substring);
480            inventoryData.setName(substring);
481                                                                                                                                    
482            nextPound = getNextPound(stringBuf, substring);
483            inventoryData.setSKU(substring);
484                                                                                                                                    
485            nextPound = getNextPound(stringBuf, substring);
486            inventoryData.setPrice(strtod(substring.c_str(), 0));
487                                                                                                                                    
488            nextPound = getNextPound(stringBuf, substring);
489            inventoryData.setQuantity(strtol(substring.c_str(), 0, 10));
490                                                                                                                                    
491            nextPound = getNextPound(stringBuf, substring);
492            inventoryData.setCategory(substring);
493                                                                                                                                    
494            nextPound = getNextPound(stringBuf, substring);
495            inventoryData.setVendor(substring);
496                                                                                                                                    
497            void *buff = (void *)inventoryData.getSKU().c_str();
498            int size = inventoryData.getSKU().size()+1;
499            Dbt key(buff, size);
500                                                                                                                                    
501            buff = inventoryData.getBuffer();
502            size = inventoryData.getBufferSize();
503            Dbt data(buff, size);
504                                                                                                                                    
505            inventoryDB.getDb().put(NULL, &amp;key, &amp;data, 0);
506        }
507    }
508    inFile.close();
509} </pre>
510          <p>
511        In the next chapter we provide an example that shows how to read
512        the inventory and vendor databases.
513    </p>
514        </div>
515      </div>
516      <br class="example-break" />
517    </div>
518    <div class="navfooter">
519      <hr />
520      <table width="100%" summary="Navigation footer">
521        <tr>
522          <td width="40%" align="left"><a accesskey="p" href="usingDbt.html">Prev</a>��</td>
523          <td width="20%" align="center">
524            <a accesskey="u" href="DBEntry.html">Up</a>
525          </td>
526          <td width="40%" align="right">��<a accesskey="n" href="Cursors.html">Next</a></td>
527        </tr>
528        <tr>
529          <td width="40%" align="left" valign="top">Reading and Writing Database Records��</td>
530          <td width="20%" align="center">
531            <a accesskey="h" href="index.html">Home</a>
532          </td>
533          <td width="40%" align="right" valign="top">��Chapter��4.��Using Cursors</td>
534        </tr>
535      </table>
536    </div>
537  </body>
538</html>
539