• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500-V1.0.1.40_1.0.68/ap/gpl/timemachine/db-4.7.25.NC/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>Adding the Replication Framework to
7                    
8                    SimpleTxn
9            </title>
10    <link rel="stylesheet" href="gettingStarted.css" type="text/css" />
11    <meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
12    <link rel="home" href="index.html" title="Getting Started with Replicated Berkeley DB Applications" />
13    <link rel="up" href="repapp.html" title="Chapter��3.��The DB Replication Framework" />
14    <link rel="previous" href="repapp.html" title="Chapter��3.��The DB Replication Framework" />
15    <link rel="next" href="fwrkpermmessage.html" title="Permanent Message Handling" />
16  </head>
17  <body>
18    <div class="navheader">
19      <table width="100%" summary="Navigation header">
20        <tr>
21          <th colspan="3" align="center">Adding the Replication Framework to
22                    
23                    SimpleTxn
24            </th>
25        </tr>
26        <tr>
27          <td width="20%" align="left"><a accesskey="p" href="repapp.html">Prev</a>��</td>
28          <th width="60%" align="center">Chapter��3.��The DB Replication Framework</th>
29          <td width="20%" align="right">��<a accesskey="n" href="fwrkpermmessage.html">Next</a></td>
30        </tr>
31      </table>
32      <hr />
33    </div>
34    <div class="sect1" lang="en" xml:lang="en">
35      <div class="titlepage">
36        <div>
37          <div>
38            <h2 class="title" style="clear: both"><a id="repmgr_init_example_c"></a>Adding the Replication Framework to
39                    
40                    <span>SimpleTxn</span>
41            </h2>
42          </div>
43        </div>
44        <div></div>
45      </div>
46      <p>
47                    We now use the methods described above to add partial
48                    support to the 
49                     
50                    <tt class="literal">SimpleTxn</tt> 
51                    example that we presented in 
52                    <a href="txnapp.html">Transactional Application</a>.
53                    That is, in this section we will:
54            </p>
55      <div class="itemizedlist">
56        <ul type="disc">
57          <li>
58            <p>
59                                    Enhance our command line options to
60                                    accept information of interest to a
61                                    replicated application.
62                            </p>
63          </li>
64          <li>
65            <p>
66                                    Configure our environment handle to use
67                                    replication and the replication framework.
68                            </p>
69          </li>
70          <li>
71            <p>
72                                    Minimally configure the replication framework.
73                            </p>
74          </li>
75          <li>
76            <p>
77                                    Start replication.
78                            </p>
79          </li>
80        </ul>
81      </div>
82      <p>
83                Note that when we are done with this section, we will be
84                only partially ready to run the application. Some critical
85                pieces will be missing; specifically, we will not yet be
86                handling the differences between a master and a
87                replica. (We do that in the next chapter).
88            </p>
89      <p>
90                Also, note that in the following code fragments, additions
91                and changes to the code are marked in <b class="userinput"><tt>bold</tt></b>.
92            </p>
93      <p>
94                To begin, we make some significant changes to our
95                <tt class="classname">RepConfig</tt> class because we will be
96                using it to maintain a lot more information that we needed
97                for our simple transactional example.
98            </p>
99      <p>
100        We begin by changing our package name and then importing a few new
101        classes. <tt class="classname">java.util.Vector</tt> is used to
102        organize a list of "other host" definitions (that is, the host and
103        port information for the other replication participants known to
104        this application). We also need a couple of classes used to manage
105        individual host and port information, as well as replication
106        startup policy information.
107</p>
108      <pre class="programlisting"><b class="userinput"><tt>package db.repquote;
109
110import java.util.Vector;
111
112import com.sleepycat.db.ReplicationHostAddress;
113import com.sleepycat.db.ReplicationManagerStartPolicy;</tt></b>
114
115public class RepConfig
116{ </pre>
117      <p>
118        Next we add considerably to the constants and data members used by
119        this class. All of this is used to manage information necessary for
120        replication purposes. We also at this point change the program's
121        name, since we will be doing that to the main class in our
122        application a little later in this description.
123</p>
124      <pre class="programlisting">    // Constant values used in the RepQuote application.
125    public static final String progname = <b class="userinput"><tt>"RepQuoteExample";</tt></b>
126    public static final int CACHESIZE = 10 * 1024 * 1024;
127    <b class="userinput"><tt>public static final int SLEEPTIME = 5000;</tt></b>
128
129    // member variables containing configuration information
130    public String home; // String specifying the home directory for rep files.
131    <b class="userinput"><tt>public Vector otherHosts; // stores an optional set of "other" hosts.
132    public int priority; // priority within the replication group.
133    public ReplicationManagerStartPolicy startPolicy;
134    public ReplicationHostAddress thisHost; // The host address to listen to.
135    // Optional parameter specifying the # of sites in the replication group.
136    public int totalSites;
137
138    // member variables used internally.
139    private int currOtherHost;
140    private boolean gotListenAddress;</tt></b></pre>
141      <p>
142        Now we update our class constructor to initialize all of these new
143        variables:
144</p>
145      <pre class="programlisting">    public RepConfig()
146    {
147        <b class="userinput"><tt>startPolicy = ReplicationManagerStartPolicy.REP_ELECTION;</tt></b>
148        home = "TESTDIR";
149        <b class="userinput"><tt>gotListenAddress = false;
150        totalSites = 0;
151        priority = 100;
152        currOtherHost = 0;
153        thisHost = new ReplicationHostAddress();
154        otherHosts = new Vector();</tt></b>
155    } </pre>
156      <p>
157        Finally, we finish updating this class by providing a series of new
158        getter and setter methods. These are used primarily for setting a
159        retrieving host information of interest to our replicated
160        application:
161</p>
162      <pre class="programlisting">    public java.io.File getHome()
163    {
164        return new java.io.File(home);
165    }
166
167    <b class="userinput"><tt>public void setThisHost(String host, int port)
168    {
169        gotListenAddress = true;
170        thisHost.port = port;
171        thisHost.host = host;
172    }
173
174    public ReplicationHostAddress getThisHost()
175    {
176        if (!gotListenAddress) {
177            System.err.println("Warning: no host specified.");
178            System.err.println("Returning default.");
179        }
180        return thisHost;
181    }
182
183    public boolean gotListenAddress() {
184        return gotListenAddress;
185    }
186
187    public void addOtherHost(String host, int port, boolean peer)
188    {
189        ReplicationHostAddress newInfo = 
190            new ReplicationHostAddress(host, port, peer);
191        otherHosts.add(newInfo);
192    }
193
194    public ReplicationHostAddress getFirstOtherHost()
195    {
196        currOtherHost = 0;
197        if (otherHosts.size() == 0)
198            return null;
199        return (ReplicationHostAddress)otherHosts.get(currOtherHost);
200    }
201
202    public ReplicationHostAddress getNextOtherHost()
203    {
204        currOtherHost++;
205        if (currOtherHost &gt;= otherHosts.size())
206            return null;
207        return (ReplicationHostAddress)otherHosts.get(currOtherHost);
208    }
209
210    public ReplicationHostAddress getOtherHost(int i)
211    {
212        if (i &gt;= otherHosts.size())
213            return null;
214        return (ReplicationHostAddress)otherHosts.get(i);
215    }</tt></b>
216} </pre>
217      <p>
218        Having completed our update to the
219         
220        <tt class="classname">RepConfig</tt> 
221        class, we can now start making
222        changes to the main portion of our program. We begin by changing
223        the program's name. <span>(This, of course, means that we copy our 
224<tt class="classname">SimpleTxn</tt> code to a file named <tt class="literal">RepQuoteExample.java</tt>.)</span>
225</p>
226      <pre class="programlisting">package <b class="userinput"><tt>db.repquote</tt></b>;
227                            
228import java.io.FileNotFoundException;
229import java.io.BufferedReader;
230import java.io.InputStreamReader;
231import java.io.IOException;
232import java.io.UnsupportedEncodingException;
233<b class="userinput"><tt>import java.lang.Thread;
234import java.lang.InterruptedException;</tt></b>
235
236import com.sleepycat.db.Cursor;
237import com.sleepycat.db.Database;
238import com.sleepycat.db.DatabaseConfig;
239import com.sleepycat.db.DatabaseEntry;
240import com.sleepycat.db.DatabaseException;
241import com.sleepycat.db.DatabaseType;
242import com.sleepycat.db.Environment;
243import com.sleepycat.db.EnvironmentConfig;
244import com.sleepycat.db.LockMode;
245import com.sleepycat.db.OperationStatus;
246import db.repquote.RepConfig;
247
248public class <b class="userinput"><tt>RepQuoteExample</tt></b>
249{
250    private RepConfig repConfig;
251    private Environment dbenv; </pre>
252      <p>
253        Next we update our usage function. The application will continue to
254        accept the <tt class="literal">-h</tt> parameter so that we can identify
255        the environment home directory used by this application. However,
256        we also add the 
257</p>
258      <div class="itemizedlist">
259        <ul type="disc">
260          <li>
261            <p>
262                    <tt class="literal">-m</tt> parameter which allows us to
263                    identify the host and port used by this application to
264                    listen for replication messages.
265                </p>
266          </li>
267          <li>
268            <p>
269                        <tt class="literal">-o</tt> parameter which allows us to
270                        specify other replicas.
271                </p>
272          </li>
273          <li>
274            <p>
275                        <tt class="literal">-n</tt> parameter which allows us to
276                        identify the number of sites in this replication
277                        group.
278                </p>
279          </li>
280          <li>
281            <p>
282                    <tt class="literal">-p</tt> option, which is used to identify
283                    this replica's priority (recall that the priority is
284                    used as a tie breaker for elections)
285                </p>
286          </li>
287        </ul>
288      </div>
289      <pre class="programlisting">
290    public <b class="userinput"><tt>RepQuoteExample()</tt></b>
291        throws DatabaseException
292    {
293        repConfig = null;
294        dbenv = null;
295    }
296
297    public static void usage()
298    {
299        System.err.println("usage: " + repConfig.progname);
300        System.err.println("[-h home]<b class="userinput"><tt>[-o host:port][-m host:port]" +
301            "[-f host:port][-n nsites][-p priority]</tt></b>");
302
303        System.err.println(<b class="userinput"><tt>"\t -m host:port (required; m stands for me)\n" +
304             "\t -o host:port (optional; o stands for other; any " +
305             "number of these may be specified)\n" +</tt></b>
306             "\t -h home directory\n" +
307             <b class="userinput"><tt>"\t -n nsites (optional; number of sites in replication " +
308             "group; defaults to 0\n" +
309             "\t    in which case we try to dynamically compute the " +
310             "number of sites in\n" +
311             "\t    the replication group)\n" +
312             "\t -p priority (optional: defaults to 100)\n");</tt></b>
313
314        System.exit(1);
315    } </pre>
316      <p>
317        Now we can begin working on our <tt class="literal">main()</tt> function.
318        We begin by adding a couple of variables that we will use to
319        collect TCP/IP host and port information. 
320
321
322        
323</p>
324      <pre class="programlisting">    public static void main(String[] argv)
325        throws Exception
326    {
327        RepConfig config = new RepConfig();
328        <b class="userinput"><tt>String tmpHost;
329        int tmpPort = 0;</tt></b> </pre>
330      <p>
331        Now we collect our command line arguments. As we do so, we will
332        configure host and port information as required, and we will
333        configure the application's election priority if necessary.
334</p>
335      <pre class="programlisting">        // Extract the command line parameters
336        for (int i = 0; i &lt; argv.length; i++)
337        {
338            if (argv[i].compareTo("-h") == 0) {
339                // home - a string arg.
340                i++;
341                config.home = argv[i];
342           <b class="userinput"><tt>} else if (argv[i].compareTo("-m") == 0) {
343                // "me" should be host:port
344                i++;
345                String[] words = argv[i].split(":");
346                if (words.length != 2) {
347                    System.err.println(
348                        "Invalid host specification host:port needed.");
349                    usage();
350                }
351                try {
352                    tmpPort = Integer.parseInt(words[1]);
353                } catch (NumberFormatException nfe) {
354                    System.err.println("Invalid host specification, " +
355                        "could not parse port number.");
356                    usage();
357                }
358                config.setThisHost(words[0], tmpPort);
359            } else if (argv[i].compareTo("-n") == 0) {
360                i++;
361                config.totalSites = Integer.parseInt(argv[i]);
362            } else if (argv[i].compareTo("-o") == 0) {
363                i++;
364                String[] words = argv[i].split(":");
365                if (words.length != 2) {
366                    System.err.println(
367                        "Invalid host specification host:port needed.");
368                    usage();
369                }
370                try {
371                    tmpPort = Integer.parseInt(words[1]);
372                } catch (NumberFormatException nfe) {
373                    System.err.println("Invalid host specification, " +
374                        "could not parse port number.");
375                    usage();
376                }
377                config.addOtherHost(words[0], tmpPort, isPeer);
378           } else if (argv[i].compareTo("-p") == 0) {
379                i++;
380                config.priority = Integer.parseInt(argv[i]);
381            }</tt></b> else {
382                System.err.println("Unrecognized option: " + argv[i]);
383                usage();
384            }
385        } 
386
387        // Error check command line.
388        if (<b class="userinput"><tt>(!config.gotListenAddress())</tt></b> || config.home.length() == 0)
389            usage(); </pre>
390      <p>
391        Having done that, the remainder of our <tt class="function">main()</tt>
392        function is left unchanged, with the exception of a few name changes required by the
393        new class name:
394</p>
395      <pre class="programlisting">        <b class="userinput"><tt>RepQuoteExample</tt></b> runner = null;
396        try {
397            runner = new <b class="userinput"><tt>RepQuoteExample();</tt></b>
398            runner.init(config);
399
400            runner.doloop();
401            runner.terminate();
402        } catch (DatabaseException dbe) {
403            System.err.println("Caught an exception during " +
404                "initialization or processing: " + dbe.toString());
405            if (runner != null)
406                runner.terminate();
407        }
408            System.exit(0);
409    } // end main     </pre>
410      <p>
411        Now we need to update our 
412            
413            <tt class="methodname">RepQuoteExample.init()</tt>
414        method. Our updates are at first related to configuring
415        replication. First, we need to update the method so that we can 
416        identify the local site to the environment handle (that is, the site identified by the 
417<tt class="literal">-m</tt> command line option):
418</p>
419      <pre class="programlisting">    public int init(RepConfig config)
420        throws DatabaseException
421    {
422        int ret = 0;
423        appConfig = config;
424        EnvironmentConfig envConfig = new EnvironmentConfig();
425        envConfig.setErrorStream(System.err);
426        envConfig.setErrorPrefix(RepConfig.progname);
427
428        <b class="userinput"><tt>envConfig.setReplicationManagerLocalSite(appConfig.getThisHost());</tt></b> </pre>
429      <p>
430    And we also add code to allow us to identify "other" sites to the environment handle (that is,
431the sites that we identify using the <tt class="literal">-o</tt> command line
432option). To do this, we iterate over each of the "other" sites provided to
433us using the <tt class="literal">-o</tt> command line option, and we add each one
434individually in turn:     
435</p>
436      <pre class="programlisting">        <b class="userinput"><tt>for (ReplicationHostAddress host = appConfig.getFirstOtherHost();
437            host != null; host = appConfig.getNextOtherHost())
438        {
439            envConfig.replicationManagerAddRemoteSite(host);
440        }</tt></b> </pre>
441      <p>
442    And then we need code to allow us to identify the total number of sites
443    in this replication group, and to set the environment's priority.
444</p>
445      <pre class="programlisting">        <b class="userinput"><tt>if (appConfig.totalSites &gt; 0)
446            envConfig.setReplicationNumSites(appConfig.totalSites);
447        envConfig.setReplicationPriority(appConfig.priority); </tt></b> </pre>
448      <p>
449            
450
451            
452
453            <span>We can now open our environment. Note that the options</span>
454
455            we use to open the environment are slightly different for a
456            replicated application than they are for a non-replicated
457            application. Namely, replication requires the
458            
459
460            <span>
461            <tt class="methodname">EnvironmentConfig.setInitializeReplication()</tt> option.
462            </span>
463    </p>
464      <p>
465            Also, because we are using the replication framework, we must prepare
466            our environment for threaded usage. For this reason, we also
467            need the <tt class="literal">DB_THREAD</tt> flag.
468    </p>
469      <pre class="programlisting">        envConfig.setCacheSize(RepConfig.CACHESIZE);
470        envConfig.setTxnNoSync(true);
471
472        envConfig.setAllowCreate(true);
473        envConfig.setRunRecovery(true);
474        <b class="userinput"><tt>envConfig.setInitializeReplication(true);</tt></b>
475        envConfig.setInitializeLocking(true);
476        envConfig.setInitializeLogging(true);
477        envConfig.setInitializeCache(true);
478        envConfig.setTransactional(true);
479        try {
480            dbenv = new Environment(appConfig.getHome(), envConfig);
481        } catch(FileNotFoundException e) {
482            System.err.println("FileNotFound exception: " + e.toString());
483            System.err.println(
484                "Ensure that the environment directory is pre-created.");
485            ret = 1;
486        } </pre>
487      <p>
488        Finally, we start replication before we exit this method.
489        Immediately after exiting this method, our application will go into
490        the 
491        
492        <tt class="methodname">RepQuoteExample.doloop()</tt>
493        method, which is where
494       the bulk of our application's work is performed. We update that
495       method in the next chapter. 
496</p>
497      <pre class="programlisting">        // start replication manager
498        dbenv.replicationManagerStart(3, appConfig.startPolicy);
499        return ret;
500    } </pre>
501      <p>
502        This completes our replication updates for the moment. We are not as
503        yet ready to actually run this program; there remains a few
504        critical pieces left to add to it. However, the work that we
505        performed in this section represents a solid foundation for the
506        remainder of our replication work.
507    </p>
508    </div>
509    <div class="navfooter">
510      <hr />
511      <table width="100%" summary="Navigation footer">
512        <tr>
513          <td width="40%" align="left"><a accesskey="p" href="repapp.html">Prev</a>��</td>
514          <td width="20%" align="center">
515            <a accesskey="u" href="repapp.html">Up</a>
516          </td>
517          <td width="40%" align="right">��<a accesskey="n" href="fwrkpermmessage.html">Next</a></td>
518        </tr>
519        <tr>
520          <td width="40%" align="left" valign="top">Chapter��3.��The DB Replication Framework��</td>
521          <td width="20%" align="center">
522            <a accesskey="h" href="index.html">Home</a>
523          </td>
524          <td width="40%" align="right" valign="top">��Permanent Message Handling</td>
525        </tr>
526      </table>
527    </div>
528  </body>
529</html>
530