1<?xml version="1.0" encoding="UTF-8" standalone="no"?> 2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3<html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 6 <title>Adding the Replication Manager to ex_rep_gsg_simple</title> 7 <link rel="stylesheet" href="gettingStarted.css" type="text/css" /> 8 <meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /> 9 <link rel="start" href="index.html" title="Getting Started with Replicated Berkeley DB Applications" /> 10 <link rel="up" href="repapp.html" title="Chapter 3. The DB Replication Manager" /> 11 <link rel="prev" href="repapp.html" title="Chapter 3. The DB Replication Manager" /> 12 <link rel="next" href="fwrkpermmessage.html" title="Permanent Message Handling" /> 13 </head> 14 <body> 15 <div class="navheader"> 16 <table width="100%" summary="Navigation header"> 17 <tr> 18 <th colspan="3" align="center">Adding the Replication Manager to 19 <span>ex_rep_gsg_simple</span> 20 21 22 </th> 23 </tr> 24 <tr> 25 <td width="20%" align="left"><a accesskey="p" href="repapp.html">Prev</a> </td> 26 <th width="60%" align="center">Chapter 3. The DB Replication Manager</th> 27 <td width="20%" align="right"> <a accesskey="n" href="fwrkpermmessage.html">Next</a></td> 28 </tr> 29 </table> 30 <hr /> 31 </div> 32 <div class="sect1" lang="en" xml:lang="en"> 33 <div class="titlepage"> 34 <div> 35 <div> 36 <h2 class="title" style="clear: both"><a id="repmgr_init_example_c"></a>Adding the Replication Manager to 37 <span>ex_rep_gsg_simple</span> 38 39 40 </h2> 41 </div> 42 </div> 43 </div> 44 <p> 45 We now use the methods described above to add partial 46 support to the 47 <span>ex_rep_gsg_simple</span> 48 49 50 example that we presented in 51 <a class="xref" href="txnapp.html" title="Chapter 2. Transactional Application">Transactional Application</a>. 52 That is, in this section we will: 53 </p> 54 <div class="itemizedlist"> 55 <ul type="disc"> 56 <li> 57 <p> 58 Enhance our command line options to 59 accept information of interest to a 60 replicated application. 61 </p> 62 </li> 63 <li> 64 <p> 65 Configure our environment handle to use 66 replication and the Replication Manager. 67 </p> 68 </li> 69 <li> 70 <p> 71 Minimally configure the Replication Manager. 72 </p> 73 </li> 74 <li> 75 <p> 76 Start replication. 77 </p> 78 </li> 79 </ul> 80 </div> 81 <p> 82 Note that when we are done with this section, we will be 83 only partially ready to run the application. Some critical 84 pieces will be missing; specifically, we will not yet be 85 handling the differences between a master and a 86 replica. (We do that in the next chapter). 87 </p> 88 <p> 89 Also, note that in the following code fragments, additions 90 and changes to the code are marked in <strong class="userinput"><code>bold</code></strong>. 91 </p> 92 <p> 93 To begin, we copy the 94 <span>ex_rep_gsg_simple</span> 95 96 code to a new file called 97 <code class="literal">ex_rep_gsg_repmgr.c</code>. 98 99 <span> 100 We then make the corresponding change to the program name. 101 </span> 102 103 104 </p> 105 <pre class="programlisting">/* 106 <strong class="userinput"><code>* File: ex_rep_gsg_repmgr.c</code></strong> 107 */ 108 109#include <stdlib.h> 110#include <string.h> 111#ifndef _WIN32 112#include <unistd.h> 113#endif 114 115#include <db.h> 116 117#ifdef _WIN32 118extern int getopt(int, char * const *, const char *); 119#endif 120 121#define CACHESIZE (10 * 1024 * 1024) 122#define DATABASE "quote.db" 123 124const char *progname = <strong class="userinput"><code>"ex_rep_gsg_repmgr";</code></strong> 125 126int create_env(const char *, DB_ENV **); 127int env_init(DB_ENV *, const char *); 128int doloop (DB_ENV *); 129int print_stocks(DBC *); </pre> 130 <p> 131 Next we update our usage function. The application will continue to 132 accept the <code class="literal">-h</code> parameter so that we can identify 133 the environment home directory used by this application. However, 134 we also add the 135</p> 136 <div class="itemizedlist"> 137 <ul type="disc"> 138 <li> 139 <p> 140 <code class="literal">-l</code> parameter which allows us to 141 identify the host and port used by this application to 142 listen for replication messages. 143 </p> 144 </li> 145 <li> 146 <p> 147 <code class="literal">-r</code> parameter which allows us to 148 specify other replicas. 149 </p> 150 </li> 151 <li> 152 <p> 153 <code class="literal">-n</code> parameter which allows us to 154 identify the number of sites in this replication 155 group. 156 </p> 157 </li> 158 <li> 159 <p> 160 <code class="literal">-p</code> option, which is used to identify 161 this replica's priority (recall that the priority is 162 used as a tie breaker for elections) 163 </p> 164 </li> 165 </ul> 166 </div> 167 <pre class="programlisting">/* Usage function */ 168static void 169usage() 170{ 171 fprintf(stderr, "usage: %s ", progname); 172 fprintf(stderr, "-h home <strong class="userinput"><code>-l host:port -n nsites</code></strong>\n"); 173 <strong class="userinput"><code>fprintf(stderr, "\t\t[-r host:port][-p priority]\n"); 174 fprintf(stderr, "where:\n"); 175 fprintf(stderr, "\t-h identifies the environment home directory "); 176 fprintf(stderr, "(required).\n"); 177 fprintf(stderr, "\t-l identifies the host and port used by this "); 178 fprintf(stderr, "site (required).\n"); 179 fprintf(stderr, "\t-n identifies the number of sites in this "); 180 fprintf(stderr, "replication group (required).\n"); 181 fprintf(stderr, "\t-r identifies another site participating in "); 182 fprintf(stderr, "this replication group\n"); 183 fprintf(stderr, "\t-p identifies the election priority used by "); 184 fprintf(stderr, "this replica.\n");</code></strong> 185 exit(EXIT_FAILURE); 186} </pre> 187 <p> 188 Now we can begin working on our <code class="literal">main()</code> function. 189 We begin by adding a couple of variables that we will use to 190 collect TCP/IP host and port information. 191 192 193 <span> 194 We also declare a couple 195 of flags that we use to make sure some required information is 196 provided to this application. 197 </span> 198</p> 199 <pre class="programlisting">int 200main(int argc, char *argv[]) 201{ 202 extern char *optarg; 203 DB_ENV *dbenv; 204 const char *home; 205 char ch, <strong class="userinput"><code>*host, *portstr</code></strong>; 206 int ret, <strong class="userinput"><code>local_is_set, totalsites</code></strong>; 207 <strong class="userinput"><code>u_int32_t port</code></strong>; 208 209 dbenv = NULL; 210 211 ret = <strong class="userinput"><code>local_is_set = totalsites = </code></strong>0; 212 home = NULL; </pre> 213 <p> 214 At this time we can create our environment handle and configure it 215 exactly as we did for <code class="literal">simple_txn</code>. 216 The only thing that we will do differently here is that we will set a priority, 217 arbitrarily picked to be 100, so that we can be sure the environment has 218 a priority other than 0 (the default value). This ensures that the 219 environment can become a master via an election. 220</p> 221 <pre class="programlisting"> if ((ret = create_env(progname, &dbenv)) != 0) 222 goto err; 223 224 /* Default priority is 100 */ 225 <strong class="userinput"><code>dbenv->rep_set_priority(dbenv, 100);</code></strong> </pre> 226 <p> 227 Now we collect our command line arguments. As we do so, we will 228 configure host and port information as required, and we will 229 configure the application's election priority if necessary. 230</p> 231 <pre class="programlisting"> /* Collect the command line options */ 232 while ((ch = getopt(argc, argv, "h:<strong class="userinput"><code>l:n:p:r:</code></strong>")) != EOF) 233 switch (ch) { 234 case 'h': 235 home = optarg; 236 break; 237 <strong class="userinput"><code>/* Set the host and port used by this environment */ 238 case 'l': 239 host = strtok(optarg, ":"); 240 if ((portstr = strtok(NULL, ":")) == NULL) { 241 fprintf(stderr, "Bad host specification.\n"); 242 goto err; 243 } 244 port = (unsigned short)atoi(portstr); 245 if (dbenv->repmgr_set_local_site(dbenv, host, port, 0) 246 != 0) { 247 fprintf(stderr, 248 "Could not set local address %s.\n", host); 249 goto err; 250 } 251 local_is_set = 1; 252 break; 253 /* Set the number of sites in this replication group */ 254 case 'n': 255 totalsites = atoi(optarg); 256 if ((ret = dbenv->rep_set_nsites(dbenv, totalsites)) 257 != 0) 258 dbenv->err(dbenv, ret, "set_nsites"); 259 break; 260 /* Set this replica's election priority */ 261 case 'p': 262 dbenv->rep_set_priority(dbenv, atoi(optarg)); 263 break; 264 /* Identify another site in the replication group */ 265 case 'r': 266 host = strtok(optarg, ":"); 267 if ((portstr = strtok(NULL, ":")) == NULL) { 268 fprintf(stderr, "Bad host specification.\n"); 269 goto err; 270 } 271 port = (unsigned short)atoi(portstr); 272 if (dbenv->repmgr_add_remote_site(dbenv, host, port, 273 NULL, 0) != 0) { 274 fprintf(stderr, 275 "Could not add site %s.\n", host); 276 goto err; 277 } 278 break;</code></strong> 279 case '?': 280 default: 281 usage(); 282 } 283 284 /* Error check command line. */ 285 if (home == NULL <strong class="userinput"><code>|| !local_is_set || !totalsites</code></strong>) 286 usage(); </pre> 287 <p> 288 Having done that, we can call <code class="function">env_init()</code>, which we use to 289 open our environment handle. Note that this function changes 290 slightly for this update (see below). 291 </p> 292 <pre class="programlisting"> if ((ret = env_init(dbenv, home)) != 0) 293 goto err; </pre> 294 <p> 295 Finally, we start replication before we go into the 296 <code class="function">doloop()</code> function (where we perform all our 297 database access). 298</p> 299 <pre class="programlisting"> 300 <strong class="userinput"><code>if ((ret = dbenv->repmgr_start(dbenv, 3, DB_REP_ELECTION)) != 0) 301 goto err; </code></strong> 302 303 if ((ret = doloop(dbenv)) != 0) { 304 dbenv->err(dbenv, ret, "Application failed"); 305 goto err; 306 } 307 308err: if (dbenv != NULL) 309 (void)dbenv->close(dbenv, 0); 310 311 return (ret); 312} </pre> 313 <p> 314 <span>Beyond that, the rest of our application remains the same for 315 now, with the exception of the <code class="function">env_init()</code> 316 function, which we use to actually open our environment handle. 317 The flags </span> 318 319 320 321 322 323 we use to open the environment are slightly different for a 324 replicated application than they are for a non-replicated 325 application. Namely, replication requires the 326 <span> 327 <code class="literal">DB_INIT_REP</code> flag. 328 </span> 329 330 331 </p> 332 <p> 333 Also, because we are using the Replication Manager, we must prepare 334 our environment for threaded usage. For this reason, we also 335 need the <code class="literal">DB_THREAD</code> flag. 336 </p> 337 <pre class="programlisting">int 338env_init(DB_ENV *dbenv, const char *home) 339{ 340 u_int32_t flags; 341 int ret; 342 343 (void)dbenv->set_cachesize(dbenv, 0, CACHESIZE, 0); 344 (void)dbenv->set_flags(dbenv, DB_TXN_NOSYNC, 1); 345 346 flags = DB_CREATE | 347 DB_INIT_LOCK | 348 DB_INIT_LOG | 349 DB_INIT_MPOOL | 350 <strong class="userinput"><code>DB_INIT_REP |</code></strong> 351 DB_INIT_TXN | 352 DB_RECOVER <strong class="userinput"><code>| 353 DB_THREAD;</code></strong> 354 if ((ret = dbenv->open(dbenv, home, flags, 0)) != 0) 355 dbenv->err(dbenv, ret, "can't open environment"); 356 return (ret); 357}</pre> 358 <p> 359 This completes our replication updates for the moment. We are not as 360 yet ready to actually run this program; there remains a few 361 critical pieces left to add to it. However, the work that we 362 performed in this section represents a solid foundation for the 363 remainder of our replication work. 364 </p> 365 </div> 366 <div class="navfooter"> 367 <hr /> 368 <table width="100%" summary="Navigation footer"> 369 <tr> 370 <td width="40%" align="left"><a accesskey="p" href="repapp.html">Prev</a> </td> 371 <td width="20%" align="center"> 372 <a accesskey="u" href="repapp.html">Up</a> 373 </td> 374 <td width="40%" align="right"> <a accesskey="n" href="fwrkpermmessage.html">Next</a></td> 375 </tr> 376 <tr> 377 <td width="40%" align="left" valign="top">Chapter 3. The DB Replication Manager </td> 378 <td width="20%" align="center"> 379 <a accesskey="h" href="index.html">Home</a> 380 </td> 381 <td width="40%" align="right" valign="top"> Permanent Message Handling</td> 382 </tr> 383 </table> 384 </div> 385 </body> 386</html> 387