Import BSDDB 4.7.25 (as of svn r89086)
This commit is contained in:
384
docs/gsg_db_rep/C/repmgr_init_example_c.html
Normal file
384
docs/gsg_db_rep/C/repmgr_init_example_c.html
Normal file
@@ -0,0 +1,384 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Adding the Replication Framework to
|
||||
simple_txn
|
||||
|
||||
</title>
|
||||
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
|
||||
<link rel="home" href="index.html" title="Getting Started with Replicated Berkeley DB Applications" />
|
||||
<link rel="up" href="repapp.html" title="Chapter 3. The DB Replication Framework" />
|
||||
<link rel="previous" href="repapp.html" title="Chapter 3. The DB Replication Framework" />
|
||||
<link rel="next" href="fwrkpermmessage.html" title="Permanent Message Handling" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Adding the Replication Framework to
|
||||
simple_txn
|
||||
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="repapp.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 3. The DB Replication Framework</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="fwrkpermmessage.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="repmgr_init_example_c"></a>Adding the Replication Framework to
|
||||
<span>simple_txn</span>
|
||||
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
We now use the methods described above to add partial
|
||||
support to the
|
||||
<tt class="literal">simple_txn</tt>
|
||||
|
||||
example that we presented in
|
||||
<a href="txnapp.html">Transactional Application</a>.
|
||||
That is, in this section we will:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Enhance our command line options to
|
||||
accept information of interest to a
|
||||
replicated application.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Configure our environment handle to use
|
||||
replication and the replication framework.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Minimally configure the replication framework.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Start replication.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
Note that when we are done with this section, we will be
|
||||
only partially ready to run the application. Some critical
|
||||
pieces will be missing; specifically, we will not yet be
|
||||
handling the differences between a master and a
|
||||
replica. (We do that in the next chapter).
|
||||
</p>
|
||||
<p>
|
||||
Also, note that in the following code fragments, additions
|
||||
and changes to the code are marked in <b class="userinput"><tt>bold</tt></b>.
|
||||
</p>
|
||||
<p>
|
||||
To begin, we copy the
|
||||
<tt class="literal">simple_txn</tt>
|
||||
|
||||
code to a new file called
|
||||
<tt class="literal">rep_mgr.c</tt>.
|
||||
|
||||
<span>
|
||||
We then make the corresponding change to the program name.
|
||||
</span>
|
||||
|
||||
|
||||
</p>
|
||||
<pre class="programlisting">/*
|
||||
<b class="userinput"><tt>* File: rep_mgr.c</tt></b>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <db.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
extern int getopt(int, char * const *, const char *);
|
||||
#endif
|
||||
|
||||
#define CACHESIZE (10 * 1024 * 1024)
|
||||
#define DATABASE "quote.db"
|
||||
|
||||
const char *progname = <b class="userinput"><tt>"rep_mgr";</tt></b>
|
||||
|
||||
int create_env(const char *, DB_ENV **);
|
||||
int env_init(DB_ENV *, const char *);
|
||||
int doloop (DB_ENV *);
|
||||
int print_stocks(DBC *); </pre>
|
||||
<p>
|
||||
Next we update our usage function. The application will continue to
|
||||
accept the <tt class="literal">-h</tt> parameter so that we can identify
|
||||
the environment home directory used by this application. However,
|
||||
we also add the
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">-m</tt> parameter which allows us to
|
||||
identify the host and port used by this application to
|
||||
listen for replication messages.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">-o</tt> parameter which allows us to
|
||||
specify other replicas.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">-n</tt> parameter which allows us to
|
||||
identify the number of sites in this replication
|
||||
group.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">-p</tt> option, which is used to identify
|
||||
this replica's priority (recall that the priority is
|
||||
used as a tie breaker for elections)
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<pre class="programlisting">/* Usage function */
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "usage: %s ", progname);
|
||||
fprintf(stderr, "[-h home] <b class="userinput"><tt>-m host:port [-o host:port]</tt></b>\n");
|
||||
<b class="userinput"><tt>fprintf(stderr, "\t\t[-p priority]\n");</tt></b>
|
||||
fprintf(stderr, "where:\n");
|
||||
fprintf(stderr, "\t-h identifies the environment home directory\n");
|
||||
<b class="userinput"><tt>fprintf(stderr, "\t-o identifies another site participating in ");
|
||||
fprintf(stderr, "this replication group\n");
|
||||
fprintf(stderr, "\t-m identifies the host and port used by this ");
|
||||
fprintf(stderr, "site (required).\n");
|
||||
fprintf(stderr, "\t-n identifies the number of sites in this ");
|
||||
fprintf(stderr, "replication group (required).\n");
|
||||
fprintf(stderr, "\t-p identifies the election priority used by ");
|
||||
fprintf(stderr, "this replica.\n");</tt></b>
|
||||
exit(EXIT_FAILURE);
|
||||
} </pre>
|
||||
<p>
|
||||
Now we can begin working on our <tt class="literal">main()</tt> function.
|
||||
We begin by adding a couple of variables that we will use to
|
||||
collect TCP/IP host and port information.
|
||||
|
||||
|
||||
<span>
|
||||
We also declare a couple
|
||||
of flags that we use to make sure some required information is
|
||||
provided to this application.
|
||||
</span>
|
||||
</p>
|
||||
<pre class="programlisting">int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
extern char *optarg;
|
||||
DB_ENV *dbenv;
|
||||
const char *home;
|
||||
char ch, <b class="userinput"><tt>*host, *portstr</tt></b>;
|
||||
int ret, <b class="userinput"><tt>local_is_set, totalsites</tt></b>;
|
||||
<b class="userinput"><tt>u_int32_t port</tt></b>;
|
||||
|
||||
dbenv = NULL;
|
||||
|
||||
ret = <b class="userinput"><tt>local_is_set = totalsites = </tt></b>0;
|
||||
home = NULL; </pre>
|
||||
<p>
|
||||
At this time we can create our environment handle and configure it
|
||||
exactly as we did for <tt class="literal">simple_txn</tt>.
|
||||
The only thing that we will do differently here is that we will set a priority,
|
||||
arbitrarily picked to be 100, so that we can be sure the environment has
|
||||
a priority other than 0 (the default value). This ensures that the
|
||||
environment can become a master via an election.
|
||||
</p>
|
||||
<pre class="programlisting"> if ((ret = create_env(progname, &dbenv)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Default priority is 100 */
|
||||
<b class="userinput"><tt>dbenv->rep_set_priority(dbenv, 100);</tt></b> </pre>
|
||||
<p>
|
||||
Now we collect our command line arguments. As we do so, we will
|
||||
configure host and port information as required, and we will
|
||||
configure the application's election priority if necessary.
|
||||
</p>
|
||||
<pre class="programlisting"> /* Collect the command line options */
|
||||
while ((ch = getopt(argc, argv, "h:<b class="userinput"><tt>m:o:p:</tt></b>")) != EOF)
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
home = optarg;
|
||||
break;
|
||||
<b class="userinput"><tt>/* Set the host and port used by this environment */
|
||||
case 'm':
|
||||
host = strtok(optarg, ":");
|
||||
if ((portstr = strtok(NULL, ":")) == NULL) {
|
||||
fprintf(stderr, "Bad host specification.\n");
|
||||
goto err;
|
||||
}
|
||||
port = (unsigned short)atoi(portstr);
|
||||
if (dbenv->repmgr_set_local_site(dbenv, host, port, 0) != 0) {
|
||||
fprintf(stderr,
|
||||
"Could not set local address %s.\n", host);
|
||||
goto err;
|
||||
}
|
||||
local_is_set = 1;
|
||||
break;
|
||||
/* Identify another site in the replication group */
|
||||
case 'o':
|
||||
host = strtok(optarg, ":");
|
||||
if ((portstr = strtok(NULL, ":")) == NULL) {
|
||||
fprintf(stderr, "Bad host specification.\n");
|
||||
goto err;
|
||||
}
|
||||
port = (unsigned short)atoi(portstr);
|
||||
if (dbenv->repmgr_add_remote_site(dbenv, host, port,
|
||||
NULL, 0) != 0) {
|
||||
fprintf(stderr,
|
||||
"Could not add site %s.\n", host);
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
/* Set the number of sites in this replication group */
|
||||
case 'n':
|
||||
totalsites = atoi(optarg);
|
||||
if ((ret = dbenv->rep_set_nsites(dbenv, totalsites)) != 0)
|
||||
dbenv->err(dbenv, ret, "set_nsites");
|
||||
break;
|
||||
/* Set this replica's election priority */
|
||||
case 'p':
|
||||
dbenv->rep_set_priority(dbenv, atoi(optarg));
|
||||
break; </tt></b>
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
/* Error check command line. */
|
||||
if (home == NULL <b class="userinput"><tt>|| !local_is_set || !totalsites</tt></b>)
|
||||
usage(); </pre>
|
||||
<p>
|
||||
Having done that, we can call <tt class="function">env_init()</tt>, which we use to
|
||||
open our environment handle. Note that this function changes
|
||||
slightly for this update (see below).
|
||||
</p>
|
||||
<pre class="programlisting"> if ((ret = env_init(dbenv, home)) != 0)
|
||||
goto err; </pre>
|
||||
<p>
|
||||
Finally, we start replication before we go into the
|
||||
<tt class="function">doloop()</tt> function (where we perform all our
|
||||
database access).
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<b class="userinput"><tt>if ((ret = dbenv->repmgr_start(dbenv, 3, DB_REP_ELECTION)) != 0)
|
||||
goto err; </tt></b>
|
||||
|
||||
if ((ret = doloop(dbenv)) != 0) {
|
||||
dbenv->err(dbenv, ret, "Application failed");
|
||||
goto err;
|
||||
}
|
||||
|
||||
err: if (dbenv != NULL)
|
||||
(void)dbenv->close(dbenv, 0);
|
||||
|
||||
return (ret);
|
||||
} </pre>
|
||||
<p>
|
||||
<span>Beyond that, the rest of our application remains the same for
|
||||
now, with the exception of the <tt class="function">env_init()</tt>
|
||||
function, which we use to actually open our environment handle.
|
||||
The flags </span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
we use to open the environment are slightly different for a
|
||||
replicated application than they are for a non-replicated
|
||||
application. Namely, replication requires the
|
||||
<span>
|
||||
<tt class="literal">DB_INIT_REP</tt> flag.
|
||||
</span>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Also, because we are using the replication framework, we must prepare
|
||||
our environment for threaded usage. For this reason, we also
|
||||
need the <tt class="literal">DB_THREAD</tt> flag.
|
||||
</p>
|
||||
<pre class="programlisting"> int
|
||||
env_init(DB_ENV *dbenv, const char *home)
|
||||
{
|
||||
u_int32_t flags;
|
||||
int ret;
|
||||
|
||||
(void)dbenv->set_cachesize(dbenv, 0, CACHESIZE, 0);
|
||||
(void)dbenv->set_flags(dbenv, DB_TXN_NOSYNC, 1);
|
||||
|
||||
flags = DB_CREATE |
|
||||
DB_INIT_LOCK |
|
||||
DB_INIT_LOG |
|
||||
DB_INIT_MPOOL |
|
||||
DB_INIT_TXN |
|
||||
<b class="userinput"><tt>DB_INIT_REP |
|
||||
DB_THREAD |</tt></b>
|
||||
DB_RECOVER;
|
||||
if ((ret = dbenv->open(dbenv, home, flags, 0)) != 0)
|
||||
dbenv->err(dbenv, ret, "can't open environment");
|
||||
return (ret);
|
||||
}</pre>
|
||||
<p>
|
||||
This completes our replication updates for the moment. We are not as
|
||||
yet ready to actually run this program; there remains a few
|
||||
critical pieces left to add to it. However, the work that we
|
||||
performed in this section represents a solid foundation for the
|
||||
remainder of our replication work.
|
||||
</p>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="repapp.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="repapp.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="fwrkpermmessage.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Chapter 3. The DB Replication Framework </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Permanent Message Handling</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user