From commits-return-6329-archive-asf-public=cust-asf.ponee.io@zookeeper.apache.org Fri May 18 00:54:42 2018 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id 7C957180634 for ; Fri, 18 May 2018 00:54:40 +0200 (CEST) Received: (qmail 46708 invoked by uid 500); 17 May 2018 22:54:39 -0000 Mailing-List: contact commits-help@zookeeper.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@zookeeper.apache.org Delivered-To: mailing list commits@zookeeper.apache.org Received: (qmail 46697 invoked by uid 99); 17 May 2018 22:54:39 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 17 May 2018 22:54:39 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 34323DFB31; Thu, 17 May 2018 22:54:39 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: phunt@apache.org To: commits@zookeeper.apache.org Date: Thu, 17 May 2018 22:54:39 -0000 Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: [01/42] zookeeper git commit: Updated website content for release 3.5.4-beta. Repository: zookeeper Updated Branches: refs/heads/website 8a71ac966 -> 74d009622 http://git-wip-us.apache.org/repos/asf/zookeeper/blob/74d00962/_released_docs/r3.5.4-beta/zookeeperStarted.html ---------------------------------------------------------------------- diff --git a/_released_docs/r3.5.4-beta/zookeeperStarted.html b/_released_docs/r3.5.4-beta/zookeeperStarted.html new file mode 100644 index 0000000..19be58d --- /dev/null +++ b/_released_docs/r3.5.4-beta/zookeeperStarted.html @@ -0,0 +1,618 @@ + + + + + + + +ZooKeeper Getting Started Guide + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + +
+
+
+
+ +
+ + +
+ +
+ +   +
+ + + + + +
+ +

ZooKeeper Getting Started Guide

+ + + + + + + +

Getting Started: Coordinating Distributed Applications with + ZooKeeper

+
+

This document contains information to get you started quickly with + ZooKeeper. It is aimed primarily at developers hoping to try it out, and + contains simple installation instructions for a single ZooKeeper server, a + few commands to verify that it is running, and a simple programming + example. Finally, as a convenience, there are a few sections regarding + more complicated installations, for example running replicated + deployments, and optimizing the transaction log. However for the complete + instructions for commercial deployments, please refer to the ZooKeeper + Administrator's Guide.

+ +

Pre-requisites

+

See + System Requirements in the Admin guide.

+ +

Download

+

To get a ZooKeeper distribution, download a recent + + stable release from one of the Apache Download + Mirrors.

+ +

Standalone Operation

+

Setting up a ZooKeeper server in standalone mode is + straightforward. The server is contained in a single JAR file, + so installation consists of creating a configuration.

+

Once you've downloaded a stable ZooKeeper release unpack + it and cd to the root

+

To start ZooKeeper you need a configuration file. Here is a sample, + create it in conf/zoo.cfg:

+
+tickTime=2000
+dataDir=/var/lib/zookeeper
+clientPort=2181
+
+

This file can be called anything, but for the sake of this + discussion call + it conf/zoo.cfg. Change the + value of dataDir to specify an + existing (empty to start with) directory. Here are the meanings + for each of the fields:

+
+ +
+ +tickTime + +
+
+

the basic time unit in milliseconds used by ZooKeeper. It is + used to do heartbeats and the minimum session timeout will be + twice the tickTime.

+
+ +
+
+ +
+ +dataDir + +
+
+

the location to store the in-memory database snapshots and, + unless specified otherwise, the transaction log of updates to the + database.

+
+ + +
+ +clientPort + +
+
+

the port to listen for client connections

+
+ +
+

Now that you created the configuration file, you can start + ZooKeeper:

+
bin/zkServer.sh start
+

ZooKeeper logs messages using log4j -- more detail + available in the + Logging + section of the Programmer's Guide. You will see log messages + coming to the console (default) and/or a log file depending on + the log4j configuration.

+

The steps outlined here run ZooKeeper in standalone mode. There is + no replication, so if ZooKeeper process fails, the service will go down. + This is fine for most development situations, but to run ZooKeeper in + replicated mode, please see Running Replicated + ZooKeeper.

+ +

Managing ZooKeeper Storage

+

For long running production systems ZooKeeper storage must + be managed externally (dataDir and logs). See the section on + maintenance for + more details.

