zookeeperTutorial.html 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  2. <html>
  3. <head>
  4. <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
  5. <meta content="Apache Forrest" name="Generator">
  6. <meta name="Forrest-version" content="0.8">
  7. <meta name="Forrest-skin-name" content="pelt">
  8. <title>Programming with ZooKeeper - A basic tutorial</title>
  9. <link type="text/css" href="skin/basic.css" rel="stylesheet">
  10. <link media="screen" type="text/css" href="skin/screen.css" rel="stylesheet">
  11. <link media="print" type="text/css" href="skin/print.css" rel="stylesheet">
  12. <link type="text/css" href="skin/profile.css" rel="stylesheet">
  13. <script src="skin/getBlank.js" language="javascript" type="text/javascript"></script><script src="skin/getMenu.js" language="javascript" type="text/javascript"></script><script src="skin/fontsize.js" language="javascript" type="text/javascript"></script>
  14. <link rel="shortcut icon" href="images/favicon.ico">
  15. </head>
  16. <body onload="init()">
  17. <script type="text/javascript">ndeSetTextSize();</script>
  18. <div id="top">
  19. <!--+
  20. |breadtrail
  21. +-->
  22. <div class="breadtrail">
  23. <a href="http://www.apache.org/">Apache</a> &gt; <a href="http://hadoop.apache.org/">Hadoop</a> &gt; <a href="http://hadoop.apache.org/zookeeper/">ZooKeeper</a><script src="skin/breadcrumbs.js" language="JavaScript" type="text/javascript"></script>
  24. </div>
  25. <!--+
  26. |header
  27. +-->
  28. <div class="header">
  29. <!--+
  30. |start group logo
  31. +-->
  32. <div class="grouplogo">
  33. <a href="http://hadoop.apache.org/"><img class="logoImage" alt="Hadoop" src="images/hadoop-logo.jpg" title="Apache Hadoop"></a>
  34. </div>
  35. <!--+
  36. |end group logo
  37. +-->
  38. <!--+
  39. |start Project Logo
  40. +-->
  41. <div class="projectlogo">
  42. <a href="http://hadoop.apache.org/zookeeper/"><img class="logoImage" alt="ZooKeeper" src="images/zookeeper_small.gif" title="ZooKeeper: distributed coordination"></a>
  43. </div>
  44. <!--+
  45. |end Project Logo
  46. +-->
  47. <!--+
  48. |start Search
  49. +-->
  50. <div class="searchbox">
  51. <form action="http://www.google.com/search" method="get" class="roundtopsmall">
  52. <input value="hadoop.apache.org" name="sitesearch" type="hidden"><input onFocus="getBlank (this, 'Search the site with google');" size="25" name="q" id="query" type="text" value="Search the site with google">&nbsp;
  53. <input name="Search" value="Search" type="submit">
  54. </form>
  55. </div>
  56. <!--+
  57. |end search
  58. +-->
  59. <!--+
  60. |start Tabs
  61. +-->
  62. <ul id="tabs">
  63. <li>
  64. <a class="unselected" href="http://hadoop.apache.org/zookeeper/">Project</a>
  65. </li>
  66. <li>
  67. <a class="unselected" href="http://wiki.apache.org/hadoop/ZooKeeper">Wiki</a>
  68. </li>
  69. <li class="current">
  70. <a class="selected" href="index.html">ZooKeeper 3.4 Documentation</a>
  71. </li>
  72. </ul>
  73. <!--+
  74. |end Tabs
  75. +-->
  76. </div>
  77. </div>
  78. <div id="main">
  79. <div id="publishedStrip">
  80. <!--+
  81. |start Subtabs
  82. +-->
  83. <div id="level2tabs"></div>
  84. <!--+
  85. |end Endtabs
  86. +-->
  87. <script type="text/javascript"><!--
  88. document.write("Last Published: " + document.lastModified);
  89. // --></script>
  90. </div>
  91. <!--+
  92. |breadtrail
  93. +-->
  94. <div class="breadtrail">
  95. &nbsp;
  96. </div>
  97. <!--+
  98. |start Menu, mainarea
  99. +-->
  100. <!--+
  101. |start Menu
  102. +-->
  103. <div id="menu">
  104. <div onclick="SwitchMenu('menu_1.1', 'skin/')" id="menu_1.1Title" class="menutitle">Overview</div>
  105. <div id="menu_1.1" class="menuitemgroup">
  106. <div class="menuitem">
  107. <a href="index.html">Welcome</a>
  108. </div>
  109. <div class="menuitem">
  110. <a href="zookeeperOver.html">Overview</a>
  111. </div>
  112. <div class="menuitem">
  113. <a href="zookeeperStarted.html">Getting Started</a>
  114. </div>
  115. <div class="menuitem">
  116. <a href="releasenotes.html">Release Notes</a>
  117. </div>
  118. </div>
  119. <div onclick="SwitchMenu('menu_selected_1.2', 'skin/')" id="menu_selected_1.2Title" class="menutitle" style="background-image: url('skin/images/chapter_open.gif');">Developer</div>
  120. <div id="menu_selected_1.2" class="selectedmenuitemgroup" style="display: block;">
  121. <div class="menuitem">
  122. <a href="api/index.html">API Docs</a>
  123. </div>
  124. <div class="menuitem">
  125. <a href="zookeeperProgrammers.html">Programmer's Guide</a>
  126. </div>
  127. <div class="menuitem">
  128. <a href="javaExample.html">Java Example</a>
  129. </div>
  130. <div class="menupage">
  131. <div class="menupagetitle">Barrier and Queue Tutorial</div>
  132. </div>
  133. <div class="menuitem">
  134. <a href="recipes.html">Recipes</a>
  135. </div>
  136. </div>
  137. <div onclick="SwitchMenu('menu_1.3', 'skin/')" id="menu_1.3Title" class="menutitle">BookKeeper</div>
  138. <div id="menu_1.3" class="menuitemgroup">
  139. <div class="menuitem">
  140. <a href="bookkeeperStarted.html">Getting started</a>
  141. </div>
  142. <div class="menuitem">
  143. <a href="bookkeeperOverview.html">Overview</a>
  144. </div>
  145. <div class="menuitem">
  146. <a href="bookkeeperConfig.html">Setup guide</a>
  147. </div>
  148. <div class="menuitem">
  149. <a href="bookkeeperProgrammer.html">Programmer's guide</a>
  150. </div>
  151. </div>
  152. <div onclick="SwitchMenu('menu_1.4', 'skin/')" id="menu_1.4Title" class="menutitle">Admin &amp; Ops</div>
  153. <div id="menu_1.4" class="menuitemgroup">
  154. <div class="menuitem">
  155. <a href="zookeeperAdmin.html">Administrator's Guide</a>
  156. </div>
  157. <div class="menuitem">
  158. <a href="zookeeperQuotas.html">Quota Guide</a>
  159. </div>
  160. <div class="menuitem">
  161. <a href="zookeeperJMX.html">JMX</a>
  162. </div>
  163. <div class="menuitem">
  164. <a href="zookeeperObservers.html">Observers Guide</a>
  165. </div>
  166. </div>
  167. <div onclick="SwitchMenu('menu_1.5', 'skin/')" id="menu_1.5Title" class="menutitle">Contributor</div>
  168. <div id="menu_1.5" class="menuitemgroup">
  169. <div class="menuitem">
  170. <a href="zookeeperInternals.html">ZooKeeper Internals</a>
  171. </div>
  172. </div>
  173. <div onclick="SwitchMenu('menu_1.6', 'skin/')" id="menu_1.6Title" class="menutitle">Miscellaneous</div>
  174. <div id="menu_1.6" class="menuitemgroup">
  175. <div class="menuitem">
  176. <a href="http://wiki.apache.org/hadoop/ZooKeeper">Wiki</a>
  177. </div>
  178. <div class="menuitem">
  179. <a href="http://wiki.apache.org/hadoop/ZooKeeper/FAQ">FAQ</a>
  180. </div>
  181. <div class="menuitem">
  182. <a href="http://hadoop.apache.org/zookeeper/mailing_lists.html">Mailing Lists</a>
  183. </div>
  184. </div>
  185. <div id="credit"></div>
  186. <div id="roundbottom">
  187. <img style="display: none" class="corner" height="15" width="15" alt="" src="skin/images/rc-b-l-15-1body-2menu-3menu.png"></div>
  188. <!--+
  189. |alternative credits
  190. +-->
  191. <div id="credit2"></div>
  192. </div>
  193. <!--+
  194. |end Menu
  195. +-->
  196. <!--+
  197. |start content
  198. +-->
  199. <div id="content">
  200. <div title="Portable Document Format" class="pdflink">
  201. <a class="dida" href="zookeeperTutorial.pdf"><img alt="PDF -icon" src="skin/images/pdfdoc.gif" class="skin"><br>
  202. PDF</a>
  203. </div>
  204. <h1>Programming with ZooKeeper - A basic tutorial</h1>
  205. <div id="minitoc-area">
  206. <ul class="minitoc">
  207. <li>
  208. <a href="#ch_Introduction">Introduction</a>
  209. </li>
  210. <li>
  211. <a href="#sc_barriers">Barriers</a>
  212. </li>
  213. <li>
  214. <a href="#sc_producerConsumerQueues">Producer-Consumer Queues</a>
  215. </li>
  216. <li>
  217. <a href="#sc_sourceListing">Complete Source Listing</a>
  218. </li>
  219. </ul>
  220. </div>
  221. <a name="N10009"></a><a name="ch_Introduction"></a>
  222. <h2 class="h3">Introduction</h2>
  223. <div class="section">
  224. <p>In this tutorial, we show simple implementations of barriers and
  225. producer-consumer queues using ZooKeeper. We call the respective classes Barrier and Queue.
  226. These examples assume that you have at least one ZooKeeper server running.</p>
  227. <p>Both primitives use the following common excerpt of code:</p>
  228. <pre class="code">
  229. static ZooKeeper zk = null;
  230. static Integer mutex;
  231. String root;
  232. SyncPrimitive(String address) {
  233. if(zk == null){
  234. try {
  235. System.out.println("Starting ZK:");
  236. zk = new ZooKeeper(address, 3000, this);
  237. mutex = new Integer(-1);
  238. System.out.println("Finished starting ZK: " + zk);
  239. } catch (IOException e) {
  240. System.out.println(e.toString());
  241. zk = null;
  242. }
  243. }
  244. }
  245. synchronized public void process(WatchedEvent event) {
  246. synchronized (mutex) {
  247. mutex.notify();
  248. }
  249. }
  250. </pre>
  251. <p>Both classes extend SyncPrimitive. In this way, we execute steps that are
  252. common to all primitives in the constructor of SyncPrimitive. To keep the examples
  253. simple, we create a ZooKeeper object the first time we instantiate either a barrier
  254. object or a queue object, and we declare a static variable that is a reference
  255. to this object. The subsequent instances of Barrier and Queue check whether a
  256. ZooKeeper object exists. Alternatively, we could have the application creating a
  257. ZooKeeper object and passing it to the constructor of Barrier and Queue.</p>
  258. <p>
  259. We use the process() method to process notifications triggered due to watches.
  260. In the following discussion, we present code that sets watches. A watch is internal
  261. structure that enables ZooKeeper to notify a client of a change to a node. For example,
  262. if a client is waiting for other clients to leave a barrier, then it can set a watch and
  263. wait for modifications to a particular node, which can indicate that it is the end of the wait.
  264. This point becomes clear once we go over the examples.
  265. </p>
  266. </div>
  267. <a name="N1001F"></a><a name="sc_barriers"></a>
  268. <h2 class="h3">Barriers</h2>
  269. <div class="section">
  270. <p>
  271. A barrier is a primitive that enables a group of processes to synchronize the
  272. beginning and the end of a computation. The general idea of this implementation
  273. is to have a barrier node that serves the purpose of being a parent for individual
  274. process nodes. Suppose that we call the barrier node "/b1". Each process "p" then
  275. creates a node "/b1/p". Once enough processes have created their corresponding
  276. nodes, joined processes can start the computation.
  277. </p>
  278. <p>In this example, each process instantiates a Barrier object, and its constructor takes as parameters:</p>
  279. <ul>
  280. <li>
  281. <p>the address of a ZooKeeper server (e.g., "zoo1.foo.com:2181")</p>
  282. </li>
  283. <li>
  284. <p>the path of the barrier node on ZooKeeper (e.g., "/b1")</p>
  285. </li>
  286. <li>
  287. <p>the size of the group of processes</p>
  288. </li>
  289. </ul>
  290. <p>The constructor of Barrier passes the address of the Zookeeper server to the
  291. constructor of the parent class. The parent class creates a ZooKeeper instance if
  292. one does not exist. The constructor of Barrier then creates a
  293. barrier node on ZooKeeper, which is the parent node of all process nodes, and
  294. we call root (<strong>Note:</strong> This is not the ZooKeeper root "/").</p>
  295. <pre class="code">
  296. /**
  297. * Barrier constructor
  298. *
  299. * @param address
  300. * @param root
  301. * @param size
  302. */
  303. Barrier(String address, String root, int size) {
  304. super(address);
  305. this.root = root;
  306. this.size = size;
  307. // Create barrier node
  308. if (zk != null) {
  309. try {
  310. Stat s = zk.exists(root, false);
  311. if (s == null) {
  312. zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
  313. CreateMode.PERSISTENT);
  314. }
  315. } catch (KeeperException e) {
  316. System.out
  317. .println("Keeper exception when instantiating queue: "
  318. + e.toString());
  319. } catch (InterruptedException e) {
  320. System.out.println("Interrupted exception");
  321. }
  322. }
  323. // My node name
  324. try {
  325. name = new String(InetAddress.getLocalHost().getCanonicalHostName().toString());
  326. } catch (UnknownHostException e) {
  327. System.out.println(e.toString());
  328. }
  329. }
  330. </pre>
  331. <p>
  332. To enter the barrier, a process calls enter(). The process creates a node under
  333. the root to represent it, using its host name to form the node name. It then wait
  334. until enough processes have entered the barrier. A process does it by checking
  335. the number of children the root node has with "getChildren()", and waiting for
  336. notifications in the case it does not have enough. To receive a notification when
  337. there is a change to the root node, a process has to set a watch, and does it
  338. through the call to "getChildren()". In the code, we have that "getChildren()"
  339. has two parameters. The first one states the node to read from, and the second is
  340. a boolean flag that enables the process to set a watch. In the code the flag is true.
  341. </p>
  342. <pre class="code">
  343. /**
  344. * Join barrier
  345. *
  346. * @return
  347. * @throws KeeperException
  348. * @throws InterruptedException
  349. */
  350. boolean enter() throws KeeperException, InterruptedException{
  351. zk.create(root + "/" + name, new byte[0], Ids.OPEN_ACL_UNSAFE,
  352. CreateMode.EPHEMERAL_SEQUENTIAL);
  353. while (true) {
  354. synchronized (mutex) {
  355. List&lt;String&gt; list = zk.getChildren(root, true);
  356. if (list.size() &lt; size) {
  357. mutex.wait();
  358. } else {
  359. return true;
  360. }
  361. }
  362. }
  363. }
  364. </pre>
  365. <p>
  366. Note that enter() throws both KeeperException and InterruptedException, so it is
  367. the reponsability of the application to catch and handle such exceptions.</p>
  368. <p>
  369. Once the computation is finished, a process calls leave() to leave the barrier.
  370. First it deletes its corresponding node, and then it gets the children of the root
  371. node. If there is at least one child, then it waits for a notification (obs: note
  372. that the second parameter of the call to getChildren() is true, meaning that
  373. ZooKeeper has to set a watch on the the root node). Upon reception of a notification,
  374. it checks once more whether the root node has any child.</p>
  375. <pre class="code">
  376. /**
  377. * Wait until all reach barrier
  378. *
  379. * @return
  380. * @throws KeeperException
  381. * @throws InterruptedException
  382. */
  383. boolean leave() throws KeeperException, InterruptedException{
  384. zk.delete(root + "/" + name, 0);
  385. while (true) {
  386. synchronized (mutex) {
  387. List&lt;String&gt; list = zk.getChildren(root, true);
  388. if (list.size() &gt; 0) {
  389. mutex.wait();
  390. } else {
  391. return true;
  392. }
  393. }
  394. }
  395. }
  396. }
  397. </pre>
  398. </div>
  399. <a name="N10051"></a><a name="sc_producerConsumerQueues"></a>
  400. <h2 class="h3">Producer-Consumer Queues</h2>
  401. <div class="section">
  402. <p>
  403. A producer-consumer queue is a distributed data estructure thata group of processes
  404. use to generate and consume items. Producer processes create new elements and add
  405. them to the queue. Consumer processes remove elements from the list, and process them.
  406. In this implementation, the elements are simple integers. The queue is represented
  407. by a root node, and to add an element to the queue, a producer process creates a new node,
  408. a child of the root node.
  409. </p>
  410. <p>
  411. The following excerpt of code corresponds to the constructor of the object. As
  412. with Barrier objects, it first calls the constructor of the parent class, SyncPrimitive,
  413. that creates a ZooKeeper object if one doesn't exist. It then verifies if the root
  414. node of the queue exists, and creates if it doesn't.
  415. </p>
  416. <pre class="code">
  417. /**
  418. * Constructor of producer-consumer queue
  419. *
  420. * @param address
  421. * @param name
  422. */
  423. Queue(String address, String name) {
  424. super(address);
  425. this.root = name;
  426. // Create ZK node name
  427. if (zk != null) {
  428. try {
  429. Stat s = zk.exists(root, false);
  430. if (s == null) {
  431. zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
  432. CreateMode.PERSISTENT);
  433. }
  434. } catch (KeeperException e) {
  435. System.out
  436. .println("Keeper exception when instantiating queue: "
  437. + e.toString());
  438. } catch (InterruptedException e) {
  439. System.out.println("Interrupted exception");
  440. }
  441. }
  442. }
  443. </pre>
  444. <p>
  445. A producer process calls "produce()" to add an element to the queue, and passes
  446. an integer as an argument. To add an element to the queue, the method creates a
  447. new node using "create()", and uses the SEQUENCE flag to instruct ZooKeeper to
  448. append the value of the sequencer counter associated to the root node. In this way,
  449. we impose a total order on the elements of the queue, thus guaranteeing that the
  450. oldest element of the queue is the next one consumed.
  451. </p>
  452. <pre class="code">
  453. /**
  454. * Add element to the queue.
  455. *
  456. * @param i
  457. * @return
  458. */
  459. boolean produce(int i) throws KeeperException, InterruptedException{
  460. ByteBuffer b = ByteBuffer.allocate(4);
  461. byte[] value;
  462. // Add child with value i
  463. b.putInt(i);
  464. value = b.array();
  465. zk.create(root + "/element", value, Ids.OPEN_ACL_UNSAFE,
  466. CreateMode.PERSISTENT_SEQUENTIAL);
  467. return true;
  468. }
  469. </pre>
  470. <p>
  471. To consume an element, a consumer process obtains the children of the root node,
  472. reads the node with smallest counter value, and returns the element. Note that
  473. if there is a conflict, then one of the two contending processes won't be able to
  474. delete the node and the delete operation will throw an exception.</p>
  475. <p>
  476. A call to getChildren() returns the list of children in lexicographic order.
  477. As lexicographic order does not necessary follow the numerical order of the counter
  478. values, we need to decide which element is the smallest. To decide which one has
  479. the smallest counter value, we traverse the list, and remove the prefix "element"
  480. from each one.</p>
  481. <pre class="code">
  482. /**
  483. * Remove first element from the queue.
  484. *
  485. * @return
  486. * @throws KeeperException
  487. * @throws InterruptedException
  488. */
  489. int consume() throws KeeperException, InterruptedException{
  490. int retvalue = -1;
  491. Stat stat = null;
  492. // Get the first element available
  493. while (true) {
  494. synchronized (mutex) {
  495. List&lt;String&gt; list = zk.getChildren(root, true);
  496. if (list.size() == 0) {
  497. System.out.println("Going to wait");
  498. mutex.wait();
  499. } else {
  500. Integer min = new Integer(list.get(0).substring(7));
  501. for(String s : list){
  502. Integer tempValue = new Integer(s.substring(7));
  503. //System.out.println("Temporary value: " + tempValue);
  504. if(tempValue &lt; min) min = tempValue;
  505. }
  506. System.out.println("Temporary value: " + root + "/element" + min);
  507. byte[] b = zk.getData(root + "/element" + min,
  508. false, stat);
  509. zk.delete(root + "/element" + min, 0);
  510. ByteBuffer buffer = ByteBuffer.wrap(b);
  511. retvalue = buffer.getInt();
  512. return retvalue;
  513. }
  514. }
  515. }
  516. }
  517. }
  518. </pre>
  519. </div>
  520. <a name="N1006F"></a><a name="sc_sourceListing"></a>
  521. <h2 class="h3">Complete Source Listing</h2>
  522. <div class="section">
  523. <div class="note example">
  524. <div class="label">SyncPrimitive.Java</div>
  525. <div class="content">
  526. <title>SyncPrimitive.Java</title>
  527. <pre class="code">
  528. import java.io.IOException;
  529. import java.net.InetAddress;
  530. import java.net.UnknownHostException;
  531. import java.nio.ByteBuffer;
  532. import java.util.List;
  533. import java.util.Random;
  534. import org.apache.zookeeper.CreateMode;
  535. import org.apache.zookeeper.KeeperException;
  536. import org.apache.zookeeper.WatchedEvent;
  537. import org.apache.zookeeper.Watcher;
  538. import org.apache.zookeeper.ZooKeeper;
  539. import org.apache.zookeeper.ZooDefs.Ids;
  540. import org.apache.zookeeper.data.Stat;
  541. public class SyncPrimitive implements Watcher {
  542. static ZooKeeper zk = null;
  543. static Integer mutex;
  544. String root;
  545. SyncPrimitive(String address) {
  546. if(zk == null){
  547. try {
  548. System.out.println("Starting ZK:");
  549. zk = new ZooKeeper(address, 3000, this);
  550. mutex = new Integer(-1);
  551. System.out.println("Finished starting ZK: " + zk);
  552. } catch (IOException e) {
  553. System.out.println(e.toString());
  554. zk = null;
  555. }
  556. }
  557. //else mutex = new Integer(-1);
  558. }
  559. synchronized public void process(WatchedEvent event) {
  560. synchronized (mutex) {
  561. //System.out.println("Process: " + event.getType());
  562. mutex.notify();
  563. }
  564. }
  565. /**
  566. * Barrier
  567. */
  568. static public class Barrier extends SyncPrimitive {
  569. int size;
  570. String name;
  571. /**
  572. * Barrier constructor
  573. *
  574. * @param address
  575. * @param root
  576. * @param size
  577. */
  578. Barrier(String address, String root, int size) {
  579. super(address);
  580. this.root = root;
  581. this.size = size;
  582. // Create barrier node
  583. if (zk != null) {
  584. try {
  585. Stat s = zk.exists(root, false);
  586. if (s == null) {
  587. zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
  588. CreateMode.PERSISTENT);
  589. }
  590. } catch (KeeperException e) {
  591. System.out
  592. .println("Keeper exception when instantiating queue: "
  593. + e.toString());
  594. } catch (InterruptedException e) {
  595. System.out.println("Interrupted exception");
  596. }
  597. }
  598. // My node name
  599. try {
  600. name = new String(InetAddress.getLocalHost().getCanonicalHostName().toString());
  601. } catch (UnknownHostException e) {
  602. System.out.println(e.toString());
  603. }
  604. }
  605. /**
  606. * Join barrier
  607. *
  608. * @return
  609. * @throws KeeperException
  610. * @throws InterruptedException
  611. */
  612. boolean enter() throws KeeperException, InterruptedException{
  613. zk.create(root + "/" + name, new byte[0], Ids.OPEN_ACL_UNSAFE,
  614. CreateMode.EPHEMERAL_SEQUENTIAL);
  615. while (true) {
  616. synchronized (mutex) {
  617. List&lt;String&gt; list = zk.getChildren(root, true);
  618. if (list.size() &lt; size) {
  619. mutex.wait();
  620. } else {
  621. return true;
  622. }
  623. }
  624. }
  625. }
  626. /**
  627. * Wait until all reach barrier
  628. *
  629. * @return
  630. * @throws KeeperException
  631. * @throws InterruptedException
  632. */
  633. boolean leave() throws KeeperException, InterruptedException{
  634. zk.delete(root + "/" + name, 0);
  635. while (true) {
  636. synchronized (mutex) {
  637. List&lt;String&gt; list = zk.getChildren(root, true);
  638. if (list.size() &gt; 0) {
  639. mutex.wait();
  640. } else {
  641. return true;
  642. }
  643. }
  644. }
  645. }
  646. }
  647. /**
  648. * Producer-Consumer queue
  649. */
  650. static public class Queue extends SyncPrimitive {
  651. /**
  652. * Constructor of producer-consumer queue
  653. *
  654. * @param address
  655. * @param name
  656. */
  657. Queue(String address, String name) {
  658. super(address);
  659. this.root = name;
  660. // Create ZK node name
  661. if (zk != null) {
  662. try {
  663. Stat s = zk.exists(root, false);
  664. if (s == null) {
  665. zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
  666. CreateMode.PERSISTENT);
  667. }
  668. } catch (KeeperException e) {
  669. System.out
  670. .println("Keeper exception when instantiating queue: "
  671. + e.toString());
  672. } catch (InterruptedException e) {
  673. System.out.println("Interrupted exception");
  674. }
  675. }
  676. }
  677. /**
  678. * Add element to the queue.
  679. *
  680. * @param i
  681. * @return
  682. */
  683. boolean produce(int i) throws KeeperException, InterruptedException{
  684. ByteBuffer b = ByteBuffer.allocate(4);
  685. byte[] value;
  686. // Add child with value i
  687. b.putInt(i);
  688. value = b.array();
  689. zk.create(root + "/element", value, Ids.OPEN_ACL_UNSAFE,
  690. CreateMode.PERSISTENT_SEQUENTIAL);
  691. return true;
  692. }
  693. /**
  694. * Remove first element from the queue.
  695. *
  696. * @return
  697. * @throws KeeperException
  698. * @throws InterruptedException
  699. */
  700. int consume() throws KeeperException, InterruptedException{
  701. int retvalue = -1;
  702. Stat stat = null;
  703. // Get the first element available
  704. while (true) {
  705. synchronized (mutex) {
  706. List&lt;String&gt; list = zk.getChildren(root, true);
  707. if (list.size() == 0) {
  708. System.out.println("Going to wait");
  709. mutex.wait();
  710. } else {
  711. Integer min = new Integer(list.get(0).substring(7));
  712. for(String s : list){
  713. Integer tempValue = new Integer(s.substring(7));
  714. //System.out.println("Temporary value: " + tempValue);
  715. if(tempValue &lt; min) min = tempValue;
  716. }
  717. System.out.println("Temporary value: " + root + "/element" + min);
  718. byte[] b = zk.getData(root + "/element" + min,
  719. false, stat);
  720. zk.delete(root + "/element" + min, 0);
  721. ByteBuffer buffer = ByteBuffer.wrap(b);
  722. retvalue = buffer.getInt();
  723. return retvalue;
  724. }
  725. }
  726. }
  727. }
  728. }
  729. public static void main(String args[]) {
  730. if (args[0].equals("qTest"))
  731. queueTest(args);
  732. else
  733. barrierTest(args);
  734. }
  735. public static void queueTest(String args[]) {
  736. Queue q = new Queue(args[1], "/app1");
  737. System.out.println("Input: " + args[1]);
  738. int i;
  739. Integer max = new Integer(args[2]);
  740. if (args[3].equals("p")) {
  741. System.out.println("Producer");
  742. for (i = 0; i &lt; max; i++)
  743. try{
  744. q.produce(10 + i);
  745. } catch (KeeperException e){
  746. } catch (InterruptedException e){
  747. }
  748. } else {
  749. System.out.println("Consumer");
  750. for (i = 0; i &lt; max; i++) {
  751. try{
  752. int r = q.consume();
  753. System.out.println("Item: " + r);
  754. } catch (KeeperException e){
  755. i--;
  756. } catch (InterruptedException e){
  757. }
  758. }
  759. }
  760. }
  761. public static void barrierTest(String args[]) {
  762. Barrier b = new Barrier(args[1], "/b1", new Integer(args[2]));
  763. try{
  764. boolean flag = b.enter();
  765. System.out.println("Entered barrier: " + args[2]);
  766. if(!flag) System.out.println("Error when entering the barrier");
  767. } catch (KeeperException e){
  768. } catch (InterruptedException e){
  769. }
  770. // Generate random integer
  771. Random rand = new Random();
  772. int r = rand.nextInt(100);
  773. // Loop for rand iterations
  774. for (int i = 0; i &lt; r; i++) {
  775. try {
  776. Thread.sleep(100);
  777. } catch (InterruptedException e) {
  778. }
  779. }
  780. try{
  781. b.leave();
  782. } catch (KeeperException e){
  783. } catch (InterruptedException e){
  784. }
  785. System.out.println("Left barrier");
  786. }
  787. }
  788. </pre>
  789. </div>
  790. </div>
  791. </div>
  792. <p align="right">
  793. <font size="-2"></font>
  794. </p>
  795. </div>
  796. <!--+
  797. |end content
  798. +-->
  799. <div class="clearboth">&nbsp;</div>
  800. </div>
  801. <div id="footer">
  802. <!--+
  803. |start bottomstrip
  804. +-->
  805. <div class="lastmodified">
  806. <script type="text/javascript"><!--
  807. document.write("Last Published: " + document.lastModified);
  808. // --></script>
  809. </div>
  810. <div class="copyright">
  811. Copyright &copy;
  812. 2008 <a href="http://www.apache.org/licenses/">The Apache Software Foundation.</a>
  813. </div>
  814. <!--+
  815. |end bottomstrip
  816. +-->
  817. </div>
  818. </body>
  819. </html>