You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by ca...@apache.org on 2016/10/08 17:37:16 UTC

[1/2] zookeeper git commit: ZOOKEEPER-2169. Enable creation of nodes with TTLs. (Jordan Zimmerman via camille)

Repository: zookeeper
Updated Branches:
  refs/heads/master 8d0154bcc -> df5519ab9


ZOOKEEPER-2169. Enable creation of nodes with TTLs. (Jordan Zimmerman via camille)


Project: http://git-wip-us.apache.org/repos/asf/zookeeper/repo
Commit: http://git-wip-us.apache.org/repos/asf/zookeeper/commit/0a4971d5
Tree: http://git-wip-us.apache.org/repos/asf/zookeeper/tree/0a4971d5
Diff: http://git-wip-us.apache.org/repos/asf/zookeeper/diff/0a4971d5

Branch: refs/heads/master
Commit: 0a4971d5efb12a35a00cf794dce1efb3f08a998c
Parents: 8d0154b
Author: Camille Fournier <ca...@apache.org>
Authored: Fri Oct 7 15:51:52 2016 -0400
Committer: Camille Fournier <ca...@apache.org>
Committed: Fri Oct 7 15:51:52 2016 -0400

----------------------------------------------------------------------
 CHANGES.txt                                     |   2 +
 docs/zookeeperAdmin.html                        |   4 +-
 docs/zookeeperProgrammers.html                  |  20 +-
 .../content/xdocs/zookeeperAdmin.xml            |   4 +-
 .../content/xdocs/zookeeperProgrammers.xml      |  19 +-
 .../main/org/apache/zookeeper/CreateMode.java   |  41 +++-
 .../zookeeper/MultiTransactionRecord.java       |   6 +
 src/java/main/org/apache/zookeeper/Op.java      | 103 ++++++++-
 src/java/main/org/apache/zookeeper/ZooDefs.java |   2 +
 .../main/org/apache/zookeeper/ZooKeeper.java    | 108 +++++++---
 .../zookeeper/server/ContainerManager.java      |  18 ++
 .../org/apache/zookeeper/server/DataNode.java   |   7 +-
 .../org/apache/zookeeper/server/DataTree.java   |  46 +++-
 .../apache/zookeeper/server/EphemeralType.java  |  77 +++++++
 .../zookeeper/server/FinalRequestProcessor.java |   2 +
 .../zookeeper/server/PrepRequestProcessor.java  | 125 +++++++----
 .../org/apache/zookeeper/server/Request.java    |   4 +
 .../apache/zookeeper/server/TraceFormatter.java |   2 +
 .../server/quorum/CommitProcessor.java          |   1 +
 .../server/quorum/FollowerRequestProcessor.java |   1 +
 .../server/quorum/ObserverRequestProcessor.java |   1 +
 .../server/quorum/ReadOnlyRequestProcessor.java |   1 +
 .../zookeeper/server/util/SerializeUtils.java   |   4 +
 .../apache/zookeeper/server/CreateTTLTest.java  | 213 +++++++++++++++++++
 .../zookeeper/server/EphemeralTypeTest.java     |  58 +++++
 src/zookeeper.jute                              |  14 ++
 26 files changed, 779 insertions(+), 104 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index e10bbdc..4a701c5 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -14,6 +14,8 @@ NEW FEATURES:
 
   ZOOKEEPER-1962: Add a CLI command to recursively list a znode and
   children (Gautam Gopalakrishnan, Hongchao Deng, Enis Soztutar via phunt)
+  
+  ZOOKEEPER-2169: Enable creation of nodes with TTLs (Jordan Zimmerman via camille)
 
 BUGFIXES:
   ZOOKEEPER-1784 wrong check for COMMITANDACTIVATE in observer code, Learner.java (rgs via shralex).

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/docs/zookeeperAdmin.html
----------------------------------------------------------------------
diff --git a/docs/zookeeperAdmin.html b/docs/zookeeperAdmin.html
index 2cd69ce..896090f 100644
--- a/docs/zookeeperAdmin.html
+++ b/docs/zookeeperAdmin.html
@@ -1787,7 +1787,7 @@ server.3=zoo3:2888:3888</pre>
 <p>
 <strong>New in 3.6.0:</strong> The
                 time interval in milliseconds for each check of candidate container
-                nodes. Default is "60000".</p>
+                and ttl nodes. Default is "60000".</p>
 </dd>
 
           
@@ -1798,7 +1798,7 @@ server.3=zoo3:2888:3888</pre>
 <p>(Java system property only)</p>
 <p>
 <strong>New in 3.6.0:</strong> The
-                maximum number of container nodes that can be deleted per
+                maximum number of container and ttl nodes that can be deleted per
                 minute. This prevents herding during container deletion.
                 Default is "10000".</p>
 </dd>

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/docs/zookeeperProgrammers.html
----------------------------------------------------------------------
diff --git a/docs/zookeeperProgrammers.html b/docs/zookeeperProgrammers.html
index 79914fc..35f9bf8 100644
--- a/docs/zookeeperProgrammers.html
+++ b/docs/zookeeperProgrammers.html
@@ -219,6 +219,9 @@ document.write("Last Published: " + document.lastModified);
 <li>
 <a href="#Container+Nodes">Container Nodes</a>
 </li>
+<li>
+<a href="#TTL+Nodes">TTL Nodes</a>
+</li>
 </ul>
 </li>
 <li>
@@ -575,15 +578,24 @@ document.write("Last Published: " + document.lastModified);
 <p>
 <strong>Added in 3.6.0</strong>
 </p>
-<p>ZooKeeper has the notion of container nodes. Container nodes are
-          special purpose nodes useful for recipes such as leader, lock, etc.
+<p>ZooKeeper has the notion of container znodes. Container znodes are
+          special purpose znodes useful for recipes such as leader, lock, etc.
           When the last child of a container is deleted, the container becomes
           a candidate to be deleted by the server at some point in the future.</p>
 <p>Given this property, you should be prepared to get
           KeeperException.NoNodeException when creating children inside of
-          container nodes. i.e. when creating child nodes inside of container nodes
+          container znodes. i.e. when creating child znodes inside of container znodes
           always check for KeeperException.NoNodeException and recreate the container
-          node when it occurs.</p>
+          znode when it occurs.</p>
+<a name="TTL+Nodes"></a>
+<h4>TTL Nodes</h4>
+<p>
+<strong>Added in 3.6.0</strong>
+</p>
+<p>When creating PERSISTENT or PERSISTENT_SEQUENTIAL znodes,
+          you can optionally set a TTL in milliseconds for the znode. If the znode
+          is not modified within the TTL and has no children it will become a candidate
+          to be deleted by the server at some point in the future.</p>
 <a name="sc_timeInZk"></a>
 <h3 class="h4">Time in ZooKeeper</h3>
 <p>ZooKeeper tracks time multiple ways:</p>

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/docs/src/documentation/content/xdocs/zookeeperAdmin.xml
----------------------------------------------------------------------
diff --git a/src/docs/src/documentation/content/xdocs/zookeeperAdmin.xml b/src/docs/src/documentation/content/xdocs/zookeeperAdmin.xml
index f729095..5a30da8 100644
--- a/src/docs/src/documentation/content/xdocs/zookeeperAdmin.xml
+++ b/src/docs/src/documentation/content/xdocs/zookeeperAdmin.xml
@@ -1439,7 +1439,7 @@ server.3=zoo3:2888:3888</programlisting>
 
               <para><emphasis role="bold">New in 3.6.0:</emphasis> The
                 time interval in milliseconds for each check of candidate container
-                nodes. Default is "60000".</para>
+                and ttl nodes. Default is "60000".</para>
             </listitem>
           </varlistentry>
 
@@ -1450,7 +1450,7 @@ server.3=zoo3:2888:3888</programlisting>
               <para>(Java system property only)</para>
 
               <para><emphasis role="bold">New in 3.6.0:</emphasis> The
-                maximum number of container nodes that can be deleted per
+                maximum number of container and ttl nodes that can be deleted per
                 minute. This prevents herding during container deletion.
                 Default is "10000".</para>
             </listitem>

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/docs/src/documentation/content/xdocs/zookeeperProgrammers.xml
----------------------------------------------------------------------
diff --git a/src/docs/src/documentation/content/xdocs/zookeeperProgrammers.xml b/src/docs/src/documentation/content/xdocs/zookeeperProgrammers.xml
index f462551..8a223dd 100644
--- a/src/docs/src/documentation/content/xdocs/zookeeperProgrammers.xml
+++ b/src/docs/src/documentation/content/xdocs/zookeeperProgrammers.xml
@@ -249,16 +249,27 @@
 
         <para><emphasis role="bold">Added in 3.6.0</emphasis></para>
 