+ +

Connecting to ZooKeeper

+
$ bin/zkCli.sh -server 127.0.0.1:2181
+

This lets you perform simple, file-like operations.

+

Once you have connected, you should see something like: +

+
+
+Connecting to localhost:2181
+log4j:WARN No appenders could be found for logger (org.apache.zookeeper.ZooKeeper).
+log4j:WARN Please initialize the log4j system properly.
+Welcome to ZooKeeper!
+JLine support is enabled
+[zkshell: 0]
+        
+

+ From the shell, type help to get a listing of commands that can be executed from the client, as in: +

+
+
+[zkshell: 0] help
+ZooKeeper host:port cmd args
+        get path [watch]
+        ls path [watch]
+        set path data [version]
+        delquota [-n|-b] path
+        quit
+        printwatches on|off
+        create path data acl
+        stat path [watch]
+        listquota path
+        history
+        setAcl path acl
+        getAcl path
+        sync path
+        redo cmdno
+        addauth scheme auth
+        delete path [version]
+        deleteall path
+        setquota -n|-b val path
+
+        
+

From here, you can try a few simple commands to get a feel for this simple command line interface. First, start by issuing the list command, as + in ls, yielding: +

+
+
+[zkshell: 8] ls /
+[zookeeper]
+        
+

Next, create a new znode by running create /zk_test my_data. This creates a new znode and associates the string "my_data" with the node. + You should see:

+
+
+[zkshell: 9] create /zk_test my_data
+Created /zk_test
+      
+

Issue another ls / command to see what the directory looks like: +

+
+
+[zkshell: 11] ls /
+[zookeeper, zk_test]
+
+        
+

+ Notice that the zk_test directory has now been created. +

+

Next, verify that the data was associated with the znode by running the get command, as in: +

+
+
+[zkshell: 12] get /zk_test
+my_data
+cZxid = 5
+ctime = Fri Jun 05 13:57:06 PDT 2009
+mZxid = 5
+mtime = Fri Jun 05 13:57:06 PDT 2009
+pZxid = 5
+cversion = 0
+dataVersion = 0
+aclVersion = 0
+ephemeralOwner = 0
+dataLength = 7
+numChildren = 0
+        
+

We can change the data associated with zk_test by issuing the set command, as in: +

+
+
+[zkshell: 14] set /zk_test junk
+cZxid = 5
+ctime = Fri Jun 05 13:57:06 PDT 2009
+mZxid = 6
+mtime = Fri Jun 05 14:01:52 PDT 2009
+pZxid = 5
+cversion = 0
+dataVersion = 1
+aclVersion = 0
+ephemeralOwner = 0
+dataLength = 4
+numChildren = 0
+[zkshell: 15] get /zk_test
+junk
+cZxid = 5
+ctime = Fri Jun 05 13:57:06 PDT 2009
+mZxid = 6
+mtime = Fri Jun 05 14:01:52 PDT 2009
+pZxid = 5
+cversion = 0
+dataVersion = 1
+aclVersion = 0
+ephemeralOwner = 0
+dataLength = 4
+numChildren = 0
+      
+

