~ubuntu-branches/ubuntu/maverick/evolution-data-server/maverick-proposed

« back to all changes in this revision

Viewing changes to libdb/docs/ref/rep/ex_rq.html

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2010-05-17 17:02:06 UTC
  • mfrom: (1.1.79 upstream) (1.6.12 experimental)
  • Revision ID: james.westby@ubuntu.com-20100517170206-4ufr52vwrhh26yh0
Tags: 2.30.1-1ubuntu1
* Merge from debian experimental. Remaining change:
  (LP: #42199, #229669, #173703, #360344, #508494)
  + debian/control:
    - add Vcs-Bzr tag
    - don't use libgnome
    - Use Breaks instead of Conflicts against evolution 2.25 and earlier.
  + debian/evolution-data-server.install,
    debian/patches/45_libcamel_providers_version.patch:
    - use the upstream versioning, not a Debian-specific one 
  + debian/libedata-book1.2-dev.install, debian/libebackend-1.2-dev.install,
    debian/libcamel1.2-dev.install, debian/libedataserverui1.2-dev.install:
    - install html documentation
  + debian/rules:
    - don't build documentation it's shipped with the tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<!--$Id$-->
2
 
<!--Copyright 1997-2002 by Sleepycat Software, Inc.-->
3
 
<!--All rights reserved.-->
4
 
<!--See the file LICENSE for redistribution information.-->
5
 
<html>
6
 
<head>
7
 
<title>Berkeley DB Reference Guide: Ex_repquote: putting it all together</title>
8
 
<meta name="description" content="Berkeley DB: An embedded database programmatic toolkit.">
9
 
<meta name="keywords" content="embedded,database,programmatic,toolkit,b+tree,btree,hash,hashing,transaction,transactions,locking,logging,access method,access methods,java,C,C++">
10
 
</head>
11
 
<body bgcolor=white>
12
 
<table width="100%"><tr valign=top>
13
 
<td><h3><dl><dt>Berkeley DB Reference Guide:<dd>Berkeley DB Replication</dl></h3></td>
14
 
<td align=right><a href="../../ref/rep/ex_comm.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../../reftoc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../../ref/xa/intro.html"><img src="../../images/next.gif" alt="Next"></a>
15
 
</td></tr></table>
16
 
<p>
17
 
<h1 align=center>Ex_repquote: putting it all together</h1>
18
 
<p>A replicated application must initialize a replicated environment, set
19
 
up its communication infrastructure, and then make sure that incoming
20
 
messages are received and processed.
21
 
<p>To initialize replication, ex_repquote creates a Berkeley DB environment and
22
 
calls <a href="../../api_c/rep_transport.html">DB_ENV-&gt;set_rep_transport</a> to establish a send function.  The following
23
 
code fragment (from the env_init function, found in
24
 
<b>ex_repquote/ex_rq_main.c</b>) demonstrates this.  Prior to calling
25
 
this function, the application has called machtab_init to initialize
26
 
its environment ID to port mapping structure and passed this structure
27
 
into env_init.
28
 
<pre><p><blockquote>if ((ret = db_env_create(&dbenv, 0)) != 0) {
29
 
        fprintf(stderr, "%s: env create failed: %s\n",
30
 
            progname, db_strerror(ret));
31
 
        return (ret);
32
 
}
33
 
dbenv-&gt;set_errfile(dbenv, stderr);
34
 
dbenv-&gt;set_errpfx(dbenv, prefix);
35
 
(void)dbenv-&gt;set_cachesize(dbenv, 0, CACHESIZE, 0);
36
 
<p>
37
 
dbenv-&gt;app_private = machtab;
38
 
(void)dbenv-&gt;set_rep_transport(dbenv, SELF_EID, quote_send);
39
 
<p>
40
 
flags = DB_CREATE | DB_THREAD |
41
 
    DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN;
42
 
<p>
43
 
ret = dbenv-&gt;open(dbenv, home, flags, 0);</blockquote></pre>
44
 
<p>ex_repquote opens a listening socket for incoming connections and opens
45
 
an outgoing connection to every machine that it knows about (that is,
46
 
all the sites listed in the <b>-o</b> command line argument).
47
 
Applications can structure the details of this in different ways, but
48
 
ex_repquote creates a user-level thread to listen on its socket, plus
49
 
a thread to loop and handle messages on each socket, in addition to the
50
 
threads needed to manage the user interface, update the database on the
51
 
master, and read from the database on the client (in other words, in
52
 
addition to the normal functionality of any database application).
53
 
<p>Once the initial threads have all been started and the communications
54
 
infrastructure is initialized, the application signals that it is ready
55
 
for replication and joins a replication group by calling
56
 
<a href="../../api_c/rep_start.html">DB_ENV-&gt;rep_start</a>:
57
 
<pre><p><blockquote>if (whoami == MASTER) {
58
 
        if ((ret = dbenv-&gt;rep_start(dbenv, NULL, DB_REP_MASTER)) != 0) {
59
 
                /* Complain and exit on error. */
60
 
        }
61
 
        /* Go run the master application code. */
62
 
} else {
63
 
        memset(&local, 0, sizeof(local));
64
 
        local.data = myaddr;
65
 
        local.size = strlen(myaddr) + 1;
66
 
        if ((ret =
67
 
            dbenv-&gt;rep_start(dbenv, &local, DB_REP_CLIENT)) != 0) {
68
 
                /* Complain and exit on error. */
69
 
        }
70
 
        /* Sleep to give ourselves a minute to find a master. */
71
 
        sleep(5);
72
 
        /* Go run the client application code. */
73
 
}</blockquote></pre>
74
 
<p>Note the use of the optional second argument to <a href="../../api_c/rep_start.html">DB_ENV-&gt;rep_start</a> in
75
 
the client initialization code.  The argument "myaddr" is a piece of
76
 
data, opaque to Berkeley DB, that will be broadcast to each member of a
77
 
replication group; it allows new clients to join a replication group,
78
 
without knowing the location of all its members;  the new client will
79
 
be contacted by the members it does not know about, who will receive
80
 
the new client's contact information that was specified in "myaddr."
81
 
See <a href="../../ref/rep/newsite.html">Connecting to a new site</a> for more
82
 
information.
83
 
<p>The final piece of a replicated application is the code that loops,
84
 
receives, and processes messages from a given remote environment.
85
 
ex_repquote runs one of these loops in a parallel thread for each socket
86
 
connection; other applications may want to queue messages somehow and
87
 
process them asynchronously, or select() on a number of sockets and
88
 
either look up the correct environment ID for each or encapsulate the
89
 
ID in the communications protocol.  The details may thus vary from
90
 
application to application, but in ex_repquote the message-handling loop
91
 
is as follows (code fragment from the hm_loop function, found in
92
 
<b>ex_repquote/ex_rq_util.c</b>):
93
 
<pre><p><blockquote>DB_ENV *dbenv;
94
 
DBT rec, control;       /* Structures encapsulating a received message. */
95
 
elect_args *ea;         /* Parameters to the elect thread. */
96
 
machtab_t *tab;         /* The environment ID to fd mapping table. */
97
 
pthread_t elect_thr;    /* Election thread spawned. */
98
 
repsite_t self;         /* My host and port identification. */
99
 
int eid;                /* Environment from whom I am receiving messages. */
100
 
int fd;                 /* FD on which I am receiving messages. */
101
 
int master_eid;         /* Global indicating the current master eid. */
102
 
int n;                  /* Number of sites; obtained from machtab_parm. */
103
 
int newm;               /* New master EID. */
104
 
int open;               /* Boolean indicating if connection already exists. */
105
 
int pri;                /* My priority. */
106
 
int r, ret;             /* Return values. */
107
 
int timeout;            /* My election timeout value. */
108
 
int tmpid;              /* Used to call dbenv-&gt;rep_process_message. */
109
 
char *c;                /* Temp used in parsing host:port names. */
110
 
char *myaddr;           /* My host/port address. */
111
 
char *progname;         /* Program name for error messages. */
112
 
void *status;           /* Pthread return status. */
113
 
for (ret = 0; ret == 0;) {
114
 
        if ((ret = get_next_message(fd, &rec, &control)) != 0) {
115
 
                /*
116
 
                 * There was some sort of network error;  close this
117
 
                 * connection and remove it from the table of
118
 
                 * environment IDs.
119
 
                 */
120
 
                close(fd);
121
 
                if ((ret = machtab_rem(tab, eid, 1)) != 0)
122
 
                        break;
123
 
<p>
124
 
                /*
125
 
                 * If I'm the master, I just lost a client and this
126
 
                 * thread is done.
127
 
                 */
128
 
                if (master_eid == SELF_EID)
129
 
                        break;
130
 
<p>
131
 
                /*
132
 
                 * If I was talking with the master and the master
133
 
                 * went away, I need to call an election; else I'm
134
 
                 * done.
135
 
                 */
136
 
                if (master_eid != eid)
137
 
                        break;
138
 
<p>
139
 
                master_eid = DB_EID_INVALID;
140
 
                /*
141
 
                 * In ex_repquote, the environment ID table stores
142
 
                 * election parameters.
143
 
                 */
144
 
                machtab_parm(tab, &n, &pri, &timeout);
145
 
                if ((ret = dbenv-&gt;rep_elect(dbenv,
146
 
                    n, pri, timeout, &newm)) != 0)
147
 
                        continue;
148
 
<p>
149
 
                /*
150
 
                 * If I won the election, become the master.
151
 
                 * Otherwise, just exit.
152
 
                 */
153
 
                if (newm == SELF_EID && (ret =
154
 
                    dbenv-&gt;rep_start(dbenv, NULL, DB_REP_MASTER)) == 0)
155
 
                        ret = domaster(dbenv, progname);
156
 
                break;
157
 
        }
158
 
<p>
159
 
        /* If we get here, we have a message to process. */
160
 
<p>
161
 
        tmpid = eid;
162
 
        switch(r = dbenv-&gt;rep_process_message(dbenv,
163
 
            &control, &rec, &tmpid)) {
164
 
        case DB_REP_NEWSITE:
165
 
                /*
166
 
                 * Check if we got sent connect information and if we
167
 
                 * did, if this is me or if we already have a
168
 
                 * connection to this new site.  If we don't,
169
 
                 * establish a new one.
170
 
                 */
171
 
<p>
172
 
                /* No connect info. */
173
 
                if (rec.size == 0)
174
 
                        break;
175
 
<p>
176
 
                /* It's me, do nothing. */
177
 
                if (strncmp(myaddr, rec.data, rec.size) == 0)
178
 
                        break;
179
 
<p>
180
 
                self.host = (char *)rec.data;
181
 
                self.host = strtok(self.host, ":");
182
 
                if ((c = strtok(NULL, ":")) == NULL) {
183
 
                        dbenv-&gt;errx(dbenv, "Bad host specification");
184
 
                        goto err;
185
 
                }
186
 
                self.port = atoi(c);
187
 
<p>
188
 
                /*
189
 
                 * We try to connect to the new site.  If we can't,
190
 
                 * we treat it as an error since we know that the site
191
 
                 * should be up if we got a message from it (even
192
 
                 * indirectly).
193
 
                 */
194
 
                if ((ret = connect_site(dbenv,
195
 
                    tab, progname, &self, &open, &eid)) != 0)
196
 
                        goto err;
197
 
                break;
198
 
        case DB_REP_HOLDELECTION:
199
 
                if (master_eid == SELF_EID)
200
 
                        break;
201
 
                /* Make sure that previous election has finished. */
202
 
                if (ea != NULL) {
203
 
                        (void)pthread_join(elect_thr, &status);
204
 
                        ea = NULL;
205
 
                }
206
 
                if ((ea = calloc(sizeof(elect_args), 1)) == NULL) {
207
 
                        ret = errno;
208
 
                        goto err;
209
 
                }
210
 
                ea-&gt;dbenv = dbenv;
211
 
                ea-&gt;machtab = tab;
212
 
                ret = pthread_create(&elect_thr,
213
 
                    NULL, elect_thread, (void *)ea);
214
 
                break;
215
 
        case DB_REP_NEWMASTER:
216
 
                /* Check if it's us. */
217
 
                master_eid = tmpid;
218
 
                if (tmpid == SELF_EID) {
219
 
                        if ((ret = dbenv-&gt;rep_start(dbenv,
220
 
                            NULL, DB_REP_MASTER)) != 0)
221
 
                                goto err;
222
 
                        ret = domaster(dbenv, progname);
223
 
                }
224
 
                break;
225
 
        case 0:
226
 
                break;
227
 
        default:
228
 
                dbenv-&gt;err(dbenv, r, "DBENV-&gt;rep_process_message");
229
 
                break;
230
 
        }
231
 
}</blockquote></pre>
232
 
<table width="100%"><tr><td><br></td><td align=right><a href="../../ref/rep/ex_comm.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../../reftoc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../../ref/xa/intro.html"><img src="../../images/next.gif" alt="Next"></a>
233
 
</td></tr></table>
234
 
<p><font size=1><a href="http://www.sleepycat.com">Copyright Sleepycat Software</a></font>
235
 
</body>
236
 
</html>