• 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_db_rep/JAVA/
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>Program Listing</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 Replicated Berkeley DB Applications" />
10    <link rel="up" href="txnapp.html" title="Chapter��2.��Transactional Application" />
11    <link rel="prev" href="txnapp.html" title="Chapter��2.��Transactional Application" />
12    <link rel="next" href="repapp.html" title="Chapter��3.��The DB Replication Manager" />
13  </head>
14  <body>
15    <div class="navheader">
16      <table width="100%" summary="Navigation header">
17        <tr>
18          <th colspan="3" align="center">Program Listing</th>
19        </tr>
20        <tr>
21          <td width="20%" align="left"><a accesskey="p" href="txnapp.html">Prev</a>��</td>
22          <th width="60%" align="center">Chapter��2.��Transactional Application</th>
23          <td width="20%" align="right">��<a accesskey="n" href="repapp.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="simpleprogramlisting"></a>Program Listing</h2>
33          </div>
34        </div>
35      </div>
36      <div class="toc">
37        <dl>
38          <dt>
39            <span class="sect2">
40              <a href="simpleprogramlisting.html#repconfiginfo_cxx">
41                            
42                            <span>Class: RepConfig</span>
43                    </a>
44            </span>
45          </dt>
46          <dt>
47            <span class="sect2">
48              <a href="simpleprogramlisting.html#simpletxnusage_java">Class: SimpleTxn</a>
49            </span>
50          </dt>
51          <dt>
52            <span class="sect2">
53              <a href="simpleprogramlisting.html#simpletxnmain_java">Method: SimpleTxn.main()</a>
54            </span>
55          </dt>
56          <dt>
57            <span class="sect2">
58              <a href="simpleprogramlisting.html#simpletxn_init_java">Method: SimpleTxn.init()</a>
59            </span>
60          </dt>
61          <dt>
62            <span class="sect2">
63              <a href="simpleprogramlisting.html#doloop_java">Method: SimpleTxn.doloop()</a>
64            </span>
65          </dt>
66          <dt>
67            <span class="sect2">
68              <a href="simpleprogramlisting.html#printstocks_c">
69                            
70                            
71                            <span>Method: SimpleTxn.printStocks()</span>
72                    </a>
73            </span>
74          </dt>
75        </dl>
76      </div>
77      <p>
78                Our example program is a fairly simple transactional
79                application. At this early stage of its development, the
80                application contains no hint that it must be network-aware
81                so the only command line argument that it takes is one that
82                allows us to specify the environment home directory.
83                (Eventually, we will specify things like host names and
84                ports from the command line).
85            </p>
86      <p>
87                Note that the application performs all writes under the
88                protection of a transaction; however, multiple database
89                operations are not performed per transaction. Consequently,
90                we simplify things a bit by using autocommit for our 
91                database writes.
92            </p>
93      <p>
94                Also, this application is single-threaded. It is possible
95                to write a multi-threaded or multi-process application that 
96                performs replication. That said, the concepts described in
97                this book are applicable to both single threaded and
98                multi-threaded applications so nothing
99                is gained by multi-threading this application other than
100                distracting complexity. This manual
101                does, however, identify where care must be taken when
102                performing replication with a non-single threaded
103                application.
104            </p>
105      <p>
106                Finally, remember that transaction processing is not described in
107                this manual. Rather, see the 
108                <em class="citetitle">Berkeley DB Getting Started with Transaction Processing</em> guide for details on 
109                that topic.
110            </p>
111      <div class="sect2" lang="en" xml:lang="en">
112        <div class="titlepage">
113          <div>
114            <div>
115              <h3 class="title"><a id="repconfiginfo_cxx"></a>
116                            
117                            <span>Class: RepConfig</span>
118                    </h3>
119            </div>
120          </div>
121        </div>
122        <p>
123                            Before we begin, we present a 
124                            class that we will use to maintain useful
125                            information for us. Under normal circumstances,
126                            this class would not be necessary for a simple
127                            transactional example such as this. However, this code will
128                            grow into a replicated example that needs to
129                            track a lot more information for the
130                            application, and so we lay the groundwork for
131                            it here.
132                    </p>
133        <p>
134                            The class that we create is called
135                            
136                            <code class="classname">RepConfig</code>
137                            and its only purpose at this time is to track
138                            the location of our environment home directory.
139                    </p>
140        <pre class="programlisting">package db.repquote_gsg;
141
142public class RepConfig
143{
144    // Constant values used in the RepQuote application.
145    public static final String progname = "SimpleTxn";
146    public static final int CACHESIZE = 10 * 1024 * 1024;
147
148    // member variables containing configuration information
149    public String home; // String specifying the home directory for 
150                        // rep files.
151
152    public RepConfig()
153    {
154        home = "TESTDIR";
155    }
156
157    public java.io.File getHome()
158    {
159        return new java.io.File(home);
160    }
161
162}  </pre>
163      </div>
164      <div class="sect2" lang="en" xml:lang="en">
165        <div class="titlepage">
166          <div>
167            <div>
168              <h3 class="title"><a id="simpletxnusage_java"></a>Class: SimpleTxn</h3>
169            </div>
170          </div>
171        </div>
172        <p>
173                            Our transactional example will 
174                            consist of a class,
175                            <code class="classname">SimpleTxn</code>, that performs
176                            all our work for us. 
177                    </p>
178        <p>
179                            First, we provide the package declaration and
180                            then a few import statements that the class
181                            needs.
182                    </p>
183        <pre class="programlisting">package db.repquote_gsg;
184
185import java.io.FileNotFoundException;
186import java.io.BufferedReader;
187import java.io.InputStreamReader;
188import java.io.IOException;
189import java.io.UnsupportedEncodingException;
190
191import com.sleepycat.db.Cursor;
192import com.sleepycat.db.Database;
193import com.sleepycat.db.DatabaseConfig;
194import com.sleepycat.db.DatabaseEntry;
195import com.sleepycat.db.DatabaseException;
196import com.sleepycat.db.DatabaseType;
197import com.sleepycat.db.Environment;
198import com.sleepycat.db.EnvironmentConfig;
199import com.sleepycat.db.LockMode;
200import com.sleepycat.db.OperationStatus;
201import db.repquote_gsg.RepConfig;
202
203public class SimpleTxn
204{
205    private RepConfig repConfig;
206    private Environment dbenv; </pre>
207        <p>
208        Next, we provide our class constructor. This simply initializes our
209        class data members.
210</p>
211        <pre class="programlisting">    public SimpleTxn()
212        throws DatabaseException
213    {
214        repConfig = null;
215        dbenv = null;
216    }  </pre>
217        <p>
218        And then we provide our <code class="methodname">usage()</code> method. At
219        this point, this method has very little to report:
220</p>
221        <pre class="programlisting">    public static void usage()
222    {
223        System.err.println("usage: " + repConfig.progname);
224        System.err.println("-h home");
225
226        System.err.println("\t -h home directory\n");
227
228        System.exit(1);
229    }  </pre>
230      </div>
231      <div class="sect2" lang="en" xml:lang="en">
232        <div class="titlepage">
233          <div>
234            <div>
235              <h3 class="title"><a id="simpletxnmain_java"></a>Method: SimpleTxn.main()</h3>
236            </div>
237          </div>
238        </div>
239        <p>
240                            Having implemented our
241                            <code class="methodname">usage()</code>
242                            method, we can jump directly into our
243                            <code class="methodname">main()</code>
244                            method. This method begins by instantiating a
245                            <code class="classname">RepConfig</code> object, and
246                            then collecting the command line arguments so
247                            that it can populate the object with the
248                            appropriate data (just the environment home
249                            directory, at this time):
250                    </p>
251        <pre class="programlisting">    public static void main(String[] argv)
252        throws Exception
253    {
254        RepConfig config = new RepConfig();
255        // Extract the command line parameters
256        for (int i = 0; i &lt; argv.length; i++)
257        {
258            if (argv[i].compareTo("-h") == 0) {
259                // home - a string arg.
260                i++;
261                config.home = argv[i];
262            } else {
263                System.err.println("Unrecognized option: " + argv[i]);
264                usage();
265            }
266        }  </pre>
267        <p>
268        And then perform a little sanity checking on the command line
269        input:
270</p>
271        <pre class="programlisting">        // Error check command line.
272        if (config.home.length() == 0)
273            usage();  </pre>
274        <p>
275            Now we perform the class' work. To begin, we initialize the
276            object. The <code class="methodname">init()</code> method actually
277            opens our environment for us (shown in the next section).
278    </p>
279        <pre class="programlisting">        SimpleTxn runner = null;
280        try {
281            runner = new SimpleTxn();
282            runner.init(config);  </pre>
283        <p>
284            And then we call our <code class="methodname">doloop()</code>
285            method. This method is where we perform all our database
286            activity. See <a class="xref" href="simpleprogramlisting.html#doloop_java" title="Method: SimpleTxn.doloop()">Method: SimpleTxn.doloop()</a>
287            for it's details.
288    </p>
289        <pre class="programlisting">                    runner.doloop();  </pre>
290        <p>
291            And then, finally terminate the application (which closes our
292            environment handle) and end the method.
293    </p>
294        <pre class="programlisting">            runner.terminate();
295        } catch (DatabaseException dbe) {
296            System.err.println("Caught an exception during " +
297                "initialization or processing: " + dbe.toString());
298            if (runner != null)
299                runner.terminate();
300        }
301            System.exit(0);
302    } // end main  </pre>
303      </div>
304      <div class="sect2" lang="en" xml:lang="en">
305        <div class="titlepage">
306          <div>
307            <div>
308              <h3 class="title"><a id="simpletxn_init_java"></a>Method: SimpleTxn.init()</h3>
309            </div>
310          </div>
311        </div>
312        <p>
313                        The <code class="methodname">SimpleTxn.init()</code>
314                        method is used to open our environment handle.
315                        For readers familiar with writing transactional
316                        DB applications, there should be no surprises
317                        here. However, we will be adding to this in later
318                        chapters as we roll replication into this example.
319                </p>
320        <p>
321        The only thing worth noting in this method here is that 
322        we relax our transactional durability guarantee for this application.
323        We do this because the application will eventually be replicated and
324        so we don't need a high durability guarantee.
325</p>
326        <pre class="programlisting">    public int init(RepConfig config)
327        throws DatabaseException
328    {
329        int ret = 0;
330        repConfig = config;
331        EnvironmentConfig envConfig = new EnvironmentConfig();
332        envConfig.setErrorStream(System.err);
333        envConfig.setErrorPrefix(RepConfig.progname);
334
335        envConfig.setCacheSize(RepConfig.CACHESIZE);
336        envConfig.setTxnNoSync(true);
337
338        envConfig.setAllowCreate(true);
339        envConfig.setRunRecovery(true);
340        envConfig.setInitializeLocking(true);
341        envConfig.setInitializeLogging(true);
342        envConfig.setInitializeCache(true);
343        envConfig.setTransactional(true);
344        try {
345            dbenv = new Environment(repConfig.getHome(), envConfig);
346        } catch(FileNotFoundException e) {
347            System.err.println("FileNotFound exception: " + e.toString());
348            System.err.println(
349                "Ensure that the environment directory is pre-created.");
350            ret = 1;
351        }
352
353        return ret;
354    }  </pre>
355        <p>
356        Finally, we present the <code class="methodname">SimpleTxn.terminate()</code>
357        method here. All this does is close the environment handle. Again,
358        there should be no surprises here, but we provide the
359        implementation for the sake of completeness anyway.
360</p>
361        <pre class="programlisting">    public void terminate()
362        throws DatabaseException
363    {
364            dbenv.close();
365    }  </pre>
366      </div>
367      <div class="sect2" lang="en" xml:lang="en">
368        <div class="titlepage">
369          <div>
370            <div>
371              <h3 class="title"><a id="doloop_java"></a>Method: SimpleTxn.doloop()</h3>
372            </div>
373          </div>
374        </div>
375        <p>
376                        We now implement our application's
377                        primary data processing method. This
378                        method provides a command prompt at which the
379                        user can enter a stock ticker value and a price for
380                        that value. This information is then entered to the
381                        database.
382                    </p>
383        <p>
384                            To display the database, simply enter
385                            <code class="literal">return</code> at the prompt.
386                    </p>
387        <p>
388                        To begin, we declare a database pointer:
389                    </p>
390        <pre class="programlisting">    public int doloop()
391        throws DatabaseException, , UnsupportedEncodingException
392    {
393        Database db = null;  </pre>
394        <p>
395                    Next, we begin the loop and we immediately open our
396                    database if it has not already been opened. 
397                </p>
398        <pre class="programlisting">        for (;;)
399        {
400            if (db == null) {
401                DatabaseConfig dbconf = new DatabaseConfig();
402                dbconf.setType(DatabaseType.BTREE);
403                dbconf.setAllowCreate(true);
404                dbconf.setTransactional(true);
405
406                try {
407                    db = dbenv.openDatabase(null,           // Txn handle
408                                        RepConfig.progname, // db filename
409                                        null,               // db name
410                                        dbconf);
411               } catch (FileNotFoundException fnfe) {
412                 System.err.println("File not found exception" + fnfe.toString());
413                // Get here only if the environment home directory
414                // somehow does not exist.
415               }
416            }  </pre>
417        <p>
418            Now we implement our command prompt. This is a simple and not
419            very robust implementation of a command prompt.
420            If the user enters the keywords <code class="literal">exit</code>
421            or <code class="literal">quit</code>, the loop is exited and the
422            application ends. If the user enters nothing and instead simply
423            presses <code class="literal">return</code>, the entire contents of the
424            database is displayed. We use our
425            <code class="methodname">printStocks()</code> method to display the
426            database. (That implementation is shown next in this chapter.)
427        </p>
428        <p>
429           Notice that very little error checking is performed on the data
430           entered at this prompt.  If the user fails to enter at least one 
431            space in the value string, a simple help message is printed and
432            the prompt is returned to the user. That is the only error
433            checking performed here. In a real-world application,
434            at a minimum the application would probably check to ensure
435            that the price was in fact an integer or float value. 
436            However, in order to keep this example code as simple as
437            possible, we refrain from implementing a thorough user interface.
438        </p>
439        <pre class="programlisting">            BufferedReader stdin =
440                new BufferedReader(new InputStreamReader(System.in));
441
442            // listen for input, and add it to the database.
443            System.out.print("QUOTESERVER&gt; ");
444            System.out.flush();
445            String nextline = null;
446            try {
447                nextline = stdin.readLine();
448            } catch (IOException ioe) {
449                System.err.println("Unable to get data from stdin");
450                break;
451            }
452            String[] words = nextline.split("\\s");
453
454            // A blank line causes the DB to be dumped to stdout.
455            if (words.length == 0 ||
456                (words.length == 1 &amp;&amp; words[0].length() == 0)) {
457                try {
458                    printStocks(db);
459                } catch (DatabaseException e) {
460                    System.err.println("Got db exception reading " +
461                        "DB: " + e.toString());
462                    break;
463                }
464                continue;
465            }
466
467            if (words.length == 1 &amp;&amp;
468                (words[0].compareToIgnoreCase("quit") == 0 ||
469                words[0].compareToIgnoreCase("exit") == 0)) {
470                break;
471            } else if (words.length != 2) {
472                System.err.println("Format: TICKER VALUE");
473                continue;
474            }  </pre>
475        <p>
476                Now we assign data to the <code class="classname">DatabaseEntry</code> 
477                classes that we will use to write the new information to the database.
478            </p>
479        <pre class="programlisting">            DatabaseEntry key =
480                    new DatabaseEntry(words[0].getBytes("UTF-8"));
481            DatabaseEntry data =
482                    new DatabaseEntry(words[1].getBytes("UTF-8"));  </pre>
483        <p>
484                Having done that, we can write the new information to the
485                database. Remember that because a transaction handle is not
486                explicitly used, but we did open the database such that it
487                supports transactions, then autocommit is automatically
488                used for this database write.
489            </p>
490        <p>
491                    Autocommit is described in the 
492                    <em class="citetitle">Berkeley DB Getting Started with Transaction Processing</em> guide.
493                </p>
494        <p>
495                Also, the database is not configured for duplicate records, so
496                the data portion of a record is overwritten if the provided
497                key already exists in the database. However, in this case
498                DB returns <code class="methodname">OperationStatus.KEYEXIST</code> ��� which
499                we ignore.
500            </p>
501        <pre class="programlisting">            db.put(null, key, data);  </pre>
502        <p>
503            Finally, we close our database before returning from the
504            method.
505        </p>
506        <pre class="programlisting">        }
507        if (db != null)
508            db.close(true);
509        return 0;
510    }  </pre>
511      </div>
512      <div class="sect2" lang="en" xml:lang="en">
513        <div class="titlepage">
514          <div>
515            <div>
516              <h3 class="title"><a id="printstocks_c"></a>
517                            
518                            
519                            <span>Method: SimpleTxn.printStocks()</span>
520                    </h3>
521            </div>
522          </div>
523        </div>
524        <p>
525                        The  
526                         <code class="methodname">printStocks()</code> 
527                        
528                        <span>method</span>
529                        simply takes a database handle, opens a cursor, and uses 
530                        it to display all the information it finds in a database.
531                        This is trivial cursor operation that should hold
532                        no surprises for you. We simply provide it here for
533                        the sake of completeness.
534                    </p>
535        <p>
536                        If you are unfamiliar with basic cursor operations,
537                        please see the <em class="citetitle">Getting Started with Berkeley DB</em>
538                        guide.
539                    </p>
540        <pre class="programlisting">    public void terminate()
541        throws DatabaseException
542    {
543            dbenv.close();
544    }
545
546    /*
547     * void return type since error conditions are propagated
548     * via exceptions.
549     */
550    private void printStocks(Database db)
551        throws DatabaseException
552    {
553        Cursor dbc = db.openCursor(null, null);
554
555        System.out.println("\tSymbol\tPrice");
556        System.out.println("\t======\t=====");
557
558        DatabaseEntry key = new DatabaseEntry();
559        DatabaseEntry data = new DatabaseEntry();
560        OperationStatus ret;
561        for (ret = dbc.getFirst(key, data, LockMode.DEFAULT);
562            ret == OperationStatus.SUCCESS;
563            ret = dbc.getNext(key, data, LockMode.DEFAULT)) {
564            String keystr = new String
565                (key.getData(), key.getOffset(), key.getSize());
566            String datastr = new String
567                (data.getData(), data.getOffset(), data.getSize());
568            System.out.println("\t"+keystr+"\t"+datastr);
569
570        }
571        dbc.close();
572    }
573} // end class  </pre>
574      </div>
575    </div>
576    <div class="navfooter">
577      <hr />
578      <table width="100%" summary="Navigation footer">
579        <tr>
580          <td width="40%" align="left"><a accesskey="p" href="txnapp.html">Prev</a>��</td>
581          <td width="20%" align="center">
582            <a accesskey="u" href="txnapp.html">Up</a>
583          </td>
584          <td width="40%" align="right">��<a accesskey="n" href="repapp.html">Next</a></td>
585        </tr>
586        <tr>
587          <td width="40%" align="left" valign="top">Chapter��2.��Transactional Application��</td>
588          <td width="20%" align="center">
589            <a accesskey="h" href="index.html">Home</a>
590          </td>
591          <td width="40%" align="right" valign="top">��Chapter��3.��The DB Replication Manager</td>
592        </tr>
593      </table>
594    </div>
595  </body>
596</html>
597