+ (Notice we did a get after setting the data and it did, indeed, change.

+

Finally, let's delete the node by issuing: +

+
+
+[zkshell: 16] delete /zk_test
+[zkshell: 17] ls /
+[zookeeper]
+[zkshell: 18]
+
+

That's it for now. To explore more, continue with the rest of this document and see the Programmer's Guide.

+ +

Programming to ZooKeeper

+

ZooKeeper has a Java bindings and C bindings. They are + functionally equivalent. The C bindings exist in two variants: single + threaded and multi-threaded. These differ only in how the messaging loop + is done. For more information, see the Programming + Examples in the ZooKeeper Programmer's Guide for + sample code using of the different APIs.

+ +

Running Replicated ZooKeeper

+

Running ZooKeeper in standalone mode is convenient for evaluation, + some development, and testing. But in production, you should run + ZooKeeper in replicated mode. A replicated group of servers in the same + application is called a quorum, and in replicated + mode, all servers in the quorum have copies of the same configuration + file.

+
+
Note
+
+ +

+ For replicated mode, a minimum of three servers are required, + and it is strongly recommended that you have an odd number of + servers. If you only have two servers, then you are in a + situation where if one of them fails, there are not enough + machines to form a majority quorum. Two servers is inherently + less + stable than a single server, because there are two single + points of failure. +

+ +
+
+

+ The required + conf/zoo.cfg + file for replicated mode is similar to the one used in standalone + mode, but with a few differences. Here is an example: +

+
+tickTime=2000
+dataDir=/var/lib/zookeeper
+clientPort=2181
+initLimit=5
+syncLimit=2
+server.1=zoo1:2888:3888
+server.2=zoo2:2888:3888
+server.3=zoo3:2888:3888
+
+

The new entry, initLimit is + timeouts ZooKeeper uses to limit the length of time the ZooKeeper + servers in quorum have to connect to a leader. The entry syncLimit limits how far out of date a server can + be from a leader.

+

With both of these timeouts, you specify the unit of time using + tickTime. In this example, the timeout + for initLimit is 5 ticks at 2000 milleseconds a tick, or 10 + seconds.

+

The entries of the form server.X list the + servers that make up the ZooKeeper service. When the server starts up, + it knows which server it is by looking for the file + myid in the data directory. That file has the + contains the server number, in ASCII.

+

Finally, note the two port numbers after each server + name: " 2888" and "3888". Peers use the former port to connect + to other peers. Such a connection is necessary so that peers + can communicate, for example, to agree upon the order of + updates. More specifically, a ZooKeeper server uses this port + to connect followers to the leader. When a new leader arises, a + follower opens a TCP connection to the leader using this + port. Because the default leader election also uses TCP, we + currently require another port for leader election. This is the + second port in the server entry. +

+
+
Note
+
+ +

If you want to test multiple servers on a single + machine, specify the servername + as localhost with unique quorum & + leader election ports (i.e. 2888:3888, 2889:3889, 2890:3890 in + the example above) for each server.X in that server's config + file. Of course separate dataDirs and + distinct clientPorts are also necessary + (in the above replicated example, running on a + single localhost, you would still have + three config files).

+ +

Please be aware that setting up multiple servers on a single + machine will not create any redundancy. If something were to + happen which caused the machine to die, all of the zookeeper + servers would be offline. Full redundancy requires that each + server have its own machine. It must be a completely separate + physical server. Multiple virtual machines on the same physical + host are still vulnerable to the complete failure of that host.

+ +
+
+ +

Other Optimizations

+

There are a couple of other configuration parameters that can + greatly increase performance:

+
    + +
  • + +

    To get low latencies on updates it is important to + have a dedicated transaction log directory. By default + transaction logs are put in the same directory as the data + snapshots and myid file. The dataLogDir + parameters indicates a different directory to use for the + transaction logs.

    + +
  • + + +
  • + +

    +[tbd: what is the other config param?] +

    + +
  • + +
+
+ +

+ +

+
+ +
 
+
+ + + http://git-wip-us.apache.org/repos/asf/zookeeper/blob/74d00962/_released_docs/r3.5.4-beta/zookeeperStarted.pdf ---------------------------------------------------------------------- diff --git a/_released_docs/r3.5.4-beta/zookeeperStarted.pdf b/_released_docs/r3.5.4-beta/zookeeperStarted.pdf new file mode 100644 index 0000000..24b3716 Binary files /dev/null and b/_released_docs/r3.5.4-beta/zookeeperStarted.pdf differ http://git-wip-us.apache.org/repos/asf/zookeeper/blob/74d00962/_released_docs/r3.5.4-beta/zookeeperTutorial.html ---------------------------------------------------------------------- diff --git a/_released_docs/r3.5.4-beta/zookeeperTutorial.html b/_released_docs/r3.5.4-beta/zookeeperTutorial.html new file mode 100644 index 0000000..39bf10e --- /dev/null +++ b/_released_docs/r3.5.4-beta/zookeeperTutorial.html @@ -0,0 +1,925 @@ + + + + + + + +Programming with ZooKeeper - A basic tutorial + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + +
+
+
+
+ +
+ + +
+ +
+ +   +
+ + + + + +
+ +

Programming with ZooKeeper - A basic tutorial

+ + + + + + + +

Introduction

+
+

In this tutorial, we show simple implementations of barriers and + producer-consumer queues using ZooKeeper. We call the respective classes Barrier and Queue. + These examples assume that you have at least one ZooKeeper server running.

+

Both primitives use the following common excerpt of code:

+
+    static ZooKeeper zk = null;
+    static Integer mutex;
+
+    String root;
+
+    SyncPrimitive(String address) {
+        if(zk == null){
+            try {
+                System.out.println("Starting ZK:");
+                zk = new ZooKeeper(address, 3000, this);
+                mutex = new Integer(-1);
+                System.out.println("Finished starting ZK: " + zk);
+            } catch (IOException e) {
+                System.out.println(e.toString());
+                zk = null;
+            }
+        }
+    }
+
+    synchronized public void process(WatchedEvent event) {
+        synchronized (mutex) {
+            mutex.notify();
+        }
+    }
+
+

Both classes extend SyncPrimitive. In this way, we execute steps that are +common to all primitives in the constructor of SyncPrimitive. To keep the examples +simple, we create a ZooKeeper object the first time we instantiate either a barrier +object or a queue object, and we declare a static variable that is a reference +to this object. The subsequent instances of Barrier and Queue check whether a +ZooKeeper object exists. Alternatively, we could have the application creating a +ZooKeeper object and passing it to the constructor of Barrier and Queue.

+

+We use the process() method to process notifications triggered due to watches. +In the following discussion, we present code that sets watches. A watch is internal +structure that enables ZooKeeper to notify a client of a change to a node. For example, +if a client is waiting for other clients to leave a barrier, then it can set a watch and +wait for modifications to a particular node, which can indicate that it is the end of the wait. +This point becomes clear once we go over the examples. +

+
+ + + +

Barriers

+
+

+ A barrier is a primitive that enables a group of processes to synchronize the + beginning and the end of a computation. The general idea of this implementation + is to have a barrier node that serves the purpose of being a parent for individual + process nodes. Suppose that we call the barrier node "/b1". Each process "p" then + creates a node "/b1/p". Once enough processes have created their corresponding + nodes, joined processes can start the computation. +

+

In this example, each process instantiates a Barrier object, and its constructor takes as parameters:

+
    +
  • +

    the address of a ZooKeeper server (e.g., "zoo1.foo.com:2181")

    +
  • + +
  • +

    the path of the barrier node on ZooKeeper (e.g., "/b1")

    +
  • + +
  • +

    the size of the group of processes

    +
  • + +
+

The constructor of Barrier passes the address of the Zookeeper server to the +constructor of the parent class. The parent class creates a ZooKeeper instance if +one does not exist. The constructor of Barrier then creates a +barrier node on ZooKeeper, which is the parent node of all process nodes, and +we call root (Note: This is not the ZooKeeper root "/").

+
+        /**
+         * Barrier constructor
+         *
+         * @param address
+         * @param root
+         * @param size
+         */
+        Barrier(String address, String root, int size) {
+            super(address);
+            this.root = root;
+            this.size = size;
+
+            // Create barrier node
+            if (zk != null) {
+                try {
+                    Stat s = zk.exists(root, false);
+                    if (s == null) {
+                        zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
+                                CreateMode.PERSISTENT);
+                    }
+                } catch (KeeperException e) {
+                    System.out
+                            .println("Keeper exception when instantiating queue: "
+                                    + e.toString());
+                } catch (InterruptedException e) {
+                    System.out.println("Interrupted exception");
+                }
+            }
+
+            // My node name
+            try {
+                name = new String(InetAddress.getLocalHost().getCanonicalHostName().toString());
+            } catch (UnknownHostException e) {
+                System.out.println(e.toString());
+            }
+
+        }
+
+

