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 running 107 as a master or a replica, you must write your 108 application as an implementation of 109 <code class="classname">com.sleepycat.db.EventHandler</code>. 110 This class gives you a series of methods within 111 which you can detect and respond to various events 112 that occur in your DB code. Some, but not all, of these methods have to 113 do with elections: 114 </p> 115 <div class="itemizedlist"> 116 <ul type="disc"> 117 <li> 118 <p> 119 120 <code class="methodname">EventHandler.handleRepMasterEvent()</code> 121 </p> 122 <p> 123 The local environment is now a master. 124 </p> 125 </li> 126 <li> 127 <p> 128 129 <code class="methodname">EventHandler.handleRepClientEvent()</code> 130 </p> 131 <p> 132 The local environment is now a replica. 133 </p> 134 </li> 135 <li> 136 <p> 137 138 <code class="methodname">EventHandler.handleRepStartupDoneEvent()</code> 139 </p> 140 <p> 141 The replica has completed startup 142 synchronization and is now 143 processing log records received 144 from the master. 145 </p> 146 </li> 147 <li> 148 <p> 149 150 <code class="methodname">EventHandler.handleRepElectedEvent()</code> 151 </p> 152 <p> 153 An election was held and a new environment was made a 154 master. However, the current environment <span class="emphasis"><em>is 155 not</em></span> the master. This event exists so that 156 you can cause your code to take some unique action in the 157 event that the replication groups switches masters. 158 </p> 159 </li> 160 <li> 161 <p> 162 <code class="methodname">EventHandler.handleRepPanicEvent()</code> 163 </p> 164 <p> 165 An error has occured in the Berkeley DB library requiring your 166 application to shut down and then run recovery. 167 </p> 168 </li> 169 <li> 170 <p> 171 <code class="methodname">EventHandler.handleRepPermFailedFailedEvent()</code> 172 </p> 173 <p> 174 The Replication Manager did not receive enough acknowledgements to 175 ensure the transaction's durability within the replicationg group. 176 The Replication Manager has therefore flushed the transaction to 177 the master's local disk for storage. 178 </p> 179 <p> 180 How the Replication Manager knows whether the acknowledgements it 181 has received is determined by the ack policy you have set for your 182 applicaton. See <a class="xref" href="fwrkpermmessage.html#fmwrkpermpolicy" title="Identifying Permanent Message Policies">Identifying Permanent Message Policies</a> 183 for more information. 184 </p> 185 </li> 186 <li> 187 <p> 188 <code class="methodname">EventHandler.handleWriteFailedEvent()</code> 189 </p> 190 <p> 191 A Berkeley DB write to stable storage failed. 192 </p> 193 </li> 194 </ul> 195 </div> 196 <p> 197 Note that these events are raised whenever the 198 state is established. That is, when the current 199 environment becomes a replica, and that includes 200 at application startup, the event is raised. 201 Also, when an election is held and a replica is elected to be a 202 master, then the event occurs. 203 </p> 204 <p> 205 The <code class="classname">EventHandler</code> 206 implementation is fairly simple. First you detect 207 the event, and then you record the state change 208 in some data member maintained in a location that 209 is convenient to you. 210 </p> 211 <p> 212 For example: 213 </p> 214 <pre class="programlisting"> 215package db.repquote; 216 217// We make our main class an EventHandler implementation 218... 219import com.sleepycat.db.EventHandler; 220... 221 222public class MyReplicationClass implements EventHandler 223{ 224 225... 226 227// Somewhere we provide a data member that is used to track 228// whether we are a master server. This could be in our main 229// class, or it could be part of a supporting class. 230private boolean isMaster; 231 232... 233 234isMaster = false; 235 236... 237 238// In the code where we open our environment and start replication, 239// we must identify the class that is the event handler. In this 240// example, we are performing this from within the class that 241// implements com.sleepycat.db.EventHandler so we identify 242// "this" class as the event handler 243envConfig.setEventHandler(this); </pre> 244 <p> 245 That done, we still need to implement the methods required for handling replication events. 246 For a simple application like this one, these implementations can be trivial. 247</p> 248 <pre class="programlisting"> public void handleRepClientEvent() 249 { 250 dbenv.setIsMaster(false); 251 } 252 253 public void handleRepMasterEvent() 254 { 255 dbenv.setIsMaster(true); 256 } 257 258 public void handleRepNewMasterEvent(int envId) 259 { 260 // Ignored for now 261 } 262 263 public void handleWriteFailedEvent(int errorCode) 264 { 265 System.err.println("Write to stable storage failed!" + 266 "Operating system error code:" + errorCode); 267 System.err.println("Continuing...."); 268 } 269 270 public void handleRepStartupDoneEvent() 271 { 272 System.out.println("Replication startup is completed."); 273 } 274 275 public void handleRepPermFailedEvent() 276 { 277 System.out.println("This application failed to receive enough" + 278 "acks for a permanent message. The transaction is flushed" + 279 "to disk on this master host."); 280 } 281 282 public void handleRepElectedEvent() 283 { 284 // Safely ignored for Replication Manager applications. 285 } 286 287 public void handlePanicEvent() 288 { 289 System.err.println("Panic encountered!"); 290 System.err.println("Shutting down."); 291 System.err.println("You should restart, running recovery."); 292 try { 293 terminate(); 294 } catch (DatabaseException dbe) { 295 System.err.println("Caught an exception during " + 296 "termination in handlePanicEvent: " + dbe.toString()); 297 } 298 System.exit(-1); 299 }</pre> 300 <p> 301 Of course, this only gives us the current state of the environment. We 302 still need the code that determines what to do when the environment 303 changes state and how to behave depending on the state (described 304 in the next section). 305</p> 306 </div> 307 </div> 308 <div class="navfooter"> 309 <hr /> 310 <table width="100%" summary="Navigation footer"> 311 <tr> 312 <td width="40%" align="left"><a accesskey="p" href="heartbeats.html">Prev</a> </td> 313 <td width="20%" align="center"> </td> 314 <td width="40%" align="right"> <a accesskey="n" href="processingloop.html">Next</a></td> 315 </tr> 316 <tr> 317 <td width="40%" align="left" valign="top">Managing Heartbeats </td> 318 <td width="20%" align="center"> 319 <a accesskey="h" href="index.html">Home</a> 320 </td> 321 <td width="40%" align="right" valign="top"> Processing Loop</td> 322 </tr> 323 </table> 324 </div> 325 </body> 326</html> 327