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->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 == NULL) { 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 if ((ret = db_create(&dbp, dbenv, 0)) != 0) 183 return (ret); 184 185 flags = DB_AUTO_COMMIT; 186 if (app_data->is_master) 187 flags |= DB_CREATE 188 /* 189 * Now you can open your database handle, passing to it the 190 * flags selected above. 191 * 192 * One thing to watch out for is a case where the databases 193 * you are trying to open do not yet exist. This can happen 194 * for replicas where the databases are being opened 195 * read-only. If this happens, ENOENT is returned by the 196 * open() call. 197 */ 198 199 if (( ret = dbp->open(...)) != 0) { 200 if (ret == ENOENT) { 201 /* Close the database handle, then null it out, then 202 * sleep for some amount of time in order to give 203 * replication a chance to create the databases. 204 */ 205 dbp->close(dbp, 0); // Ignoring ret code. 206 // Not robust! 207 dbp = NULL; 208 sleep(SOME_SLEEPTIME); 209 continue; 210 } 211 /* 212 * Otherwise, some other error has happened and general 213 * error handling should be used. 214 */ 215 goto err; 216 } 217 } 218 219 /* 220 * Now that the databases have been opened, continue with general 221 * processing, depending on whether we are a master or a replica. 222 */ 223 if (app_data->is_master) { 224 /* 225 * Do master stuff here. Don't forget to include a way to 226 * gracefully exit the loop. */ 227 */ 228 } else { 229 /* 230 * Do replica stuff here. As is the case with the master 231 * code, be sure to include a way to gracefully exit the 232 * loop. 233 */ 234 } 235} </pre> 236 </div> 237 <div class="navfooter"> 238 <hr /> 239 <table width="100%" summary="Navigation footer"> 240 <tr> 241 <td width="40%" align="left"><a accesskey="p" href="fwrkmasterreplica.html">Prev</a> </td> 242 <td width="20%" align="center"> 243 <a accesskey="u" href="fwrkmasterreplica.html">Up</a> 244 </td> 245 <td width="40%" align="right"> <a accesskey="n" href="exampledoloop.html">Next</a></td> 246 </tr> 247 <tr> 248 <td width="40%" align="left" valign="top">Chapter 4. Replica versus Master Processes </td> 249 <td width="20%" align="center"> 250 <a accesskey="h" href="index.html">Home</a> 251 </td> 252 <td width="40%" align="right" valign="top"> Example Processing Loop</td> 253 </tr> 254 </table> 255 </div> 256 </body> 257</html> 258