+To enter the barrier, a process calls enter(). The process creates a node under +the root to represent it, using its host name to form the node name. It then wait +until enough processes have entered the barrier. A process does it by checking +the number of children the root node has with "getChildren()", and waiting for +notifications in the case it does not have enough. To receive a notification when +there is a change to the root node, a process has to set a watch, and does it +through the call to "getChildren()". In the code, we have that "getChildren()" +has two parameters. The first one states the node to read from, and the second is +a boolean flag that enables the process to set a watch. In the code the flag is true. +

+
+        /**
+         * Join barrier
+         *
+         * @return
+         * @throws KeeperException
+         * @throws InterruptedException
+         */
+
+        boolean enter() throws KeeperException, InterruptedException{
+            zk.create(root + "/" + name, new byte[0], Ids.OPEN_ACL_UNSAFE,
+                    CreateMode.EPHEMERAL_SEQUENTIAL);
+            while (true) {
+                synchronized (mutex) {
+                    List<String> list = zk.getChildren(root, true);
+
+                    if (list.size() < size) {
+                        mutex.wait();
+                    } else {
+                        return true;
+                    }
+                }
+            }
+        }
+
+

+Note that enter() throws both KeeperException and InterruptedException, so it is +the responsibility of the application to catch and handle such exceptions.

