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