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>Chapter 4. Replica versus Master Processes</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="index.html" title="Getting Started with Replicated Berkeley DB Applications" /> 11 <link rel="prev" href="heartbeats.html" title="Managing Heartbeats" /> 12 <link rel="next" href="processingloop.html" title="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">Chapter 4. Replica versus Master Processes</th> 19 </tr> 20 <tr> 21 <td width="20%" align="left"><a accesskey="p" href="heartbeats.html">Prev</a> </td> 22 <th width="60%" align="center"> </th> 23 <td width="20%" align="right"> <a accesskey="n" href="processingloop.html">Next</a></td> 24 </tr> 25 </table> 26 <hr /> 27 </div> 28 <div class="chapter" lang="en" xml:lang="en"> 29 <div class="titlepage"> 30 <div> 31 <div> 32 <h2 class="title"><a id="fwrkmasterreplica"></a>Chapter 4. Replica versus Master Processes</h2> 33 </div> 34 </div> 35 </div> 36 <div class="toc"> 37 <p> 38 <b>Table of Contents</b> 39 </p> 40 <dl> 41 <dt> 42 <span class="sect1"> 43 <a href="fwrkmasterreplica.html#determinestate">Determining State</a> 44 </span> 45 </dt> 46 <dt> 47 <span class="sect1"> 48 <a href="processingloop.html">Processing Loop</a> 49 </span> 50 </dt> 51 <dt> 52 <span class="sect1"> 53 <a href="exampledoloop.html">Example Processing Loop</a> 54 </span> 55 </dt> 56 <dd> 57 <dl> 58 <dt> 59 <span class="sect2"> 60 <a href="exampledoloop.html#runningit">Running It</a> 61 </span> 62 </dt> 63 </dl> 64 </dd> 65 </dl> 66 </div> 67 <p> 68 Every environment participating in a replicated application 69 must know whether it is a <span class="emphasis"><em>master</em></span> or 70 <span class="emphasis"><em>replica</em></span>. The reason for this is 71 because, simply, the master can modify the database while 72 replicas cannot. As a result, not only will you open 73 databases differently depended on whether the environment is 74 running as a master, but the environment will frequently 75 behave quite a bit differently depending on whether it 76 thinks it is operating as the read/write interface for 77 your database. 78 </p> 79 <p> 80 Moreover, an environment must also be capable of 81 gracefully switching between master and replica states. 82 This means that the environment must be able to detect when 83 it has switched states. 84 </p> 85 <p> 86 Not surprisingly, a large part of your application's code 87 will be tied up in knowing which state a given 88 environment is in and then in the logic of how to behave depending on 89 its state. 90 </p> 91 <p> 92 This chapter shows you how to determine your environment's 93 state, and it then shows you some sample code on how 94 an application might behave depending on whether it is a 95 master or a replica in a replicated application. 96 </p> 97 <div class="sect1" lang="en" xml:lang="en"> 98 <div class="titlepage"> 99 <div> 100 <div> 101 <h2 class="title" style="clear: both"><a id="determinestate"></a>Determining State</h2> 102 </div> 103 </div> 104 </div> 105 <p> 106 In order to determine whether your code is 107 running as a master or a replica, you implement a 108 callback whose function it is to respond to 109 events that happen within the DB library. 110 Note that these events are raised whenever the state is established. 111 For example, when the current environment becomes a client — 112 including at application startup — the 113 <code class="literal">DB_EVENT_REP_CLIENT</code> event is raised. Also, when an 114 election is held and a replica is elected to be a master, the 115 <code class="literal">DB_EVENT_REP_MASTER</code> event is raised on the newly elected master and the 116 <code class="literal">DB_EVENT_REP_NEWMASTER</code> is raised on the other replicas. 117 </p> 118 <p> 119 Note that this callback is usable for events beyond 120 those required for replication purposes. In this 121 section, however, we only discuss the 122 replication-specific events. 123 </p> 124 <p> 125 The callback is required to determine 126 which event has been passed to it, and then take 127 action depending on the event. For replication, 128 the events that we care about are: 129 </p> 130 <div class="itemizedlist"> 131 <ul type="disc"> 132 <li> 133 <p> 134 <code class="literal">DB_EVENT_REP_MASTER</code> 135 136 </p> 137 <p> 138 The local environment is now a master. 139 </p> 140 </li> 141 <li> 142 <p> 143 <code class="literal">DB_EVENT_REP_CLIENT</code> 144 145 </p> 146 <p> 147 The local environment is now a replica. 148 </p> 149 </li> 150 <li> 151 <p> 152 <code class="literal">DB_EVENT_REP_STARTUPDONE</code> 153 154 </p> 155 <p> 156 The replica has completed startup 157 synchronization and is now 158 processing log records received 159 from the master. 160 </p> 161 </li> 162 <li> 163 <p> 164 <code class="literal">DB_EVENT_REP_NEWMASTER</code> 165 166 </p> 167 <p> 168 An election was held and a new environment was made a 169 master. However, the current environment <span class="emphasis"><em>is 170 not</em></span> the master. This event exists so that 171 you can cause your code to take some unique action in the 172 event that the replication groups switches masters. 173 </p> 174 </li> 175 </ul> 176 </div> 177 <p> 178 Note that these events are raised whenever the 179 state is established. That is, when the current 180 environment becomes a replica, and that includes 181 at application startup, the event is raised. 182 Also, when an election is held and a replica is elected to be a 183 master, then the event occurs. 184 </p> 185 <p> 186 The implementation of this callback is fairly 187 simple. First you pass a structure to the 188 environment handle that you can use to record the 189 environment's state, and then you implement a switch 190 statement within the callback that you use to 191 record the current state, depending on the 192 arriving event. 193 </p> 194 <p> 195 For example: 196 </p> 197 <pre class="programlisting">#include <db.h> 198/* Forward declaration */ 199void *event_callback(DB_ENV *, u_int32_t, void *); 200 201... 202 203/* The structure we use to track our environment's state */ 204typedef struct { 205 int is_master; 206} APP_DATA; 207 208... 209 210/* 211 * Inside our main() function, we declare an APP_DATA variable. 212 */ 213APP_DATA my_app_data; 214my_app_data.is_master = 0; /* Assume we start as a replica */ 215 216... 217 218/* 219 * Now we create our environment handle and set the APP_DATA structure 220 * to it's app_private member. 221 */ 222if ((ret = db_env_create(&dbenv, 0)) != 0 ) { 223 fprintf(stderr, "Error creating handles: %s\n", 224 db_strerror(ret)); 225 goto err; 226} 227dbenv->app_private = &my_app_data; 228 229/* Having done that, register the callback with the 230 * Berkeley DB library 231 */ 232dbenv->set_event_notify(dbenv, event_callback); </pre> 233 <p> 234 That done, we still need to implement the callback itself. This 235 implementation can be fairly trivial. 236</p> 237 <pre class="programlisting">/* 238 * A callback used to determine whether the local environment is a 239 * replica or a master. This is called by the Replication Manager 240 * when the local environment changes state. 241 */ 242void * 243event_callback(DB_ENV *dbenv, u_int32_t which, void *info) 244{ 245 APP_DATA *app = dbenv->app_private; 246 247 info = NULL; /* Currently unused. */ 248 249 switch (which) { 250 case DB_EVENT_REP_MASTER: 251 app->is_master = 1; 252 break; 253 254 case DB_EVENT_REP_CLIENT: 255 app->is_master = 0; 256 break; 257 258 case DB_EVENT_REP_STARTUPDONE: /* fallthrough */ 259 case DB_EVENT_REP_NEWMASTER: 260 /* Ignore. */ 261 break; 262 263 default: 264 dbenv->errx(dbenv, "ignoring event %d", which); 265 } 266} </pre> 267 <p> 268 Notice how we access the 269 <code class="literal">APP_DATA</code> information using the environment 270 handle's <code class="literal">app_private</code> data member. We also ignore 271 the <code class="literal">DB_EVENT_REP_NEWMASTER</code> and 272 <code class="literal">DB_EVENT_REP_STARTUPDONE</code> cases since these are not 273 relevant for simple replicated applications. 274</p> 275 <p> 276 Of course, this only gives us the current state of the environment. We 277 still need the code that determines what to do when the environment 278 changes state and how to behave depending on the state (described 279 in the next section). 280</p> 281 </div> 282 </div> 283 <div class="navfooter"> 284 <hr /> 285 <table width="100%" summary="Navigation footer"> 286 <tr> 287 <td width="40%" align="left"><a accesskey="p" href="heartbeats.html">Prev</a> </td> 288 <td width="20%" align="center"> </td> 289 <td width="40%" align="right"> <a accesskey="n" href="processingloop.html">Next</a></td> 290 </tr> 291 <tr> 292 <td width="40%" align="left" valign="top">Managing Heartbeats </td> 293 <td width="20%" align="center"> 294 <a accesskey="h" href="index.html">Home</a> 295 </td> 296 <td width="40%" align="right" valign="top"> Processing Loop</td> 297 </tr> 298 </table> 299 </div> 300 </body> 301</html> 302