+

+Once the computation is finished, a process calls leave() to leave the barrier. +First it deletes its corresponding node, and then it gets the children of the root +node. If there is at least one child, then it waits for a notification (obs: note +that the second parameter of the call to getChildren() is true, meaning that +ZooKeeper has to set a watch on the the root node). Upon reception of a notification, +it checks once more whether the root node has any children.

+
+        /**
+         * Wait until all reach barrier
+         *
+         * @return
+         * @throws KeeperException
+         * @throws InterruptedException
+         */
+
+        boolean leave() throws KeeperException, InterruptedException{
+            zk.delete(root + "/" + name, 0);
+            while (true) {
+                synchronized (mutex) {
+                    List<String> list = zk.getChildren(root, true);
+                        if (list.size() > 0) {
+                            mutex.wait();
+                        } else {
+                            return true;
+                        }
+                    }
+                }
+        }
+    }
+
+
+ + +

Producer-Consumer Queues

+
+

+A producer-consumer queue is a distributed data structure that groups of processes +use to generate and consume items. Producer processes create new elements and add +them to the queue. Consumer processes remove elements from the list, and process them. +In this implementation, the elements are simple integers. The queue is represented +by a root node, and to add an element to the queue, a producer process creates a new node, +a child of the root node. +

+

+The following excerpt of code corresponds to the constructor of the object. As +with Barrier objects, it first calls the constructor of the parent class, SyncPrimitive, +that creates a ZooKeeper object if one doesn't exist. It then verifies if the root +node of the queue exists, and creates if it doesn't. +

+
+        /**
+         * Constructor of producer-consumer queue
+         *
+         * @param address
+         * @param name
+         */
+        Queue(String address, String name) {
+            super(address);
+            this.root = name;
+            // Create ZK node name
+            if (zk != null) {
+                try {
+                    Stat s = zk.exists(root, false);
+                    if (s == null) {
+                        zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
+                                CreateMode.PERSISTENT);
+                    }
+                } catch (KeeperException e) {
+                    System.out
+                            .println("Keeper exception when instantiating queue: "
+                                    + e.toString());
+                } catch (InterruptedException e) {
+                    System.out.println("Interrupted exception");
+                }
+            }
+        }
+
+

+A producer process calls "produce()" to add an element to the queue, and passes +an integer as an argument. To add an element to the queue, the method creates a +new node using "create()", and uses the SEQUENCE flag to instruct ZooKeeper to +append the value of the sequencer counter associated to the root node. In this way, +we impose a total order on the elements of the queue, thus guaranteeing that the +oldest element of the queue is the next one consumed. +

+
+        /**
+         * Add element to the queue.
+         *
+         * @param i
+         * @return
+         */
+
+        boolean produce(int i) throws KeeperException, InterruptedException{
+            ByteBuffer b = ByteBuffer.allocate(4);
+            byte[] value;
+
+            // Add child with value i
+            b.putInt(i);
+            value = b.array();
+            zk.create(root + "/element", value, Ids.OPEN_ACL_UNSAFE,
+                        CreateMode.PERSISTENT_SEQUENTIAL);
+
+            return true;
+        }
+
+

+To consume an element, a consumer process obtains the children of the root node, +reads the node with smallest counter value, and returns the element. Note that +if there is a conflict, then one of the two contending processes won't be able to +delete the node and the delete operation will throw an exception.

+