-        <para>ZooKeeper has the notion of container nodes. Container nodes are
-          special purpose nodes useful for recipes such as leader, lock, etc.
+        <para>ZooKeeper has the notion of container znodes. Container znodes are
+          special purpose znodes useful for recipes such as leader, lock, etc.
           When the last child of a container is deleted, the container becomes
           a candidate to be deleted by the server at some point in the future.</para>
 
         <para>Given this property, you should be prepared to get
           KeeperException.NoNodeException when creating children inside of
-          container nodes. i.e. when creating child nodes inside of container nodes
+          container znodes. i.e. when creating child znodes inside of container znodes
           always check for KeeperException.NoNodeException and recreate the container
-          node when it occurs.</para>
+          znode when it occurs.</para>
+      </section>
+
+      <section>
+        <title>TTL Nodes</title>
+
+        <para><emphasis role="bold">Added in 3.6.0</emphasis></para>
+
+        <para>When creating PERSISTENT or PERSISTENT_SEQUENTIAL znodes,
+          you can optionally set a TTL in milliseconds for the znode. If the znode
+          is not modified within the TTL and has no children it will become a candidate
+          to be deleted by the server at some point in the future.</para>
       </section>
     </section>
 

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/CreateMode.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/CreateMode.java b/src/java/main/org/apache/zookeeper/CreateMode.java
index a5c1bb1..35a5730 100644
--- a/src/java/main/org/apache/zookeeper/CreateMode.java
+++ b/src/java/main/org/apache/zookeeper/CreateMode.java
@@ -28,21 +28,21 @@ public enum CreateMode {
     /**
      * The znode will not be automatically deleted upon client's disconnect.
      */
-    PERSISTENT (0, false, false, false),
+    PERSISTENT (0, false, false, false, false),
     /**
     * The znode will not be automatically deleted upon client's disconnect,
     * and its name will be appended with a monotonically increasing number.
     */
-    PERSISTENT_SEQUENTIAL (2, false, true, false),
+    PERSISTENT_SEQUENTIAL (2, false, true, false, false),
     /**
      * The znode will be deleted upon the client's disconnect.
      */
-    EPHEMERAL (1, true, false, false),
+    EPHEMERAL (1, true, false, false, false),
     /**
      * The znode will be deleted upon the client's disconnect, and its name
      * will be appended with a monotonically increasing number.
      */
-    EPHEMERAL_SEQUENTIAL (3, true, true, false),
+    EPHEMERAL_SEQUENTIAL (3, true, true, false, false),
     /**
      * The znode will be a container node. Container
      * nodes are special purpose nodes useful for recipes such as leader, lock,
@@ -52,7 +52,20 @@ public enum CreateMode {
      * {@link org.apache.zookeeper.KeeperException.NoNodeException}
      * when creating children inside of this container node.
      */
-    CONTAINER (4, false, false, true);
+    CONTAINER (4, false, false, true, false),
+    /**
+     * The znode will not be automatically deleted upon client's disconnect.
+     * However if the znode has not been modified within the given TTL, it
+     * will be deleted once it has no children.
+     */
+    PERSISTENT_WITH_TTL(5, false, false, false, true),
+    /**
+     * The znode will not be automatically deleted upon client's disconnect,
+     * and its name will be appended with a monotonically increasing number.
+     * However if the znode has not been modified within the given TTL, it
+     * will be deleted once it has no children.
+     */
+    PERSISTENT_SEQUENTIAL_WITH_TTL(6, false, true, false, true);
 
     private static final Logger LOG = LoggerFactory.getLogger(CreateMode.class);
 
@@ -60,13 +73,15 @@ public enum CreateMode {
     private boolean sequential;
     private final boolean isContainer;
     private int flag;
+    private boolean isTTL;
 
     CreateMode(int flag, boolean ephemeral, boolean sequential,
-               boolean isContainer) {
+               boolean isContainer, boolean isTTL) {
         this.flag = flag;
         this.ephemeral = ephemeral;
         this.sequential = sequential;
         this.isContainer = isContainer;
+        this.isTTL = isTTL;
     }
 
     public boolean isEphemeral() { 
@@ -81,6 +96,10 @@ public enum CreateMode {
         return isContainer;
     }
 
+    public boolean isTTL() {
+        return isTTL;
+    }
+
     public int toFlag() {
         return flag;
     }
@@ -100,6 +119,10 @@ public enum CreateMode {
 
         case 4: return CreateMode.CONTAINER;
 
+        case 5: return CreateMode.PERSISTENT_WITH_TTL;
+
+        case 6: return CreateMode.PERSISTENT_SEQUENTIAL_WITH_TTL;
+
         default:
             String errMsg = "Received an invalid flag value: " + flag
                     + " to convert to a CreateMode";
@@ -128,6 +151,12 @@ public enum CreateMode {
             case 4:
                 return CreateMode.CONTAINER;
 
+            case 5:
+                return CreateMode.PERSISTENT_WITH_TTL;
+
+            case 6:
+                return CreateMode.PERSISTENT_SEQUENTIAL_WITH_TTL;
+
             default:
                 return defaultMode;
         }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/MultiTransactionRecord.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/MultiTransactionRecord.java b/src/java/main/org/apache/zookeeper/MultiTransactionRecord.java
index fa46b48..336a677 100644
--- a/src/java/main/org/apache/zookeeper/MultiTransactionRecord.java
+++ b/src/java/main/org/apache/zookeeper/MultiTransactionRecord.java
@@ -68,6 +68,7 @@ public class MultiTransactionRecord implements Record, Iterable<Op> {
             switch (op.getType()) {
                 case ZooDefs.OpCode.create:
                 case ZooDefs.OpCode.create2:
+                case ZooDefs.OpCode.createTTL:
                 case ZooDefs.OpCode.createContainer:
                 case ZooDefs.OpCode.delete:
                 case ZooDefs.OpCode.setData:
@@ -97,6 +98,11 @@ public class MultiTransactionRecord implements Record, Iterable<Op> {
                     cr.deserialize(archive, tag);
                     add(Op.create(cr.getPath(), cr.getData(), cr.getAcl(), cr.getFlags()));
                     break;
+                case ZooDefs.OpCode.createTTL:
+                    CreateTTLRequest crTtl = new CreateTTLRequest();
+                    crTtl.deserialize(archive, tag);
+                    add(Op.create(crTtl.getPath(), crTtl.getData(), crTtl.getAcl(), crTtl.getFlags(), crTtl.getTtl()));
+                    break;
                 case ZooDefs.OpCode.delete:
                     DeleteRequest dr = new DeleteRequest();
                     dr.deserialize(archive, tag);

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/Op.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/Op.java b/src/java/main/org/apache/zookeeper/Op.java
index b6c3a95..c73cc79 100644
--- a/src/java/main/org/apache/zookeeper/Op.java
+++ b/src/java/main/org/apache/zookeeper/Op.java
@@ -22,8 +22,10 @@ import org.apache.zookeeper.common.PathUtils;
 import org.apache.zookeeper.data.ACL;
 import org.apache.zookeeper.proto.CheckVersionRequest;
 import org.apache.zookeeper.proto.CreateRequest;
+import org.apache.zookeeper.proto.CreateTTLRequest;
 import org.apache.zookeeper.proto.DeleteRequest;
 import org.apache.zookeeper.proto.SetDataRequest;
+import org.apache.zookeeper.server.EphemeralType;
 
 import java.util.Arrays;
 import java.util.Iterator;
@@ -71,6 +73,32 @@ public abstract class Op {
     }
 
     /**
+     * Constructs a create operation.  Arguments are as for the ZooKeeper method of the same name
+     * but adding an optional ttl
+     * @see ZooKeeper#create(String, byte[], java.util.List, CreateMode)
+     * @see CreateMode#fromFlag(int)
+     *
+     * @param path
+     *                the path for the node
+     * @param data
+     *                the initial data for the node
+     * @param acl
+     *                the acl for the node
+     * @param flags
+     *                specifying whether the node to be created is ephemeral
+     *                and/or sequential but using the integer encoding.
+     * @param ttl
+     *                optional ttl or 0 (flags must imply a TTL creation mode)
+     */
+    public static Op create(String path, byte[] data, List<ACL> acl, int flags, long ttl) {
+        CreateMode createMode = CreateMode.fromFlag(flags, CreateMode.PERSISTENT);
+        if (createMode.isTTL()) {
+            return new CreateTTL(path, data, acl, createMode, ttl);
+        }
+        return new Create(path, data, acl, flags);
+    }
+
+    /**
      * Constructs a create operation.  Arguments are as for the ZooKeeper method of the same name.
      * @see ZooKeeper#create(String, byte[], java.util.List, CreateMode)
      *
@@ -89,6 +117,30 @@ public abstract class Op {
     }
 
     /**
+     * Constructs a create operation.  Arguments are as for the ZooKeeper method of the same name
+     * but adding an optional ttl
+     * @see ZooKeeper#create(String, byte[], java.util.List, CreateMode)
+     *
+     * @param path
+     *                the path for the node
+     * @param data
+     *                the initial data for the node
+     * @param acl
+     *                the acl for the node
+     * @param createMode
+     *                specifying whether the node to be created is ephemeral
+     *                and/or sequential
+     * @param ttl
+     *                optional ttl or 0 (createMode must imply a TTL)
+     */
+    public static Op create(String path, byte[] data, List<ACL> acl, CreateMode createMode, long ttl) {
+        if (createMode.isTTL()) {
+            return new CreateTTL(path, data, acl, createMode, ttl);
+        }
+        return new Create(path, data, acl, createMode);
+    }
+
+    /**
      * Constructs a delete operation.  Arguments are as for the ZooKeeper method of the same name.
      * @see ZooKeeper#delete(String, int)
      *
@@ -178,9 +230,9 @@ public abstract class Op {
     // these internal classes are public, but should not generally be referenced.
     //
     public static class Create extends Op {
-        private byte[] data;
-        private List<ACL> acl;
-        private int flags;
+        protected byte[] data;
+        protected List<ACL> acl;
+        protected int flags;
 
         private Create(String path, byte[] data, List<ACL> acl, int flags) {
             super(getOpcode(CreateMode.fromFlag(flags, CreateMode.PERSISTENT)), path);
@@ -190,6 +242,9 @@ public abstract class Op {
         }
 
         private static int getOpcode(CreateMode createMode) {
+            if (createMode.isTTL()) {
+                return ZooDefs.OpCode.createTTL;
+            }
             return createMode.isContainer() ? ZooDefs.OpCode.createContainer : ZooDefs.OpCode.create;
         }
 
@@ -243,6 +298,48 @@ public abstract class Op {
         void validate() throws KeeperException {
             CreateMode createMode = CreateMode.fromFlag(flags);
             PathUtils.validatePath(getPath(), createMode.isSequential());
+            EphemeralType.validateTTL(createMode, -1);
+        }
+    }
+
+    public static class CreateTTL extends Create {
+        private final long ttl;
+
+        private CreateTTL(String path, byte[] data, List<ACL> acl, int flags, long ttl) {
+            super(path, data, acl, flags);
+            this.ttl = ttl;
+        }
+
+        private CreateTTL(String path, byte[] data, List<ACL> acl, CreateMode createMode, long ttl) {
+            super(path, data, acl, createMode);
+            this.ttl = ttl;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            return super.equals(o) && (o instanceof CreateTTL) && (ttl == ((CreateTTL)o).ttl);
+        }
+
+        @Override
+        public int hashCode() {
+            return super.hashCode() + (int)(ttl ^ (ttl >>> 32));
+        }
+
+        @Override
+        public Record toRequestRecord() {
+            return new CreateTTLRequest(getPath(), data, acl, flags, ttl);
+        }
+
+        @Override
+        Op withChroot(String path) {
+            return new CreateTTL(path, data, acl, flags, ttl);
+        }
+
+        @Override
+        void validate() throws KeeperException {
+            CreateMode createMode = CreateMode.fromFlag(flags);
+            PathUtils.validatePath(getPath(), createMode.isSequential());
+            EphemeralType.validateTTL(createMode, ttl);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/ZooDefs.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/ZooDefs.java b/src/java/main/org/apache/zookeeper/ZooDefs.java
index 021d421..cd26c73 100644
--- a/src/java/main/org/apache/zookeeper/ZooDefs.java
+++ b/src/java/main/org/apache/zookeeper/ZooDefs.java
@@ -69,6 +69,8 @@ public class ZooDefs {
 
         public final int deleteContainer = 20;
 
+        public final int createTTL = 21;
+
         public final int auth = 100;
 
         public final int setWatches = 101;

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/ZooKeeper.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/ZooKeeper.java b/src/java/main/org/apache/zookeeper/ZooKeeper.java
index f2ec3d7..1c9ed4e 100644
--- a/src/java/main/org/apache/zookeeper/ZooKeeper.java
+++ b/src/java/main/org/apache/zookeeper/ZooKeeper.java
@@ -18,18 +18,6 @@
 
 package org.apache.zookeeper;
 
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 import org.apache.jute.Record;
 import org.apache.zookeeper.AsyncCallback.ACLCallback;
 import org.apache.zookeeper.AsyncCallback.Children2Callback;
@@ -45,10 +33,10 @@ import org.apache.zookeeper.KeeperException.NoWatcherException;
 import org.apache.zookeeper.OpResult.ErrorResult;
 import org.apache.zookeeper.Watcher.Event.EventType;
 import org.apache.zookeeper.Watcher.WatcherType;
-import org.apache.zookeeper.client.ZKClientConfig;
 import org.apache.zookeeper.client.ConnectStringParser;
 import org.apache.zookeeper.client.HostProvider;
 import org.apache.zookeeper.client.StaticHostProvider;
+import org.apache.zookeeper.client.ZKClientConfig;
 import org.apache.zookeeper.client.ZooKeeperSaslClient;
 import org.apache.zookeeper.common.PathUtils;
 import org.apache.zookeeper.common.StringUtils;
@@ -58,6 +46,7 @@ import org.apache.zookeeper.proto.CheckWatchesRequest;
 import org.apache.zookeeper.proto.Create2Response;
 import org.apache.zookeeper.proto.CreateRequest;
 import org.apache.zookeeper.proto.CreateResponse;
+import org.apache.zookeeper.proto.CreateTTLRequest;
 import org.apache.zookeeper.proto.DeleteRequest;
 import org.apache.zookeeper.proto.ExistsRequest;
 import org.apache.zookeeper.proto.GetACLRequest;
@@ -79,9 +68,22 @@ import org.apache.zookeeper.proto.SetDataResponse;
 import org.apache.zookeeper.proto.SyncRequest;
 import org.apache.zookeeper.proto.SyncResponse;
 import org.apache.zookeeper.server.DataTree;
+import org.apache.zookeeper.server.EphemeralType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * This is the main class of ZooKeeper client library. To use a ZooKeeper
  * service, an application must first instantiate an object of ZooKeeper class.
@@ -1393,6 +1395,7 @@ public class ZooKeeper {
     {
         final String clientPath = path;
         PathUtils.validatePath(clientPath, createMode.isSequential());
+        EphemeralType.validateTTL(createMode, -1);
 
         final String serverPath = prependChroot(clientPath);
 
@@ -1479,23 +1482,34 @@ public class ZooKeeper {
     public String create(final String path, byte data[], List<ACL> acl,
             CreateMode createMode, Stat stat)
             throws KeeperException, InterruptedException {
+        return create(path, data, acl, createMode, stat, -1);
+    }
+
+    /**
+     * same as {@link #create(String, byte[], List, CreateMode, Stat)} but
+     * allows for specifying a TTL when mode is {@link CreateMode#PERSISTENT_WITH_TTL}
+     * or {@link CreateMode#PERSISTENT_SEQUENTIAL_WITH_TTL}. If the znode has not been modified
+     * within the given TTL, it will be deleted once it has no children. The TTL unit is
+     * milliseconds and must be greater than 0 and less than or equal to
+     * {@link EphemeralType#MAX_TTL}.
+     */
+    public String create(final String path, byte data[], List<ACL> acl,
+            CreateMode createMode, Stat stat, long ttl)
+            throws KeeperException, InterruptedException {
         final String clientPath = path;
         PathUtils.validatePath(clientPath, createMode.isSequential());
+        EphemeralType.validateTTL(createMode, ttl);
 
         final String serverPath = prependChroot(clientPath);
 
         RequestHeader h = new RequestHeader();
-        h.setType(createMode.isContainer() ? ZooDefs.OpCode.createContainer : ZooDefs.OpCode.create2);
-        CreateRequest request = new CreateRequest();
+        setCreateHeader(createMode, h);
         Create2Response response = new Create2Response();
-        request.setData(data);
-        request.setFlags(createMode.toFlag());
-        request.setPath(serverPath);
         if (acl != null && acl.size() == 0) {
             throw new KeeperException.InvalidACLException();
         }
-        request.setAcl(acl);
-        ReplyHeader r = cnxn.submitRequest(h, request, response, null);
+        Record record = makeCreateRecord(createMode, serverPath, data, acl, ttl);
+        ReplyHeader r = cnxn.submitRequest(h, record, response, null);
         if (r.getErr() != 0) {
             throw KeeperException.create(KeeperException.Code.get(r.getErr()),
                     clientPath);
@@ -1510,6 +1524,35 @@ public class ZooKeeper {
         }
     }
 
+    private void setCreateHeader(CreateMode createMode, RequestHeader h) {
+        if (createMode.isTTL()) {
+            h.setType(ZooDefs.OpCode.createTTL);
+        } else {
+            h.setType(createMode.isContainer() ? ZooDefs.OpCode.createContainer : ZooDefs.OpCode.create2);
+        }
+    }
+
+    private Record makeCreateRecord(CreateMode createMode, String serverPath, byte[] data, List<ACL> acl, long ttl) {
+        Record record;
+        if (createMode.isTTL()) {
+            CreateTTLRequest request = new CreateTTLRequest();
+            request.setData(data);
+            request.setFlags(createMode.toFlag());
+            request.setPath(serverPath);
+            request.setAcl(acl);
+            request.setTtl(ttl);
+            record = request;
+        } else {
+            CreateRequest request = new CreateRequest();
+            request.setData(data);
+            request.setFlags(createMode.toFlag());
+            request.setPath(serverPath);
+            request.setAcl(acl);
+            record = request;
+        }
+        return record;
+    }
+
     /**
      * The asynchronous version of create.
      *
@@ -1520,6 +1563,7 @@ public class ZooKeeper {
     {
         final String clientPath = path;
         PathUtils.validatePath(clientPath, createMode.isSequential());
+        EphemeralType.validateTTL(createMode, -1);
 
         final String serverPath = prependChroot(clientPath);
 
@@ -1544,21 +1588,29 @@ public class ZooKeeper {
     public void create(final String path, byte data[], List<ACL> acl,
             CreateMode createMode, Create2Callback cb, Object ctx)
     {
+        create(path, data, acl, createMode, cb, ctx, -1);
+    }
+
+    /**
+     * The asynchronous version of create with ttl.
+     *
+     * @see #create(String, byte[], List, CreateMode, Stat, long)
+     */
+    public void create(final String path, byte data[], List<ACL> acl,
+            CreateMode createMode, Create2Callback cb, Object ctx, long ttl)
+    {
         final String clientPath = path;
         PathUtils.validatePath(clientPath, createMode.isSequential());
+        EphemeralType.validateTTL(createMode, ttl);
 
         final String serverPath = prependChroot(clientPath);
 
         RequestHeader h = new RequestHeader();
-        h.setType(createMode.isContainer() ? ZooDefs.OpCode.createContainer : ZooDefs.OpCode.create2);
-        CreateRequest request = new CreateRequest();
-        Create2Response response = new Create2Response();
+        setCreateHeader(createMode, h);
         ReplyHeader r = new ReplyHeader();
-        request.setData(data);
-        request.setFlags(createMode.toFlag());
-        request.setPath(serverPath);
-        request.setAcl(acl);
-        cnxn.queuePacket(h, r, request, response, cb, clientPath,
+        Create2Response response = new Create2Response();
+        Record record = makeCreateRecord(createMode, serverPath, data, acl, ttl);
+        cnxn.queuePacket(h, r, record, response, cb, clientPath,
                 serverPath, ctx, null);
     }
 

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/server/ContainerManager.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/ContainerManager.java b/src/java/main/org/apache/zookeeper/server/ContainerManager.java
index 7eca968..8834f29 100644
--- a/src/java/main/org/apache/zookeeper/server/ContainerManager.java
+++ b/src/java/main/org/apache/zookeeper/server/ContainerManager.java
@@ -153,6 +153,24 @@ public class ContainerManager {
                 candidates.add(containerPath);
             }
         }
+        for (String ttlPath : zkDb.getDataTree().getTtls()) {
+            DataNode node = zkDb.getDataTree().getNode(ttlPath);
+            if (node != null) {
+                Set<String> children = node.getChildren();
+                if ((children == null) || (children.size() == 0)) {
+                    long elapsed = getElapsed(node);
+                    long ttl = EphemeralType.getTTL(node.stat.getEphemeralOwner());
+                    if ((ttl != 0) && (elapsed > ttl)) {
+                        candidates.add(ttlPath);
+                    }
+                }
+            }
+        }
         return candidates;
     }
+
+    // VisibleForTesting
+    protected long getElapsed(DataNode node) {
+        return Time.currentWallTime() - node.stat.getMtime();
+    }
 }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/server/DataNode.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/DataNode.java b/src/java/main/org/apache/zookeeper/server/DataNode.java
index 40cc8ea..ce359cd 100644
--- a/src/java/main/org/apache/zookeeper/server/DataNode.java
+++ b/src/java/main/org/apache/zookeeper/server/DataNode.java
@@ -159,8 +159,11 @@ public class DataNode implements Record {
     }
 
     private static long getClientEphemeralOwner(StatPersisted stat) {
-        return (stat.getEphemeralOwner() == DataTree.CONTAINER_EPHEMERAL_OWNER)
-                ? 0 : stat.getEphemeralOwner();
+        EphemeralType ephemeralType = EphemeralType.get(stat.getEphemeralOwner());
+        if (ephemeralType != EphemeralType.NORMAL) {
+            return 0;
+        }
+        return stat.getEphemeralOwner();
     }
 
     synchronized public void deserialize(InputArchive archive, String tag)

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/server/DataTree.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/DataTree.java b/src/java/main/org/apache/zookeeper/server/DataTree.java
index 06c80d3..4666578 100644
--- a/src/java/main/org/apache/zookeeper/server/DataTree.java
+++ b/src/java/main/org/apache/zookeeper/server/DataTree.java
@@ -41,6 +41,7 @@ import org.apache.zookeeper.data.Stat;
 import org.apache.zookeeper.data.StatPersisted;
 import org.apache.zookeeper.txn.CheckVersionTxn;
 import org.apache.zookeeper.txn.CreateContainerTxn;
+import org.apache.zookeeper.txn.CreateTTLTxn;
 import org.apache.zookeeper.txn.CreateTxn;
 import org.apache.zookeeper.txn.DeleteTxn;
 import org.apache.zookeeper.txn.ErrorTxn;
@@ -78,8 +79,6 @@ import java.util.concurrent.ConcurrentHashMap;
 public class DataTree {
     private static final Logger LOG = LoggerFactory.getLogger(DataTree.class);
 
-    public static final long CONTAINER_EPHEMERAL_OWNER = Long.MIN_VALUE;
-
     /**
      * This hashtable provides a fast lookup to the datanodes. The tree is the
      * source of truth and is where all the locking occurs
@@ -137,6 +136,12 @@ public class DataTree {
     private final Set<String> containers =
             Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
 
+    /**
+     * This set contains the paths of all ttl nodes
+     */
+    private final Set<String> ttls =
+            Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
+
     private final ReferenceCountedACLCache aclCache = new ReferenceCountedACLCache();
 
     @SuppressWarnings("unchecked")
@@ -156,6 +161,10 @@ public class DataTree {
         return new HashSet<String>(containers);
     }
 
+    public Set<String> getTtls() {
+        return new HashSet<String>(ttls);
+    }
+
     public Collection<Long> getSessions() {
         return ephemerals.keySet();
     }
@@ -455,8 +464,11 @@ public class DataTree {
             DataNode child = new DataNode(data, longval, stat);
             parent.addChild(childName);
             nodes.put(path, child);
-            if (ephemeralOwner == CONTAINER_EPHEMERAL_OWNER) {
+            EphemeralType ephemeralType = EphemeralType.get(ephemeralOwner);
+            if (ephemeralType == EphemeralType.CONTAINER) {
                 containers.add(path);
+            } else if (ephemeralType == EphemeralType.TTL) {
+                ttls.add(path);
             } else if (ephemeralOwner != 0) {
                 HashSet<String> list = ephemerals.get(ephemeralOwner);
                 if (list == null) {
@@ -526,8 +538,11 @@ public class DataTree {
             parent.removeChild(childName);
             parent.stat.setPzxid(zxid);
             long eowner = node.stat.getEphemeralOwner();
-            if (eowner == CONTAINER_EPHEMERAL_OWNER) {
+            EphemeralType ephemeralType = EphemeralType.get(eowner);
+            if (ephemeralType == EphemeralType.CONTAINER) {
                 containers.remove(path);
+            } else if (ephemeralType == EphemeralType.TTL) {
+                ttls.remove(path);
             } else if (eowner != 0) {
                 HashSet<String> nodes = ephemerals.get(eowner);
                 if (nodes != null) {
@@ -790,6 +805,19 @@ public class DataTree {
                             header.getZxid(), header.getTime(), stat);
                     rc.stat = stat;
                     break;
+                case OpCode.createTTL:
+                    CreateTTLTxn createTtlTxn = (CreateTTLTxn) txn;
+                    rc.path = createTtlTxn.getPath();
+                    stat = new Stat();
+                    createNode(
+                            createTtlTxn.getPath(),
+                            createTtlTxn.getData(),
+                            createTtlTxn.getAcl(),
+                            EphemeralType.ttlToEphemeralOwner(createTtlTxn.getTtl()),
+                            createTtlTxn.getParentCVersion(),
+                            header.getZxid(), header.getTime(), stat);
+                    rc.stat = stat;
+                    break;
                 case OpCode.createContainer:
                     CreateContainerTxn createContainerTxn = (CreateContainerTxn) txn;
                     rc.path = createContainerTxn.getPath();
@@ -798,7 +826,7 @@ public class DataTree {
                             createContainerTxn.getPath(),
                             createContainerTxn.getData(),
                             createContainerTxn.getAcl(),
-                            CONTAINER_EPHEMERAL_OWNER,
+                            EphemeralType.CONTAINER_EPHEMERAL_OWNER,
                             createContainerTxn.getParentCVersion(),
                             header.getZxid(), header.getTime(), stat);
                     rc.stat = stat;
@@ -854,6 +882,9 @@ public class DataTree {
                             case OpCode.create:
                                 record = new CreateTxn();
                                 break;
+                            case OpCode.createTTL:
+                                record = new CreateTTLTxn();
+                                break;
                             case OpCode.createContainer:
                                 record = new CreateContainerTxn();
                                 break;
@@ -1184,8 +1215,11 @@ public class DataTree {
                 }
                 parent.addChild(path.substring(lastSlash + 1));
                 long eowner = node.stat.getEphemeralOwner();
-                if (eowner == CONTAINER_EPHEMERAL_OWNER) {
+                EphemeralType ephemeralType = EphemeralType.get(eowner);
+                if (ephemeralType == EphemeralType.CONTAINER) {
                     containers.add(path);
+                } else if (ephemeralType == EphemeralType.TTL) {
+                    ttls.add(path);
                 } else if (eowner != 0) {
                     HashSet<String> list = ephemerals.get(eowner);
                     if (list == null) {

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/server/EphemeralType.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/EphemeralType.java b/src/java/main/org/apache/zookeeper/server/EphemeralType.java
new file mode 100644
index 0000000..6d7bb25
--- /dev/null
+++ b/src/java/main/org/apache/zookeeper/server/EphemeralType.java
@@ -0,0 +1,77 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.server;
+
+import org.apache.zookeeper.CreateMode;
+
+
+public enum EphemeralType {
+    /**
+     * Not ephemeral
+     */
+    VOID,
+    /**
+     * Standard, pre-3.5.x EPHEMERAL
+     */
+    NORMAL,
+    /**
+     * Container node
+     */
+    CONTAINER,
+    /**
+     * TTL node
+     */
+    TTL;
+
+    public static final long CONTAINER_EPHEMERAL_OWNER = Long.MIN_VALUE;
+    public static final long MAX_TTL = 0x0fffffffffffffffL;
+    public static final long TTL_MASK = 0x8000000000000000L;
+
+    public static EphemeralType get(long ephemeralOwner) {
+        if (ephemeralOwner == CONTAINER_EPHEMERAL_OWNER) {
+            return CONTAINER;
+        }
+        if (ephemeralOwner < 0) {
+            return TTL;
+        }
+        return (ephemeralOwner == 0) ? VOID : NORMAL;
+    }
+
+    public static void validateTTL(CreateMode mode, long ttl) {
+        if (mode.isTTL()) {
+            ttlToEphemeralOwner(ttl);
+        } else if (ttl >= 0) {
+            throw new IllegalArgumentException("ttl not valid for mode: " + mode);
+        }
+    }
+
+    public static long getTTL(long ephemeralOwner) {
+        if ((ephemeralOwner < 0) && (ephemeralOwner != CONTAINER_EPHEMERAL_OWNER)) {
+            return (ephemeralOwner & MAX_TTL);
+        }
+        return 0;
+    }
+
+    public static long ttlToEphemeralOwner(long ttl) {
+        if ((ttl > MAX_TTL) || (ttl <= 0)) {
+            throw new IllegalArgumentException("ttl must be positive and cannot be larger than: " + MAX_TTL);
+        }
+        return TTL_MASK | ttl;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java b/src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java
index b41e03e..75a859f 100644
--- a/src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java
+++ b/src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java
@@ -215,6 +215,7 @@ public class FinalRequestProcessor implements RequestProcessor {
                             subResult = new CreateResult(subTxnResult.path);
                             break;
                         case OpCode.create2:
+                        case OpCode.createTTL:
                         case OpCode.createContainer:
                             subResult = new CreateResult(subTxnResult.path, subTxnResult.stat);
                             break;
@@ -244,6 +245,7 @@ public class FinalRequestProcessor implements RequestProcessor {
                 break;
             }
             case OpCode.create2:
+            case OpCode.createTTL:
             case OpCode.createContainer: {
                 lastOp = "CREA";
                 rsp = new Create2Response(rc.path, rc.stat);

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java b/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java
index 33f638d..e275f9c 100644
--- a/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java
+++ b/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java
@@ -36,6 +36,7 @@ import org.apache.zookeeper.data.Id;
 import org.apache.zookeeper.data.StatPersisted;
 import org.apache.zookeeper.proto.CheckVersionRequest;
 import org.apache.zookeeper.proto.CreateRequest;
+import org.apache.zookeeper.proto.CreateTTLRequest;
 import org.apache.zookeeper.proto.DeleteRequest;
 import org.apache.zookeeper.proto.ReconfigRequest;
 import org.apache.zookeeper.proto.SetACLRequest;
@@ -53,6 +54,7 @@ import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier;
 import org.apache.zookeeper.txn.CheckVersionTxn;
 import org.apache.zookeeper.txn.CreateContainerTxn;
 import org.apache.zookeeper.txn.CreateSessionTxn;
+import org.apache.zookeeper.txn.CreateTTLTxn;
 import org.apache.zookeeper.txn.CreateTxn;
 import org.apache.zookeeper.txn.DeleteTxn;
 import org.apache.zookeeper.txn.ErrorTxn;
@@ -364,53 +366,9 @@ public class PrepRequestProcessor extends ZooKeeperCriticalThread implements
         switch (type) {
             case OpCode.create:
             case OpCode.create2:
+            case OpCode.createTTL:
             case OpCode.createContainer: {
-                CreateRequest createRequest = (CreateRequest)record;
-                if (deserialize) {
-                    ByteBufferInputStream.byteBuffer2Record(request.request, createRequest);
-                }
-                CreateMode createMode = CreateMode.fromFlag(createRequest.getFlags());
-                validateCreateRequest(createMode, request);
-                String path = createRequest.getPath();
-                String parentPath = validatePathForCreate(path, request.sessionId);
-
-                List<ACL> listACL = fixupACL(path, request.authInfo, createRequest.getAcl());
-                ChangeRecord parentRecord = getRecordForPath(parentPath);
-
-                checkACL(zks, parentRecord.acl, ZooDefs.Perms.CREATE, request.authInfo);
-                int parentCVersion = parentRecord.stat.getCversion();
-                if (createMode.isSequential()) {
-                    path = path + String.format(Locale.ENGLISH, "%010d", parentCVersion);
-                }
-                validatePath(path, request.sessionId);
-                try {
-                    if (getRecordForPath(path) != null) {
-                        throw new KeeperException.NodeExistsException(path);
-                    }
-                } catch (KeeperException.NoNodeException e) {
-                    // ignore this one
-                }
-                boolean ephemeralParent = (parentRecord.stat.getEphemeralOwner() != 0) &&
-                        (parentRecord.stat.getEphemeralOwner() != DataTree.CONTAINER_EPHEMERAL_OWNER);
-                if (ephemeralParent) {
-                    throw new KeeperException.NoChildrenForEphemeralsException(path);
-                }
-                int newCversion = parentRecord.stat.getCversion()+1;
-                if (type == OpCode.createContainer) {
-                    request.setTxn(new CreateContainerTxn(path, createRequest.getData(), listACL, newCversion));
-                } else {
-                    request.setTxn(new CreateTxn(path, createRequest.getData(), listACL, createMode.isEphemeral(),
-                            newCversion));
-                }
-                StatPersisted s = new StatPersisted();
-                if (createMode.isEphemeral()) {
-                    s.setEphemeralOwner(request.sessionId);
-                }
-                parentRecord = parentRecord.duplicate(request.getHdr().getZxid());
-                parentRecord.childCount++;
-                parentRecord.stat.setCversion(newCversion);
-                addChangeRecord(parentRecord);
-                addChangeRecord(new ChangeRecord(request.getHdr().getZxid(), path, s, 0, listACL));
+                pRequest2TxnCreate(type, request, record, deserialize);
                 break;
             }
             case OpCode.deleteContainer: {
@@ -421,7 +379,7 @@ public class PrepRequestProcessor extends ZooKeeperCriticalThread implements
                 if (nodeRecord.childCount > 0) {
                     throw new KeeperException.NotEmptyException(path);
                 }
-                if (nodeRecord.stat.getEphemeralOwner() != DataTree.CONTAINER_EPHEMERAL_OWNER) {
+                if (EphemeralType.get(nodeRecord.stat.getEphemeralOwner()) == EphemeralType.NORMAL) {
                     throw new KeeperException.BadVersionException(path);
                 }
                 request.setTxn(new DeleteTxn(path));
@@ -665,6 +623,75 @@ public class PrepRequestProcessor extends ZooKeeperCriticalThread implements
         }
     }
 
+    private void pRequest2TxnCreate(int type, Request request, Record record, boolean deserialize) throws IOException, KeeperException {
+        if (deserialize) {
+            ByteBufferInputStream.byteBuffer2Record(request.request, record);
+        }
+
+        int flags;
+        String path;
+        List<ACL> acl;
+        byte[] data;
+        long ttl;
+        if (type == OpCode.createTTL) {
+            CreateTTLRequest createTtlRequest = (CreateTTLRequest)record;
+            flags = createTtlRequest.getFlags();
+            path = createTtlRequest.getPath();
+            acl = createTtlRequest.getAcl();
+            data = createTtlRequest.getData();
+            ttl = createTtlRequest.getTtl();
+        } else {
+            CreateRequest createRequest = (CreateRequest)record;
+            flags = createRequest.getFlags();
+            path = createRequest.getPath();
+            acl = createRequest.getAcl();
+            data = createRequest.getData();
+            ttl = 0;
+        }
+        CreateMode createMode = CreateMode.fromFlag(flags);
+        validateCreateRequest(createMode, request);
+        String parentPath = validatePathForCreate(path, request.sessionId);
+
+        List<ACL> listACL = fixupACL(path, request.authInfo, acl);
+        ChangeRecord parentRecord = getRecordForPath(parentPath);
+
+        checkACL(zks, parentRecord.acl, ZooDefs.Perms.CREATE, request.authInfo);
+        int parentCVersion = parentRecord.stat.getCversion();
+        if (createMode.isSequential()) {
+            path = path + String.format(Locale.ENGLISH, "%010d", parentCVersion);
+        }
+        validatePath(path, request.sessionId);
+        try {
+            if (getRecordForPath(path) != null) {
+                throw new KeeperException.NodeExistsException(path);
+            }
+        } catch (KeeperException.NoNodeException e) {
+            // ignore this one
+        }
+        boolean ephemeralParent = EphemeralType.get(parentRecord.stat.getEphemeralOwner()) == EphemeralType.NORMAL;
+        if (ephemeralParent) {
+            throw new KeeperException.NoChildrenForEphemeralsException(path);
+        }
+        int newCversion = parentRecord.stat.getCversion()+1;
+        if (type == OpCode.createContainer) {
+            request.setTxn(new CreateContainerTxn(path, data, listACL, newCversion));
+        } else if (type == OpCode.createTTL) {
+            request.setTxn(new CreateTTLTxn(path, data, listACL, newCversion, ttl));
+        } else {
+            request.setTxn(new CreateTxn(path, data, listACL, createMode.isEphemeral(),
+                    newCversion));
+        }
+        StatPersisted s = new StatPersisted();
+        if (createMode.isEphemeral()) {
+            s.setEphemeralOwner(request.sessionId);
+        }
+        parentRecord = parentRecord.duplicate(request.getHdr().getZxid());
+        parentRecord.childCount++;
+        parentRecord.stat.setCversion(newCversion);
+        addChangeRecord(parentRecord);
+        addChangeRecord(new ChangeRecord(request.getHdr().getZxid(), path, s, 0, listACL));
+    }
+
     private void validatePath(String path, long sessionId) throws BadArgumentsException {
         try {
             PathUtils.validatePath(path);
@@ -713,6 +740,10 @@ public class PrepRequestProcessor extends ZooKeeperCriticalThread implements
                 CreateRequest create2Request = new CreateRequest();
                 pRequest2Txn(request.type, zks.getNextZxid(), request, create2Request, true);
                 break;
+            case OpCode.createTTL:
+                CreateTTLRequest createTtlRequest = new CreateTTLRequest();
+                pRequest2Txn(request.type, zks.getNextZxid(), request, createTtlRequest, true);
+                break;
             case OpCode.deleteContainer:
             case OpCode.delete:
                 DeleteRequest deleteRequest = new DeleteRequest();

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/server/Request.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/Request.java b/src/java/main/org/apache/zookeeper/server/Request.java
index d34efe6..ede9280 100644
--- a/src/java/main/org/apache/zookeeper/server/Request.java
+++ b/src/java/main/org/apache/zookeeper/server/Request.java
@@ -137,6 +137,7 @@ public class Request {
         case OpCode.closeSession:
         case OpCode.create:
         case OpCode.create2:
+        case OpCode.createTTL:
         case OpCode.createContainer:
         case OpCode.createSession:
         case OpCode.delete:
@@ -171,6 +172,7 @@ public class Request {
             return false;
         case OpCode.create:
         case OpCode.create2:
+        case OpCode.createTTL:
         case OpCode.createContainer:
         case OpCode.error:
         case OpCode.delete:
@@ -197,6 +199,8 @@ public class Request {
             return "create";
         case OpCode.create2:
             return "create2";
+        case OpCode.createTTL:
+            return "createTtl";
         case OpCode.createContainer:
             return "createContainer";
         case OpCode.setWatches:

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/server/TraceFormatter.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/TraceFormatter.java b/src/java/main/org/apache/zookeeper/server/TraceFormatter.java
index 955a724..63a3edd 100644
--- a/src/java/main/org/apache/zookeeper/server/TraceFormatter.java
+++ b/src/java/main/org/apache/zookeeper/server/TraceFormatter.java
@@ -37,6 +37,8 @@ public class TraceFormatter {
             return "create";
         case OpCode.create2:
             return "create2";
+        case OpCode.createTTL:
+            return "createTtl";
         case OpCode.createContainer:
             return "createContainer";
         case OpCode.delete:

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/server/quorum/CommitProcessor.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/quorum/CommitProcessor.java b/src/java/main/org/apache/zookeeper/server/quorum/CommitProcessor.java
index 4e28868..07719ff 100644
--- a/src/java/main/org/apache/zookeeper/server/quorum/CommitProcessor.java
+++ b/src/java/main/org/apache/zookeeper/server/quorum/CommitProcessor.java
@@ -133,6 +133,7 @@ public class CommitProcessor extends ZooKeeperCriticalThread implements
         switch (request.type) {
             case OpCode.create:
             case OpCode.create2:
+            case OpCode.createTTL:
             case OpCode.createContainer:
             case OpCode.delete:
             case OpCode.deleteContainer:

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/server/quorum/FollowerRequestProcessor.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/quorum/FollowerRequestProcessor.java b/src/java/main/org/apache/zookeeper/server/quorum/FollowerRequestProcessor.java
index 832e4fa..c623eba 100644
--- a/src/java/main/org/apache/zookeeper/server/quorum/FollowerRequestProcessor.java
+++ b/src/java/main/org/apache/zookeeper/server/quorum/FollowerRequestProcessor.java
@@ -84,6 +84,7 @@ public class FollowerRequestProcessor extends ZooKeeperCriticalThread implements
                     break;
                 case OpCode.create:
                 case OpCode.create2:
+                case OpCode.createTTL:
                 case OpCode.createContainer:
                 case OpCode.delete:
                 case OpCode.deleteContainer:

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/server/quorum/ObserverRequestProcessor.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/quorum/ObserverRequestProcessor.java b/src/java/main/org/apache/zookeeper/server/quorum/ObserverRequestProcessor.java
index f5604a5..85a5212 100644
--- a/src/java/main/org/apache/zookeeper/server/quorum/ObserverRequestProcessor.java
+++ b/src/java/main/org/apache/zookeeper/server/quorum/ObserverRequestProcessor.java
@@ -93,6 +93,7 @@ public class ObserverRequestProcessor extends ZooKeeperCriticalThread implements
                     break;
                 case OpCode.create:
                 case OpCode.create2:
+                case OpCode.createTTL:
                 case OpCode.createContainer:
                 case OpCode.delete:
                 case OpCode.deleteContainer:

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/server/quorum/ReadOnlyRequestProcessor.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/quorum/ReadOnlyRequestProcessor.java b/src/java/main/org/apache/zookeeper/server/quorum/ReadOnlyRequestProcessor.java
index 4a36f11..c62eb42 100644
--- a/src/java/main/org/apache/zookeeper/server/quorum/ReadOnlyRequestProcessor.java
+++ b/src/java/main/org/apache/zookeeper/server/quorum/ReadOnlyRequestProcessor.java
@@ -82,6 +82,7 @@ public class ReadOnlyRequestProcessor extends ZooKeeperCriticalThread implements
                 case OpCode.sync:
                 case OpCode.create:
                 case OpCode.create2:
+                case OpCode.createTTL:
                 case OpCode.createContainer:
                 case OpCode.delete:
                 case OpCode.deleteContainer:

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/main/org/apache/zookeeper/server/util/SerializeUtils.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/util/SerializeUtils.java b/src/java/main/org/apache/zookeeper/server/util/SerializeUtils.java
index bfb6f1a..b7936f1 100644
--- a/src/java/main/org/apache/zookeeper/server/util/SerializeUtils.java
+++ b/src/java/main/org/apache/zookeeper/server/util/SerializeUtils.java
@@ -27,6 +27,7 @@ import org.apache.zookeeper.server.DataTree;
 import org.apache.zookeeper.server.ZooTrace;
 import org.apache.zookeeper.txn.CreateContainerTxn;
 import org.apache.zookeeper.txn.CreateSessionTxn;
+import org.apache.zookeeper.txn.CreateTTLTxn;
 import org.apache.zookeeper.txn.CreateTxn;
 import org.apache.zookeeper.txn.CreateTxnV0;
 import org.apache.zookeeper.txn.DeleteTxn;
@@ -68,6 +69,9 @@ public class SerializeUtils {
         case OpCode.create2:
             txn = new CreateTxn();
             break;
+        case OpCode.createTTL:
+            txn = new CreateTTLTxn();
+            break;
         case OpCode.createContainer:
             txn = new CreateContainerTxn();
             break;

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/test/org/apache/zookeeper/server/CreateTTLTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/server/CreateTTLTest.java b/src/java/test/org/apache/zookeeper/server/CreateTTLTest.java
new file mode 100644
index 0000000..66d17eb
--- /dev/null
+++ b/src/java/test/org/apache/zookeeper/server/CreateTTLTest.java
@@ -0,0 +1,213 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.server;
+
+import org.apache.zookeeper.AsyncCallback;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.Op;
+import org.apache.zookeeper.OpResult;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.test.ClientBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class CreateTTLTest extends ClientBase {
+    private ZooKeeper zk;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        zk = createClient();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+        zk.close();
+    }
+
+    @Test
+    public void testCreate()
+            throws IOException, KeeperException, InterruptedException {
+        Stat stat = new Stat();
+        zk.create("/foo", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_WITH_TTL, stat, 100);
+        Assert.assertEquals(0, stat.getEphemeralOwner());
+
+        final AtomicLong fakeElapsed = new AtomicLong(0);
+        ContainerManager containerManager = newContainerManager(fakeElapsed);
+        containerManager.checkContainers();
+        Assert.assertNotNull("Ttl node should not have been deleted yet", zk.exists("/foo", false));
+
+        fakeElapsed.set(1000);
+        containerManager.checkContainers();
+        Assert.assertNull("Ttl node should have been deleted", zk.exists("/foo", false));
+    }
+
+    @Test
+    public void testCreateSequential()
+            throws IOException, KeeperException, InterruptedException {
+        Stat stat = new Stat();
+        String path = zk.create("/foo", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL_WITH_TTL, stat, 100);
+        Assert.assertEquals(0, stat.getEphemeralOwner());
+
+        final AtomicLong fakeElapsed = new AtomicLong(0);
+        ContainerManager containerManager = newContainerManager(fakeElapsed);
+        containerManager.checkContainers();
+        Assert.assertNotNull("Ttl node should not have been deleted yet", zk.exists(path, false));
+
+        fakeElapsed.set(1000);
+        containerManager.checkContainers();
+        Assert.assertNull("Ttl node should have been deleted", zk.exists(path, false));
+    }
+
+    @Test
+    public void testCreateAsync()
+            throws IOException, KeeperException, InterruptedException {
+        AsyncCallback.Create2Callback callback = new AsyncCallback.Create2Callback() {
+            @Override
+            public void processResult(int rc, String path, Object ctx, String name, Stat stat) {
+                // NOP
+            }
+        };
+        zk.create("/foo", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_WITH_TTL, callback, null, 100);
+
+        final AtomicLong fakeElapsed = new AtomicLong(0);
+        ContainerManager containerManager = newContainerManager(fakeElapsed);
+        containerManager.checkContainers();
+        Assert.assertNotNull("Ttl node should not have been deleted yet", zk.exists("/foo", false));
+
+        fakeElapsed.set(1000);
+        containerManager.checkContainers();
+        Assert.assertNull("Ttl node should have been deleted", zk.exists("/foo", false));
+    }
+
+    @Test
+    public void testModifying()
+            throws IOException, KeeperException, InterruptedException {
+        Stat stat = new Stat();
+        zk.create("/foo", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_WITH_TTL, stat, 100);
+        Assert.assertEquals(0, stat.getEphemeralOwner());
+
+        final AtomicLong fakeElapsed = new AtomicLong(0);
+        ContainerManager containerManager = newContainerManager(fakeElapsed);
+        containerManager.checkContainers();
+        Assert.assertNotNull("Ttl node should not have been deleted yet", zk.exists("/foo", false));
+
+        for ( int i = 0; i < 10; ++i ) {
+            fakeElapsed.set(50);
+            zk.setData("/foo", new byte[i + 1], -1);
+            containerManager.checkContainers();
+            Assert.assertNotNull("Ttl node should not have been deleted yet", zk.exists("/foo", false));
+        }
+
+        fakeElapsed.set(200);
+        containerManager.checkContainers();
+        Assert.assertNull("Ttl node should have been deleted", zk.exists("/foo", false));
+    }
+
+    @Test
+    public void testMulti()
+            throws IOException, KeeperException, InterruptedException {
+        Op createTtl = Op.create("/a", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_WITH_TTL, 100);
+        Op createTtlSequential = Op.create("/b", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL_WITH_TTL, 200);
+        Op createNonTtl = Op.create("/c", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+        List<OpResult> results = zk.multi(Arrays.asList(createTtl, createTtlSequential, createNonTtl));
+        String sequentialPath = ((OpResult.CreateResult)results.get(1)).getPath();
+
+        final AtomicLong fakeElapsed = new AtomicLong(0);
+        ContainerManager containerManager = newContainerManager(fakeElapsed);
+        containerManager.checkContainers();
+        Assert.assertNotNull("node should not have been deleted yet", zk.exists("/a", false));
+        Assert.assertNotNull("node should not have been deleted yet", zk.exists(sequentialPath, false));
+        Assert.assertNotNull("node should never be deleted", zk.exists("/c", false));
+
+        fakeElapsed.set(110);
+        containerManager.checkContainers();
+        Assert.assertNull("node should have been deleted", zk.exists("/a", false));
+        Assert.assertNotNull("node should not have been deleted yet", zk.exists(sequentialPath, false));
+        Assert.assertNotNull("node should never be deleted", zk.exists("/c", false));
+
+        fakeElapsed.set(210);
+        containerManager.checkContainers();
+        Assert.assertNull("node should have been deleted", zk.exists("/a", false));
+        Assert.assertNull("node should have been deleted", zk.exists(sequentialPath, false));
+        Assert.assertNotNull("node should never be deleted", zk.exists("/c", false));
+    }
+
+    @Test
+    public void testBadUsage() throws KeeperException, InterruptedException {
+        for ( CreateMode createMode : CreateMode.values() ) {
+            try {
+                zk.create("/foo", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, createMode, new Stat(), createMode.isTTL() ? 0 : 100);
+                Assert.fail("should have thrown IllegalArgumentException");
+            } catch (IllegalArgumentException dummy) {
+                // correct
+            }
+        }
+
+        for ( CreateMode createMode : CreateMode.values() ) {
+            AsyncCallback.Create2Callback callback = new AsyncCallback.Create2Callback() {
+                @Override
+                public void processResult(int rc, String path, Object ctx, String name, Stat stat) {
+                    // NOP
+                }
+            };
+            try {
+                zk.create("/foo", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, createMode, callback, null, createMode.isTTL() ? 0 : 100);
+                Assert.fail("should have thrown IllegalArgumentException");
+            } catch (IllegalArgumentException dummy) {
+                // correct
+            }
+        }
+
+        try {
+            Op op = Op.create("/foo", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_WITH_TTL, 0);
+            zk.multi(Collections.singleton(op));
+            Assert.fail("should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException dummy) {
+            // correct
+        }
+        try {
+            Op op = Op.create("/foo", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL_WITH_TTL, 0);
+            zk.multi(Collections.singleton(op));
+            Assert.fail("should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException dummy) {
+            // correct
+        }
+    }
+
+    private ContainerManager newContainerManager(final AtomicLong fakeElapsed) {
+        return new ContainerManager(serverFactory.getZooKeeperServer()
+                .getZKDatabase(), serverFactory.getZooKeeperServer().firstProcessor, 1, 100) {
+            @Override
+            protected long getElapsed(DataNode node) {
+                return fakeElapsed.get();
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/java/test/org/apache/zookeeper/server/EphemeralTypeTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/server/EphemeralTypeTest.java b/src/java/test/org/apache/zookeeper/server/EphemeralTypeTest.java
new file mode 100644
index 0000000..2e6b3c7
--- /dev/null
+++ b/src/java/test/org/apache/zookeeper/server/EphemeralTypeTest.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.server;
+
+import org.apache.zookeeper.CreateMode;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EphemeralTypeTest {
+    @Test
+    public void testTtls() {
+        long ttls[] = {100, 1, EphemeralType.MAX_TTL};
+        for (long ttl : ttls) {
+            long ephemeralOwner = EphemeralType.ttlToEphemeralOwner(ttl);
+            Assert.assertEquals(EphemeralType.TTL, EphemeralType.get(ephemeralOwner));
+            Assert.assertEquals(ttl, EphemeralType.getTTL(ephemeralOwner));
+        }
+
+        EphemeralType.validateTTL(CreateMode.PERSISTENT_WITH_TTL, 100);
+        EphemeralType.validateTTL(CreateMode.PERSISTENT_SEQUENTIAL_WITH_TTL, 100);
+
+        try {
+            EphemeralType.validateTTL(CreateMode.EPHEMERAL, 100);
+            Assert.fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException dummy) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testContainerValue() {
+        Assert.assertEquals(Long.MIN_VALUE, EphemeralType.CONTAINER_EPHEMERAL_OWNER);
+        Assert.assertEquals(EphemeralType.CONTAINER, EphemeralType.get(EphemeralType.CONTAINER_EPHEMERAL_OWNER));
+    }
+
+    @Test
+    public void testNonSpecial() {
+        Assert.assertEquals(EphemeralType.VOID, EphemeralType.get(0));
+        Assert.assertEquals(EphemeralType.NORMAL, EphemeralType.get(1));
+        Assert.assertEquals(EphemeralType.NORMAL, EphemeralType.get(Long.MAX_VALUE));
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/0a4971d5/src/zookeeper.jute
----------------------------------------------------------------------
diff --git a/src/zookeeper.jute b/src/zookeeper.jute
index 3858081..a404e78 100644
--- a/src/zookeeper.jute
+++ b/src/zookeeper.jute
@@ -127,6 +127,13 @@ module org.apache.zookeeper.proto {
         vector<org.apache.zookeeper.data.ACL> acl;
         int flags;
     }
+    class CreateTTLRequest {
+        ustring path;
+        buffer data;
+        vector<org.apache.zookeeper.data.ACL> acl;
+        int flags;
+        long ttl;
+    }
     class DeleteRequest {
         ustring path;
         int version;
@@ -260,6 +267,13 @@ module org.apache.zookeeper.txn {
         boolean ephemeral;
         int parentCVersion;
     }
+    class CreateTTLTxn {
+        ustring path;
+        buffer data;
+        vector<org.apache.zookeeper.data.ACL> acl;
+        int parentCVersion;
+        long ttl;
+    }
     class CreateContainerTxn {
         ustring path;
         buffer data;


[2/2] zookeeper git commit: ZOOKEEPER-2169. Enable creation of nodes with TTLs. (Jordan Zimmerman via camille)

Posted by ca...@apache.org.
ZOOKEEPER-2169. Enable creation of nodes with TTLs. (Jordan Zimmerman via camille)


Project: http://git-wip-us.apache.org/repos/asf/zookeeper/repo
Commit: http://git-wip-us.apache.org/repos/asf/zookeeper/commit/df5519ab
Tree: http://git-wip-us.apache.org/repos/asf/zookeeper/tree/df5519ab
Diff: http://git-wip-us.apache.org/repos/asf/zookeeper/diff/df5519ab

Branch: refs/heads/master
Commit: df5519ab9dac9940f35cc4b308b560f2603aec7f
Parents: 0a4971d
Author: Camille Fournier <ca...@apache.org>
Authored: Sat Oct 8 13:28:05 2016 -0400
Committer: Camille Fournier <ca...@apache.org>
Committed: Sat Oct 8 13:28:05 2016 -0400

----------------------------------------------------------------------
 docs/index.pdf                        | Bin 12668 -> 12664 bytes
 docs/javaExample.pdf                  | Bin 33901 -> 33897 bytes
 docs/linkmap.pdf                      | Bin 10833 -> 10829 bytes
 docs/recipes.pdf                      | Bin 33907 -> 33903 bytes
 docs/zookeeperAdmin.pdf               | Bin 92295 -> 92297 bytes
 docs/zookeeperHierarchicalQuorums.pdf | Bin 6660 -> 6656 bytes
 docs/zookeeperInternals.pdf           | Bin 48873 -> 48869 bytes
 docs/zookeeperJMX.pdf                 | Bin 16498 -> 16494 bytes
 docs/zookeeperObservers.pdf           | Bin 12885 -> 12881 bytes
 docs/zookeeperOver.pdf                | Bin 302520 -> 302527 bytes
 docs/zookeeperProgrammers.pdf         | Bin 142179 -> 142335 bytes
 docs/zookeeperQuotas.pdf              | Bin 11195 -> 11191 bytes
 docs/zookeeperReconfig.pdf            | Bin 53703 -> 53699 bytes
 docs/zookeeperStarted.pdf             | Bin 28124 -> 28120 bytes
 docs/zookeeperTutorial.pdf            | Bin 30558 -> 30554 bytes
 15 files changed, 0 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/index.pdf
----------------------------------------------------------------------
diff --git a/docs/index.pdf b/docs/index.pdf
index 0fa269d..cc8bb1f 100644
Binary files a/docs/index.pdf and b/docs/index.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/javaExample.pdf
----------------------------------------------------------------------
diff --git a/docs/javaExample.pdf b/docs/javaExample.pdf
index 7598c6d..ad63226 100644
Binary files a/docs/javaExample.pdf and b/docs/javaExample.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/linkmap.pdf
----------------------------------------------------------------------
diff --git a/docs/linkmap.pdf b/docs/linkmap.pdf
index 1f29d02..03da0bb 100644
Binary files a/docs/linkmap.pdf and b/docs/linkmap.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/recipes.pdf
----------------------------------------------------------------------
diff --git a/docs/recipes.pdf b/docs/recipes.pdf
index 42f17ba..3f05a67 100644
Binary files a/docs/recipes.pdf and b/docs/recipes.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/zookeeperAdmin.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperAdmin.pdf b/docs/zookeeperAdmin.pdf
index e94ced8..c0533e1 100644
Binary files a/docs/zookeeperAdmin.pdf and b/docs/zookeeperAdmin.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/zookeeperHierarchicalQuorums.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperHierarchicalQuorums.pdf b/docs/zookeeperHierarchicalQuorums.pdf
index 05e7457..e38de6a 100644
Binary files a/docs/zookeeperHierarchicalQuorums.pdf and b/docs/zookeeperHierarchicalQuorums.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/zookeeperInternals.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperInternals.pdf b/docs/zookeeperInternals.pdf
index 3ed8d61..a8223a3 100644
Binary files a/docs/zookeeperInternals.pdf and b/docs/zookeeperInternals.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/zookeeperJMX.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperJMX.pdf b/docs/zookeeperJMX.pdf
index 8681d2e..0e1866c 100644
Binary files a/docs/zookeeperJMX.pdf and b/docs/zookeeperJMX.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/zookeeperObservers.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperObservers.pdf b/docs/zookeeperObservers.pdf
index ca37b92..2f9fca1 100644
Binary files a/docs/zookeeperObservers.pdf and b/docs/zookeeperObservers.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/zookeeperOver.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperOver.pdf b/docs/zookeeperOver.pdf
index a0c8890..4046ede 100644
Binary files a/docs/zookeeperOver.pdf and b/docs/zookeeperOver.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/zookeeperProgrammers.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperProgrammers.pdf b/docs/zookeeperProgrammers.pdf
index 558a86a..2f9945c 100644
Binary files a/docs/zookeeperProgrammers.pdf and b/docs/zookeeperProgrammers.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/zookeeperQuotas.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperQuotas.pdf b/docs/zookeeperQuotas.pdf
index 26cdf8b..047b1c5 100644
Binary files a/docs/zookeeperQuotas.pdf and b/docs/zookeeperQuotas.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/zookeeperReconfig.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperReconfig.pdf b/docs/zookeeperReconfig.pdf
index c071b31..66704b9 100644
Binary files a/docs/zookeeperReconfig.pdf and b/docs/zookeeperReconfig.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/zookeeperStarted.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperStarted.pdf b/docs/zookeeperStarted.pdf
index b926eca..879df11 100644
Binary files a/docs/zookeeperStarted.pdf and b/docs/zookeeperStarted.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/df5519ab/docs/zookeeperTutorial.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperTutorial.pdf b/docs/zookeeperTutorial.pdf
index 7ee54ae..c8009f7 100644
Binary files a/docs/zookeeperTutorial.pdf and b/docs/zookeeperTutorial.pdf differ