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>Processing Loop</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="fwrkmasterreplica.html" title="Chapter 4. Replica versus Master Processes" /> 11 <link rel="prev" href="fwrkmasterreplica.html" title="Chapter 4. Replica versus Master Processes" /> 12 <link rel="next" href="exampledoloop.html" title="Example Processing Loop" /> 13 </head> 14 <body> 15 <div class="navheader"> 16 <table width="100%" summary="Navigation header"> 17 <tr> 18 <th colspan="3" align="center">Processing Loop</th> 19 </tr> 20 <tr> 21 <td width="20%" align="left"><a accesskey="p" href="fwrkmasterreplica.html">Prev</a> </td> 22 <th width="60%" align="center">Chapter 4. Replica versus Master Processes</th> 23 <td width="20%" align="right"> <a accesskey="n" href="exampledoloop.html">Next</a></td> 24 </tr> 25 </table> 26 <hr /> 27 </div> 28 <div class="sect1" lang="en" xml:lang="en"> 29 <div class="titlepage"> 30 <div> 31 <div> 32 <h2 class="title" style="clear: both"><a id="processingloop"></a>Processing Loop</h2> 33 </div> 34 </div> 35 </div> 36 <p> 37 Typically the central part of any replication application 38 is some sort of a continuous loop that constantly 39 checks the state of the environment (whether it is a 40 replica or a master), opens and/or closes the 41 databases as is necessary, and performs other useful 42 work. A loop such as this one must of necessity 43 take special care to know whether it is operating 44 on a master or a replica environment because all of its 45 activities are dependent upon that state. 46 </p> 47 <p> 48 The flow of activities through the loop will 49 generally be as follows: 50 </p> 51 <div class="orderedlist"> 52 <ol type="1"> 53 <li> 54 <p> 55 Check whether the environment has 56 changed state. If it has, you 57 might want to reopen your 58 database handles, especially if 59 you opened your replica's 60 database handles as read-only. 61 In this case, you might need to 62 reopen them as read-write. 63 However, if you always open your 64 database handles as read-write, 65 then it is not automatically necessary to 66 reopen the databases due to a 67 state change. Instead, you 68 could check for a 69 <span> 70 <code class="literal">DB_REP_HANDLE_DEAD</code> 71 return code 72 </span> 73 74 75 when you use your 76 database handle(s). If you see 77 this, then you need to reopen 78 your database handle(s). 79 </p> 80 </li> 81 <li> 82 <p> 83 If the databases are closed, 84 create new database handles, 85 configure the handle as is 86 appropriate, and then open the 87 databases. Note that handle 88 configuration will be different, 89 depending on whether the handle 90 is opened as a replica or a 91 master. At a minimum, the master 92 should be opened with database 93 creation privileges, whereas the 94 replica does not need to be. You 95 must also open the master such 96 that its databases are 97 read-write. You 98 <span class="emphasis"><em>can</em></span> open 99 replicas with read-only 100 databases, so long as you are 101 prepared to close and then reopen 102 the handle in the event the 103 client becomes a master. 104 </p> 105 <p> 106 Also, note that if the local 107 environment 108 is a replica, then it is possible 109 that databases do not currently 110 exist. In this case, the database 111 open attempts will fail. Your 112 code will have to take this 113 corner case into account 114 (described below). 115 </p> 116 </li> 117 <li> 118 <p> 119 Once the databases are opened, 120 check to see if the local 121 environment is a 122 master. If it is, do whatever it is 123 a master should do for your 124 application. 125 </p> 126 <p> 127 Remember that the code for your 128 master should include some way 129 for you to tell the master 130 to exit gracefully. 131 </p> 132 </li> 133 <li> 134 <p> 135 If the local environment is not a 136 master, then do whatever it is 137 your replica environments should do. 138 Again, like the code for your 139 master environments, you should provide 140 a way for your replicas to exit 141 the processing loop gracefully. 142 </p> 143 </li> 144 </ol> 145 </div> 146 <p> 147 The following code fragment illustrates 148 these points (note that we fill out this 149 fragment with a working example 150 next in this chapter): 151 </p> 152 <pre class="programlisting">/* loop to manage replication activities */ 153 154Db *dbp; 155int ret; 156APP_DATA *app_data; 157u_int32_t flags; 158 159dbp = NULL; 160ret = 0; 161 162/* 163 * Remember that for this to work, an APP_DATA struct would have first 164 * had to been set to the environment handle's app_private data 165 * member. (dbenv is presumably declared and opened in another part of 166 * the code.) 167 */ 168app_data = dbenv->get_app_private(); 169 170 171/* 172 * Infinite loop. We exit depending on how the master and replica code 173 * is written. 174 */ 175for (;;) { 176 /* If dbp is not opened, we need to open it. */ 177 if (dbp == 0) { 178 /* 179 * Create the handle and then configure it. Before you open 180 * it, you have to decide what open flags to use: 181 */ 182 dbp = new Db(&dbenv, 0); 183 184 /* 185 * Now you can open your database handle. 186 * 187 * One thing to watch out for is a case where the databases 188 * you are trying to open do not yet exist. This can happen 189 * for replicas where the databases are being opened 190 * read-only. If this happens, ENOENT is returned by the 191 * open() call. 192 */ 193 try { 194 dbp->open(NULL, DATABASE, NULL, DB_BTREE, 195 app_data->is_master ? DB_CREATE | DB_AUTO_COMMIT : 196 DB_AUTO_COMMIT, 0); 197 } catch(DbException dbe) { 198 if (dbe.get_errno() == ENOENT) { 199 cout << "No stock db available yet - retrying." << endl; 200 try { 201 dbp->close(0); 202 } catch (DbException dbe2) { 203 cout << "Unexpected error closing after failed" << 204 " open, message: " << dbe2.what() << endl; 205 dbp = NULL; 206 goto err; 207 } 208 dbp = NULL; 209 sleep(SLEEPTIME); 210 continue; 211 } else { 212 dbenv.err(ret, "DB->open"); 213 throw dbe; 214 } 215 } 216 } 217 218 /* 219 * Now that the databases have been opened, continue with general 220 * processing, depending on whether we are a master or a replica. 221 */ 222 if (app_data->is_master) { 223 /* 224 * Do master stuff here. Don't forget to include a way to 225 * gracefully exit the loop. */ 226 */ 227 } else { 228 /* 229 * Do replica stuff here. As is the case with the master 230 * code, be sure to include a way to gracefully exit the 231 * loop. 232 */ 233 } 234} </pre> 235 </div> 236 <div class="navfooter"> 237 <hr /> 238 <table width="100%" summary="Navigation footer"> 239 <tr> 240 <td width="40%" align="left"><a accesskey="p" href="fwrkmasterreplica.html">Prev</a> </td> 241 <td width="20%" align="center"> 242 <a accesskey="u" href="fwrkmasterreplica.html">Up</a> 243 </td> 244 <td width="40%" align="right"> <a accesskey="n" href="exampledoloop.html">Next</a></td> 245 </tr> 246 <tr> 247 <td width="40%" align="left" valign="top">Chapter 4. Replica versus Master Processes </td> 248 <td width="20%" align="center"> 249 <a accesskey="h" href="index.html">Home</a> 250 </td> 251 <td width="40%" align="right" valign="top"> Example Processing Loop</td> 252 </tr> 253 </table> 254 </div> 255 </body> 256</html> 257