+A call to getChildren() returns the list of children in lexicographic order. +As lexicographic order does not necessary follow the numerical order of the counter +values, we need to decide which element is the smallest. To decide which one has +the smallest counter value, we traverse the list, and remove the prefix "element" +from each one.

+
+        /**
+         * Remove first element from the queue.
+         *
+         * @return
+         * @throws KeeperException
+         * @throws InterruptedException
+         */
+        int consume() throws KeeperException, InterruptedException{
+            int retvalue = -1;
+            Stat stat = null;
+
+            // Get the first element available
+            while (true) {
+                synchronized (mutex) {
+                    List<String> list = zk.getChildren(root, true);
+                    if (list.size() == 0) {
+                        System.out.println("Going to wait");
+                        mutex.wait();
+                    } else {
+                        Integer min = new Integer(list.get(0).substring(7));
+                        for(String s : list){
+                            Integer tempValue = new Integer(s.substring(7));
+                            //System.out.println("Temporary value: " + tempValue);
+                            if(tempValue < min) min = tempValue;
+                        }
+                        System.out.println("Temporary value: " + root + "/element" + min);
+                        byte[] b = zk.getData(root + "/element" + min,
+                                    false, stat);
+                        zk.delete(root + "/element" + min, 0);
+                        ByteBuffer buffer = ByteBuffer.wrap(b);
+                        retvalue = buffer.getInt();
+
+                        return retvalue;
+                    }
+                }
+            }
+        }
+    }
+
+
+ + + +

Complete example

+
+

+In the following section you can find a complete command line application to demonstrate the above mentioned +recipes. Use the following command to run it. +

+
+ZOOBINDIR="[path_to_distro]/bin"
+. "$ZOOBINDIR"/zkEnv.sh
+java SyncPrimitive [Test Type] [ZK server] [No of elements] [Client type]
+
+ +

Queue test

+

Start a producer to create 100 elements

+
+java SyncPrimitive qTest localhost 100 p
+
+

Start a consumer to consume 100 elements

+
+java SyncPrimitive qTest localhost 100 c
+
+ +

Barrier test

+

