repmgr_init_example_c.html [plain text]
<?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>