Import BSDDB 4.7.25 (as of svn r89086)
This commit is contained in:
BIN
docs/gsg_db_rep/CXX/Replication-CXX-GSG.pdf
Normal file
BIN
docs/gsg_db_rep/CXX/Replication-CXX-GSG.pdf
Normal file
Binary file not shown.
191
docs/gsg_db_rep/CXX/addfeatures.html
Normal file
191
docs/gsg_db_rep/CXX/addfeatures.html
Normal file
@@ -0,0 +1,191 @@
|
||||
<?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>Chapter 5. Additional Features</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="index.html" title="Getting Started with Replicated Berkeley DB Applications" />
|
||||
<link rel="previous" href="exampledoloop.html" title="Example Processing Loop" />
|
||||
<link rel="next" href="manageblock.html" title="Managing Blocking Operations" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Chapter 5. Additional Features</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="exampledoloop.html">Prev</a> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="manageblock.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="chapter" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title"><a id="addfeatures"></a>Chapter 5. Additional Features</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="addfeatures.html#delayedsync">Delayed Synchronization</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="manageblock.html">Managing Blocking Operations</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="noautoinit.html">Stop Auto-Initialization</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="c2ctransfer.html">Client to Client Transfer</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="c2ctransfer.html#fmwrkpeerserver">Identifying Peers</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="bulk.html">Bulk Transfers</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
Beyond the basic functionality that we have discussed so far in
|
||||
this book, there are several replication features that you
|
||||
should understand. These are all optional to use, but provide
|
||||
useful functionality under the right circumstances.
|
||||
</p>
|
||||
<p>
|
||||
These additional features are:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
<a href="addfeatures.html#delayedsync">Delayed Synchronization</a>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<a href="manageblock.html">Managing Blocking Operations</a>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<a href="noautoinit.html">Stop Auto-Initialization</a>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<a href="c2ctransfer.html">Client to Client Transfer</a>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<a href="bulk.html">Bulk Transfers</a>
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="delayedsync"></a>Delayed Synchronization</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
When a replication group has a new master, all replicas must
|
||||
synchronize with that master. This means they must ensure
|
||||
that the contents of their local database(s) are identical
|
||||
to that contained by the new master.
|
||||
</p>
|
||||
<p>
|
||||
This synchronization process can result in quite a lot of
|
||||
network activity. It can also put a large strain on the
|
||||
master server, especially if is part of a large
|
||||
replication group or if there is somehow a large difference between
|
||||
the master's database(s) and the contents of its replicas.
|
||||
</p>
|
||||
<p>
|
||||
It is therefore possible to delay synchronization for any
|
||||
replica that discovers it has a new master. You would do
|
||||
this so as to give the master time to synchronize other
|
||||
replicas before proceeding with the delayed replicas.
|
||||
</p>
|
||||
<p>
|
||||
To delay synchronization of a replica environment, you
|
||||
specify
|
||||
<span>
|
||||
<tt class="literal">DB_REP_CONF_DELAYCLIENT</tt> to
|
||||
|
||||
<tt class="methodname">DbEnv::rep_set_config()</tt>
|
||||
and then specify <tt class="literal">1</tt> to the <tt class="literal">onoff</tt>
|
||||
parameter. (Specify <tt class="literal">0</tt> to turn the feature off.)
|
||||
</span>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
If you use delayed synchronization, then you must manually
|
||||
synchronize the replica at some future time. Until you do this, the replica is out of
|
||||
sync with the master, and it will ignore all database changes forwarded to it from
|
||||
the master.
|
||||
</p>
|
||||
<p>
|
||||
You synchronize a delayed replica by calling
|
||||
|
||||
<tt class="methodname">DbEnv::rep_sync()</tt>
|
||||
|
||||
on the replica that has been delayed.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="exampledoloop.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="index.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="manageblock.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Example Processing Loop </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Managing Blocking Operations</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
225
docs/gsg_db_rep/CXX/apioverview.html
Normal file
225
docs/gsg_db_rep/CXX/apioverview.html
Normal file
@@ -0,0 +1,225 @@
|
||||
<?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>The Replication APIs</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="introduction.html" title="Chapter 1. Introduction" />
|
||||
<link rel="previous" href="repadvantage.html" title="Replication Benefits" />
|
||||
<link rel="next" href="elections.html" title="Holding Elections" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">The Replication APIs</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="repadvantage.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 1. Introduction</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="elections.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="apioverview"></a>The Replication APIs</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
There are two ways that you can choose to implement
|
||||
replication in your transactional application. The first,
|
||||
and preferred, mechanism is to use the pre-packaged
|
||||
replication framework that comes with the
|
||||
DB distribution. This framework should be sufficient
|
||||
for most customers.
|
||||
</p>
|
||||
<p>
|
||||
If for some reason the Replication Framework
|
||||
does not meet your application's technical requirements,
|
||||
you will have to use the replication APIs available
|
||||
through the Berkeley DB library to write your own custom
|
||||
replication framework.
|
||||
</p>
|
||||
<p>
|
||||
Both of these approaches are described in slightly greater
|
||||
detail in this section. The bulk of the chapters later in
|
||||
this book are dedicated to these two replication
|
||||
implementation mechanisms.
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="repframeworkoverview"></a>Replication Framework Overview</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
DB's pre-packaged replication framework exists
|
||||
as a layer on top of the DB library. The replication framework is a
|
||||
multi-threaded implementation that allows you to easily add
|
||||
replication to your existing transactional application.
|
||||
<span>
|
||||
You access and manage the replication framework using methods that are
|
||||
available off the
|
||||
|
||||
<tt class="classname">DbEnv</tt>
|
||||
class.
|
||||
</span>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
The replication framework:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Provides a multi-threaded communications layer
|
||||
using pthreads (on Unix-style systems and
|
||||
similar derivatives such as Mac OS X), or
|
||||
Windows threads on Microsoft Windows systems.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Uses TCP/IP sockets. Network traffic is
|
||||
handled via threads that handle inbound and
|
||||
outbound messages. However, each
|
||||
process uses a single socket
|
||||
that is shared using <tt class="function">select()</tt>.
|
||||
</p>
|
||||
<p>
|
||||
Note that for this reason, the replication framework is
|
||||
limited to a maximum of 60 replicas (on
|
||||
Windows) and approximately 1000 replicas (on
|
||||
Unix and related systems), depending on how
|
||||
your system is configured.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Requires a single process for the master replica.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Requires that only one instance of the
|
||||
environment handle be used.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Upon application startup, a master can be
|
||||
selected either manually or via elections.
|
||||
After startup time, however, during the course of
|
||||
normal operations it is possible for the
|
||||
replication group to need to locate a new master (due
|
||||
to network or other hardware related problems,
|
||||
for example) and in this scenario elections are
|
||||
always used to select the new master.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
If your application has technical requirements that do
|
||||
not conform to the implementation provided by the
|
||||
replication framework, you must write a custom
|
||||
replication framework using the DB replication APIs
|
||||
directly. See the next section for introductory
|
||||
details.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="repapioverview"></a>Replication API Overview</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The replication API is a series of Berkeley DB library
|
||||
classes and methods that you can use to build your own
|
||||
replication infrastructure. You should use the
|
||||
replication API only if the replication framework does not meet your
|
||||
application's technical requirements.
|
||||
</p>
|
||||
<p>
|
||||
To make use of the replication API, you must write your
|
||||
own networking code. This frees you from the technical
|
||||
constraints imposed by the replication framework. For example, by
|
||||
writing your own framework, you can:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Use a threading package other than
|
||||
pthreads (Unix) or Windows threads
|
||||
(Microsoft Windows). This might be interesting
|
||||
to you if you are using a platform
|
||||
whose preferred threading package
|
||||
is something other than (for
|
||||
example) pthreads, such as is the case for
|
||||
Sun Microsystem's Solaris operating systems.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Implement your own sockets. The
|
||||
replication framework uses TCP/IP sockets. While
|
||||
this should be acceptable for the
|
||||
majority of applications, sometimes
|
||||
UDP or even raw sockets might be
|
||||
desired.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Write a multi-process master
|
||||
replica.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
For information on writing a replicated application
|
||||
using the Berkeley DB replication APIs, see the
|
||||
<i class="citetitle">Berkeley DB Programmer's Reference Guide</i>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="repadvantage.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="introduction.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="elections.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Replication Benefits </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Holding Elections</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
139
docs/gsg_db_rep/CXX/bulk.html
Normal file
139
docs/gsg_db_rep/CXX/bulk.html
Normal file
@@ -0,0 +1,139 @@
|
||||
<?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>Bulk Transfers</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="addfeatures.html" title="Chapter 5. Additional Features" />
|
||||
<link rel="previous" href="c2ctransfer.html" title="Client to Client Transfer" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Bulk Transfers</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="c2ctransfer.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 5. Additional Features</th>
|
||||
<td width="20%" align="right"> </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="bulk"></a>Bulk Transfers</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
By default, messages are sent from the master to replicas as they are generated.
|
||||
This can degrade replication performance because the various participating
|
||||
environments must handle a fair amount of network I/O activity.
|
||||
</p>
|
||||
<p>
|
||||
You can alleviate this problem by configuring your master environment for bulk
|
||||
transfers. Bulk transfers simply cause replication messages to accumulate in a
|
||||
buffer until a triggering event occurs. When this event occurs, the entire
|
||||
contents of the buffer is sent to the replica, thereby eliminating excessive
|
||||
network I/O.
|
||||
</p>
|
||||
<p>
|
||||
Note that if you are using replica to replica transfers, then you might want any
|
||||
replica that can service replication requests to also be configured for bulk
|
||||
transfers.
|
||||
</p>
|
||||
<p>
|
||||
The events that result in a bulk transfer of replication messages to a replica
|
||||
will differ depending on if the transmitting environment is a master or a
|
||||
replica.
|
||||
</p>
|
||||
<p>
|
||||
If the servicing environment is a master environment, then bulk a bulk transfer
|
||||
occurs when:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Bulk transfers are configured for the master environment, and
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
the message buffer is full or
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
a permanent record (for example, a transaction commit or a
|
||||
checkpoint record) is placed in the buffer for the replica.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p>
|
||||
If the servicing environment is a replica environment (that is, replica to replica
|
||||
transfers are in use), then a bulk transfer occurs when:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Bulk transfers are configured for the transmitting replica, and
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
the message buffer is full or
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
the replica servicing the request is able to completely satisfy
|
||||
the request with the contents of the message buffer.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p>
|
||||
To configure bulk transfers, specify
|
||||
|
||||
<span>
|
||||
<tt class="literal">DB_REP_CONF_BULK</tt> to
|
||||
|
||||
<tt class="methodname">DbEnv::rep_set_config()</tt>
|
||||
and then specify <tt class="literal">1</tt> to the <tt class="literal">onoff</tt>
|
||||
parameter. (Specify <tt class="literal">0</tt> to turn the feature off.)
|
||||
</span>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="c2ctransfer.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="addfeatures.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Client to Client Transfer </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
131
docs/gsg_db_rep/CXX/c2ctransfer.html
Normal file
131
docs/gsg_db_rep/CXX/c2ctransfer.html
Normal file
@@ -0,0 +1,131 @@
|
||||
<?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>Client to Client Transfer</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="addfeatures.html" title="Chapter 5. Additional Features" />
|
||||
<link rel="previous" href="noautoinit.html" title="Stop Auto-Initialization" />
|
||||
<link rel="next" href="bulk.html" title="Bulk Transfers" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Client to Client Transfer</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="noautoinit.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 5. Additional Features</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="bulk.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="c2ctransfer"></a>Client to Client Transfer</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
It is possible to use a replica instead of a master to synchronize another
|
||||
replica. This serves to take the request load off a master that might otherwise
|
||||
occur if multiple replicas attempted to synchronize with the master at the same
|
||||
time.
|
||||
</p>
|
||||
<p>
|
||||
For best results, use this feature combined with the delayed synchronization
|
||||
feature (see <a href="addfeatures.html#delayedsync">Delayed Synchronization</a>).
|
||||
</p>
|
||||
<p>
|
||||
For example, suppose your replication group consists of four environments. Upon
|
||||
application startup, all three replicas will immediately attempt to synchronize
|
||||
with the master. But at the same time, the master itself might be busy with a heavy
|
||||
database write load.
|
||||
</p>
|
||||
<p>
|
||||
To solve this problem, delay synchronization for two of the three replicas. Allow
|
||||
the third replica to synchronize as normal with the master. Then, start
|
||||
synchronization for each of the delayed replicas (since this is a manual process,
|
||||
you can do them one at a time if that best suits your application).
|
||||
Assuming you have configured replica to replica synchronization correctly, the
|
||||
delayed replicas will synchronize using the up-to-date replica, rather than using
|
||||
the master.
|
||||
</p>
|
||||
<p>
|
||||
When you are using the replication framework, you configure replica to replica synchronization by
|
||||
declaring one environment to be a peer of another environment. If an
|
||||
environment is a peer, then
|
||||
it can be used for synchronization purposes.
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="fmwrkpeerserver"></a>Identifying Peers</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
You can designate one replica to be a peer of
|
||||
another, and then use this special
|
||||
status for permanent message acknowledgments,
|
||||
and for replica-to-replica synchronization.
|
||||
You might want to do this if you have
|
||||
machines that you know are on fast, reliable
|
||||
network connections and so you are willing to
|
||||
accept the overhead of waiting for
|
||||
acknowledgments from those specific machines.
|
||||
</p>
|
||||
<p>
|
||||
An environment is currently allowed to have only one
|
||||
peer.
|
||||
</p>
|
||||
<p>
|
||||
Note that peers are not required to be a
|
||||
bi-directional. That is, just because machine A
|
||||
declares machine B to be a peer, that does not mean
|
||||
machine B must also declare machine A to be a peer.
|
||||
</p>
|
||||
<p>
|
||||
You declare a peer for the current environment
|
||||
when you add that environment to the list of known
|
||||
sites. You do this by
|
||||
<span>specifying the
|
||||
<tt class="literal">DB_REPMGR_PEER</tt> flag to
|
||||
|
||||
<span><tt class="methodname">DbEnv::repmgr_add_remote_site()</tt>.</span>
|
||||
</span>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="noautoinit.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="addfeatures.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="bulk.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Stop Auto-Initialization </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Bulk Transfers</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
227
docs/gsg_db_rep/CXX/elections.html
Normal file
227
docs/gsg_db_rep/CXX/elections.html
Normal file
@@ -0,0 +1,227 @@
|
||||
<?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>Holding Elections</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="introduction.html" title="Chapter 1. Introduction" />
|
||||
<link rel="previous" href="apioverview.html" title="The Replication APIs" />
|
||||
<link rel="next" href="permmessages.html" title="Permanent Message Handling" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Holding Elections</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="apioverview.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 1. Introduction</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="permmessages.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="elections"></a>Holding Elections</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Finding a master environment is one of the fundamental activities that
|
||||
every replication replica must perform. Upon startup, the
|
||||
underlying DB replication code will attempt to
|
||||
locate a master. If a master cannot be found, then the
|
||||
environment should initiate an election.
|
||||
</p>
|
||||
<p>
|
||||
How elections are held depends upon the API that you use to
|
||||
implement replication. For example, if you are using the
|
||||
replication framework elections are held transparently without any
|
||||
input from your application's code. In this case,
|
||||
DB will determine which environment is the master and which
|
||||
are replicas.
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="influencingelections"></a>Influencing Elections</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
If you want to control the election process, you can declare
|
||||
a specific environment to be the master. Note that for the replication framework,
|
||||
it is only possible to do this at application startup.
|
||||
Should the master become unavailable during run-time for any
|
||||
reason, an election is held. The environment that receives
|
||||
the most number of votes, wins the election and becomes the
|
||||
master. A machine receives a vote because it has the most
|
||||
number of log records.
|
||||
</p>
|
||||
<p>
|
||||
Because ties are possible when elections are held,
|
||||
it is possible to influence which environment will win
|
||||
the election. How you do this depends on which API you
|
||||
are using. In particular, if you are writing a custom replication
|
||||
layer, then there are a great many ways to manually influence
|
||||
elections.
|
||||
</p>
|
||||
<p>
|
||||
One such mechanism is priorities. When votes are
|
||||
cast during an election, both the number of log records
|
||||
contained in the environment <span class="emphasis"><em>and</em></span>
|
||||
the environment's priority are considered. So given two
|
||||
environments with the same number of log records, votes
|
||||
are cast for the environment with the higher priority.
|
||||
</p>
|
||||
<p>
|
||||
Therefore, if you have a machine that you prefer to
|
||||
become a master in the event of an election, assign it
|
||||
a high priority. Assuming that the election is held at
|
||||
a time when the preferred machine has up-to-date log
|
||||
records, that machine will win the election.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="winningelections"></a>Winning Elections</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
To win an election:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
There cannot currently be a
|
||||
master environment.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
The environment must have the most
|
||||
recent log records. Part of
|
||||
holding the election is
|
||||
determining which environments have
|
||||
the most recent log records.
|
||||
This process happens
|
||||
automatically; your code does
|
||||
not need to involve itself in
|
||||
this process.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
The environment must receive the most
|
||||
number of votes from the
|
||||
replication environments that are
|
||||
participating in the election.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p>
|
||||
If you are using the replication framework, then in the event of a
|
||||
tie vote the environment with the highest priority wins
|
||||
the election. If two or more environments receive the same
|
||||
number of votes and have the same priority, then
|
||||
the underlying replication code picks one of the
|
||||
environments to
|
||||
be the winner. Which winner will be picked by the
|
||||
replication code is unpredictable from the
|
||||
perspective of your application code.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="switchingmasters"></a>Switching Masters</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
To switch masters:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Start up the environment that you want
|
||||
to be master as normal. At this
|
||||
time it is a replica. Make
|
||||
sure this environment has a higher
|
||||
priority than all the other
|
||||
environments.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Allow the new environment to run for a
|
||||
time as a replica. This allows
|
||||
it to obtain the most recent
|
||||
copies of the log files.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Shut down the current master.
|
||||
This should force an election.
|
||||
Because the new environment has the
|
||||
highest priority, it will win
|
||||
the election, provided it has
|
||||
had enough time to obtain all
|
||||
the log records.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Optionally restart the old
|
||||
master environment. Because there is
|
||||
currently a master environment, an
|
||||
election will not be held and
|
||||
the old master will now run as
|
||||
a replica environment.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="apioverview.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="introduction.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="permmessages.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">The Replication APIs </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>
|
||||
152
docs/gsg_db_rep/CXX/electiontimes.html
Normal file
152
docs/gsg_db_rep/CXX/electiontimes.html
Normal file
@@ -0,0 +1,152 @@
|
||||
<?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>Managing Election Times</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="fwrkpermmessage.html" title="Permanent Message Handling" />
|
||||
<link rel="next" href="fmwrkconnectretry.html" title="Managing Connection Retries" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Managing Election Times</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="fwrkpermmessage.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="fmwrkconnectretry.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="electiontimes"></a>Managing Election Times</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Where it comes to elections, there are two timeout
|
||||
values with which you should be concerned: election
|
||||
timeouts and election retries.
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="electiontimeout"></a>Managing Election Timeouts</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
When a environment calls for an election, it will wait
|
||||
some amount of time for the other replicas in the
|
||||
replication group to respond. The amount of time
|
||||
that the environment will wait before declaring the
|
||||
election completed is the <span class="emphasis"><em>election timeout</em></span>.
|
||||
</p>
|
||||
<p>
|
||||
If the environment hears from all other known replicas before
|
||||
the election timeout occurs, the election is considered
|
||||
a success and a master is elected.
|
||||
</p>
|
||||
<p>
|
||||
If only a subset of replicas respond, then the success
|
||||
or failure of the election is determined by (1)
|
||||
how many replicas have responded and (2) the
|
||||
election policy that is in place at the time.
|
||||
For example, usually it only takes a simple
|
||||
majority of replicas to elect a master. If
|
||||
there are enough votes for a given environment to
|
||||
meet that standard, then the master has been
|
||||
elected and the election is considered a
|
||||
success.
|
||||
</p>
|
||||
<p>
|
||||
However, upon application startup you can
|
||||
require that all known replicas must participate in the
|
||||
election. Or, it is possible that not enough
|
||||
votes are cast to select a master even with a
|
||||
simple majority. If either of these conditions
|
||||
occur when the election timeout value is
|
||||
reached, the election is considered a failure
|
||||
and a master is not elected. At this point,
|
||||
your replication group is operating without a
|
||||
master, which means that, essentially,
|
||||
your replicated application has been placed in
|
||||
read-only mode.
|
||||
</p>
|
||||
<p>
|
||||
Note, however, that the replication framework will attempt a
|
||||
new election after a given amount of time has
|
||||
passed. See the next section for details.
|
||||
</p>
|
||||
<p>
|
||||
You set the election timeout value using
|
||||
|
||||
<span><tt class="methodname">DbEnv::rep_set_timeout()</tt>.</span>
|
||||
To do so, specify the
|
||||
<tt class="literal">DB_REP_ELECTION_TIMEOUT</tt>
|
||||
flag to the <tt class="literal">which</tt> parameter and then a
|
||||
timeout value in microseconds to the
|
||||
<tt class="literal">timeout</tt> parameter.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="electretrytime"></a>Managing Election Retry Times</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
In the event that a election fails (see the
|
||||
previous section), an election will not be
|
||||
attempted again until the election retry
|
||||
timeout value has expired.
|
||||
</p>
|
||||
<p>
|
||||
You set the retry timeout value using
|
||||
|
||||
<span><tt class="methodname">DbEnv::rep_set_timeout()</tt>.</span>
|
||||
To do so, specify the
|
||||
<tt class="literal">DB_REP_ELECTION_RETRY</tt>
|
||||
flag to the <tt class="literal">which</tt> parameter and then a
|
||||
retry value in microseconds to the
|
||||
<tt class="literal">timeout</tt> parameter.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="fwrkpermmessage.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="fmwrkconnectretry.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Permanent Message Handling </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Managing Connection Retries</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
541
docs/gsg_db_rep/CXX/exampledoloop.html
Normal file
541
docs/gsg_db_rep/CXX/exampledoloop.html
Normal file
@@ -0,0 +1,541 @@
|
||||
<?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>Example Processing Loop</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="fwrkmasterreplica.html" title="Chapter 4. Replica versus Master Processes" />
|
||||
<link rel="previous" href="processingloop.html" title="Processing Loop" />
|
||||
<link rel="next" href="addfeatures.html" title="Chapter 5. Additional Features" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Example Processing Loop</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="processingloop.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 4. Replica versus Master Processes</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="addfeatures.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="exampledoloop"></a>Example Processing Loop</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
In this section we take the example
|
||||
processing loop that we presented in the
|
||||
previous section and we flesh it out to
|
||||
provide a more complete example. We do this
|
||||
by updating the
|
||||
<tt class="function">doloop()</tt>
|
||||
function that our original transaction
|
||||
application used
|
||||
|
||||
<span>(see <a href="simpleprogramlisting.html#doloop_cxx">Method: RepMgr::doloop()</a>)</span>
|
||||
|
||||
to fully support our replicated application.
|
||||
</p>
|
||||
<p>
|
||||
In the following example code, code that we
|
||||
add to the original example is presented in
|
||||
<b class="userinput"><tt>bold</tt></b>.
|
||||
</p>
|
||||
<p>
|
||||
To begin, we include a new header file into
|
||||
our application so that we can check for the
|
||||
<tt class="literal">ENOENT</tt> return value later
|
||||
in our processing loop. We also define our
|
||||
<tt class="literal">APP_DATA</tt>
|
||||
structure, and we define a
|
||||
<tt class="literal">sleeptime</tt> value.
|
||||
|
||||
|
||||
|
||||
<span>
|
||||
Finally, we update <tt class="classname">RepMgr</tt>
|
||||
to have a new method for our event notification
|
||||
callback, and to add a new data member for our
|
||||
<tt class="literal">APP_DATA</tt> data member.
|
||||
</span>
|
||||
</p>
|
||||
<pre class="programlisting">#include <db_cxx.h>
|
||||
#include <iostream>
|
||||
<b class="userinput"><tt>#include <errno.h></tt></b>
|
||||
|
||||
...
|
||||
// Skipping all the RepHostInfoObj and RepConfigInfo code, which does not
|
||||
// change.
|
||||
...
|
||||
|
||||
using std::cout;
|
||||
using std::cin;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::flush;
|
||||
|
||||
#define CACHESIZE (10 * 1024 * 1024)
|
||||
#define DATABASE "quote.db"
|
||||
<b class="userinput"><tt>#define SLEEPTIME 3</tt></b>
|
||||
|
||||
const char *progname = "RepMgr";
|
||||
|
||||
<b class="userinput"><tt>// Struct used to store information in Db app_private field.
|
||||
typedef struct {
|
||||
int is_master;
|
||||
} APP_DATA;</tt></b>
|
||||
|
||||
class RepMgr
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
RepMgr();
|
||||
// Initialization method. Creates and opens our environment handle.
|
||||
int init(RepConfigInfo* config);
|
||||
// The doloop is where all the work is performed.
|
||||
int doloop();
|
||||
// terminate() provides our shutdown code.
|
||||
int terminate();
|
||||
|
||||
<b class="userinput"><tt>// event notification callback
|
||||
static void
|
||||
event_callback(DbEnv * dbenv, u_int32_t which, void *info);</tt></b>
|
||||
|
||||
private:
|
||||
// disable copy constructor.
|
||||
RepMgr(const RepMgr &);
|
||||
void operator = (const RepMgr &);
|
||||
|
||||
// internal data members.
|
||||
<b class="userinput"><tt>APP_DATA app_data;</tt></b>
|
||||
RepConfigInfo *app_config;
|
||||
DbEnv dbenv;
|
||||
|
||||
// private methods.
|
||||
// print_stocks() is used to display the contents of our database.
|
||||
static int print_stocks(Db *dbp);
|
||||
}; </pre>
|
||||
<p>
|
||||
That done, we can skip the
|
||||
|
||||
<span><tt class="methodname">main()</tt> method, because it does not change.</span>
|
||||
|
||||
|
||||
Instead, we skip down to our
|
||||
<span><tt class="classname">RepMgr</tt> constructor where we initialize our
|
||||
<tt class="literal">APP_DATA is_master</tt> data member:</span>
|
||||
|
||||
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
RepMgr::RepMgr() : app_config(0), dbenv(0)
|
||||
{
|
||||
<b class="userinput"><tt>app_data.is_master = 0; // assume I start out as client</tt></b>
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
That done, we must also
|
||||
update <tt class="methodname">RepMgr::init()</tt> to do a couple
|
||||
of things. First, we need to register our event callback with
|
||||
the environment handle. We also need to make our
|
||||
<tt class="literal">APP_DATA</tt> data member available through our
|
||||
environment handle's <tt class="methodname">app_private</tt>
|
||||
field. This is a fairly trivial update, and it happens at the
|
||||
top of the method (we skip the rest of the method's listing
|
||||
since it does not change):
|
||||
|
||||
</p>
|
||||
<pre class="programlisting">int RepMgr::init(RepConfigInfo *config)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
app_config = config;
|
||||
|
||||
dbenv.set_errfile(stderr);
|
||||
dbenv.set_errpfx(progname);
|
||||
<b class="userinput"><tt>dbenv.set_app_private(&app_data);
|
||||
dbenv.set_event_notify(event_callback);</tt></b>
|
||||
|
||||
... </pre>
|
||||
<p>
|
||||
That done, we need to implement our
|
||||
<tt class="function">event_callback()</tt> callback. Note that what we use
|
||||
here is no different from the callback that we described in
|
||||
the previous section. However, for the sake of completeness we
|
||||
provide the implementation here again.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<b class="userinput">
|
||||
<tt>/*
|
||||
* A callback used to determine whether the local environment is a replica
|
||||
* or a master. This is called by the replication framework
|
||||
* when the local replication environment changes state.
|
||||
*/
|
||||
void RepMgr::event_callback(DbEnv *dbenv, u_int32_t which, void *info)
|
||||
{
|
||||
APP_DATA *app = dbenv->get_app_private();
|
||||
|
||||
info = NULL; /* Currently unused. */
|
||||
|
||||
switch (which) {
|
||||
case DB_EVENT_REP_MASTER:
|
||||
app->is_master = 1;
|
||||
break;
|
||||
|
||||
case DB_EVENT_REP_CLIENT:
|
||||
app->is_master = 0;
|
||||
break;
|
||||
|
||||
case DB_EVENT_REP_STARTUPDONE: /* fallthrough */
|
||||
case DB_EVENT_REP_NEWMASTER:
|
||||
/* Ignore. */
|
||||
break;
|
||||
|
||||
default:
|
||||
dbenv->errx(dbenv, "ignoring event %d", which);
|
||||
}
|
||||
}</tt>
|
||||
</b>
|
||||
</pre>
|
||||
<p>
|
||||
That done, we need to update our
|
||||
<tt class="function">doloop()</tt>
|
||||
|
||||
|
||||
<span>method.</span>
|
||||
</p>
|
||||
<p>
|
||||
We begin by updating our database handle open flags to
|
||||
determine which flags to use, depending on whether the
|
||||
application is running as a master.
|
||||
</p>
|
||||
<pre class="programlisting">#define BUFSIZE 1024
|
||||
int RepMgr::doloop()
|
||||
{
|
||||
Db *dbp;
|
||||
Dbt key, data;
|
||||
char buf[BUFSIZE], *rbuf;
|
||||
int ret;
|
||||
|
||||
dbp = NULL;
|
||||
memset(&key, 0, sizeof(key));
|
||||
memset(&data, 0, sizeof(data));
|
||||
ret = 0;
|
||||
|
||||
for (;;) {
|
||||
if (dbp == NULL) {
|
||||
dbp = new Db(&dbenv, 0);
|
||||
|
||||
// Set page size small so page allocation is cheap.
|
||||
if ((ret = dbp->set_pagesize(512)) != 0)
|
||||
goto err;
|
||||
|
||||
try {
|
||||
dbp->open(NULL, DATABASE, NULL, DB_BTREE,
|
||||
<b class="userinput"><tt>app_data.is_master ? DB_CREATE | DB_AUTO_COMMIT :
|
||||
DB_AUTO_COMMIT</tt></b>, 0); </pre>
|
||||
<p>
|
||||
When we open the database, we modify our error handling to
|
||||
account for the case where the database does not yet exist. This can
|
||||
happen if our code is running as a replica and the replication framework has not
|
||||
yet had a chance to create the databases for us. Recall that replicas never
|
||||
write to their own databases directly, and so they cannot
|
||||
create databases on their own.
|
||||
</p>
|
||||
<p>
|
||||
If we detect that the database does not yet exist, we simply
|
||||
close the database handle, sleep for a short period of time
|
||||
and then continue processing. This gives the replication framework a chance to
|
||||
create the database so that our replica can continue
|
||||
operations.
|
||||
</p>
|
||||
<pre class="programlisting"> } catch(DbException dbe) {
|
||||
<b class="userinput"><tt>/* It is expected that this condition will be triggered
|
||||
* when client sites start up.
|
||||
* It can take a while for the master site to be found
|
||||
* and synced, and no DB will be available until then.
|
||||
*/
|
||||
if (dbe.get_errno() == ENOENT) {
|
||||
cout << "No stock db available yet - retrying." << endl;
|
||||
try {
|
||||
dbp->close(0);
|
||||
} catch (DbException dbe2) {
|
||||
cout << "Unexpected error closing after failed"
|
||||
<< " open, message: " << dbe2.what() << endl;
|
||||
dbp = NULL;
|
||||
goto err;
|
||||
}
|
||||
dbp = NULL;
|
||||
sleep(SLEEPTIME);
|
||||
continue;
|
||||
} else {</tt></b>
|
||||
dbenv.err(ret, "DB->open");
|
||||
throw dbe;
|
||||
<b class="userinput"><tt>}</tt></b>
|
||||
}
|
||||
} </pre>
|
||||
<p>
|
||||
Next we modify our prompt, so that if the local process is running
|
||||
as a replica, we can tell from the shell that the prompt is for a
|
||||
read-only process.
|
||||
</p>
|
||||
<pre class="programlisting"> <b class="userinput"><tt>cout << "QUOTESERVER" ;
|
||||
if (!app_data.is_master)
|
||||
cout << "(read-only)";
|
||||
cout << "> " << flush; </tt></b></pre>
|
||||
<p>
|
||||
When we collect data from the prompt, there is a case that says
|
||||
if no data is entered then show the entire stocks database.
|
||||
This display is performed by our
|
||||
<tt class="function">print_stocks()</tt>
|
||||
|
||||
<span>method</span>
|
||||
(which has not
|
||||
required a modification since we first introduced it in
|
||||
<a href="simpleprogramlisting.html#printstocks_c">
|
||||
|
||||
<span>Method: RepMgr::print_stocks()</span>
|
||||
|
||||
</a>).
|
||||
</p>
|
||||
<p>
|
||||
When we call
|
||||
<span><tt class="function">print_stocks()</tt>, </span>
|
||||
|
||||
we check for a dead replication handle. Dead
|
||||
replication handles happen whenever a replication election
|
||||
results in a previously committed transaction becoming
|
||||
invalid. This is an error scenario caused by a new master having a
|
||||
slightly older version of the data than the original
|
||||
master and so all replicas must modify their database(s) to
|
||||
reflect that of the new master. In this situation, some
|
||||
number of previously committed transactions may have to be
|
||||
unrolled. From the replica's perspective, the database
|
||||
handles should all be closed and then opened again.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL)
|
||||
break;
|
||||
if (strtok(&buf[0], " \t\n") == NULL) {
|
||||
switch ((ret = print_stocks(dbp))) {
|
||||
case 0:
|
||||
continue;
|
||||
<b class="userinput"><tt>case DB_REP_HANDLE_DEAD:
|
||||
(void)dbp->close(DB_NOSYNC);
|
||||
cout << "closing db handle due to rep handle dead" << endl;
|
||||
dbp = NULL;
|
||||
continue;</tt></b>
|
||||
default:
|
||||
dbp->err(ret, "Error traversing data");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
rbuf = strtok(NULL, " \t\n");
|
||||
if (rbuf == NULL || rbuf[0] == '\0') {
|
||||
if (strncmp(buf, "exit", 4) == 0 ||
|
||||
strncmp(buf, "quit", 4) == 0)
|
||||
break;
|
||||
dbenv.errx("Format: TICKER VALUE");
|
||||
continue;
|
||||
} </pre>
|
||||
<p>
|
||||
That done, we need to add a little error checking to our
|
||||
command prompt to make sure the user is not attempting to
|
||||
modify the database at a replica. Remember, replicas must never
|
||||
modify their local databases on their own. This guards against
|
||||
that happening due to user input at the prompt.
|
||||
</p>
|
||||
<pre class="programlisting"> <b class="userinput"><tt>if (!app_data.is_master) {
|
||||
dbenv->errx(dbenv, "Can't update at client");
|
||||
continue;
|
||||
}</tt></b>
|
||||
|
||||
key.set_data(buf);
|
||||
key.set_size((u_int32_t)strlen(buf));
|
||||
|
||||
data.set_data(rbuf);
|
||||
data.set_size((u_int32_t)strlen(rbuf));
|
||||
|
||||
if ((ret = dbp->put(NULL, &key, &data, 0)) != 0)
|
||||
{
|
||||
dbp->err(ret, "DB->put");
|
||||
if (ret != DB_KEYEXIST)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
err: if (dbp != NULL)
|
||||
(void)dbp->close(dbp, DB_NOSYNC);
|
||||
|
||||
return (ret);
|
||||
} </pre>
|
||||
<p>
|
||||
With that completed, we are all done updating our application
|
||||
for replication.
|
||||
|
||||
The only remaining
|
||||
|
||||
<span>method, <tt class="function">print_stocks()</tt>,</span>
|
||||
|
||||
|
||||
is unmodified from when we
|
||||
originally introduced it. For details on that function, see
|
||||
<a href="simpleprogramlisting.html#printstocks_c">
|
||||
|
||||
<span>Method: RepMgr::print_stocks()</span>
|
||||
|
||||
</a>.
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="runningit"></a>Running It</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
To run our replicated application, we need to make
|
||||
sure each participating environment has its own unique
|
||||
home directory. We can do this by running
|
||||
each site on a separate networked machine, but that
|
||||
is not strictly necessary; multiple instances of this
|
||||
code can run on the same machine provided the
|
||||
environment home restriction is observed.
|
||||
</p>
|
||||
<p>
|
||||
To run a process, make sure the environment home
|
||||
exists and then start the process using the
|
||||
<tt class="literal">-h</tt> option to specify that
|
||||
directory. You must also use the <tt class="literal">-m</tt>
|
||||
option to identify the local host and port that this
|
||||
process will use to listen for replication messages, and
|
||||
the <tt class="literal">-o</tt> option to identify the other
|
||||
processes in the replication group. Finally, use the
|
||||
<tt class="literal">-p</tt> option to specify a priority.
|
||||
The process that you designate to have the highest priority will become
|
||||
the master.
|
||||
</p>
|
||||
<pre class="programlisting">> mkdir env1
|
||||
> ./RepMgr -h env1 -n 2 -m localhost:8080 -o localhost:8081 -p 10
|
||||
No stock database yet available.
|
||||
No stock database yet available. </pre>
|
||||
<p>
|
||||
Now, start another process. This time, change the environment
|
||||
home to something else, use the <tt class="literal">-m</tt> to at
|
||||
least change the port number the process is listening on, and
|
||||
use the <tt class="literal">-o</tt> option to identify the host and
|
||||
port of the other replication process:
|
||||
</p>
|
||||
<pre class="programlisting">> mkdir env2
|
||||
> ./RepMgr -h env2 -n 2 -m localhost:8081 -o localhost:8080 -p 20</pre>
|
||||
<p>
|
||||
After a short pause, the second process should display the master
|
||||
prompt:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
QUOTESERVER > </pre>
|
||||
<p>
|
||||
And the first process should
|
||||
display the read-only prompt:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
QUOTESERVER (read-only)> </pre>
|
||||
<p>
|
||||
Now go to the master process and give it a couple of stocks and stock
|
||||
prices:
|
||||
</p>
|
||||
<pre class="programlisting">QUOTESERVER> FAKECO 9.87
|
||||
QUOTESERVER> NOINC .23
|
||||
QUOTESERVER> </pre>
|
||||
<p>
|
||||
Then, go to the replica and hit <b class="userinput"><tt>return</tt></b> at the prompt to
|
||||
see the new values:
|
||||
</p>
|
||||
<pre class="programlisting">QUOTESERVER (read-only)>
|
||||
Symbol Price
|
||||
====== =====
|
||||
FAKECO 9.87
|
||||
NOINC .23
|
||||
QUOTESERVER (read-only)> </pre>
|
||||
<p>
|
||||
Doing the same at the master results in the same thing:
|
||||
</p>
|
||||
<pre class="programlisting">QUOTESERVER>
|
||||
Symbol Price
|
||||
====== =====
|
||||
FAKECO 9.87
|
||||
NOINC .23
|
||||
QUOTESERVER> </pre>
|
||||
<p>
|
||||
You can change a stock by simply entering the stock value and
|
||||
new price at the master's prompt:
|
||||
</p>
|
||||
<pre class="programlisting">QUOTESERVER> FAKECO 10.01
|
||||
QUOTESERVER> </pre>
|
||||
<p>
|
||||
Then, go to either the master or the replica to see the updated
|
||||
database:
|
||||
</p>
|
||||
<pre class="programlisting">QUOTESERVER>
|
||||
Symbol Price
|
||||
====== =====
|
||||
FAKECO 10.01
|
||||
NOINC .23
|
||||
QUOTESERVER> </pre>
|
||||
<p>
|
||||
And on the replica:
|
||||
</p>
|
||||
<pre class="programlisting">QUOTESERVER (read-only)>
|
||||
Symbol Price
|
||||
====== =====
|
||||
FAKECO 10.01
|
||||
NOINC .23
|
||||
QUOTESERVER (read-only)> </pre>
|
||||
<p>
|
||||
Finally, to quit the applications, simply type
|
||||
<tt class="literal">quit</tt> at both prompts:
|
||||
</p>
|
||||
<pre class="programlisting">QUOTESERVER (read-only)> quit
|
||||
> </pre>
|
||||
<p>
|
||||
And on the master as well:
|
||||
</p>
|
||||
<pre class="programlisting">QUOTESERVER> quit
|
||||
> </pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="processingloop.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="fwrkmasterreplica.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="addfeatures.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Processing Loop </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Chapter 5. Additional Features</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
76
docs/gsg_db_rep/CXX/fmwrkconnectretry.html
Normal file
76
docs/gsg_db_rep/CXX/fmwrkconnectretry.html
Normal file
@@ -0,0 +1,76 @@
|
||||
<?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>Managing Connection Retries</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="electiontimes.html" title="Managing Election Times" />
|
||||
<link rel="next" href="heartbeats.html" title="Managing Heartbeats" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Managing Connection Retries</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="electiontimes.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="heartbeats.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="fmwrkconnectretry"></a>Managing Connection Retries</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
In the event that a communication failure occurs between
|
||||
two environments in a replication group, the replication framework will wait a set
|
||||
amount of time before attempting to re-establish the
|
||||
connection. You can configure this wait value using
|
||||
|
||||
<span>
|
||||
|
||||
<span><tt class="methodname">DbEnv::rep_set_timeout()</tt>.</span>
|
||||
To do so, specify the
|
||||
<tt class="literal">DB_REP_CONNECTION_RETRY</tt>
|
||||
flag to the <tt class="literal">which</tt> parameter and then a
|
||||
retry value in microseconds to the
|
||||
<tt class="literal">timeout</tt> parameter.
|
||||
</span>
|
||||
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="electiontimes.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="heartbeats.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Managing Election Times </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Managing Heartbeats</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
297
docs/gsg_db_rep/CXX/fwrkmasterreplica.html
Normal file
297
docs/gsg_db_rep/CXX/fwrkmasterreplica.html
Normal file
@@ -0,0 +1,297 @@
|
||||
<?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>Chapter 4. Replica versus Master Processes</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="index.html" title="Getting Started with Replicated Berkeley DB Applications" />
|
||||
<link rel="previous" href="heartbeats.html" title="Managing Heartbeats" />
|
||||
<link rel="next" href="processingloop.html" title="Processing Loop" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Chapter 4. Replica versus Master Processes</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="heartbeats.html">Prev</a> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="processingloop.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="chapter" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title"><a id="fwrkmasterreplica"></a>Chapter 4. Replica versus Master Processes</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="fwrkmasterreplica.html#determinestate">Determining State</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="processingloop.html">Processing Loop</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="exampledoloop.html">Example Processing Loop</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="exampledoloop.html#runningit">Running It</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
Every environment participating in a replicated application
|
||||
must know whether it is a <span class="emphasis"><em>master</em></span> or
|
||||
<span class="emphasis"><em>replica</em></span>. The reason for this is
|
||||
because, simply, the master can modify the database while
|
||||
replicas cannot. As a result, not only will you open
|
||||
databases differently depended on whether the environment is
|
||||
running as a master, but the environment will frequently
|
||||
behave quit a bit differently depending on whether it
|
||||
thinks it is operating as the read/write interface for
|
||||
your database.
|
||||
</p>
|
||||
<p>
|
||||
Moreover, an environment must also be capable of
|
||||
gracefully switching between master and replica states.
|
||||
This means that the environment must be able to detect when
|
||||
it has switched states.
|
||||
</p>
|
||||
<p>
|
||||
Not surprisingly, a large part of your application's code
|
||||
will be tied up in knowing which state a given
|
||||
environment is in and then in the logic of how to behave depending on
|
||||
its state.
|
||||
</p>
|
||||
<p>
|
||||
This chapter shows you how to determine your environment's
|
||||
state, and it then shows you some sample code on how
|
||||
an application might behave depending on whether it is a
|
||||
master or a replica in a replicated application.
|
||||
</p>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="determinestate"></a>Determining State</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
In order to determine whether your code is
|
||||
running as a master or a replica, you implement a
|
||||
callback whose function it is to respond to
|
||||
events that happen within the DB library.
|
||||
</p>
|
||||
<p>
|
||||
Note that this callback is usable for events beyond
|
||||
those required for replication purposes. In this
|
||||
section, however, we only discuss the
|
||||
replication-specific events.
|
||||
</p>
|
||||
<p>
|
||||
The callback is required to determine
|
||||
which event has been passed to it, and then take
|
||||
action depending on the event. For replication,
|
||||
the events that we care about are:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">DB_EVENT_REP_MASTER</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
The local environment is now a master.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">DB_EVENT_REP_CLIENT</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
The local environment is now a replica.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">DB_EVENT_REP_STARTUPDONE</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
The replica has completed startup
|
||||
synchronization and is now
|
||||
processing log records received
|
||||
from the master.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">DB_EVENT_REP_NEWMASTER</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
An election was held and a new
|
||||
environment was made a master. However,
|
||||
the current environment <span class="emphasis"><em>is
|
||||
not</em></span> the master. This
|
||||
event exists so that you can
|
||||
cause your code to take some
|
||||
unique action in the event that the
|
||||
replication groups switches masters.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
Note that these events are raised whenever the
|
||||
state is established. That is, when the current
|
||||
environment becomes a client, and that includes
|
||||
at application startup, the event is raised.
|
||||
Also, when an election is held and a client is elected to be a
|
||||
master, then the event occurs.
|
||||
</p>
|
||||
<p>
|
||||
The implementation of this callback is fairly
|
||||
simple. First you pass a structure to the
|
||||
environment handle that you can use to record the
|
||||
environment's state, and then you implement a switch
|
||||
statement within the callback that you use to
|
||||
record the current state, depending on the
|
||||
arriving event.
|
||||
</p>
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting">#include <db_cxx.h>
|
||||
/* Forward declaration */
|
||||
void *event_callback(DbEnv *, u_int32_t, void *);
|
||||
|
||||
...
|
||||
|
||||
/* The structure we use to track our environment's state */
|
||||
typedef struct {
|
||||
int is_master;
|
||||
} APP_DATA;
|
||||
|
||||
...
|
||||
|
||||
/*
|
||||
* Inside our main() function, we declare an APP_DATA variable.
|
||||
*/
|
||||
APP_DATA my_app_data;
|
||||
my_app_data.is_master = 0; /* Assume we start as a replica */
|
||||
|
||||
...
|
||||
|
||||
/*
|
||||
* Now we open our environment handle and set the APP_DATA structure
|
||||
* to it's app_private member.
|
||||
*/
|
||||
DbEnv *dbenv = new DbEnv(0);
|
||||
dbenv->set_app_private(&my_app_data);
|
||||
|
||||
/* Having done that, register the callback with the
|
||||
* Berkeley DB library
|
||||
*/
|
||||
dbenv->set_event_notify(event_callback); </pre>
|
||||
<p>
|
||||
That done, we still need to implement the callback itself. This
|
||||
implementation can be fairly trivial.
|
||||
</p>
|
||||
<pre class="programlisting">/*
|
||||
* A callback used to determine whether the local environment is a replica
|
||||
* or a master. This is called by the replication framework
|
||||
* when the local environment changes state.
|
||||
*/
|
||||
void *
|
||||
event_callback(DbEnv *dbenv, u_int32_t which, void *info)
|
||||
{
|
||||
APP_DATA *app = dbenv->get_app_private();
|
||||
|
||||
info = NULL; /* Currently unused. */
|
||||
|
||||
switch (which) {
|
||||
case DB_EVENT_REP_MASTER:
|
||||
app->is_master = 1;
|
||||
break;
|
||||
|
||||
case DB_EVENT_REP_CLIENT:
|
||||
app->is_master = 0;
|
||||
break;
|
||||
|
||||
case DB_EVENT_REP_STARTUPDONE: /* fallthrough */
|
||||
case DB_EVENT_REP_NEWMASTER:
|
||||
/* Ignore. */
|
||||
break;
|
||||
|
||||
default:
|
||||
dbenv->errx(dbenv, "ignoring event %d", which);
|
||||
}
|
||||
} </pre>
|
||||
<p>
|
||||
Notice how we access the
|
||||
<tt class="literal">APP_DATA</tt> information using the environment
|
||||
handle's <tt class="literal">app_private</tt> data member. We also ignore
|
||||
the <tt class="literal">DB_EVENT_REP_NEWMASTER</tt> and
|
||||
<tt class="literal">DB_EVENT_REP_STARTUPDONE</tt> cases since these are not
|
||||
relevant for simple replicated applications.
|
||||
</p>
|
||||
<p>
|
||||
Of course, this only gives us the current state of the environment. We
|
||||
still need the code that determines what to do when the environment
|
||||
changes state and how to behave depending on the state (described
|
||||
in the next section).
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="heartbeats.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="index.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="processingloop.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Managing Heartbeats </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Processing Loop</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
372
docs/gsg_db_rep/CXX/fwrkpermmessage.html
Normal file
372
docs/gsg_db_rep/CXX/fwrkpermmessage.html
Normal file
@@ -0,0 +1,372 @@
|
||||
<?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>Permanent Message Handling</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="repmgr_init_example_c.html" title="Adding the Replication Framework to SimpleTxn " />
|
||||
<link rel="next" href="electiontimes.html" title="Managing Election Times" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Permanent Message Handling</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="repmgr_init_example_c.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="electiontimes.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="fwrkpermmessage"></a>Permanent Message Handling</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
As described in <a href="permmessages.html">Permanent Message Handling</a>,
|
||||
messages are marked permanent if they contain database
|
||||
modifications that should be committed at the replica.
|
||||
DB's replication code decides if it must flush its
|
||||
transaction logs to disk depending on whether it receives
|
||||
sufficient permanent message acknowledgments from the
|
||||
participating replica. More importantly, the thread
|
||||
performing the transaction commit blocks
|
||||
until it either receives enough acknowledgments, or the
|
||||
acknowledgment timeout expires.
|
||||
</p>
|
||||
<p>
|
||||
The replication framework is fully capable of managing permanent messages
|
||||
for you if your application requires it (most do).
|
||||
Almost all of the details of this are handled by the
|
||||
replication framework for you. However, you do have to set some policies
|
||||
that tell the replication framework how to handle permanent messages.
|
||||
</p>
|
||||
<p>
|
||||
There are two things that you have to do:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Determine how many acknowledgments
|
||||
must be received by the master.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Identify the amount of time that
|
||||
replicas have to send their
|
||||
acknowledgments.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="fmwrkpermpolicy"></a>Identifying Permanent Message Policies</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
|
||||
You identify permanent message policies using the
|
||||
|
||||
|
||||
|
||||
|
||||
Note that you can set permanent message
|
||||
policies at any time during the life of the
|
||||
application.
|
||||
</p>
|
||||
<p>
|
||||
The following permanent message policies are available when you use
|
||||
the replication framework:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">DB_REPMGR_ACKS_NONE</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
No permanent message acknowledgments are required. If
|
||||
this policy is selected, permanent message handling is
|
||||
essentially "turned off." That is, the master will
|
||||
never wait for replica acknowledgments. In this case,
|
||||
transaction log data is either flushed or not strictly
|
||||
depending on the type of commit that is being performed
|
||||
(synchronous or asynchronous).
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">DB_REPMGR_ACKS_ONE</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
At least one replica must acknowledge the permanent
|
||||
message within the timeout period.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">DB_REPMGR_ACKS_ONE_PEER</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
At least one electable peer must acknowledge the permanent
|
||||
message within the timeout period.
|
||||
|
||||
Note that an
|
||||
<span class="emphasis"><em>electable peer</em></span> is simply another
|
||||
environment that can be elected to be a master (that
|
||||
is, it has a priority greater than 0). Do not confuse
|
||||
this with the concept of a peer as used for client to
|
||||
client transfers. See
|
||||
<a href="c2ctransfer.html">Client to Client Transfer</a>
|
||||
for more information on client to client transfers.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">DB_REPMGR_ACKS_ALL</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
All environments must acknowledge the message within
|
||||
the timeout period. This
|
||||
policy should be selected only if your replication
|
||||
group has a small number of replicas, and those replicas
|
||||
are on extremely reliable networks and servers.
|
||||
</p>
|
||||
<p>
|
||||
When this flag is used, the actual number of
|
||||
environments that must respond is
|
||||
determined by the value set for
|
||||
|
||||
<span><tt class="methodname">DbEnv::rep_set_nsites()</tt>.</span>
|
||||
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">DB_REPMGR_ACKS_ALL_PEERS</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
All electable peers must acknowledge the message within the
|
||||
timeout period. This
|
||||
policy should be selected only if your replication
|
||||
group is small, and its various environments
|
||||
are on extremely reliable networks and servers.
|
||||
</p>
|
||||
<p>
|
||||
Note that an
|
||||
<span class="emphasis"><em>electable peer</em></span> is simply another
|
||||
environment that can be elected to be a master (that
|
||||
is, it has a priority greater than 0). Do not confuse
|
||||
this with the concept of a peer as used for client to
|
||||
client transfers. See
|
||||
<a href="c2ctransfer.html">Client to Client Transfer</a>
|
||||
for more information on client to client transfers.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">DB_REPMGR_ACKS_QUORUM</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
A quorum of electable peers must acknowledge the message within the timeout period.
|
||||
A quorum is reached when acknowledgments are received from the minimum number
|
||||
of environments needed to ensure that the record remains durable
|
||||
if an election is held. That is, the master wants to hear from enough
|
||||
electable replicas that they have committed the record so that if an election
|
||||
is held, the master knows the record will exist even if a new master is selected.
|
||||
</p>
|
||||
<p>
|
||||
Note that an
|
||||
<span class="emphasis"><em>electable peer</em></span> is simply another
|
||||
environment that can be elected to be a master (that
|
||||
is, it has a priority greater than 0). Do not confuse
|
||||
this with the concept of a peer as used for client to
|
||||
client transfers. See
|
||||
<a href="c2ctransfer.html">Client to Client Transfer</a>
|
||||
for more information on client to client transfers.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
By default, a quorum of sites must must acknowledge a permanent
|
||||
message in order for it considered to have been successfully
|
||||
transmitted. The actual number of environments that must respond is
|
||||
calculated using the value set with
|
||||
|
||||
<span><tt class="methodname">DbEnv::rep_set_nsites()</tt>.</span>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="fmwrkpermtimeout"></a>Setting the Permanent Message Timeout</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The permanent message timeout represents the
|
||||
maximum amount of time the committing thread
|
||||
will block waiting for message
|
||||
acknowledgments. If sufficient
|
||||
acknowledgments arrive before this timeout has
|
||||
expired, the thread continues operations as
|
||||
normal. However, if this timeout expires, the
|
||||
committing thread flushes its transaction log
|
||||
buffer before continuing with normal
|
||||
operations.
|
||||
</p>
|
||||
<p>
|
||||
You set the timeout value using the
|
||||
|
||||
<tt class="methodname">DbEnv::rep_set_timeout()</tt>
|
||||
method. When you do this, you provide the
|
||||
<tt class="literal">DB_REP_ACK_TIMEOUT</tt> flag to
|
||||
the <tt class="literal">which</tt> parameter, and the
|
||||
timeout value in microseconds to the
|
||||
<tt class="literal">timeout</tt> parameter.
|
||||
</p>
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting"> dbenv->rep_set_timeout(DB_REP_ACK_TIMEOUT, 100); </pre>
|
||||
<p>
|
||||
This timeout value can be set at anytime during the
|
||||
life of the application.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="perm2fmwrkexample"></a>Adding a Permanent Message Policy to
|
||||
|
||||
<span>RepMgr</span>
|
||||
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
For illustration purposes, we will now update
|
||||
|
||||
<tt class="literal">RepMgr</tt>
|
||||
|
||||
such that it requires only one acknowledgment from
|
||||
a replica on transactional commits. Also, we will give
|
||||
this acknowledgment a 500 microsecond timeout
|
||||
value. This means that our application's main
|
||||
thread will block for up to 500 microseconds waiting
|
||||
for an acknowledgment. If it does not receive at
|
||||
least one acknowledgment in that amount of time,
|
||||
DB will flush the transaction logs to disk
|
||||
before continuing on.
|
||||
</p>
|
||||
<p>
|
||||
This is a very simple update. We can perform the
|
||||
entire thing in
|
||||
<tt class="methodname">RepMgr::init()</tt>
|
||||
|
||||
immediately after we set the application's priority
|
||||
and before we open our environment handle.
|
||||
</p>
|
||||
<pre class="programlisting">int RepMgr::init(RepConfigInfo *config)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
app_config = config;
|
||||
|
||||
dbenv.set_errfile(stderr);
|
||||
dbenv.set_errpfx(progname);
|
||||
|
||||
if ((ret = dbenv.repmgr_set_local_site(app_config->this_host.host,
|
||||
app_config->this_host.port, 0)) != 0) {
|
||||
cerr << "Could not set listen address to host:port "
|
||||
<< app_config->this_host.host << ":"
|
||||
<< app_config->this_host.port
|
||||
<< "error: " << ret << endl;
|
||||
}
|
||||
|
||||
for ( REP_HOST_INFO *cur = app_config->other_hosts; cur != NULL;
|
||||
cur = cur->next) {
|
||||
if ((ret = dbenv.repmgr_add_remote_site(cur->host, cur->port,
|
||||
NULL, 0)) != 0) {
|
||||
cerr << "could not add site." << endl
|
||||
}
|
||||
}
|
||||
|
||||
if (app_config->totalsites > 0) {
|
||||
try {
|
||||
if ((ret = dbenv.rep_set_nsites(app_config->totalsites)) != 0)
|
||||
dbenv.err(ret, "set_nsites");
|
||||
} catch (DbException dbe) {
|
||||
cerr << "rep_set_nsites call failed. Continuing." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
dbenv.rep_set_priority(app_config->priority);
|
||||
|
||||
<b class="userinput"><tt>/* Permanent messages require at least one ack */
|
||||
dbenv.repmgr_set_ack_policy(DB_REPMGR_ACKS_ONE);
|
||||
/* Give 500 microseconds to receive the ack */
|
||||
dbenv.rep_set_timeout(DB_REP_ACK_TIMEOUT, 500);</tt></b>
|
||||
|
||||
dbenv.set_cachesize(0, CACHESIZE, 0);
|
||||
dbenv.set_flags(DB_TXN_NOSYNC, 1);
|
||||
|
||||
... </pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="repmgr_init_example_c.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="electiontimes.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Adding the Replication Framework to
|
||||
|
||||
SimpleTxn
|
||||
</td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Managing Election Times</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
41
docs/gsg_db_rep/CXX/gettingStarted.css
Normal file
41
docs/gsg_db_rep/CXX/gettingStarted.css
Normal file
@@ -0,0 +1,41 @@
|
||||
body { width: 45em;
|
||||
margin-left: 3em;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
h2.title { margin-left: -1em;
|
||||
font-family: Verdana, serif;
|
||||
font-size: 16pt;
|
||||
}
|
||||
|
||||
h3.title { font-family: Verdana, serif;
|
||||
font-size: 14pt;
|
||||
}
|
||||
|
||||
pre.programlisting {
|
||||
font-family: monospace;
|
||||
background-color: #eae8e9;
|
||||
}
|
||||
|
||||
div.navheader { font-size: 9pt;
|
||||
width: 60em;
|
||||
margin-left: -2em;
|
||||
}
|
||||
|
||||
div.navheader table tr td { font-size: 9pt; }
|
||||
|
||||
div.navfooter { font-size: 9pt;
|
||||
width: 60em;
|
||||
margin-left: -2em;
|
||||
}
|
||||
div.navfooter table tr td { font-size: 9pt; }
|
||||
|
||||
span.emphasis { font-style: italic; font-size: 9pt;}
|
||||
|
||||
div.appendix div.informaltable { font-size: 9pt; }
|
||||
div.appendix div.informaltable td { vertical-align: top; }
|
||||
div.appendix div.informaltable p { margin-top: .25em; }
|
||||
div.appendix div.informaltable p { margin-bottom: .25em; }
|
||||
|
||||
|
||||
103
docs/gsg_db_rep/CXX/heartbeats.html
Normal file
103
docs/gsg_db_rep/CXX/heartbeats.html
Normal file
@@ -0,0 +1,103 @@
|
||||
<?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>Managing Heartbeats</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="fmwrkconnectretry.html" title="Managing Connection Retries" />
|
||||
<link rel="next" href="fwrkmasterreplica.html" title="Chapter 4. Replica versus Master Processes" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Managing Heartbeats</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="fmwrkconnectretry.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="fwrkmasterreplica.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="heartbeats"></a>Managing Heartbeats</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
If your replicated application experiences few updates,
|
||||
it is possible for the replication group to lose a
|
||||
master without noticing it. This is because normally a
|
||||
replicated application only knows that a master has
|
||||
gone missing when update activity causes messages to be
|
||||
passed between the master and clients.
|
||||
</p>
|
||||
<p>
|
||||
To guard against this, you can configure a heartbeat.
|
||||
The heartbeat must be configured for both the master
|
||||
and each of the clients.
|
||||
</p>
|
||||
<p>
|
||||
On the master, you configure the application to send a
|
||||
heartbeat on a defined interval when it is otherwise
|
||||
idle. Do this by using the
|
||||
<span>
|
||||
<tt class="literal">DB_REP_HEARTBEAT_SEND</tt> flag
|
||||
with the
|
||||
|
||||
<tt class="methodname">DbEnv::rep_set_timeout()</tt>
|
||||
method.
|
||||
</span>
|
||||
|
||||
You must also provide the method a value representing the frequency of
|
||||
the heartbeat. Note that the heartbeat is sent only if the
|
||||
system is idle.
|
||||
</p>
|
||||
<p>
|
||||
On the client, you configure the application to listen
|
||||
for a heartbeat. The time that you configure here is
|
||||
the amount of time the client will wait for some
|
||||
message from the master (either the heartbeat or some
|
||||
other message) before concluding that the connection is
|
||||
lost. You do this using the
|
||||
<span>
|
||||
<tt class="literal">DB_REP_HEARTBEAT_MONITOR</tt> flag
|
||||
with the
|
||||
|
||||
<tt class="methodname">DbEnv::rep_set_timeout()</tt>
|
||||
method and a timeout value in microseconds.
|
||||
</span>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="fmwrkconnectretry.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="fwrkmasterreplica.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Managing Connection Retries </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Chapter 4. Replica versus Master Processes</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
465
docs/gsg_db_rep/CXX/index.html
Normal file
465
docs/gsg_db_rep/CXX/index.html
Normal file
@@ -0,0 +1,465 @@
|
||||
<?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>Getting Started with Replicated Berkeley DB Applications</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="next" href="preface.html" title="Preface" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Getting Started with Replicated Berkeley DB Applications</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="preface.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="book" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h1 class="title"><a id="id613728"></a>Getting Started with Replicated Berkeley DB Applications</h1>
|
||||
</div>
|
||||
<div>
|
||||
<div class="legalnotice">
|
||||
<p class="legalnotice-title">
|
||||
<b>Legal Notice</b>
|
||||
</p>
|
||||
<p>
|
||||
This documentation is distributed under an open source license.
|
||||
You may review the terms of this license at:
|
||||
<a href="http://www.oracle.com/technology/software/products/berkeley-db/htdocs/oslicense.html" target="_top">http://www.oracle.com/technology/software/products/berkeley-db/htdocs/oslicense.html</a>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Oracle, Berkeley DB,
|
||||
|
||||
|
||||
and
|
||||
Sleepycat are trademarks or registered trademarks of
|
||||
Oracle. All rights to these marks are reserved.
|
||||
No third-party use is permitted without the
|
||||
express prior written consent of Oracle.
|
||||
</p>
|
||||
<p>
|
||||
To obtain a copy of this document's original source code, please
|
||||
submit a request to the Oracle Technology Network forum at:
|
||||
<a href="http://forums.oracle.com/forums/forum.jspa?forumID=271" target="_top">http://forums.oracle.com/forums/forum.jspa?forumID=271</a>
|
||||
|
||||
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="pubdate">4/25/2008</p>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="preface">
|
||||
<a href="preface.html">Preface</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="preface.html#conventions">Conventions Used in this Book</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="preface.html#moreinfo">For More Information</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="chapter">
|
||||
<a href="introduction.html">1. Introduction</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="introduction.html#overview">Overview</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="introduction.html#repenvirons">Replication Environments</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="introduction.html#repdbs">Replication Databases</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="introduction.html#commlayer">Communications Layer</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="introduction.html#masterselect">Selecting a Master</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="repadvantage.html">Replication Benefits</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="apioverview.html">The Replication APIs</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="apioverview.html#repframeworkoverview">Replication Framework Overview</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="apioverview.html#repapioverview">Replication API Overview</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="elections.html">Holding Elections</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="elections.html#influencingelections">Influencing Elections</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="elections.html#winningelections">Winning Elections</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="elections.html#switchingmasters">Switching Masters</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="permmessages.html">Permanent Message Handling</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="permmessages.html#permmessagenot">When Not to Manage
|
||||
Permanent Messages</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="permmessages.html#permmanage">Managing Permanent Messages</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="permmessages.html#permimplement">Implementing Permanent
|
||||
Message Handling</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="chapter">
|
||||
<a href="txnapp.html">2. Transactional Application</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txnapp.html#appoverview">Application Overview</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="simpleprogramlisting.html">Program Listing</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="simpleprogramlisting.html#repconfiginfo_cxx">
|
||||
Class: RepConfigInfo
|
||||
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="simpleprogramlisting.html#repmgr_cxx">Class: RepMgr</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="simpleprogramlisting.html#usage_cxx">Function: usage()</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="simpleprogramlisting.html#main_cxx">Function: main()</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="simpleprogramlisting.html#repmgr_init_cxx">Method: RepMgr::init()</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="simpleprogramlisting.html#doloop_cxx">Method: RepMgr::doloop()</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="simpleprogramlisting.html#printstocks_c">
|
||||
|
||||
Method: RepMgr::print_stocks()
|
||||
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="chapter">
|
||||
<a href="repapp.html">3. The DB Replication Framework</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="repapp.html#rep_init_code">
|
||||
Starting and Stopping Replication
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="repapp.html#election_flags">Managing Election Policies</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="repapp.html#thread_count">Selecting the Number of Threads</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="repmgr_init_example_c.html">Adding the Replication Framework to
|
||||
|
||||
SimpleTxn
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="fwrkpermmessage.html">Permanent Message Handling</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="fwrkpermmessage.html#fmwrkpermpolicy">Identifying Permanent Message Policies</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="fwrkpermmessage.html#fmwrkpermtimeout">Setting the Permanent Message Timeout</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="fwrkpermmessage.html#perm2fmwrkexample">Adding a Permanent Message Policy to
|
||||
|
||||
RepMgr
|
||||
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="electiontimes.html">Managing Election Times</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="electiontimes.html#electiontimeout">Managing Election Timeouts</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="electiontimes.html#electretrytime">Managing Election Retry Times</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="fmwrkconnectretry.html">Managing Connection Retries</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="heartbeats.html">Managing Heartbeats</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="chapter">
|
||||
<a href="fwrkmasterreplica.html">4. Replica versus Master Processes</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="fwrkmasterreplica.html#determinestate">Determining State</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="processingloop.html">Processing Loop</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="exampledoloop.html">Example Processing Loop</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="exampledoloop.html#runningit">Running It</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="chapter">
|
||||
<a href="addfeatures.html">5. Additional Features</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="addfeatures.html#delayedsync">Delayed Synchronization</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="manageblock.html">Managing Blocking Operations</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="noautoinit.html">Stop Auto-Initialization</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="c2ctransfer.html">Client to Client Transfer</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="c2ctransfer.html#fmwrkpeerserver">Identifying Peers</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="bulk.html">Bulk Transfers</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"> </td>
|
||||
<td width="20%" align="center"> </td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="preface.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top"> </td>
|
||||
<td width="20%" align="center"> </td>
|
||||
<td width="40%" align="right" valign="top"> Preface</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
395
docs/gsg_db_rep/CXX/introduction.html
Normal file
395
docs/gsg_db_rep/CXX/introduction.html
Normal file
@@ -0,0 +1,395 @@
|
||||
<?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>Chapter 1. Introduction</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="index.html" title="Getting Started with Replicated Berkeley DB Applications" />
|
||||
<link rel="previous" href="preface.html" title="Preface" />
|
||||
<link rel="next" href="repadvantage.html" title="Replication Benefits" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Chapter 1. Introduction</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="preface.html">Prev</a> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="repadvantage.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="chapter" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title"><a id="introduction"></a>Chapter 1. Introduction</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="introduction.html#overview">Overview</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="introduction.html#repenvirons">Replication Environments</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="introduction.html#repdbs">Replication Databases</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="introduction.html#commlayer">Communications Layer</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="introduction.html#masterselect">Selecting a Master</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="repadvantage.html">Replication Benefits</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="apioverview.html">The Replication APIs</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="apioverview.html#repframeworkoverview">Replication Framework Overview</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="apioverview.html#repapioverview">Replication API Overview</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="elections.html">Holding Elections</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="elections.html#influencingelections">Influencing Elections</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="elections.html#winningelections">Winning Elections</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="elections.html#switchingmasters">Switching Masters</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="permmessages.html">Permanent Message Handling</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="permmessages.html#permmessagenot">When Not to Manage
|
||||
Permanent Messages</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="permmessages.html#permmanage">Managing Permanent Messages</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="permmessages.html#permimplement">Implementing Permanent
|
||||
Message Handling</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
This book provides a thorough introduction and discussion on
|
||||
replication as used with Berkeley DB (DB). It begins by offering a
|
||||
general overview to replication and the benefits it provides. It also
|
||||
describes the APIs that you use to implement replication, and it
|
||||
describes architecturally the things that you need to do to your
|
||||
application code in order to use the replication APIs. Finally, it
|
||||
discusses the differences in backup and restore strategies that you
|
||||
might pursue when using replication, especially where it comes to log
|
||||
file removal.
|
||||
</p>
|
||||
<p>
|
||||
You should understand the concepts from the
|
||||
<span>
|
||||
<i class="citetitle">Berkeley DB Getting Started with Transaction Processing</i>
|
||||
</span>
|
||||
|
||||
|
||||
guide before reading this book.
|
||||
</p>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="overview"></a>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The DB replication APIs allow you to distribute your database
|
||||
write operations (performed on a read-write master) to one or
|
||||
more read-only <span class="emphasis"><em>replicas</em></span>.
|
||||
For this reason, DB's replication implementation is said to be a
|
||||
<span class="emphasis"><em>single master, multiple replica</em></span> replication strategy.
|
||||
</p>
|
||||
<p>
|
||||
Note that your database write operations can occur only on the
|
||||
master; any attempt to write to a replica results in an error
|
||||
being
|
||||
|
||||
<span>raised by</span>
|
||||
the DB API used to perform the write.
|
||||
</p>
|
||||
<p>
|
||||
A single replication master and all of its replicas are referred
|
||||
to as a <span class="emphasis"><em>replication group</em></span>. While all
|
||||
members of the replication group can reside on the same
|
||||
machine, usually each replication participant is placed on a
|
||||
separate physical machine somewhere on the network.
|
||||
</p>
|
||||
<p>
|
||||
Note that all replication applications must first be
|
||||
transactional applications. The data that the master transmits
|
||||
its replicas are log records that are generated as records are
|
||||
updated. Upon transactional commit, the master transmits a
|
||||
transaction record which tells the replicas to commit the
|
||||
records they previously received from the master. In order for
|
||||
all of this to work, your replicated application must also be a
|
||||
transactional application. For this reason, it is
|
||||
recommended that you write and debug your DB application as
|
||||
a stand-alone transactional application before introducing the
|
||||
replication layer to your code.
|
||||
</p>
|
||||
<p>
|
||||
Finally, be aware that all machines participating in the
|
||||
replication group must share identical
|
||||
<span class="emphasis"><em>endianess</em></span>. Endianess is the byte-order
|
||||
strategy used by the computing platform to store multibyte
|
||||
numbers. Berkeley DB is sensitive to byte order and so your
|
||||
replication infrastructure must be consistent in this area.
|
||||
We expect to remove this requirement in some future
|
||||
release of the product.
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="repenvirons"></a>Replication Environments</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The most important requirement for a replication
|
||||
participant is that it must use a unique Berkeley DB database
|
||||
environment independent of all other replication
|
||||
participants. So while multiple replication participants
|
||||
can reside on the same physical machine, no two such participants
|
||||
can share the same environment home directory.
|
||||
</p>
|
||||
<p>
|
||||
For this reason, technically replication occurs between
|
||||
unique <span class="emphasis"><em>database environments</em></span>. So in the strictest sense,
|
||||
a replication group consists of a <span class="emphasis"><em>master
|
||||
environment</em></span> and
|
||||
one or more <span class="emphasis"><em>replica environments</em></span>. However, the reality
|
||||
is that for production code, each such environment will
|
||||
usually be located on its own unique machine. Consequently,
|
||||
this manual sometimes talks about <span class="emphasis"><em>replication sites</em></span>, meaning the
|
||||
unique combination of environment home directory, host and port that a specific
|
||||
replication application is using.
|
||||
</p>
|
||||
<p>
|
||||
There is no DB-specified limit to the number of
|
||||
environments which can participate in a replication group.
|
||||
The only limitation here is one of resources —
|
||||
network bandwidth, for example.
|
||||
</p>
|
||||
<p>
|
||||
(Note, however, that the replication framework does place a limit on the
|
||||
number of environments you can use. See
|
||||
<a href="apioverview.html#repframeworkoverview">Replication Framework Overview</a>
|
||||
for details.)
|
||||
</p>
|
||||
<p>
|
||||
Also, DB's replication implementation requires all
|
||||
participating environments to be assigned IDs that are
|
||||
locally unique to the given environment. Depending on the
|
||||
replication APIs that you choose to use, you may or may not
|
||||
need to manage this particular detail.
|
||||
</p>
|
||||
<p>
|
||||
For detailed information on database environments, see
|
||||
the <i class="citetitle">Berkeley DB Getting Started with Transaction Processing</i>
|
||||
guide. For more information on environment IDs, see
|
||||
the <i class="citetitle">Berkeley DB Programmer's Reference Guide</i>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="repdbs"></a>Replication Databases</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
DB's databases are managed and used in exactly the same way
|
||||
as if you were writing a non-replicated application, with
|
||||
a couple of caveats. First, the databases maintained in a replicated environment
|
||||
must reside either in the <tt class="literal">ENV_HOME</tt>
|
||||
directory, or in the directory identified by the
|
||||
|
||||
<tt class="methodname">DbEnv::set_data_dir()</tt>
|
||||
|
||||
method. Unlike non-replication applications, you cannot place your
|
||||
databases in a subdirectory below these locations. You should
|
||||
also not use full path names for your databases or
|
||||
environments as these are likely to break as to replicated
|
||||
to other machines.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="commlayer"></a>Communications Layer</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
In order to transmit database writes to the replication
|
||||
replicas, DB requires a communications layer.
|
||||
DB is agnostic as to what this layer should
|
||||
look like. The only requirement is that it
|
||||
be capable of passing two opaque data objects and an
|
||||
environment ID from the master to its replicas without
|
||||
corruption.
|
||||
</p>
|
||||
<p>
|
||||
Because replicas are usually placed on different machines on
|
||||
the network, the communications layer is usually some kind
|
||||
of a network-aware implementation. Beyond that, its
|
||||
implementation details are largely up to you. It could use
|
||||
TCP/IP sockets, for example, or it could use
|
||||
raw sockets if they perform better for your particular
|
||||
application.
|
||||
</p>
|
||||
<p>
|
||||
Note that you may not have to write your own communications
|
||||
layer. DB provides a replication framework that
|
||||
includes a fully-functional TCP/IP-based communications layer.
|
||||
See <a href="apioverview.html">The Replication APIs</a>
|
||||
for more information.
|
||||
</p>
|
||||
<p>
|
||||
See the <i class="citetitle">Berkeley DB Programmer's Reference Guide</i>
|
||||
for a description of how to
|
||||
write your own custom replication communications layer.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="masterselect"></a>Selecting a Master</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Every replication group is allowed one and only one
|
||||
master environment. Almost always, masters are selected by
|
||||
holding an <span class="emphasis"><em>election</em></span>. All such
|
||||
elections are performed by the underlying Berkeley DB
|
||||
replication code so you have to do very little to
|
||||
implement them.
|
||||
</p>
|
||||
<p>
|
||||
When holding an election, replicas "vote" on who should
|
||||
be the master. Among replicas participating in the
|
||||
election, the one with the most up-to-date set of log
|
||||
records will win the election. Note that it's possible
|
||||
for there to be a tie. When this occurs, priorities are
|
||||
used to select the master. See
|
||||
<a href="elections.html">Holding Elections</a>
|
||||
for details.
|
||||
</p>
|
||||
<p>
|
||||
For more information on holding and managing elections,
|
||||
see <a href="elections.html">Holding Elections</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="preface.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="index.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="repadvantage.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Preface </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Replication Benefits</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
88
docs/gsg_db_rep/CXX/manageblock.html
Normal file
88
docs/gsg_db_rep/CXX/manageblock.html
Normal file
@@ -0,0 +1,88 @@
|
||||
<?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>Managing Blocking Operations</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="addfeatures.html" title="Chapter 5. Additional Features" />
|
||||
<link rel="previous" href="addfeatures.html" title="Chapter 5. Additional Features" />
|
||||
<link rel="next" href="noautoinit.html" title="Stop Auto-Initialization" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Managing Blocking Operations</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="addfeatures.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 5. Additional Features</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="noautoinit.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="manageblock"></a>Managing Blocking Operations</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
When a replica is in the process of synchronizing with its master, all DB
|
||||
operations are blocked until such a time as the synchronization is completed.
|
||||
For replicas with a heavy read load, these blocked operations may represent an
|
||||
unacceptable loss in throughput.
|
||||
</p>
|
||||
<p>
|
||||
You can configure DB so that it will not block when synchronization is in
|
||||
process. Instead, the DB operation will fail,
|
||||
|
||||
<span>
|
||||
immediately returning a <tt class="literal">DB_REP_LOCKOUT</tt> error.
|
||||
</span>
|
||||
|
||||
|
||||
When this happens, it is up to your application to your application to determine
|
||||
what action to take (that is, logging the event, making an appropriate user
|
||||
response, retrying the operation, and so forth).
|
||||
</p>
|
||||
<p>
|
||||
To turn off blocking on synchronization, specify
|
||||
<span>
|
||||
<tt class="literal">DB_REP_CONF_NOWAIT</tt> to
|
||||
|
||||
<tt class="methodname">DbEnv::rep_set_config()</tt>
|
||||
and then specify <tt class="literal">1</tt> to the <tt class="literal">onoff</tt>
|
||||
parameter. (Specify <tt class="literal">0</tt> to turn the feature off.)
|
||||
</span>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="addfeatures.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="addfeatures.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="noautoinit.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Chapter 5. Additional Features </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Stop Auto-Initialization</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
88
docs/gsg_db_rep/CXX/noautoinit.html
Normal file
88
docs/gsg_db_rep/CXX/noautoinit.html
Normal file
@@ -0,0 +1,88 @@
|
||||
<?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>Stop Auto-Initialization</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="addfeatures.html" title="Chapter 5. Additional Features" />
|
||||
<link rel="previous" href="manageblock.html" title="Managing Blocking Operations" />
|
||||
<link rel="next" href="c2ctransfer.html" title="Client to Client Transfer" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Stop Auto-Initialization</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="manageblock.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 5. Additional Features</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="c2ctransfer.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="noautoinit"></a>Stop Auto-Initialization</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
As stated in the previous section, when a replication replica is synchronizing
|
||||
with its master, it will block all DB operations until the synchronization
|
||||
is completed. You can turn off this behavior (see <a href="manageblock.html">Managing Blocking Operations</a>), but for replicas that have been out of touch
|
||||
from their master for a very long time, this may not be enough.
|
||||
</p>
|
||||
<p>
|
||||
If a replica has been out of touch from its master long enough, it may find that
|
||||
it is not possible to perform synchronization. When this happens, by default the
|
||||
master and replica internally decided to completely re-initialize the replica.
|
||||
This re-initialization involves discarding the replica's current database(s) and
|
||||
transferring new ones to it from the master. Depending on the size of the master's
|
||||
databases, this can take a long time, during which time the replica will be
|
||||
complete non-responsive when it comes to performing database operations.
|
||||
</p>
|
||||
<p>
|
||||
It is possible that there is a time of the day when it is better to perform a replica
|
||||
re-initialization. Or, you simply might want to decide to bring the replica up to
|
||||
speed by restoring it's databases using a hot-backup taken from the master. Either
|
||||
way, you can decide to prevent automatic-initialization of your replica. To do this
|
||||
specify
|
||||
<span>
|
||||
<tt class="literal">DB_REP_CONF_NOAUTOINIT</tt> to
|
||||
|
||||
<tt class="methodname">DbEnv::rep_set_config()</tt>
|
||||
and then specify <tt class="literal">1</tt> to the <tt class="literal">onoff</tt>
|
||||
parameter. (Specify <tt class="literal">0</tt> to turn the feature off.)
|
||||
</span>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="manageblock.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="addfeatures.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="c2ctransfer.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Managing Blocking Operations </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Client to Client Transfer</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
390
docs/gsg_db_rep/CXX/permmessages.html
Normal file
390
docs/gsg_db_rep/CXX/permmessages.html
Normal file
@@ -0,0 +1,390 @@
|
||||
<?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>Permanent Message Handling</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="introduction.html" title="Chapter 1. Introduction" />
|
||||
<link rel="previous" href="elections.html" title="Holding Elections" />
|
||||
<link rel="next" href="txnapp.html" title="Chapter 2. Transactional Application" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Permanent Message Handling</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="elections.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 1. Introduction</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="txnapp.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="permmessages"></a>Permanent Message Handling</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Messages received by a replica may be marked with an
|
||||
special flag that indicates the message is permanent.
|
||||
Custom replicated applications will receive notification of
|
||||
this flag via the <tt class="literal">DB_REP_ISPERM</tt> return value
|
||||
from the
|
||||
|
||||
<tt class="methodname">DbEnv::rep_process_message()</tt>
|
||||
method.
|
||||
|
||||
There is no hard requirement that a replication application look for, or
|
||||
respond to, this return code. However, because robust replicated
|
||||
applications typically do manage permanent messages, we introduce
|
||||
the concept here.
|
||||
</p>
|
||||
<p>
|
||||
A message is marked as being permanent if the message
|
||||
affects transactional integrity. For example,
|
||||
transaction commit messages are an example of a message
|
||||
that is marked permanent. What the application does
|
||||
about the permanent message is driven by the durability
|
||||
guarantees required by the application.
|
||||
</p>
|
||||
<p>
|
||||
For example, consider what the replication framework does when it
|
||||
has permanent message handling turned on and a
|
||||
transactional commit record is sent to the replicas.
|
||||
First, the replicas must transactional-commit the data
|
||||
modifications identified by the message. And then, upon
|
||||
a successful commit, the replication framework sends the master a
|
||||
message acknowledgment.
|
||||
</p>
|
||||
<p>
|
||||
For the master (again, using the replication framework), things are a little more complicated than
|
||||
simple message acknowledgment. Usually in a replicated
|
||||
application, the master commits transactions
|
||||
asynchronously; that is, the commit operation does not
|
||||
block waiting for log data to be flushed to disk before
|
||||
returning. So when a master is managing permanent
|
||||
messages, it typically blocks the committing thread
|
||||
immediately before <tt class="methodname">commit()</tt>
|
||||
returns. The thread then waits for acknowledgments from
|
||||
its replicas. If it receives enough acknowledgments, it
|
||||
continues to operate as normal.
|
||||
</p>
|
||||
<p>
|
||||
If the master does not
|
||||
receive message acknowledgments — or, more likely, it does not receive
|
||||
<span class="emphasis"><em>enough</em></span> acknowledgments — the
|
||||
committing thread flushes its log data to disk and then
|
||||
continues operations as normal. The master application can
|
||||
do this because replicas that fail to handle a message, for
|
||||
whatever reason, will eventually catch up to the master. So
|
||||
by flushing the transaction logs to disk, the master is
|
||||
ensuring that the data modifications have made it to
|
||||
stable storage in one location (its own hard drive).
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="permmessagenot"></a>When Not to Manage
|
||||
Permanent Messages</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
There are two reasons why you might
|
||||
choose to not implement permanent messages.
|
||||
In part, these go to why you are using
|
||||
replication in the first place.
|
||||
</p>
|
||||
<p>
|
||||
One class of applications uses replication so that
|
||||
the application can improve transaction
|
||||
through-put. Essentially, the application chooses a
|
||||
reduced transactional durability guarantee so as to
|
||||
avoid the overhead forced by the disk I/O required
|
||||
to flush transaction logs to disk. However, the
|
||||
application can then regain that durability
|
||||
guarantee to a certain degree by replicating the
|
||||
commit to some number of replicas.
|
||||
</p>
|
||||
<p>
|
||||
Using replication to improve an application's
|
||||
transactional commit guarantee is called
|
||||
<span class="emphasis"><em>replicating to the network.</em></span>
|
||||
</p>
|
||||
<p>
|
||||
In extreme cases where performance is of critical
|
||||
importance to the application, the master might
|
||||
choose to both use asynchronous commits
|
||||
<span class="emphasis"><em>and</em></span> decide not to wait for
|
||||
message acknowledgments. In this case the master
|
||||
is simply broadcasting its commit activities to its
|
||||
replicas without waiting for any sort of a reply. An
|
||||
application like this might also choose to use
|
||||
something other than TCP/IP for its network
|
||||
communications since that protocol involves a fair
|
||||
amount of packet acknowledgment all on its own. Of
|
||||
course, this sort of an application should also be
|
||||
very sure about the reliability of both its network and
|
||||
the machines that are hosting its replicas.
|
||||
</p>
|
||||
<p>
|
||||
At the other end of the extreme, there is a
|
||||
class of applications that use replication
|
||||
purely to improve read performance. This sort
|
||||
of application might choose to use synchronous
|
||||
commits on the master because write
|
||||
performance there is not of critical
|
||||
performance. In any case, this kind of an
|
||||
application might not care to know whether its
|
||||
replicas have received and successfully handled
|
||||
permanent messages because the primary storage
|
||||
location is assumed to be on the master, not
|
||||
the replicas.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="permmanage"></a>Managing Permanent Messages</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
With the exception of a rare breed of
|
||||
replicated applications, most masters need some
|
||||
view as to whether commits are occurring on
|
||||
replicas as expected. At a minimum, this is because
|
||||
masters will not flush their log buffers unless
|
||||
they have reason to expect that permanent
|
||||
messages have not been committed on the
|
||||
replicas.
|
||||
</p>
|
||||
<p>
|
||||
That said, it is important to remember that
|
||||
managing permanent messages involves a fair amount
|
||||
of network traffic. The messages must be sent to
|
||||
the replicas and the replicas must then acknowledge
|
||||
the message. This represents a performance overhead
|
||||
that can be worsened by congested networks or
|
||||
outright outages.
|
||||
</p>
|
||||
<p>
|
||||
Therefore, when managing permanent messages, you
|
||||
must first decide on how many of your replicas must
|
||||
send acknowledgments before your master decides
|
||||
that all is well and it can continue normal
|
||||
operations. When making this decision, you could
|
||||
decide that <span class="emphasis"><em>all</em></span> replicas must
|
||||
send acknowledgments. But unless you have only one
|
||||
or two replicas, or you are replicating over a very
|
||||
fast and reliable network, this policy could prove
|
||||
very harmful to your application's performance.
|
||||
</p>
|
||||
<p>
|
||||
Therefore, a common strategy is to wait for an
|
||||
acknowledgment from a simple majority of replicas.
|
||||
This ensures that commit activity has occurred on
|
||||
enough machines that you can be reliably certain
|
||||
that data writes are preserved across your network.
|
||||
</p>
|
||||
<p>
|
||||
Remember that replicas that do not acknowledge a
|
||||
permanent message are not necessarily unable to
|
||||
perform the commit; it might be that network
|
||||
problems have simply resulted in a delay at the
|
||||
replica. In any case, the underlying DB
|
||||
replication code is written such that a replica that
|
||||
falls behind the master will eventually take action
|
||||
to catch up.
|
||||
</p>
|
||||
<p>
|
||||
Depending on your application, it may be
|
||||
possible for you to code your permanent message
|
||||
handling such that acknowledgment must come
|
||||
from only one or two replicas. This is a
|
||||
particularly attractive strategy if you are
|
||||
closely managing which machines are eligible to
|
||||
become masters. Assuming that you have one or
|
||||
two machines designated to be a master in the
|
||||
event that the current master goes down, you
|
||||
may only want to receive acknowledgments from
|
||||
those specific machines.
|
||||
</p>
|
||||
<p>
|
||||
Finally, beyond simple message acknowledgment, you
|
||||
also need to implement an acknowledgment timeout
|
||||
for your application. This timeout value is simply
|
||||
meant to ensure that your master does not hang
|
||||
indefinitely waiting for responses that will never
|
||||
come because a machine or router is down.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="permimplement"></a>Implementing Permanent
|
||||
Message Handling</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
How you implement permanent message handling
|
||||
depends on which API you are using to implement
|
||||
replication. If you are using the replication framework, then
|
||||
permanent message handling is configured using
|
||||
policies that you specify to the framework. In
|
||||
this case, you can configure your application
|
||||
to:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Ignore permanent messages (the master
|
||||
does not wait for acknowledgments).
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Require acknowledgments from a
|
||||
quorum. A quorum is reached when
|
||||
acknowledgments are received from the
|
||||
minimum number of electable
|
||||
replicas needed to ensure that
|
||||
the record remains durable if
|
||||
an election is held.
|
||||
</p>
|
||||
<p>
|
||||
The goal here is to be
|
||||
absolutely sure the record is
|
||||
durable. The master wants to
|
||||
hear from enough electable
|
||||
replicas that they have
|
||||
committed the record so that if
|
||||
an election is held, the master
|
||||
knows the record will exist even
|
||||
if a new master is selected.
|
||||
</p>
|
||||
<p>
|
||||
This is the default policy.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Require an acknowledgment from at least one replica.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Require acknowledgments from
|
||||
all replicas.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Require an acknowledgment from a
|
||||
peer. (The replication framework allows you to
|
||||
designate one environment as a peer of
|
||||
another).
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Require acknowledgments from
|
||||
all peers.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
Note that the replication framework simply flushes its transaction
|
||||
logs and moves on if a permanent message is not
|
||||
sufficiently acknowledged.
|
||||
</p>
|
||||
<p>
|
||||
For details on permanent message handling with the
|
||||
replication framework, see <a href="fwrkpermmessage.html">Permanent Message Handling</a>.
|
||||
</p>
|
||||
<p>
|
||||
If these policies are not sufficient for your
|
||||
needs, or if you want your application to take more
|
||||
corrective action than simply flushing log buffers
|
||||
in the event of an unsuccessful commit, then you
|
||||
must use write a custom replication implementation.
|
||||
</p>
|
||||
<p>
|
||||
For custom replication implementation, messages are
|
||||
sent from the master to its replica using a
|
||||
<tt class="function">send()</tt> callback that you
|
||||
implement. Note, however, that DB's replication
|
||||
code automatically sets the permanent
|
||||
flag for you where appropriate.
|
||||
</p>
|
||||
<p>
|
||||
If the <tt class="function">send()</tt> callback returns with a
|
||||
non-zero status, DB flushes the transaction log
|
||||
buffers for you. Therefore, you must cause your
|
||||
<tt class="function">send()</tt> callback to block waiting
|
||||
for acknowledgments from your replicas.
|
||||
As a part of implementing the
|
||||
<tt class="function">send()</tt> callback, you implement
|
||||
your permanent message handling policies. This
|
||||
means that you identify how many replicas must
|
||||
acknowledge the message before the callback can
|
||||
return <tt class="literal">0</tt>. You must also
|
||||
implement the acknowledgment timeout, if any.
|
||||
</p>
|
||||
<p>
|
||||
Further, message acknowledgments are sent from the
|
||||
replicas to the master using a communications
|
||||
channel that you implement (the replication code
|
||||
does not provide a channel for acknowledgments).
|
||||
So implementing permanent messages means that when
|
||||
you write your replication communications channel,
|
||||
you must also write it in such a way as to also
|
||||
handle permanent message acknowledgments.
|
||||
</p>
|
||||
<p>
|
||||
For more information on implementing permanent
|
||||
message handling using a custom replication layer,
|
||||
see the <i class="citetitle">Berkeley DB Programmer's Reference Guide</i>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="elections.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="introduction.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="txnapp.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Holding Elections </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Chapter 2. Transactional Application</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
216
docs/gsg_db_rep/CXX/preface.html
Normal file
216
docs/gsg_db_rep/CXX/preface.html
Normal file
@@ -0,0 +1,216 @@
|
||||
<?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>Preface</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="index.html" title="Getting Started with Replicated Berkeley DB Applications" />
|
||||
<link rel="previous" href="index.html" title="Getting Started with Replicated Berkeley DB Applications" />
|
||||
<link rel="next" href="introduction.html" title="Chapter 1. Introduction" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Preface</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="index.html">Prev</a> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="introduction.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="preface" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title"><a id="preface"></a>Preface</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="preface.html#conventions">Conventions Used in this Book</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="preface.html#moreinfo">For More Information</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
This document describes how to write replicated Berkeley DB applications.
|
||||
The APIs used to implement replication in your application
|
||||
are described here. This book describes the concepts surrounding replication, the scenarios under which you
|
||||
might choose to use it, and the architectural requirements that a replication application has over a
|
||||
transactional application.
|
||||
</p>
|
||||
<p>
|
||||
This book is aimed at the software engineer responsible for writing a
|
||||
replicated DB application.
|
||||
</p>
|
||||
<p>
|
||||
This book assumes that you have already read and understood the
|
||||
concepts contained in the
|
||||
<span><i class="citetitle">Berkeley DB Getting Started with Transaction Processing</i> guide.</span>
|
||||
|
||||
</p>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="conventions"></a>Conventions Used in this Book</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The following typographical conventions are used within in this manual:
|
||||
</p>
|
||||
<p>
|
||||
Class names are represented in <tt class="classname">monospaced font</tt>, as are <tt class="methodname">method
|
||||
names</tt>. For example:
|
||||
|
||||
|
||||
|
||||
<span>"<tt class="methodname">DbEnv::open()</tt> is a
|
||||
<tt class="classname">DbEnv</tt> class method."</span>
|
||||
</p>
|
||||
<p>
|
||||
Variable or non-literal text is presented in <span class="emphasis"><em>italics</em></span>. For example: "Go to your
|
||||
<span class="emphasis"><em>DB_INSTALL</em></span> directory."
|
||||
</p>
|
||||
<p>
|
||||
Program examples are displayed in a <tt class="classname">monospaced font</tt> on a shaded background.
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting">typedef struct vendor {
|
||||
char name[MAXFIELD]; // Vendor name
|
||||
char street[MAXFIELD]; // Street name and number
|
||||
char city[MAXFIELD]; // City
|
||||
char state[3]; // Two-digit US state code
|
||||
char zipcode[6]; // US zipcode
|
||||
char phone_number[13]; // Vendor phone number
|
||||
} VENDOR; </pre>
|
||||
<p>
|
||||
In some situations, programming examples are updated from one chapter to the next. When
|
||||
this occurs, the new code is presented in <b class="userinput"><tt>monospaced bold</tt></b> font. For example:
|
||||
</p>
|
||||
<pre class="programlisting">typedef struct vendor {
|
||||
char name[MAXFIELD]; // Vendor name
|
||||
char street[MAXFIELD]; // Street name and number
|
||||
char city[MAXFIELD]; // City
|
||||
char state[3]; // Two-digit US state code
|
||||
char zipcode[6]; // US zipcode
|
||||
char phone_number[13]; // Vendor phone number
|
||||
<b class="userinput"><tt>char sales_rep[MAXFIELD]; // Name of sales representative
|
||||
char sales_rep_phone[MAXFIELD]; // Sales rep's phone number </tt></b>
|
||||
} VENDOR; </pre>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
Finally, notes of special interest are represented using a note block such
|
||||
as this.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="moreinfo"></a>For More Information</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Beyond this manual, you may also find the following sources of information useful when building a
|
||||
transactional DB application:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/gsg_txn/CXX/index.html" target="_top">
|
||||
Getting Started with Transaction Processing for C++
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/gsg/CXX/index.html" target="_top">
|
||||
Getting Started with Berkeley DB for C++
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/ref/toc.html" target="_top">
|
||||
Berkeley DB Programmer's Reference Guide
|
||||
</a>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/api_cxx/frame.html" target="_top">
|
||||
Berkeley DB C++ API
|
||||
</a>
|
||||
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="index.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="index.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="introduction.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Getting Started with Replicated Berkeley DB Applications </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Chapter 1. Introduction</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
259
docs/gsg_db_rep/CXX/processingloop.html
Normal file
259
docs/gsg_db_rep/CXX/processingloop.html
Normal file
@@ -0,0 +1,259 @@
|
||||
<?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>Processing Loop</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="fwrkmasterreplica.html" title="Chapter 4. Replica versus Master Processes" />
|
||||
<link rel="previous" href="fwrkmasterreplica.html" title="Chapter 4. Replica versus Master Processes" />
|
||||
<link rel="next" href="exampledoloop.html" title="Example Processing Loop" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Processing Loop</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="fwrkmasterreplica.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 4. Replica versus Master Processes</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="exampledoloop.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="processingloop"></a>Processing Loop</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Typically the central part of any replication application
|
||||
is some sort of a continuous loop that constantly
|
||||
checks the state of the environment (whether it is a
|
||||
replica or a master), opens and/or closes the
|
||||
databases as is necessary, and performs other useful
|
||||
work. A loop such as this one must of necessity
|
||||
take special care to know whether it is operating
|
||||
on a master or a replica environment because all of its
|
||||
activities are dependent upon that state.
|
||||
</p>
|
||||
<p>
|
||||
The flow of activities through the loop will
|
||||
generally be as follows:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Check whether the environment has
|
||||
changed state. If it has, you
|
||||
might want to reopen your
|
||||
database handles, especially if
|
||||
you opened your replica's
|
||||
database handles as read-only.
|
||||
In this case, you might need to
|
||||
reopen them as read-write.
|
||||
However, if you always open your
|
||||
database handles as read-write,
|
||||
then it is not automatically necessary to
|
||||
reopen the databases due to a
|
||||
state change. Instead, you
|
||||
could check for a
|
||||
<span>
|
||||
<tt class="literal">DB_REP_HANDLE_DEAD</tt>
|
||||
return code
|
||||
</span>
|
||||
|
||||
|
||||
when you use your
|
||||
database handle(s). If you see
|
||||
this, then you need to reopen
|
||||
your database handle(s).
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
If the databases are closed,
|
||||
create new database handles,
|
||||
configure the handle as is
|
||||
appropriate, and then open the
|
||||
databases. Note that handle
|
||||
configuration will be different,
|
||||
depending on whether the handle
|
||||
is opened as a replica or a
|
||||
master. At a minimum, the master
|
||||
should be opened with database
|
||||
creation privileges, whereas the
|
||||
replica does not need to be. You
|
||||
must also open the master such
|
||||
that its databases are
|
||||
read-write. You
|
||||
<span class="emphasis"><em>can</em></span> open
|
||||
replicas with read-only
|
||||
databases, so long as you are
|
||||
prepared to closed and the reopen
|
||||
the handle in the event the
|
||||
client becomes a master.
|
||||
</p>
|
||||
<p>
|
||||
Also, note that if the local
|
||||
environment
|
||||
is a replica, then it is possible
|
||||
that databases do not currently
|
||||
exist. In this case, the database
|
||||
open attempts will fail. Your
|
||||
code will have to take this
|
||||
corner case into account
|
||||
(described below).
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Once the databases are opened,
|
||||
check to see if the local
|
||||
environment is a
|
||||
master. If it is, do whatever it is
|
||||
a master should do for your
|
||||
application.
|
||||
</p>
|
||||
<p>
|
||||
Remember that the code for your
|
||||
master should include some way
|
||||
for you to tell the master
|
||||
to exit gracefully.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
If the local environment is not a
|
||||
master, then do whatever it is
|
||||
your replica environments should do.
|
||||
Again, like the code for your
|
||||
master environments, you should provide
|
||||
a way for your replicas to exit
|
||||
the processing loop gracefully.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p>
|
||||
The following code fragment illustrates
|
||||
these points (note that we fill out this
|
||||
fragment with a working example
|
||||
next in this chapter):
|
||||
</p>
|
||||
<pre class="programlisting">/* loop to manage replication activities */
|
||||
|
||||
Db *dbp;
|
||||
int ret;
|
||||
APP_DATA *app_data;
|
||||
u_int32_t flags;
|
||||
|
||||
dbp = NULL;
|
||||
ret = 0;
|
||||
|
||||
/*
|
||||
* Remember that for this to work, an APP_DATA struct would have first
|
||||
* had to been set to the environment handle's app_private data
|
||||
* member. (dbenv is presumable declared and opened in another part of
|
||||
* the code.)
|
||||
*/
|
||||
app_data = dbenv->get_app_private();
|
||||
|
||||
|
||||
/*
|
||||
* Infinite loop. We exit depending on how the master and replica code
|
||||
* is written.
|
||||
*/
|
||||
for (;;) {
|
||||
/* If dbp is not opened, we need to open it. */
|
||||
if (dbp == NULL) {
|
||||
/*
|
||||
* Create the handle and then configure it. Before you open
|
||||
* it, you have to decide what open flags to use:
|
||||
*/
|
||||
flags = DB_AUTO_COMMIT;
|
||||
if (app_data->is_master)
|
||||
flags |= DB_CREATE
|
||||
/*
|
||||
* Now you can open your database handle, passing to it the
|
||||
* flags selected above.
|
||||
*
|
||||
* One thing to watch out for is a case where the databases
|
||||
* you are trying to open do not yet exist. This can happen
|
||||
* for replicas where the databases are being opened
|
||||
* read-only. If this happens, ENOENT is returned by the
|
||||
* open() call.
|
||||
*/
|
||||
try {
|
||||
dbp->open(NULL, DATABASE, NULL, DB_BTREE,
|
||||
app_data->is_master ? DB_CREATE | DB_AUTO_COMMIT :
|
||||
DB_AUTO_COMMIT, 0);
|
||||
} catch(DbException dbe) {
|
||||
if (dbe.get_errno() == ENOENT) {
|
||||
cout << "No stock db available yet - retrying." << endl;
|
||||
try {
|
||||
dbp->close(0);
|
||||
} catch (DbException dbe2) {
|
||||
cout << "Unexpected error closing after failed" <<
|
||||
" open, message: " << dbe2.what() << endl;
|
||||
dbp = NULL;
|
||||
goto err;
|
||||
}
|
||||
dbp = NULL;
|
||||
sleep(SLEEPTIME);
|
||||
continue;
|
||||
} else {
|
||||
dbenv.err(ret, "DB->open");
|
||||
throw dbe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that the databases have been opened, continue with general
|
||||
* processing, depending on whether we are a master or a replica.
|
||||
*/
|
||||
if (app_data->is_master) {
|
||||
/*
|
||||
* Do master stuff here. Don't forget to include a way to
|
||||
* gracefully exit the loop. */
|
||||
*/
|
||||
} else {
|
||||
/*
|
||||
* Do replica stuff here. As is the case with the master
|
||||
* code, be sure to include a way to gracefully exit the
|
||||
* loop.
|
||||
*/
|
||||
}
|
||||
} </pre>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="fwrkmasterreplica.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="fwrkmasterreplica.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="exampledoloop.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Chapter 4. Replica versus Master Processes </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Example Processing Loop</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
184
docs/gsg_db_rep/CXX/repadvantage.html
Normal file
184
docs/gsg_db_rep/CXX/repadvantage.html
Normal file
@@ -0,0 +1,184 @@
|
||||
<?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>Replication Benefits</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="introduction.html" title="Chapter 1. Introduction" />
|
||||
<link rel="previous" href="introduction.html" title="Chapter 1. Introduction" />
|
||||
<link rel="next" href="apioverview.html" title="The Replication APIs" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Replication Benefits</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="introduction.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 1. Introduction</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="apioverview.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="repadvantage"></a>Replication Benefits</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
|
||||
Replication offers your application a number of benefits that
|
||||
can be a tremendous help. Primarily replication's benefits
|
||||
revolve around performance, but there is also a benefit in
|
||||
terms of data durability guarantees.
|
||||
</p>
|
||||
<p>
|
||||
Briefly, the reasons why you might choose to implement
|
||||
replication in your DB application are:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<div class="itemizedlist">
|
||||
<ul type="circle">
|
||||
<li>
|
||||
<p>
|
||||
Improved application reliability.
|
||||
</p>
|
||||
<p>
|
||||
By spreading your data across multiple
|
||||
machines, you can ensure that your
|
||||
application's data continues to be
|
||||
available even in the event of a
|
||||
hardware failure on any given machine in
|
||||
the replication group.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Improve read performance.
|
||||
</p>
|
||||
<p>
|
||||
By using replication you can spread data reads across
|
||||
multiple machines on your network. Doing so allows you
|
||||
to vastly improve your application's read performance.
|
||||
This strategy might be particularly interesting for
|
||||
applications that have readers on remote network nodes;
|
||||
you can push your data to the network's edges thereby
|
||||
improving application data read responsiveness.
|
||||
</p>
|
||||
<p>
|
||||
Additionally, depending on how you partition your
|
||||
data across your replicas, any given replica may
|
||||
only need to cache part of your data, decreasing
|
||||
cache misses and reducing I/O on the client.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Improve transactional commit performance
|
||||
</p>
|
||||
<p>
|
||||
In order to commit a transaction and achieve a
|
||||
transactional durability guarantee, the commit must be
|
||||
made <span class="emphasis"><em>durable</em></span>. That is, the commit
|
||||
must be written to disk (usually, but not always,
|
||||
synchronously) before the application's thread of
|
||||
control can continue operations.
|
||||
</p>
|
||||
<p>
|
||||
Replication allows you to avoid this disk I/O and still
|
||||
maintain a degree of durability by <span class="emphasis"><em>committing
|
||||
to the network</em></span>. In other words, you relax
|
||||
your transactional durability guarantees on the master,
|
||||
but by virtue of replicating the data across the
|
||||
network you gain some additional durability guarantees
|
||||
above what is provided locally.
|
||||
</p>
|
||||
<p>
|
||||
Usually this strategy is implemented using some form of
|
||||
an asynchronous transactional commit on the master. In
|
||||
this way your data writes will eventually be written to
|
||||
disk, but your application will not have to wait for
|
||||
the disk I/O to complete before continuing with its
|
||||
next operation.
|
||||
</p>
|
||||
<p>
|
||||
Note that it is possible to cause DB's replication
|
||||
implementation to wait to hear from one or
|
||||
more replica's as to whether they have successfully
|
||||
saved the write before continuing. However, in this
|
||||
case you might be trading performance for a even
|
||||
higher durability guarantee (see below).
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Improve data durability guarantee.
|
||||
</p>
|
||||
<p>
|
||||
In a traditional transactional application, you commit your
|
||||
transactions such that data modifications are saved to
|
||||
disk. Beyond this, the durability of your data is
|
||||
dependent upon the backup strategy that you choose to
|
||||
implement for your site.
|
||||
</p>
|
||||
<p>
|
||||
Replication allows you to increase this durability
|
||||
guarantee by ensuring that data modifications are
|
||||
written to multiple machines. This means that multiple
|
||||
disks, disk controllers, power supplies, and CPUs are
|
||||
used to ensure that your data modification makes it to
|
||||
stable storage. In other words, replication allows you
|
||||
to minimize the problem of a single point of failure
|
||||
by using more hardware to guarantee your data writes.
|
||||
</p>
|
||||
<p>
|
||||
If you are using replication for this reason, then you
|
||||
probably will want to configure your application such
|
||||
that it waits to hear about a successful commit from
|
||||
one or more replicas before continuing with the next
|
||||
operation. This will obviously impact your
|
||||
application's write performance to some degree
|
||||
— with the performance penalty being largely dependent
|
||||
upon the speed and stability of the network connecting
|
||||
your replication group.
|
||||
</p>
|
||||
<p>
|
||||
For more information, see <a href="fwrkpermmessage.html">Permanent Message Handling</a>.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="introduction.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="introduction.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="apioverview.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Chapter 1. Introduction </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> The Replication APIs</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
703
docs/gsg_db_rep/CXX/repapp.html
Normal file
703
docs/gsg_db_rep/CXX/repapp.html
Normal file
@@ -0,0 +1,703 @@
|
||||
<?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>Chapter 3. The DB Replication Framework</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="index.html" title="Getting Started with Replicated Berkeley DB Applications" />
|
||||
<link rel="previous" href="simpleprogramlisting.html" title="Program Listing" />
|
||||
<link rel="next" href="repmgr_init_example_c.html" title="Adding the Replication Framework to SimpleTxn " />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Chapter 3. The DB Replication Framework</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="simpleprogramlisting.html">Prev</a> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="repmgr_init_example_c.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="chapter" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title"><a id="repapp"></a>Chapter 3. The DB Replication Framework</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="repapp.html#rep_init_code">
|
||||
Starting and Stopping Replication
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="repapp.html#election_flags">Managing Election Policies</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="repapp.html#thread_count">Selecting the Number of Threads</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="repmgr_init_example_c.html">Adding the Replication Framework to
|
||||
|
||||
SimpleTxn
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="fwrkpermmessage.html">Permanent Message Handling</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="fwrkpermmessage.html#fmwrkpermpolicy">Identifying Permanent Message Policies</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="fwrkpermmessage.html#fmwrkpermtimeout">Setting the Permanent Message Timeout</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="fwrkpermmessage.html#perm2fmwrkexample">Adding a Permanent Message Policy to
|
||||
|
||||
RepMgr
|
||||
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="electiontimes.html">Managing Election Times</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="electiontimes.html#electiontimeout">Managing Election Timeouts</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="electiontimes.html#electretrytime">Managing Election Retry Times</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="fmwrkconnectretry.html">Managing Connection Retries</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="heartbeats.html">Managing Heartbeats</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
The easiest way to add replication to your transactional
|
||||
application is to use the replication framework. The replication framework provides a comprehensive
|
||||
communications layer that enables replication. For a brief listing
|
||||
of the replication framework's feature set, see
|
||||
<a href="apioverview.html#repframeworkoverview">Replication Framework Overview</a>.
|
||||
</p>
|
||||
<p>
|
||||
To use the replication framework, you make use of special methods off the
|
||||
|
||||
<span><tt class="classname">DbEnv</tt> class.</span>
|
||||
That is:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Create an environment handle as normal.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Configure your environment handle as
|
||||
needed (e.g. set the error file and
|
||||
error prefix values, if desired).
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Use the replication framework replication methods to
|
||||
configure the replication framework. Using these
|
||||
methods causes DB to know that you
|
||||
are using the replication framework.
|
||||
</p>
|
||||
<p>
|
||||
Configuring the replication framework
|
||||
entails setting its replication
|
||||
priority, setting the TCP/IP address
|
||||
that this replication environment will use for
|
||||
incoming replication messages, identify
|
||||
TCP/IP addresses of other replication
|
||||
environments, setting the number of
|
||||
replication environments in the
|
||||
replication group, and so forth. These actions are
|
||||
discussed throughout the remainder of
|
||||
this chapter.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Open your environment handle. When you
|
||||
do this, be sure to specify
|
||||
|
||||
<span><tt class="literal">DB_INIT_REP</tt> and
|
||||
<tt class="literal">DB_THREAD</tt> to your
|
||||
open flags. (This is in addition to the
|
||||
flags that you normally use for a
|
||||
single-threaded transactional
|
||||
application). The first of these causes
|
||||
replication to be initialized for the
|
||||
application. The second causes your
|
||||
environment handle to be free-threaded
|
||||
(thread safe). Both flags are required
|
||||
for replication framework usage.
|
||||
</span>
|
||||
|
||||
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Start replication by calling
|
||||
|
||||
<span><tt class="methodname">DbEnv::repmgr_start()</tt>.</span>
|
||||
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Open your databases as needed. Masters
|
||||
must open their databases for read
|
||||
and write activity. Replicas can open
|
||||
their databases for read-only activity, but
|
||||
doing so means they must re-open the
|
||||
databases if the replica ever becomes a
|
||||
master. Either way, replicas should never attempt to
|
||||
write to the database(s) directly.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
The replication framework allows you to only use one
|
||||
environment handle per process.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
When you are ready to shut down your application:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Close your databases
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Close your environment. This causes
|
||||
replication to stop as well.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
Before you can use the replication framework, you may have to
|
||||
enable it in your DB library. This is
|
||||
<span class="emphasis"><em>not</em></span> a requirement for
|
||||
Microsoft Windows systems, or Unix systems that
|
||||
use pthread mutexes by default. Other systems,
|
||||
notably BSD and BSD-derived systems (such as
|
||||
Mac OS X), must enable the replication framework when you
|
||||
configure the DB build.
|
||||
</p>
|
||||
<p>
|
||||
You do this by <span class="emphasis"><em>not</em></span>
|
||||
disabling replication and by configuring the
|
||||
library with POSIX threads support. In other
|
||||
words, replication must be turned on in the
|
||||
build (it is by default), and POSIX thread
|
||||
support must be enabled if it is not already by
|
||||
default. To do this, use the
|
||||
<tt class="literal">--enable-pthread_api</tt> switch
|
||||
on the configure script.
|
||||
</p>
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting">../dist/configure --enable-pthread-api</pre>
|
||||
</div>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="rep_init_code"></a>
|
||||
Starting and Stopping Replication
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
As described above, you introduce replication to an
|
||||
application by starting with a transactional
|
||||
application, performing some basic replication
|
||||
configuration, and then starting replication using
|
||||
|
||||
<span><tt class="methodname">DbEnv::repmgr_start()</tt>.</span>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
You stop replication by closing your environment
|
||||
cleanly, as is normal for an DB application.
|
||||
</p>
|
||||
<p>
|
||||
For example, the following code fragment initializes, then
|
||||
stops and starts replication. Note that other replication
|
||||
activities are omitted for brevity.
|
||||
</p>
|
||||
<pre class="programlisting">#include <db_cxx.h>
|
||||
|
||||
/* Use a 10mb cache */
|
||||
#define CACHESIZE (10 * 1024 * 1024)
|
||||
|
||||
...
|
||||
|
||||
DbEnv *dbenv; /* Environment handle. */
|
||||
const char *progname; /* Program name. */
|
||||
const char *envHome; /* Environment home directory. */
|
||||
const char *listen_host; /* A TCP/IP hostname. */
|
||||
const char *other_host; /* A TCP/IP hostname. */
|
||||
u_int16 listen_port; /* A TCP/IP port. */
|
||||
u_int16 other_port; /* A TCP/IP port. */
|
||||
|
||||
/* Initialize variables */
|
||||
dbenv = NULL;
|
||||
progname = "example_replication";
|
||||
envHome = "ENVIRONMENT_HOME";
|
||||
listen_host = "mymachine.sleepycat.com";
|
||||
listen_port = 5001;
|
||||
other_host = "anothermachine.sleepycat.com";
|
||||
other_port = 4555;
|
||||
|
||||
try {
|
||||
/* Create the environment handle */
|
||||
dbenv = new DbEnv(0);
|
||||
|
||||
/*
|
||||
* Configure the environment handle. Here we configure
|
||||
* asynchronous transactional commits for performance reasons.
|
||||
*/
|
||||
dbenv->set_errfile(stderr);
|
||||
dbenv->set_errpfx(progname);
|
||||
(void)dbenv->set_cachesize(0, CACHESIZE, 0);
|
||||
(void)dbenv->set_flags(DB_TXN_NOSYNC, 1);
|
||||
|
||||
/*
|
||||
* Configure the local address. This is the local hostname and
|
||||
* port that this replication participant will use to receive
|
||||
* incoming replication messages. Note that this can be performed
|
||||
* only once for the application. It is required.
|
||||
*/
|
||||
dbenv->repmgr_set_local_site(listen_host, listen_port, 0);
|
||||
|
||||
/*
|
||||
* Set this application's priority. This is used for elections.
|
||||
*
|
||||
* Set this number to a positive integer, or 0 if you do not want
|
||||
* this site to be able to become a master.
|
||||
*/
|
||||
dbenv->rep_set_priority(100);
|
||||
|
||||
/*
|
||||
* Add a site to the list of replication environments known to
|
||||
* this application.
|
||||
*/
|
||||
dbenv->repmgr_add_remote_site(dbenv, other_host, other_port,
|
||||
NULL, 0);
|
||||
|
||||
/*
|
||||
* Identify the number of sites in the replication group. This is
|
||||
* necessary so that elections and permanent message handling can
|
||||
* be performed correctly.
|
||||
*/
|
||||
dbenv->repmgr_set_nsites(dbenv, 2);
|
||||
|
||||
/* Open the environment handle. Note that we add DB_THREAD and
|
||||
* DB_INIT_REP to the list of flags. These are required.
|
||||
*/
|
||||
dbenv->open(home, DB_CREATE | DB_RECOVER |
|
||||
DB_INIT_LOCK | DB_INIT_LOG |
|
||||
DB_INIT_MPOOL | DB_INIT_TXN |
|
||||
DB_THREAD | DB_INIT_REP,
|
||||
0);
|
||||
|
||||
/* Start the replication framework such that it uses 3 threads. */
|
||||
dbenv->repmgr_start(3, DB_REP_ELECTION);
|
||||
|
||||
/* Sleep to give ourselves time to find a master */
|
||||
sleep(5);
|
||||
|
||||
/*
|
||||
**********************************************************
|
||||
*** All other application code goes here, including *****
|
||||
*** database opens *****
|
||||
**********************************************************
|
||||
*/
|
||||
|
||||
|
||||
} catch (DbException &de) {
|
||||
/* Error handling goes here */
|
||||
}
|
||||
|
||||
/* Close out the application here.
|
||||
try {
|
||||
/*
|
||||
* Make sure all your database handles are closed
|
||||
* (omitted from this example).
|
||||
*/
|
||||
|
||||
/* Close the environment */
|
||||
if (dbenv != NULL)
|
||||
(void)dbenv->close(dbenv, 0);
|
||||
|
||||
} catch (DbException &de) {
|
||||
/* Error handling goes here */
|
||||
}
|
||||
|
||||
/* All done */ </pre>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="election_flags"></a>Managing Election Policies</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Before continuing, it is worth taking a look at the
|
||||
|
||||
<span>
|
||||
startup election flags accepted by
|
||||
|
||||
<span><tt class="methodname">DbEnv::repgmr_start()</tt>.</span>
|
||||
These flags control how your replication application will
|
||||
behave when it first starts up.
|
||||
</span>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
In the previous example, we specified
|
||||
<tt class="literal">DB_REP_ELECTION</tt>
|
||||
|
||||
when we started replication. This causes the
|
||||
application to try to find a master upon startup. If it
|
||||
cannot, it calls for an election. In the event an
|
||||
election is held, the environment receiving the most number of
|
||||
votes will become the master.
|
||||
</p>
|
||||
<p>
|
||||
There's some important points to make here:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
This
|
||||
<span>flag</span>
|
||||
|
||||
only requires that other
|
||||
environments in the replication group
|
||||
participate in the vote. There is no
|
||||
requirement that
|
||||
<span class="emphasis"><em>all</em></span> such
|
||||
environments participate. In other
|
||||
words, if an environment
|
||||
starts up, it can call for an
|
||||
election, and select a master, even
|
||||
if all other environment have not yet
|
||||
joined the replication group.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
It only requires a simple majority of
|
||||
participating environments to elect a master. The number of
|
||||
environments used to calculate the simple
|
||||
majority is based on the value set for
|
||||
|
||||
|
||||
<span><tt class="methodname">DbEnv::rep_set_nsites()</tt>.</span>
|
||||
|
||||
|
||||
|
||||
This is always true of elections held using the replication framework.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
As always, the environment participating in the election with the most
|
||||
up-to-date log files is selected as
|
||||
master. If an environment with better log files
|
||||
has not yet joined the replication
|
||||
group, it may not become the master.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
Any one of these points may be enough to cause a
|
||||
less-than-optimum environment to be selected as master.
|
||||
Therefore, to give you a better degree of control over
|
||||
which environment becomes a master at application startup,
|
||||
the replication framework offers the following start-up
|
||||
<span>flags:</span>
|
||||
|
||||
</p>
|
||||
<div class="informaltable">
|
||||
<table border="1" width="80%">
|
||||
<colgroup>
|
||||
<col />
|
||||
<col />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Flag</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<tt class="literal">DB_REP_MASTER</tt>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
The application starts up and declares itself to be a master
|
||||
without calling for an election. It is an error for more
|
||||
than one environment to start up using this flag, or for
|
||||
an environment
|
||||
to use this flag when a master already exists.
|
||||
</p>
|
||||
<p>
|
||||
Note that no replication group should
|
||||
<span class="emphasis"><em>ever</em></span> operate with more than
|
||||
one master.
|
||||
</p>
|
||||
<p>
|
||||
In the event that a environment attempts to become a
|
||||
master when a master already exists, the
|
||||
replication code will resolve the problem by
|
||||
holding an election. Note, however, that there
|
||||
is always a possibility of data loss in the face
|
||||
of duplicate masters, because once a master is
|
||||
selected, the environment that loses the election will
|
||||
have to roll back any transactions committed
|
||||
until it is in sync with the "real" master.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<tt class="literal">DB_REP_CLIENT</tt>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
The application starts up and declares
|
||||
itself to be a replica without calling for
|
||||
an election. Note that the application
|
||||
can still become a master if a subsequent
|
||||
application starts up, calls for an
|
||||
election, and this application is elected
|
||||
master.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<tt class="literal">DB_REP_ELECTION</tt>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
As described above, the application starts up,
|
||||
looks for a master, and if one is not found calls
|
||||
for an election.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<tt class="literal">DB_REP_FULL_ELECTION</tt>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Identical to
|
||||
<tt class="literal">DB_REP_ELECTION</tt>
|
||||
|
||||
except that the election requires all
|
||||
known members of the replication group to
|
||||
participate. If a given environment has not yet
|
||||
started but it is included in the
|
||||
replication group count (using
|
||||
|
||||
<span><tt class="methodname">DbEnv::rep_set_nsites()</tt>)</span>
|
||||
|
||||
then a master can not be elected.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="thread_count"></a>Selecting the Number of Threads</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Under the hood, the replication framework is threaded and you can
|
||||
control the number of threads used to process messages received from
|
||||
other replicas. The threads that the replication framework uses are:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Incoming message thread. This thread
|
||||
receives messages from the site's
|
||||
socket and passes those messages to
|
||||
message processing threads (see below)
|
||||
for handling.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Outgoing message thread. Outgoing
|
||||
are performed in whatever thread
|
||||
performed a write to the database(s).
|
||||
That is, the thread that called, for
|
||||
example,
|
||||
|
||||
<tt class="methodname">Db::put()</tt>
|
||||
|
||||
is the thread that writes replication messages
|
||||
about that fact to the socket.
|
||||
</p>
|
||||
<p>
|
||||
Note that if this write activity would
|
||||
cause the thread to be blocked due to
|
||||
some condition on the socket, the replication framework
|
||||
will hand the outgoing message to the
|
||||
incoming message thread, and it will
|
||||
then write the message to the socket.
|
||||
This prevents your database write
|
||||
threads from blocking due to abnormal
|
||||
network I/O conditions.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Message processing threads are
|
||||
responsible for parsing and then
|
||||
responding to incoming replication
|
||||
messages. Typically, a response will
|
||||
include write activity to your
|
||||
database(s), so these threads can be
|
||||
busy performing disk I/O.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
Of these threads, the only ones that you have any
|
||||
configuration control over are the message processing
|
||||
threads. In this case, you can determine how many
|
||||
of these threads you want to run.
|
||||
</p>
|
||||
<p>
|
||||
It is always a bit of an art to decide on a thread count,
|
||||
but the short answer is you probably do not need more
|
||||
than three threads here, and it is likely that one will
|
||||
suffice. That said, the best thing to do is set your
|
||||
thread count to a fairly low number and then increase
|
||||
it if it appears that your application will benefit
|
||||
from the additional threads.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="simpleprogramlisting.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="index.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="repmgr_init_example_c.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Program Listing </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Adding the Replication Framework to
|
||||
|
||||
SimpleTxn
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
520
docs/gsg_db_rep/CXX/repmgr_init_example_c.html
Normal file
520
docs/gsg_db_rep/CXX/repmgr_init_example_c.html
Normal file
@@ -0,0 +1,520 @@
|
||||
<?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
|
||||
|
||||
SimpleTxn
|
||||
</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
|
||||
|
||||
SimpleTxn
|
||||
</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>SimpleTxn</span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
We now use the methods described above to add partial
|
||||
support to the
|
||||
|
||||
<tt class="literal">SimpleTxn</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">SimpleTxn</tt>
|
||||
code to a new file called
|
||||
<tt class="literal">RepMgr.cpp</tt>.
|
||||
|
||||
|
||||
|
||||
<span>
|
||||
Having done that, we must make some significant
|
||||
changes to our
|
||||
<tt class="classname">RepConfigInfo</tt>
|
||||
class because now we will be using it to
|
||||
maintain a lot more information.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
First, we create a new structure,
|
||||
<tt class="literal">RepHostInfoObj</tt>, which we use to store
|
||||
host and port information for all "other" servers
|
||||
identified to the application via the
|
||||
<tt class="literal">-o</tt> command line option. This structure
|
||||
is chain-able, which makes cleaning up at program shutdown
|
||||
time easier.
|
||||
</p>
|
||||
<pre class="programlisting">#include <db_cxx.h>
|
||||
#include <iostream>
|
||||
|
||||
<b class="userinput"><tt>// Chain-able struct used to store host information.
|
||||
typedef struct RepHostInfoObj{
|
||||
char* host;
|
||||
int port;
|
||||
RepHostInfoObj* next; // used for chaining multiple "other" hosts.
|
||||
} REP_HOST_INFO; </tt></b></pre>
|
||||
<p>
|
||||
Next, we update our <tt class="classname">RepConfigInfo</tt> class
|
||||
definition to manage a lot more information and a new method.
|
||||
</p>
|
||||
<pre class="programlisting">class RepConfigInfo {
|
||||
public:
|
||||
RepConfigInfo();
|
||||
virtual ~RepConfigInfo();
|
||||
|
||||
<b class="userinput"><tt>void addOtherHost(char* host, int port);</tt></b>
|
||||
public:
|
||||
<b class="userinput"><tt>u_int32_t start_policy;</tt></b>
|
||||
char* home;
|
||||
<b class="userinput"><tt>bool got_listen_address;
|
||||
REP_HOST_INFO this_host;
|
||||
int totalsites;
|
||||
int priority;
|
||||
// used to store a set of optional other hosts.
|
||||
REP_HOST_INFO *other_hosts;</tt></b>
|
||||
}; </pre>
|
||||
<p>
|
||||
Then, we update our constructor to initialize our new variables.
|
||||
</p>
|
||||
<pre class="programlisting">RepConfigInfo::RepConfigInfo()
|
||||
{
|
||||
<b class="userinput"><tt>start_policy = DB_REP_ELECTION;</tt></b>
|
||||
home = "TESTDIR";
|
||||
<b class="userinput"><tt>got_listen_address = false;
|
||||
totalsites = 0;
|
||||
priority = 100;
|
||||
other_hosts = NULL;</tt></b>
|
||||
} </pre>
|
||||
<p>
|
||||
Next, we implement our new method, <tt class="methodname">RepConfigInfo::addOtherHost</tt>,
|
||||
which is used to create <tt class="literal">RepHostInfoObj</tt> instances and add them to
|
||||
the chain of "other" hosts.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<b class="userinput">
|
||||
<tt>RepConfigInfo::addOtherHost(char* host, int port)
|
||||
{
|
||||
REP_HOST_INFO *newinfo;
|
||||
newinfo = (REP_HOST_INFO*)malloc(sizeof(REP_HOST_INFO));
|
||||
newinfo->host = host;
|
||||
newinfo->port = port;
|
||||
if (other_hosts == NULL) {
|
||||
other_hosts = newinfo;
|
||||
newinfo->next = NULL;
|
||||
} else {
|
||||
newinfo->next = other_hosts;
|
||||
other_hosts = newinfo;
|
||||
}
|
||||
} </tt>
|
||||
</b>
|
||||
</pre>
|
||||
<p>
|
||||
Having done that, we update our class destructor to release the <tt class="literal">RepHostInfoObj</tt>
|
||||
chain of objects at class destruction time.
|
||||
</p>
|
||||
<pre class="programlisting">RepConfigInfo::~RepConfigInfo()
|
||||
{
|
||||
<b class="userinput"><tt>// release any other_hosts structs.
|
||||
if (other_hosts != NULL) {
|
||||
REP_HOST_INFO *CurItem = other_hosts;
|
||||
while (CurItem->next != NULL)
|
||||
{
|
||||
REP_HOST_INFO *TmpItem = CurItem;
|
||||
free(CurItem);
|
||||
CurItem = TmpItem;
|
||||
}
|
||||
free(CurItem);
|
||||
}
|
||||
other_hosts = NULL;</tt></b>
|
||||
} </pre>
|
||||
<p>
|
||||
Having completed our update to the
|
||||
<tt class="classname">RepConfigInfo</tt>
|
||||
|
||||
class, we can now start making
|
||||
changes to the main portion of our program. We begin by changing
|
||||
the program's name.
|
||||
</p>
|
||||
<pre class="programlisting">using std::cout;
|
||||
using std::cin;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::flush;
|
||||
|
||||
#define CACHESIZE (10 * 1024 * 1024)
|
||||
#define DATABASE "quote.db"
|
||||
|
||||
<b class="userinput"><tt>const char *progname = "RepMgr";</tt></b> </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">class RepMgr
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
RepMgr();
|
||||
// Initialization method. Creates and opens our environment handle.
|
||||
int init(RepConfigInfo* config);
|
||||
// The doloop is where all the work is performed.
|
||||
int doloop();
|
||||
// terminate() provides our shutdown code.
|
||||
int terminate();
|
||||
|
||||
private:
|
||||
// disable copy constructor.
|
||||
RepMgr(const RepMgr &);
|
||||
void operator = (const RepMgr &);
|
||||
|
||||
// internal data members.
|
||||
RepConfigInfo *app_config;
|
||||
DbEnv dbenv;
|
||||
|
||||
// private methods.
|
||||
// print_stocks() is used to display the contents of our database.
|
||||
static int print_stocks(Db *dbp);
|
||||
};
|
||||
|
||||
static void usage()
|
||||
{
|
||||
cerr << "usage: " << progname << endl
|
||||
<< "[-h home]<b class="userinput"><tt>[-o host:port][-m host:port]</tt></b>"
|
||||
<b class="userinput"><tt><< "[-n nsites][-p priority]" << endl;</tt></b>
|
||||
|
||||
cerr <b class="userinput"><tt><< "\t -m host:port (required; m stands for me)" << endl
|
||||
<< "\t -o host:port (optional; o stands for other; any "
|
||||
<< "number of these may be specified)" << endl</tt></b>
|
||||
<< "\t -h home directory" << endl
|
||||
<b class="userinput"><tt><< "\t -n nsites (optional; number of sites in replication "
|
||||
<< "group; defaults to 0" << endl
|
||||
<< "\t in which case we try to dynamically compute the "
|
||||
<< "number of sites in" << endl
|
||||
<< "\t the replication group)" << endl
|
||||
<< "\t -p priority (optional: defaults to 100)" << endl;</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.
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
<pre class="programlisting">int main(int argc, char **argv)
|
||||
{
|
||||
RepConfigInfo config;
|
||||
char ch<b class="userinput"><tt>, *portstr, *tmphost;
|
||||
int tmpport;</tt></b>
|
||||
int ret; </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"> // Extract the command line parameters
|
||||
while ((ch = getopt(argc, argv, "h:<b class="userinput"><tt>m:n:o:p:</tt></b>")) != EOF) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
config.home = optarg;
|
||||
break;
|
||||
<b class="userinput"><tt>case 'm':
|
||||
config.this_host.host = strtok(optarg, ":");
|
||||
if ((portstr = strtok(NULL, ":")) == NULL) {
|
||||
cerr << "Bad host specification." << endl;
|
||||
usage();
|
||||
}
|
||||
config.this_host.port = (unsigned short)atoi(portstr);
|
||||
config.got_listen_address = true;
|
||||
break;
|
||||
case 'n':
|
||||
config.totalsites = atoi(optarg);
|
||||
break;
|
||||
case 'o':
|
||||
tmphost = strtok(optarg, ":");
|
||||
if ((portstr = strtok(NULL, ":")) == NULL) {
|
||||
cerr << "Bad host specification." << endl;
|
||||
usage();
|
||||
}
|
||||
tmpport = (unsigned short)atoi(portstr);
|
||||
config.addOtherHost(tmphost, tmpport);
|
||||
break;
|
||||
case 'p':
|
||||
config.priority = atoi(optarg);
|
||||
break;</tt></b>
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
// Error check command line.
|
||||
if ((!config.got_listen_address) || config.home == NULL)
|
||||
usage(); </pre>
|
||||
<p>
|
||||
Having done that, the remainder of our <tt class="function">main()</tt>
|
||||
function is left unchanged:
|
||||
</p>
|
||||
<pre class="programlisting"> RepMgr runner;
|
||||
try {
|
||||
if((ret = runner.init(&config)) != 0)
|
||||
goto err;
|
||||
if((ret = runner.doloop()) != 0)
|
||||
goto err;
|
||||
} catch (DbException dbe) {
|
||||
cerr << "Caught an exception during initialization or"
|
||||
<< " processing: " << dbe.what() << endl;
|
||||
}
|
||||
err:
|
||||
runner.terminate();
|
||||
return 0;
|
||||
} </pre>
|
||||
<p>
|
||||
Now we need to update our
|
||||
<tt class="methodname">RepMgr::init()</tt>
|
||||
|
||||
method. Our updates are at first related to configuring
|
||||
replication. First, we need to update the method so that we can
|
||||
identify the local site to the environment handle (that is, the site identified by the
|
||||
<tt class="literal">-m</tt> command line option):
|
||||
</p>
|
||||
<pre class="programlisting">RepMgr::RepMgr() : app_config(0), dbenv(0)
|
||||
{
|
||||
}
|
||||
|
||||
int RepMgr::init(RepConfigInfo *config)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
app_config = config;
|
||||
|
||||
dbenv.set_errfile(stderr);
|
||||
dbenv.set_errpfx(progname);
|
||||
|
||||
<b class="userinput"><tt>if ((ret = dbenv.repmgr_set_local_site(app_config->this_host.host,
|
||||
app_config->this_host.port, 0)) != 0) {
|
||||
cerr << "Could not set listen address to host:port "
|
||||
<< app_config->this_host.host << ":"
|
||||
<< app_config->this_host.port
|
||||
<< "error: " << ret << endl;
|
||||
}</tt></b> </pre>
|
||||
<p>
|
||||
And we also add code to allow us to identify "other" sites to the environment handle (that is,
|
||||
the sites that we identify using the <tt class="literal">-o</tt> command line
|
||||
option). To do this, we iterate over each of the "other" sites provided to
|
||||
us using the <tt class="literal">-o</tt> command line option, and we add each one
|
||||
individually in turn:
|
||||
</p>
|
||||
<pre class="programlisting"> <b class="userinput"><tt>for ( REP_HOST_INFO *cur = app_config->other_hosts; cur != NULL;
|
||||
cur = cur->next) {
|
||||
if ((ret = dbenv.repmgr_add_remote_site(cur->host, cur->port,
|
||||
NULL, 0)) != 0) {
|
||||
cerr << "could not add site." << endl
|
||||
}
|
||||
} </tt></b> </pre>
|
||||
<p>
|
||||
And then we need code to allow us to identify the total number of sites
|
||||
in this replication group, and to set the environment's priority.
|
||||
</p>
|
||||
<pre class="programlisting"> <b class="userinput"><tt>if (app_config->totalsites > 0) {
|
||||
try {
|
||||
if ((ret = dbenv.rep_set_nsites(app_config->totalsites)) != 0)
|
||||
dbenv.err(ret, "set_nsites");
|
||||
} catch (DbException dbe) {
|
||||
cerr << "rep_set_nsites call failed. Continuing." << endl;
|
||||
}
|
||||
}
|
||||
dbenv.rep_set_priority(app_config->priority); </tt></b> </pre>
|
||||
<p>
|
||||
|
||||
|
||||
<span>We can now open our environment. Note that 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"> dbenv.set_cachesize(0, CACHESIZE, 0);
|
||||
dbenv.set_flags(DB_TXN_NOSYNC, 1);
|
||||
|
||||
try {
|
||||
dbenv.open(app_config->home,
|
||||
DB_CREATE |
|
||||
DB_RECOVER |
|
||||
<b class="userinput"><tt>DB_THREAD |
|
||||
DB_INIT_REP |</tt></b>
|
||||
DB_INIT_LOCK |
|
||||
DB_INIT_LOG |
|
||||
DB_INIT_MPOOL |
|
||||
DB_INIT_TXN,
|
||||
0);
|
||||
} catch(DbException dbe) {
|
||||
cerr << "Caught an exception during DB environment open." << endl
|
||||
<< "Ensure that the home directory is created prior to starting"
|
||||
<< " the application." << endl;
|
||||
ret = ENOENT;
|
||||
goto err;
|
||||
}</pre>
|
||||
<p>
|
||||
Finally, we start replication before we exit this method.
|
||||
Immediately after exiting this method, our application will go into
|
||||
the
|
||||
<tt class="methodname">RepMgr::doloop()</tt>
|
||||
|
||||
method, which is where
|
||||
the bulk of our application's work is performed. We update that
|
||||
method in the next chapter.
|
||||
</p>
|
||||
<pre class="programlisting"> if ((ret = dbenv.repmgr_start(3, app_config->start_policy)) != 0)
|
||||
goto err;
|
||||
|
||||
err:
|
||||
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>
|
||||
628
docs/gsg_db_rep/CXX/simpleprogramlisting.html
Normal file
628
docs/gsg_db_rep/CXX/simpleprogramlisting.html
Normal file
@@ -0,0 +1,628 @@
|
||||
<?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>Program Listing</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="txnapp.html" title="Chapter 2. Transactional Application" />
|
||||
<link rel="previous" href="txnapp.html" title="Chapter 2. Transactional Application" />
|
||||
<link rel="next" href="repapp.html" title="Chapter 3. The DB Replication Framework" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Program Listing</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="txnapp.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 2. Transactional Application</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="repapp.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="simpleprogramlisting"></a>Program Listing</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Our example program is a fairly simple transactional
|
||||
application. At this early stage of its development, the
|
||||
application contains no hint that it must be network-aware
|
||||
so the only command line argument that it takes is one that
|
||||
allows us to specify the environment home directory.
|
||||
(Eventually, we will specify things like host names and
|
||||
ports from the command line).
|
||||
</p>
|
||||
<p>
|
||||
Note that the application performs all writes under the
|
||||
protection of a transaction; however, multiple database
|
||||
operations are not performed per transaction. Consequently,
|
||||
we simplify things a bit by using autocommit for our
|
||||
database writes.
|
||||
</p>
|
||||
<p>
|
||||
Also, this application is single-threaded. It is possible
|
||||
to write a multi-threaded or multi-process application that
|
||||
performs replication. That said, the concepts described in
|
||||
this book are applicable to both single threaded and
|
||||
multi-threaded applications so nothing
|
||||
is gained by multi-threading this application other than
|
||||
distracting complexity. This manual
|
||||
does, however, identify where care must be taken when
|
||||
performing replication with a non-single threaded
|
||||
application.
|
||||
</p>
|
||||
<p>
|
||||
Finally, remember that transaction processing is not described in
|
||||
this manual. Rather, see the
|
||||
<i class="citetitle">Berkeley DB Getting Started with Transaction Processing</i> guide for details on
|
||||
that topic.
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="repconfiginfo_cxx"></a>
|
||||
<span>Class: RepConfigInfo</span>
|
||||
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Before we begin, we present a
|
||||
class that we will use to maintain useful
|
||||
information for us. Under normal circumstances,
|
||||
this class would not be necessary for a simple
|
||||
transactional example such as this. However, this code will
|
||||
grow into a replicated example that needs to
|
||||
track a lot more information for the
|
||||
application, and so we lay the groundwork for
|
||||
it here.
|
||||
</p>
|
||||
<p>
|
||||
The class that we create is called
|
||||
<tt class="classname">RepConfigInfo</tt>
|
||||
|
||||
and its only purpose at this time is to track
|
||||
the location of our environment home directory.
|
||||
</p>
|
||||
<pre class="programlisting">#include <db_cxx.h>
|
||||
#include <iostream>
|
||||
|
||||
class RepConfigInfo {
|
||||
public:
|
||||
RepConfigInfo();
|
||||
virtual ~RepConfigInfo();
|
||||
|
||||
public:
|
||||
char* home;
|
||||
};
|
||||
|
||||
|
||||
RepConfigInfo::RepConfigInfo()
|
||||
{
|
||||
home = "TESTDIR";
|
||||
}
|
||||
|
||||
RepConfigInfo::~RepConfigInfo()
|
||||
{
|
||||
} </pre>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="repmgr_cxx"></a>Class: RepMgr</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Our transactional example will
|
||||
instantiate a class,
|
||||
<tt class="classname">RepMgr</tt>, that performs
|
||||
all our work for us. Before we implement our
|
||||
<tt class="function">main()</tt> function, we show
|
||||
the <tt class="classname">RepMgr</tt> class
|
||||
declaration.
|
||||
</p>
|
||||
<p>
|
||||
First, we provide some declarations and
|
||||
definitions that are needed later in
|
||||
our example:
|
||||
</p>
|
||||
<pre class="programlisting">using std::cout;
|
||||
using std::cin;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::flush;
|
||||
|
||||
#define CACHESIZE (10 * 1024 * 1024)
|
||||
#define DATABASE "quote.db"
|
||||
|
||||
const char *progname = "SimpleTxn"; </pre>
|
||||
<p>
|
||||
And then we define our <tt class="classname">RepMgr</tt> class:
|
||||
</p>
|
||||
<pre class="programlisting">class RepMgr
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
RepMgr();
|
||||
// Initialization method. Creates and opens our environment handle.
|
||||
int init(RepConfigInfo* config);
|
||||
// The doloop is where all the work is performed.
|
||||
int doloop();
|
||||
// terminate() provides our shutdown code.
|
||||
int terminate();
|
||||
|
||||
private:
|
||||
// disable copy constructor.
|
||||
RepMgr(const RepMgr &);
|
||||
void operator = (const RepMgr &);
|
||||
|
||||
// internal data members.
|
||||
RepConfigInfo *app_config;
|
||||
DbEnv dbenv;
|
||||
|
||||
// private methods.
|
||||
// print_stocks() is used to display the contents of our database.
|
||||
static int print_stocks(Db *dbp);
|
||||
}; </pre>
|
||||
<p>
|
||||
Note that we show the implementation of the various
|
||||
<tt class="classname">RepMgr</tt> methods later in this section.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="usage_cxx"></a>Function: usage()</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Our <tt class="function">usage()</tt> is at this
|
||||
stage of development trivial because we only
|
||||
have one command line argument to manage.
|
||||
Still, we show it here for the sake of
|
||||
completeness.
|
||||
</p>
|
||||
<pre class="programlisting">static void usage()
|
||||
{
|
||||
cerr << "usage: " << progname << endl
|
||||
<< "-h home" << endl;
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
} </pre>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="main_cxx"></a>Function: main()</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Now we provide our <tt class="function">main()</tt>
|
||||
function. This is a trivial function whose only
|
||||
job is to collect command line information,
|
||||
then instantiate a <tt class="classname">RepMgr</tt>
|
||||
object, run it, then terminate it.
|
||||
</p>
|
||||
<p>
|
||||
We begin by declaring some useful variables. Of
|
||||
these, note that we instantiate our
|
||||
<tt class="classname">RepConfigInfo</tt>
|
||||
object here. Recall that this is used to store
|
||||
information useful to our code. This class becomes more
|
||||
interesting later in this book.
|
||||
</p>
|
||||
<pre class="programlisting">int main(int argc, char **argv)
|
||||
{
|
||||
RepConfigInfo config;
|
||||
char ch;
|
||||
int ret; </pre>
|
||||
<p>
|
||||
Then we collect our command line information. Again, this is at
|
||||
this point fairly trivial:
|
||||
</p>
|
||||
<pre class="programlisting"> // Extract the command line parameters
|
||||
while ((ch = getopt(argc, argv, "h:")) != EOF) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
config.home = optarg;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
// Error check command line.
|
||||
if (config.home == NULL)
|
||||
usage(); </pre>
|
||||
<p>
|
||||
Now we instantiate and initialize our <tt class="classname">RepMgr</tt>
|
||||
class, which is what is responsible for doing all our real work.
|
||||
The <tt class="methodname">RepMgr::init()</tt> method creates and
|
||||
opens our environment handle.
|
||||
</p>
|
||||
<pre class="programlisting"> RepMgr runner;
|
||||
try {
|
||||
if((ret = runner.init(&config)) != 0)
|
||||
goto err; </pre>
|
||||
<p>
|
||||
Then we call the <tt class="methodname">RepMgr::doloop()</tt>
|
||||
method, which is where the actual transactional work is
|
||||
performed for this application.
|
||||
</p>
|
||||
<pre class="programlisting"> if((ret = runner.doloop()) != 0)
|
||||
goto err; </pre>
|
||||
<p>
|
||||
Finally, catch exceptions and terminate the program:
|
||||
</p>
|
||||
<pre class="programlisting"> } catch (DbException dbe) {
|
||||
cerr << "Caught an exception during initialization or"
|
||||
<< " processing: " << dbe.what() << endl;
|
||||
}
|
||||
err:
|
||||
runner.terminate();
|
||||
return 0;
|
||||
} </pre>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="repmgr_init_cxx"></a>Method: RepMgr::init()</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The <tt class="methodname">RepMgr::init()</tt>
|
||||
method is used to create and open our environment handle.
|
||||
For readers familiar with writing transactional
|
||||
DB applications, there should be no surprises
|
||||
here. However, we will be adding to this in later
|
||||
chapters as we roll replication into this example.
|
||||
</p>
|
||||
<p>
|
||||
First, we show the class constructor
|
||||
implementation, which is only used to initialize a
|
||||
few variables:
|
||||
</p>
|
||||
<pre class="programlisting">RepMgr::RepMgr() : app_config(0), dbenv(0)
|
||||
{
|
||||
} </pre>
|
||||
<p>
|
||||
We now provide the <tt class="methodname">init()</tt> method
|
||||
implementation. The only thing of interest here is that we specify
|
||||
<tt class="literal">DB_TXN_NOSYNC</tt> to our environment. This causes
|
||||
our transactional commits to become non-durable, which is something
|
||||
that we are doing only because of the nature of our example.
|
||||
</p>
|
||||
<pre class="programlisting">int RepMgr::init(RepConfigInfo *config)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
app_config = config;
|
||||
|
||||
dbenv.set_errfile(stderr);
|
||||
dbenv.set_errpfx(progname);
|
||||
|
||||
/*
|
||||
* We can now open our environment.
|
||||
*/
|
||||
dbenv.set_cachesize(0, CACHESIZE, 0);
|
||||
dbenv.set_flags(DB_TXN_NOSYNC, 1);
|
||||
|
||||
try {
|
||||
dbenv.open(app_config->home,
|
||||
DB_CREATE |
|
||||
DB_RECOVER |
|
||||
DB_INIT_LOCK |
|
||||
DB_INIT_LOG |
|
||||
DB_INIT_MPOOL |
|
||||
DB_INIT_TXN,
|
||||
0);
|
||||
} catch(DbException dbe) {
|
||||
cerr << "Caught an exception during DB environment open." << endl
|
||||
<< "Ensure that the home directory is created prior to starting"
|
||||
<< " the application." << endl;
|
||||
ret = ENOENT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
err:
|
||||
return ret;
|
||||
} </pre>
|
||||
<p>
|
||||
Finally, we present the <tt class="methodname">RepMgr::terminate()</tt>
|
||||
method here. All this does is close the environment handle. Again,
|
||||
there should be no surprises here, but we provide the
|
||||
implementation for the sake of completeness anyway.
|
||||
</p>
|
||||
<pre class="programlisting">int RepMgr::terminate()
|
||||
{
|
||||
try {
|
||||
dbenv.close(0);
|
||||
} catch (DbException dbe) {
|
||||
cerr << "error closing environment: " << dbe.what() << endl;
|
||||
}
|
||||
return 0;
|
||||
} </pre>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="doloop_cxx"></a>Method: RepMgr::doloop()</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Having written our <tt class="function">main()</tt>
|
||||
function and support utility methods, we now implement
|
||||
our application's
|
||||
primary data processing method. This
|
||||
method provides a command prompt at which the
|
||||
user can enter a stock ticker value and a price for
|
||||
that value. This information is then entered to the
|
||||
database.
|
||||
</p>
|
||||
<p>
|
||||
To display the database, simply enter
|
||||
<tt class="literal">return</tt> at the prompt.
|
||||
</p>
|
||||
<p>
|
||||
To begin, we declare a database pointer,
|
||||
several <tt class="classname">Dbt</tt> variables, and
|
||||
the usual assortment of variables used for buffers
|
||||
and return codes. We also initialize all of this.
|
||||
</p>
|
||||
<pre class="programlisting">#define BUFSIZE 1024
|
||||
int RepMgr::doloop()
|
||||
{
|
||||
Db *dbp;
|
||||
Dbt key, data;
|
||||
char buf[BUFSIZE], *rbuf;
|
||||
int ret;
|
||||
|
||||
dbp = NULL;
|
||||
memset(&key, 0, sizeof(key));
|
||||
memset(&data, 0, sizeof(data));
|
||||
ret = 0; </pre>
|
||||
<p>
|
||||
Next, we begin the loop and we immediately open our
|
||||
database if it has not already been opened. Notice that
|
||||
we specify autocommit when we open the database. In
|
||||
this case, autocommit is important because we will only
|
||||
ever write to our database using it. There is no need
|
||||
for explicit transaction handles and commit/abort code
|
||||
in this application, because we are not combining
|
||||
multiple database operations together under a single
|
||||
transaction.
|
||||
</p>
|
||||
<p>
|
||||
Autocommit is described in greater detail in the
|
||||
<i class="citetitle">Berkeley DB Getting Started with Transaction Processing</i> guide.
|
||||
</p>
|
||||
<pre class="programlisting"> for (;;) {
|
||||
if (dbp == NULL) {
|
||||
dbp = new Db(&dbenv, 0);
|
||||
|
||||
// Set page size small so page allocation is cheap.
|
||||
if ((ret = dbp->set_pagesize(512)) != 0)
|
||||
goto err;
|
||||
|
||||
try {
|
||||
dbp->open(NULL, DATABASE, NULL, DB_BTREE,
|
||||
DB_CREATE | DB_AUTO_COMMIT, 0);
|
||||
} catch(DbException dbe) {
|
||||
dbenv.err(ret, "DB->open");
|
||||
throw dbe;
|
||||
}
|
||||
} </pre>
|
||||
<p>
|
||||
Now we implement our command prompt. This is a simple and not
|
||||
very robust implementation of a command prompt.
|
||||
If the user enters the keywords <tt class="literal">exit</tt>
|
||||
or <tt class="literal">quit</tt>, the loop is exited and the
|
||||
application ends. If the user enters nothing and instead simply
|
||||
presses <tt class="literal">return</tt>, the entire contents of the
|
||||
database is displayed. We use our
|
||||
<tt class="function">print_stocks()</tt> method to display the
|
||||
database. (That implementation is shown next in this chapter.)
|
||||
</p>
|
||||
<p>
|
||||
Notice that very little error checking is performed on the data
|
||||
entered at this prompt. If the user fails to enter at least one
|
||||
space in the value string, a simple help message is printed and
|
||||
the prompt is returned to the user. That is the only error
|
||||
checking performed here. In a real-world application,
|
||||
at a minimum the application would probably check to ensure
|
||||
that the price was in fact an integer or float value.
|
||||
However, in order to keep this example code as simple as
|
||||
possible, we refrain from implementing a thorough user interface.
|
||||
</p>
|
||||
<pre class="programlisting"> cout << "QUOTESERVER" ;
|
||||
cout << "> " << flush;
|
||||
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL)
|
||||
break;
|
||||
if (strtok(&buf[0], " \t\n") == NULL) {
|
||||
switch ((ret = print_stocks(dbp))) {
|
||||
case 0:
|
||||
continue;
|
||||
default:
|
||||
dbp->err(ret, "Error traversing data");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
rbuf = strtok(NULL, " \t\n");
|
||||
if (rbuf == NULL || rbuf[0] == '\0') {
|
||||
if (strncmp(buf, "exit", 4) == 0 ||
|
||||
strncmp(buf, "quit", 4) == 0)
|
||||
break;
|
||||
dbenv.errx("Format: TICKER VALUE");
|
||||
continue;
|
||||
} </pre>
|
||||
<p>
|
||||
Now we assign data to the <tt class="classname">Dbt</tt>s that
|
||||
we will use to write the new information to the database.
|
||||
</p>
|
||||
<pre class="programlisting"> key.set_data(buf);
|
||||
key.set_size((u_int32_t)strlen(buf));
|
||||
|
||||
data.set_data(rbuf);
|
||||
data.set_size((u_int32_t)strlen(rbuf)); </pre>
|
||||
<p>
|
||||
Having done that, we can write the new information to the
|
||||
database. Remember that this application uses autocommit,
|
||||
so no explicit transaction management is required. Also,
|
||||
the database is not configured for duplicate records, so
|
||||
the data portion of a record is overwritten if the provided
|
||||
key already exists in the database. However, in this case
|
||||
DB returns <tt class="literal">DB_KEYEXIST</tt> — which
|
||||
we ignore.
|
||||
</p>
|
||||
<pre class="programlisting"> if ((ret = dbp->put(NULL, &key, &data, 0)) != 0)
|
||||
{
|
||||
dbp->err(ret, "DB->put");
|
||||
if (ret != DB_KEYEXIST)
|
||||
goto err;
|
||||
}
|
||||
} </pre>
|
||||
<p>
|
||||
Finally, we close our database before returning from the
|
||||
method.
|
||||
</p>
|
||||
<pre class="programlisting">err: if (dbp != NULL) {
|
||||
(void)dbp->close(DB_NOSYNC);
|
||||
cout << "database closed" << endl;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
} </pre>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="printstocks_c"></a>
|
||||
|
||||
<span>Method: RepMgr::print_stocks()</span>
|
||||
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The <tt class="function">print_stocks()</tt>
|
||||
|
||||
|
||||
<span>method</span>
|
||||
simply takes a database handle, opens a cursor, and uses
|
||||
it to display all the information it finds in a database.
|
||||
This is trivial cursor operation that should hold
|
||||
no surprises for you. We simply provide it here for
|
||||
the sake of completeness.
|
||||
</p>
|
||||
<p>
|
||||
If you are unfamiliar with basic cursor operations,
|
||||
please see the <i class="citetitle">Getting Started with Berkeley DB</i>
|
||||
guide.
|
||||
</p>
|
||||
<pre class="programlisting">int RepMgr::print_stocks(Db *dbp)
|
||||
{
|
||||
Dbc *dbc;
|
||||
Dbt key, data;
|
||||
#define MAXKEYSIZE 10
|
||||
#define MAXDATASIZE 20
|
||||
char keybuf[MAXKEYSIZE + 1], databuf[MAXDATASIZE + 1];
|
||||
int ret, t_ret;
|
||||
u_int32_t keysize, datasize;
|
||||
|
||||
if ((ret = dbp->cursor(NULL, &dbc, 0)) != 0) {
|
||||
dbp->err(ret, "can't open cursor");
|
||||
return (ret);
|
||||
}
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
cout << "\tSymbol\tPrice" << endl
|
||||
<< "\t======\t=====" << endl;
|
||||
|
||||
for (ret = dbc->get(&key, &data, DB_FIRST);
|
||||
ret == 0;
|
||||
ret = dbc->get(&key, &data, DB_NEXT)) {
|
||||
keysize = key.get_size() > MAXKEYSIZE ? MAXKEYSIZE : key.get_size();
|
||||
memcpy(keybuf, key.get_data(), keysize);
|
||||
keybuf[keysize] = '\0';
|
||||
|
||||
datasize = data.get_size() >=
|
||||
MAXDATASIZE ? MAXDATASIZE : data.get_size();
|
||||
memcpy(databuf, data.get_data(), datasize);
|
||||
databuf[datasize] = '\0';
|
||||
|
||||
cout << "\t" << keybuf << "\t" << databuf << endl;
|
||||
}
|
||||
cout << endl << flush;
|
||||
|
||||
if ((t_ret = dbc->close()) != 0 && ret == 0) {
|
||||
cout << "closed cursor" << endl;
|
||||
ret = t_ret;
|
||||
}
|
||||
|
||||
switch (ret) {
|
||||
case 0:
|
||||
case DB_NOTFOUND:
|
||||
return (0);
|
||||
default:
|
||||
return (ret);
|
||||
}
|
||||
} </pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="txnapp.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="txnapp.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="repapp.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Chapter 2. Transactional Application </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Chapter 3. The DB Replication Framework</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
187
docs/gsg_db_rep/CXX/txnapp.html
Normal file
187
docs/gsg_db_rep/CXX/txnapp.html
Normal file
@@ -0,0 +1,187 @@
|
||||
<?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>Chapter 2. Transactional Application</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="index.html" title="Getting Started with Replicated Berkeley DB Applications" />
|
||||
<link rel="previous" href="permmessages.html" title="Permanent Message Handling" />
|
||||
<link rel="next" href="simpleprogramlisting.html" title="Program Listing" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Chapter 2. Transactional Application</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="permmessages.html">Prev</a> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="simpleprogramlisting.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="chapter" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title"><a id="txnapp"></a>Chapter 2. Transactional Application</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txnapp.html#appoverview">Application Overview</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="simpleprogramlisting.html">Program Listing</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="simpleprogramlisting.html#repconfiginfo_cxx">
|
||||
Class: RepConfigInfo
|
||||
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="simpleprogramlisting.html#repmgr_cxx">Class: RepMgr</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="simpleprogramlisting.html#usage_cxx">Function: usage()</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="simpleprogramlisting.html#main_cxx">Function: main()</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="simpleprogramlisting.html#repmgr_init_cxx">Method: RepMgr::init()</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="simpleprogramlisting.html#doloop_cxx">Method: RepMgr::doloop()</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="simpleprogramlisting.html#printstocks_c">
|
||||
|
||||
Method: RepMgr::print_stocks()
|
||||
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
In this chapter, we build a simple transaction-protected DB
|
||||
application. Throughout the remainder of this book, we will add
|
||||
replication to this example. We do this to underscore the concepts
|
||||
that we are presenting in this book; the first being that you
|
||||
should start with a working transactional program and then add
|
||||
replication to it.
|
||||
</p>
|
||||
<p>
|
||||
Note that this book assumes you already know how to write a
|
||||
transaction-protected DB application, so we will not be
|
||||
covering those concepts in this book. To learn how to write a
|
||||
transaction-protected application, see the
|
||||
<i class="citetitle">Berkeley DB Getting Started with Transaction Processing</i> guide.
|
||||
</p>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="appoverview"></a>Application Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Our application maintains a stock market quotes database.
|
||||
This database contains records whose key is the stock
|
||||
market symbol and whose data is the stock's price.
|
||||
</p>
|
||||
<p>
|
||||
The application operates by presenting you with a command
|
||||
line prompt. You then enter the stock symbol and its value,
|
||||
separated by a space. The application takes this
|
||||
information, writes it to the database.
|
||||
</p>
|
||||
<p>
|
||||
To see the contents of the database, simply press
|
||||
<tt class="literal">return</tt> at the command prompt.
|
||||
</p>
|
||||
<p>
|
||||
To quit the application, type 'quit' or 'exit' at the
|
||||
command prompt.
|
||||
</p>
|
||||
<p>
|
||||
For example, the following illustrates the application's
|
||||
usage. In it, we use entirely fictitious stock market
|
||||
symbols and price values.
|
||||
</p>
|
||||
<pre class="programlisting">> ./SimpleTxn -h env_home_dir
|
||||
QUOTESERVER> stock1 88
|
||||
QUOTESERVER> stock2 .08
|
||||
QUOTESERVER>
|
||||
Symbol Price
|
||||
====== =====
|
||||
stock1 88
|
||||
|
||||
QUOTESERVER> stock1 88.9
|
||||
QUOTESERVER>
|
||||
Symbol Price
|
||||
====== =====
|
||||
stock1 88.9
|
||||
stock2 .08
|
||||
|
||||
QUOTESERVER> quit
|
||||
></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="permmessages.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="index.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="simpleprogramlisting.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Permanent Message Handling </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Program Listing</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user