Start a barrier with 2 participants (start as many times as many participants you'd like to enter)

+
+java SyncPrimitive bTest localhost 2
+
+ +

Source Listing

+
+
SyncPrimitive.Java
+
+ +SyncPrimitive.Java + +
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.data.Stat;
+
+public class SyncPrimitive implements Watcher {
+
+    static ZooKeeper zk = null;
+    static Integer mutex;
+
+    String root;
+
+    SyncPrimitive(String address) {
+        if(zk == null){
+            try {
+                System.out.println("Starting ZK:");
+                zk = new ZooKeeper(address, 3000, this);
+                mutex = new Integer(-1);
+                System.out.println("Finished starting ZK: " + zk);
+            } catch (IOException e) {
+                System.out.println(e.toString());
+                zk = null;
+            }
+        }
+        //else mutex = new Integer(-1);
+    }
+
+    synchronized public void process(WatchedEvent event) {
+        synchronized (mutex) {
+            //System.out.println("Process: " + event.getType());
+            mutex.notify();
+        }
+    }
+
+    /**
+     * Barrier
+     */
+    static public class Barrier extends SyncPrimitive {
+        int size;
+        String name;
+
+        /**
+         * Barrier constructor
+         *
+         * @param address
+         * @param root
+         * @param size
+         */
+        Barrier(String address, String root, int size) {
+            super(address);
+            this.root = root;
+            this.size = size;
+
+            // Create barrier node
+            if (zk != null) {
+                try {
+                    Stat s = zk.exists(root, false);
+                    if (s == null) {
+                        zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
+                                CreateMode.PERSISTENT);
+                    }
+                } catch (KeeperException e) {
+                    System.out
+                            .println("Keeper exception when instantiating queue: "
+                                    + e.toString());
+                } catch (InterruptedException e) {
+                    System.out.println("Interrupted exception");
+                }
+            }
+
+            // My node name
+            try {
+                name = new String(InetAddress.getLocalHost().getCanonicalHostName().toString());
+            } catch (UnknownHostException e) {
+                System.out.println(e.toString());
+            }
+
+        }
+
+        /**
+         * Join barrier
+         *
+         * @return
+         * @throws KeeperException
+         * @throws InterruptedException
+         */
+
+        boolean enter() throws KeeperException, InterruptedException{
+            zk.create(root + "/" + name, new byte[0], Ids.OPEN_ACL_UNSAFE,
+                    CreateMode.EPHEMERAL_SEQUENTIAL);
+            while (true) {
+                synchronized (mutex) {
+                    List<String> list = zk.getChildren(root, true);
+
+                    if (list.size() < size) {
+                        mutex.wait();
+                    } else {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        /**
+         * Wait until all reach barrier
+         *
+         * @return
+         * @throws KeeperException
+         * @throws InterruptedException
+         */
+
+        boolean leave() throws KeeperException, InterruptedException{
+            zk.delete(root + "/" + name, 0);
+            while (true) {
+                synchronized (mutex) {
+                    List<String> list = zk.getChildren(root, true);
+                        if (list.size() > 0) {
+                            mutex.wait();
+                        } else {
+                            return true;
+                        }
+                    }
+                }
+        }
+    }
+
+    /**
+     * Producer-Consumer queue
+     */
+    static public class Queue extends SyncPrimitive {
+
+        /**
+         * Constructor of producer-consumer queue
+         *
+         * @param address
+         * @param name
+         */
+        Queue(String address, String name) {
+            super(address);
+            this.root = name;
+            // Create ZK node name
+            if (zk != null) {
+                try {
+                    Stat s = zk.exists(root, false);
+                    if (s == null) {
+                        zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
+                                CreateMode.PERSISTENT);
+                    }
+                } catch (KeeperException e) {
+                    System.out
+                            .println("Keeper exception when instantiating queue: "
+                                    + e.toString());
+                } catch (InterruptedException e) {
+                    System.out.println("Interrupted exception");
+                }
+            }
+        }
+
+        /**
+         * Add element to the queue.
+         *
+         * @param i
+         * @return
+         */
+
+        boolean produce(int i) throws KeeperException, InterruptedException{
+            ByteBuffer b = ByteBuffer.allocate(4);
+            byte[] value;
+
+            // Add child with value i
+            b.putInt(i);
+            value = b.array();
+            zk.create(root + "/element", value, Ids.OPEN_ACL_UNSAFE,
+                        CreateMode.PERSISTENT_SEQUENTIAL);
+
+            return true;
+        }
+
+
+        /**
+         * Remove first element from the queue.
+         *
+         * @return
+         * @throws KeeperException
+         * @throws InterruptedException
+         */
+        int consume() throws KeeperException, InterruptedException{
+            int retvalue = -1;
+            Stat stat = null;
+
+            // Get the first element available
+            while (true) {
+                synchronized (mutex) {
+                    List<String> list = zk.getChildren(root, true);
+                    if (list.size() == 0) {
+                        System.out.println("Going to wait");
+                        mutex.wait();
+                    } else {
+                        Integer min = new Integer(list.get(0).substring(7));
+                        String minNode = list.get(0);
+                        for(String s : list){
+                            Integer tempValue = new Integer(s.substring(7));
+                            //System.out.println("Temporary value: " + tempValue);
+                            if(tempValue < min) {
+                                min = tempValue;
+                                minNode = s;
+                            }
+                        }
+                        System.out.println("Temporary value: " + root + "/" + minNode);
+                        byte[] b = zk.getData(root + "/" + minNode,
+                        false, stat);
+                        zk.delete(root + "/" + minNode, 0);
+                        ByteBuffer buffer = ByteBuffer.wrap(b);
+                        retvalue = buffer.getInt();
+
+                        return retvalue;
+                    }
+                }
+            }
+        }
+    }
+
+    public static void main(String args[]) {
+        if (args[0].equals("qTest"))
+            queueTest(args);
+        else
+            barrierTest(args);
+
+    }
+
+    public static void queueTest(String args[]) {
+        Queue q = new Queue(args[1], "/app1");
+
+        System.out.println("Input: " + args[1]);
+        int i;
+        Integer max = new Integer(args[2]);
+
+        if (args[3].equals("p")) {
+            System.out.println("Producer");
+            for (i = 0; i < max; i++)
+                try{
+                    q.produce(10 + i);
+                } catch (KeeperException e){
+
+                } catch (InterruptedException e){
+
+                }
+        } else {
+            System.out.println("Consumer");
+
+            for (i = 0; i < max; i++) {
+                try{
+                    int r = q.consume();
+                    System.out.println("Item: " + r);
+                } catch (KeeperException e){
+                    i--;
+                } catch (InterruptedException e){
+
+                }
+            }
+        }
+    }
+
+    public static void barrierTest(String args[]) {
+        Barrier b = new Barrier(args[1], "/b1", new Integer(args[2]));
+        try{
+            boolean flag = b.enter();
+            System.out.println("Entered barrier: " + args[2]);
+            if(!flag) System.out.println("Error when entering the barrier");
+        } catch (KeeperException e){
+
+        } catch (InterruptedException e){
+
+        }
+
+        // Generate random integer
+        Random rand = new Random();
+        int r = rand.nextInt(100);
+        // Loop for rand iterations
+        for (int i = 0; i < r; i++) {
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException e) {
+
+            }
+        }
+        try{
+            b.leave();
+        } catch (KeeperException e){
+
+        } catch (InterruptedException e){
+
+        }
+        System.out.println("Left barrier");
+    }
+}
+
+
+
+
+ + +

+ +

+
+ +
 
+
+ + + http://git-wip-us.apache.org/repos/asf/zookeeper/blob/74d00962/_released_docs/r3.5.4-beta/zookeeperTutorial.pdf ---------------------------------------------------------------------- diff --git a/_released_docs/r3.5.4-beta/zookeeperTutorial.pdf b/_released_docs/r3.5.4-beta/zookeeperTutorial.pdf new file mode 100644 index 0000000..81cda17 Binary files /dev/null and b/_released_docs/r3.5.4-beta/zookeeperTutorial.pdf differ http://git-wip-us.apache.org/repos/asf/zookeeper/blob/74d00962/documentation.md ---------------------------------------------------------------------- diff --git a/documentation.md b/documentation.md index 593cf23..2c8e2e7 100644 --- a/documentation.md +++ b/documentation.md @@ -6,6 +6,7 @@ title: Documentation Setup instructions, programming guides, and other documentation are available for each stable version of ZooKeeper below: +* [ZooKeeper 3.5.4-beta](doc/r3.5.4-beta/index.html) * [ZooKeeper 3.5.3-beta](doc/r3.5.3-beta/index.html) * [ZooKeeper 3.5.2-alpha](doc/r3.5.2-alpha/index.html) * [ZooKeeper 3.5.1-alpha](doc/r3.5.1-alpha/index.html) http://git-wip-us.apache.org/repos/asf/zookeeper/blob/74d00962/releases.md ---------------------------------------------------------------------- diff --git a/releases.md b/releases.md index e7e0e01..47d9a0e 100644 --- a/releases.md +++ b/releases.md @@ -26,6 +26,12 @@ Release notes for Apache Zookeeper releases are available in Jira: [Browse relea ## News {#news} +### 17 May, 2018: release 3.5.4-beta available + +3.5.4-beta is the second beta in the planned 3.5 release line leading up to a stable 3.5 release. It comprises 113 bug fixes and improvements. + +Release 3.5.3 added a new feature ZOOKEEPER-2169 "Enable creation of nodes with TTLs". There was a major oversight when TTL nodes were implemented. The session ID generator for each server is seeded with the configured Server ID in the high byte. TTL Nodes were using the highest bit to denote a TTL node when used in the ephemeral owner. This meant that Server IDs > 127 that created ephemeral nodes would have those nodes always considered TTL nodes (with the TTL being essentially a random number). ZOOKEEPER-2901 fixes the issue. By default TTL is disabled and must now be enabled in zoo.cfg. When TTL Nodes are enabled, the max Server ID changes from 255 to 254. See the documentation for TTL in the administrator guide (or the referenced JIRAs) for more details. + ### 1 May, 2018: release 3.4.12 available This release fixes 22 issues, including issues that affect incorrect handling of the dataDir and the dataLogDir. See [ZooKeeper 3.4.12 Release Notes](https://zookeeper.apache.org/doc/r3.4.12/releasenotes.html) for details.