[SCM] Apache ZooKeeper branch, master, updated. debian/3.3.5+dfsg1-2-5-g1545dde

James Page james.page at ubuntu.com
Wed Sep 19 09:57:06 UTC 2012


The following commit has been merged in the master branch:
commit 51939aae0d7a10da6fdc305c3d54da66f70e63da
Author: James Page <james.page at ubuntu.com>
Date:   Wed Aug 8 10:46:00 2012 +0100

    Imported Debian patch 3.3.6+dfsg-0ubuntu1

diff --git a/CHANGES.txt b/CHANGES.txt
index c73b361..0cd3cf6 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,47 @@
+Release 3.3.6 - 2012-08-01
+Backward compatible changes:
+
+BUGFIXES:
+
+  ZOOKEEPER-1466. QuorumCnxManager.shutdown missing synchronization.
+  (Patrick Hunt via mahadev)
+
+  ZOOKEEPER-1403. zkCli.sh script quoting issue (James Page via phunt)
+
+  ZOOKEEPER-1433. improve ZxidRolloverTest (test seems flakey) (phunt via henryr)
+
+  ZOOKEEPER-1395. node-watcher double-free redux (Mike Lundy via henryr)   
+  
+  ZOOKEEPER-1450. Backport of ZOOKEEPER-1294 fix to 3.4 and 3.3 (Norman Bishop via camille)
+
+  ZOOKEEPER-1305. zookeeper.c:prepend_string func can dereference null ptr (Daniel Lescohier via michim)
+
+  ZOOKEEPER-1048. addauth command does not work in cli_mt/cli_st (allengao via michim)
+
+  ZOOKEEPER-1339. C client doesn't build with --enable-debug (Eric Liang via michim)
+
+  ZOOKEEPER-1318. In Python binding, get_children (and get and exists, and probably others)
+  with expired session doesn't raise exception properly (henryr via michim)
+
+  ZOOKEEPER-1431. zkpython async calls leak memory (Kapil Thangavelu and Andre Cruz via henryr)
+
+  ZOOKEEPER-1163. Memory leak in zk_hashtable.c:do_insert_watcher_object()
+  (Anupam Chanda via michim)
+
+  ZOOKEEPER-1489. Data loss after truncate on transaction log (phunt)
+
+  ZOOKEEPER-1521. LearnerHandler initLimit/syncLimit problems
+    specifying follower socket timeout limits (phunt)
+
+  ZOOKEEPER-1493. C Client: zookeeper_process doesn't invoke
+    completion callback if zookeeper_close has been called
+    (Michi Mutsuzaki via phunt and mahadev)
+
+IMPROVEMENTS:
+
+  ZOOKEEPER-1454. Document how to run autoreconf if cppunit is
+    installed in a non-standard directory (Michi Mutsuzaki via phunt)
+
 Release 3.3.5 - 2012-03-18
 Backward compatible changes:
 
diff --git a/bin/zkCli.sh b/bin/zkCli.sh
index cae8b12..fd33370 100755
--- a/bin/zkCli.sh
+++ b/bin/zkCli.sh
@@ -38,4 +38,4 @@ ZOOBINDIR=`dirname "$ZOOBIN"`
 
 $JAVA "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
      -cp "$CLASSPATH" $CLIENT_JVMFLAGS $JVMFLAGS \
-     org.apache.zookeeper.ZooKeeperMain $@
+     org.apache.zookeeper.ZooKeeperMain "$@"
diff --git a/build.xml b/build.xml
index 8ce72c7..548100d 100644
--- a/build.xml
+++ b/build.xml
@@ -24,7 +24,7 @@
 
     <property environment="env"/>
     
-    <property name="version" value="3.3.5" />
+    <property name="version" value="3.3.6" />
     <property name="final.name" value="${name}-${version}"/>
     <property name="revision.dir" value="${basedir}/.revision" />
     <property name="revision.properties" value="revision.properties" />
diff --git a/debian/ant.properties b/debian/ant.properties
index cf69e84..bf4f5aa 100644
--- a/debian/ant.properties
+++ b/debian/ant.properties
@@ -1,6 +1,9 @@
-contrib.dir=debian
-version=3.3.4
-jar.name=zookeeper.jar
-final.name=zookeeper
-user.name=Debian
-lib.cppunit=/usr/lib
+# Ensure that source and target are 1.5
+# For backwards compat on Java 7
+ant.build.javac.source=1.5
+ant.build.javac.target=1.5
+target.jdk=1.5
+lastRevision=-1
+ivy.jar.exists=true
+ivy.initialized=true
+dest.dir=../../build/zookeeper
diff --git a/debian/changelog b/debian/changelog
index 3094432..86f664d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,9 +1,16 @@
-zookeeper (3.3.5+dfsg1-2ubuntu1) UNRELEASED; urgency=low
+zookeeper (3.3.6+dfsg-0ubuntu1) quantal; urgency=low
 
-  * d/{orig-tar.sh,watch,README.source}: Repack upstream tarball when
-    downloading using uscan.
-
- -- James Page <james.page at ubuntu.com>  Tue, 07 Aug 2012 15:14:43 +0100
+  * New upstream release:
+    - Dropped patches for ZOOKEEPER-1403 and ZOOKEEPER-1431; included upstream.
+    - Refreshed all other patches.
+  * d/{watch,orig-tar.sh,README.source}: Repack upstream tarball using uscan
+    to ease new upstream releases.
+  * d/control: Version debhelper (>= 9~).
+  * d/rules: Refactor contrib builds to use properties file.
+  * d/ant.properties: Collate properties for contrib builds ensuring that
+    bytecode built is backwards compatible.
+
+ -- James Page <james.page at ubuntu.com>  Wed, 08 Aug 2012 10:46:00 +0100
 
 zookeeper (3.3.5+dfsg1-2) unstable; urgency=low
 
diff --git a/debian/control b/debian/control
index 5493878..7041089 100644
--- a/debian/control
+++ b/debian/control
@@ -1,7 +1,8 @@
 Source: zookeeper
 Section: java
 Priority: optional
-Maintainer: Debian Java Maintainers <pkg-java-maintainers at lists.alioth.debian.org>
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss at lists.ubuntu.com>
+XSBC-Original-Maintainer: Debian Java Maintainers <pkg-java-maintainers at lists.alioth.debian.org>
 Uploaders: James Page <james.page at ubuntu.com>
 Homepage: http://hadoop.apache.org/zookeeper
 Vcs-Browser: http://git.debian.org/?p=pkg-java/zookeeper.git
@@ -12,7 +13,7 @@ Build-Depends:
  ant-optional,
  autoconf,
  automake,
- debhelper (>= 8.9.7~),
+ debhelper (>= 9~),
  default-jdk (>= 1:1.6),
  default-jdk-doc,
  help2man,
diff --git a/debian/patches/debian/patch-build-system b/debian/patches/debian/patch-build-system
index 1561634..d34661a 100644
--- a/debian/patches/debian/patch-build-system
+++ b/debian/patches/debian/patch-build-system
@@ -6,12 +6,12 @@ Forwarded: not-needed
 
 Index: zookeeper/build.xml
 ===================================================================
---- zookeeper.orig/build.xml	2012-03-21 21:14:50.000000000 +0000
-+++ zookeeper/build.xml	2012-03-21 21:17:09.456905785 +0000
+--- zookeeper.orig/build.xml	2012-08-08 09:39:55.000000000 +0100
++++ zookeeper/build.xml	2012-08-08 09:40:57.822032084 +0100
 @@ -25,7 +25,7 @@
      <property environment="env"/>
      
-     <property name="version" value="3.3.5" />
+     <property name="version" value="3.3.6" />
 -    <property name="final.name" value="${name}-${version}"/>
 +    <property name="final.name" value="${name}"/>
      <property name="revision.dir" value="${basedir}/.revision" />
@@ -112,8 +112,8 @@ Index: zookeeper/build.xml
            <batchtest todir="${test.log.dir}" if="testcase">
 Index: zookeeper/src/contrib/bookkeeper/build.xml
 ===================================================================
---- zookeeper.orig/src/contrib/bookkeeper/build.xml	2012-03-21 21:14:35.000000000 +0000
-+++ zookeeper/src/contrib/bookkeeper/build.xml	2012-03-21 21:16:42.916844204 +0000
+--- zookeeper.orig/src/contrib/bookkeeper/build.xml	2012-08-08 09:39:55.000000000 +0100
++++ zookeeper/src/contrib/bookkeeper/build.xml	2012-08-08 09:40:47.673998090 +0100
 @@ -34,7 +34,7 @@
  
    <target name="setjarname">
@@ -125,8 +125,8 @@ Index: zookeeper/src/contrib/bookkeeper/build.xml
    <target name="init" depends="checkMainCompiled, zookeeperbuildcontrib.init"/>
 Index: zookeeper/src/contrib/build-contrib.xml
 ===================================================================
---- zookeeper.orig/src/contrib/build-contrib.xml	2012-03-21 21:14:35.000000000 +0000
-+++ zookeeper/src/contrib/build-contrib.xml	2012-03-21 21:16:42.916844204 +0000
+--- zookeeper.orig/src/contrib/build-contrib.xml	2012-08-08 09:39:55.000000000 +0100
++++ zookeeper/src/contrib/build-contrib.xml	2012-08-08 09:40:47.673998090 +0100
 @@ -70,25 +70,14 @@
  
    <path id="classpath">
@@ -186,8 +186,8 @@ Index: zookeeper/src/contrib/build-contrib.xml
  
 Index: zookeeper/src/contrib/zooinspector/build.xml
 ===================================================================
---- zookeeper.orig/src/contrib/zooinspector/build.xml	2012-03-21 21:14:35.000000000 +0000
-+++ zookeeper/src/contrib/zooinspector/build.xml	2012-03-21 21:16:42.920844213 +0000
+--- zookeeper.orig/src/contrib/zooinspector/build.xml	2012-08-08 09:39:55.000000000 +0100
++++ zookeeper/src/contrib/zooinspector/build.xml	2012-08-08 09:40:47.673998090 +0100
 @@ -20,7 +20,7 @@
  
  
diff --git a/debian/patches/fixes/ZOOKEEPER-1033 b/debian/patches/fixes/ZOOKEEPER-1033
index 82976a7..6a0a78b 100644
--- a/debian/patches/fixes/ZOOKEEPER-1033
+++ b/debian/patches/fixes/ZOOKEEPER-1033
@@ -5,14 +5,14 @@ Origin: https://issues.apache.org/jira/browse/ZOOKEEPER-1033
 
 Index: zookeeper/src/c/configure.ac
 ===================================================================
---- zookeeper.orig/src/c/configure.ac	2012-03-21 21:14:50.000000000 +0000
-+++ zookeeper/src/c/configure.ac	2012-03-21 21:18:13.509055030 +0000
+--- zookeeper.orig/src/c/configure.ac	2012-08-08 09:39:55.000000000 +0100
++++ zookeeper/src/c/configure.ac	2012-08-08 09:41:33.358151084 +0100
 @@ -3,7 +3,7 @@
  
  AC_PREREQ(2.59)
  
--AC_INIT([zookeeper C client],3.3.5,[zookeeper-user at hadoop.apache.org],[c-client-src])
-+AC_INIT([zookeeper C client],3.3.5,[zookeeper-user at hadoop.apache.org],[zookeeper])
+-AC_INIT([zookeeper C client],3.3.6,[zookeeper-user at hadoop.apache.org],[c-client-src])
++AC_INIT([zookeeper C client],3.3.6,[zookeeper-user at hadoop.apache.org],[zookeeper])
  AC_CONFIG_SRCDIR([src/zookeeper.c])
  
  # initialize Doxygen support
diff --git a/debian/patches/fixes/ZOOKEEPER-1403 b/debian/patches/fixes/ZOOKEEPER-1403
deleted file mode 100644
index 9de78e9..0000000
--- a/debian/patches/fixes/ZOOKEEPER-1403
+++ /dev/null
@@ -1,15 +0,0 @@
-Description: Ensure that parameters to zkCli.sh are correctly
- passed to the supporting Java code.
-Author: John Eikenberry <jae at zhar.net>
-Bug: https://issues.apache.org/jira/browse/ZOOKEEPER-1403
-
-Index: zookeeper/bin/zkCli.sh
-===================================================================
---- zookeeper.orig/bin/zkCli.sh	2012-01-03 10:21:37.000000000 +0000
-+++ zookeeper/bin/zkCli.sh	2012-03-02 11:13:34.076917800 +0000
-@@ -38,4 +38,4 @@
- 
- $JAVA "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
-      -cp "$CLASSPATH" $CLIENT_JVMFLAGS $JVMFLAGS \
--     org.apache.zookeeper.ZooKeeperMain $@
-+     org.apache.zookeeper.ZooKeeperMain "$@"
diff --git a/debian/patches/fixes/ZOOKEEPER-1431 b/debian/patches/fixes/ZOOKEEPER-1431
deleted file mode 100644
index aaf4f90..0000000
--- a/debian/patches/fixes/ZOOKEEPER-1431
+++ /dev/null
@@ -1,71 +0,0 @@
-Description: Fix up memory leak for large results set in zk
- python bindings.
-Author: Kapil Thangavelu <kapil.thangavelu at canonical.com>
-Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/zookeeper/+bug/963280
-Bug: https://issues.apache.org/jira/browse/ZOOKEEPER-1431
-
-Index: a/src/contrib/zkpython/src/c/zookeeper.c
-===================================================================
---- a/src/contrib/zkpython/src/c/zookeeper.c	(revision 1304459)
-+++ b/src/contrib/zkpython/src/c/zookeeper.c	(working copy)
-@@ -436,7 +436,8 @@
-   if (PyObject_CallObject((PyObject*)callback, arglist) == NULL) {
-     PyErr_Print();
-   }
--  if (pyw->permanent == 0 && (type != ZOO_SESSION_EVENT || is_unrecoverable(zzh) == ZINVALIDSTATE)) {
-+  Py_DECREF(arglist);
-+  if (pyw->permanent == 0 && (type != ZOO_SESSION_EVENT || is_unrecoverable(zzh) == ZINVALIDSTATE)) {   
-     free_pywatcher(pyw);
-   }
-   PyGILState_Release(gstate);
-@@ -457,6 +458,7 @@
-   PyObject *arglist = Py_BuildValue("(i,i)", pyw->zhandle, rc);
-   if (PyObject_CallObject((PyObject*)callback, arglist) == NULL)
-     PyErr_Print();
-+  Py_DECREF(arglist);
-   free_pywatcher(pyw);
-   PyGILState_Release(gstate);
- }
-@@ -474,9 +476,9 @@
-   PyObject *pystat = build_stat(stat);
-   PyObject *arglist = Py_BuildValue("(i,i,O)", pyw->zhandle,rc, pystat);
-   Py_DECREF(pystat);
--
-   if (PyObject_CallObject((PyObject*)callback, arglist) == NULL)
-     PyErr_Print();
-+  Py_DECREF(arglist);
-   free_pywatcher(pyw);
-   PyGILState_Release(gstate);
- }
-@@ -498,6 +500,7 @@
- 
-   if (PyObject_CallObject((PyObject*)callback, arglist) == NULL)
-     PyErr_Print();
-+  Py_DECREF(arglist);
-   free_pywatcher(pyw);
-   PyGILState_Release(gstate);
- }
-@@ -518,6 +521,7 @@
-       PyObject *arglist = Py_BuildValue("(i,i,O)", pyw->zhandle, rc, pystrings);   
-       if (arglist == NULL || PyObject_CallObject((PyObject*)callback, arglist) == NULL)
-         PyErr_Print();
-+      Py_DECREF(arglist);
-     }
-   else
-     PyErr_Print();
-@@ -540,6 +544,7 @@
-   PyObject *arglist = Py_BuildValue("(i,i,s)", pyw->zhandle,rc, value);
-   if (PyObject_CallObject((PyObject*)callback, arglist) == NULL)
-     PyErr_Print();
-+  Py_DECREF(arglist);
-   free_pywatcher(pyw);
-   PyGILState_Release(gstate);
- }
-@@ -565,6 +570,7 @@
-   if (PyObject_CallObject((PyObject*)callback, arglist) == NULL) {
-     PyErr_Print();
-   }
-+  Py_DECREF(arglist);
-   free_pywatcher(pyw);
-   PyGILState_Release(gstate);
- }
diff --git a/debian/patches/series b/debian/patches/series
index 4b62d71..1cb74d4 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -4,6 +4,4 @@ debian/disable-cygwin-detection
 fixes/ZOOKEEPER-705
 fixes/ZOOKEEPER-1033
 fixes/ZOOKEEPER-1374
-fixes/ZOOKEEPER-1403
 ftbfs-gcc-4.7.diff
-fixes/ZOOKEEPER-1431
diff --git a/debian/rules b/debian/rules
index 658d018..5c17fbe 100755
--- a/debian/rules
+++ b/debian/rules
@@ -23,9 +23,15 @@ override_dh_auto_build:
 	$(MAKE) -C src/c
 
 	# Compile contribs - bookkeeper
-	cd src/contrib && ant -Dversion=$(DEB_UPSTREAM_VERSION) -DlastRevision=-1 -Ddest.dir=../../build/zookeeper -Divy.jar.exists=true -Divy.initialized=true -Dcontribfilesetincludes="bookkeeper/build.xml"
+	cd src/contrib && \
+		ant -Dversion=$(DEB_UPSTREAM_VERSION) \
+			-propertyfile ../../debian/ant.properties \
+			-Dcontribfilesetincludes="bookkeeper/build.xml"
 	# Compile contribs - zooinspector
-	cd src/contrib && ant -Dversion=$(DEB_UPSTREAM_VERSION) -DlastRevision=-1 -Ddest.dir=../../build/zookeeper -Divy.jar.exists=true -Divy.initialized=true -Dcontribfilesetincludes="zooinspector/build.xml"
+	cd src/contrib && \
+		ant -Dversion=$(DEB_UPSTREAM_VERSION) \
+			-propertyfile ../../debian/ant.properties \
+			-Dcontribfilesetincludes="zooinspector/build.xml"
 
 	# Build Python Bindings
 	cd src/contrib/zkpython && \
diff --git a/lib/jdiff/zookeeper_3.3.5.xml b/lib/jdiff/zookeeper_3.3.6.xml
similarity index 99%
rename from lib/jdiff/zookeeper_3.3.5.xml
rename to lib/jdiff/zookeeper_3.3.6.xml
index 2b3678e..9e4692e 100644
--- a/lib/jdiff/zookeeper_3.3.5.xml
+++ b/lib/jdiff/zookeeper_3.3.6.xml
@@ -1,15 +1,15 @@
 <?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
 <!-- Generated by the JDiff Javadoc doclet -->
 <!-- (http://www.jdiff.org) -->
-<!-- on Thu Mar 15 13:09:41 PDT 2012 -->
+<!-- on Sat Jul 28 23:23:13 PDT 2012 -->
 
 <api
   xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
   xsi:noNamespaceSchemaLocation='api.xsd'
-  name="zookeeper 3.3.5"
+  name="zookeeper 3.3.6"
   jdversion="1.0.9">
 
-<!--  Command line arguments =  -doclet jdiff.JDiff -docletpath /home/phunt/dev/rels/3.3.5-rc1/branch-3.3/build/jdiff/lib/jdiff-1.0.9.jar:/home/phunt/dev/rels/3.3.5-rc1/branch-3.3/build/jdiff/lib/xerces-1.4.4.jar -classpath /home/phunt/dev/rels/3.3.5-rc1/branch-3.3/build/classes:/home/phunt/dev/rels/3.3.5-rc1/branch-3.3/src/java/lib/ivy-2.1.0.jar:/home/phunt/dev/rels/3.3.5-rc1/branch-3.3/build/lib/jline-0.9.94.jar:/home/phunt/dev/rels/3.3.5-rc1/branch-3.3/build/lib/log4j-1.2.15.jar -sourcepath /home/phunt/dev/rels/3.3.5-rc1/branch-3.3/src/java/main -apidir /home/phunt/dev/rels/3.3.5-rc1/branch-3.3/src/java/lib/jdiff -apiname zookeeper 3.3.5 -->
+<!--  Command line arguments =  -doclet jdiff.JDiff -docletpath /home/phunt/dev/rels/3.3.6/branch-3.3/build/jdiff/lib/jdiff-1.0.9.jar:/home/phunt/dev/rels/3.3.6/branch-3.3/build/jdiff/lib/xerces-1.4.4.jar -classpath /home/phunt/dev/rels/3.3.6/branch-3.3/build/classes:/home/phunt/dev/rels/3.3.6/branch-3.3/src/java/lib/ivy-2.1.0.jar:/home/phunt/dev/rels/3.3.6/branch-3.3/build/lib/jline-0.9.94.jar:/home/phunt/dev/rels/3.3.6/branch-3.3/build/lib/log4j-1.2.15.jar -sourcepath /home/phunt/dev/rels/3.3.6/branch-3.3/src/java/main -apidir /home/phunt/dev/rels/3.3.6/branch-3.3/src/java/lib/jdiff -apiname zookeeper 3.3.6 -->
 <package name="org.apache.zookeeper">
   <!-- start interface org.apache.zookeeper.AsyncCallback -->
   <interface name="AsyncCallback"    abstract="true"
diff --git a/src/c/README b/src/c/README
index 397d04c..005341f 100644
--- a/src/c/README
+++ b/src/c/README
@@ -43,7 +43,12 @@ tar downloaded from Apache please skip to step 2.
 2) unzip/untar the source tarball and cd to the zookeeper-x.x.x/src/c directory
 3) change directory to src/c and do a "autoreconf -if" to bootstrap
    autoconf, automake and libtool. Please make sure you have autoconf
-   version 2.59 or greater installed.
+   version 2.59 or greater installed. If cppunit is installed in a non-standard
+   directory, you need to specify where to find cppunit.m4. For example, if
+   cppunit is installed under /usr/local, run:
+   
+       ACLOCAL="aclocal -I /usr/local/share/aclocal" autoreconf -if
+
 4) do a "./configure [OPTIONS]" to generate the makefile. See INSTALL
    for general information about running configure. Additionally, the
    configure supports the following options:
diff --git a/src/c/configure.ac b/src/c/configure.ac
index 7ff5e94..dba43bf 100644
--- a/src/c/configure.ac
+++ b/src/c/configure.ac
@@ -3,7 +3,7 @@
 
 AC_PREREQ(2.59)
 
-AC_INIT([zookeeper C client],3.3.5,[zookeeper-user at hadoop.apache.org],[c-client-src])
+AC_INIT([zookeeper C client],3.3.6,[zookeeper-user at hadoop.apache.org],[c-client-src])
 AC_CONFIG_SRCDIR([src/zookeeper.c])
 
 # initialize Doxygen support
diff --git a/src/c/depcomp b/src/c/depcomp
index df8eea7..bd0ac08 100755
--- a/src/c/depcomp
+++ b/src/c/depcomp
@@ -1,10 +1,10 @@
 #! /bin/sh
 # depcomp - compile a program generating dependencies as side-effects
 
-scriptversion=2009-04-28.21; # UTC
+scriptversion=2011-12-04.11; # UTC
 
-# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
-# Software Foundation, Inc.
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
+# 2011 Free Software Foundation, Inc.
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@ Environment variables:
   object      Object file output by `PROGRAMS ARGS'.
   DEPDIR      directory where to store dependencies.
   depfile     Dependency file to output.
-  tmpdepfile  Temporary file to use when outputing dependencies.
+  tmpdepfile  Temporary file to use when outputting dependencies.
   libtool     Whether libtool is used (yes/no).
 
 Report bugs to <bug-automake at gnu.org>.
@@ -90,10 +90,18 @@ if test "$depmode" = msvcmsys; then
    # This is just like msvisualcpp but w/o cygpath translation.
    # Just convert the backslash-escaped backslashes to single forward
    # slashes to satisfy depend.m4
-   cygpath_u="sed s,\\\\\\\\,/,g"
+   cygpath_u='sed s,\\\\,/,g'
    depmode=msvisualcpp
 fi
 
+if test "$depmode" = msvc7msys; then
+   # This is just like msvc7 but w/o cygpath translation.
+   # Just convert the backslash-escaped backslashes to single forward
+   # slashes to satisfy depend.m4
+   cygpath_u='sed s,\\\\,/,g'
+   depmode=msvc7
+fi
+
 case "$depmode" in
 gcc3)
 ## gcc 3 implements dependency tracking that does exactly what
@@ -158,10 +166,12 @@ gcc)
 ' < "$tmpdepfile" |
 ## Some versions of gcc put a space before the `:'.  On the theory
 ## that the space means something, we add a space to the output as
-## well.
+## well.  hp depmode also adds that space, but also prefixes the VPATH
+## to the object.  Take care to not repeat it in the output.
 ## Some versions of the HPUX 10.20 sed can't process this invocation
 ## correctly.  Breaking it into two sed invocations is a workaround.
-    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+    sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
+      | sed -e 's/$/ :/' >> "$depfile"
   rm -f "$tmpdepfile"
   ;;
 
@@ -405,6 +415,52 @@ tru64)
    rm -f "$tmpdepfile"
    ;;
 
+msvc7)
+  if test "$libtool" = yes; then
+    showIncludes=-Wc,-showIncludes
+  else
+    showIncludes=-showIncludes
+  fi
+  "$@" $showIncludes > "$tmpdepfile"
+  stat=$?
+  grep -v '^Note: including file: ' "$tmpdepfile"
+  if test "$stat" = 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  # The first sed program below extracts the file names and escapes
+  # backslashes for cygpath.  The second sed program outputs the file
+  # name when reading, but also accumulates all include files in the
+  # hold buffer in order to output them again at the end.  This only
+  # works with sed implementations that can handle large buffers.
+  sed < "$tmpdepfile" -n '
+/^Note: including file:  *\(.*\)/ {
+  s//\1/
+  s/\\/\\\\/g
+  p
+}' | $cygpath_u | sort -u | sed -n '
+s/ /\\ /g
+s/\(.*\)/	\1 \\/p
+s/.\(.*\) \\/\1:/
+H
+$ {
+  s/.*/	/
+  G
+  p
+}' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvc7msys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
 #nosideeffect)
   # This comment above is used by automake to tell side-effect
   # dependency tracking mechanisms from slower ones.
@@ -503,7 +559,9 @@ makedepend)
   touch "$tmpdepfile"
   ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
   rm -f "$depfile"
-  cat < "$tmpdepfile" > "$depfile"
+  # makedepend may prepend the VPATH from the source file name to the object.
+  # No need to regex-escape $object, excess matching of '.' is harmless.
+  sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
   sed '1,2d' "$tmpdepfile" | tr ' ' '
 ' | \
 ## Some versions of the HPUX 10.20 sed can't process this invocation
diff --git a/src/c/include/zookeeper_version.h b/src/c/include/zookeeper_version.h
index c46c8f5..a1db1b8 100644
--- a/src/c/include/zookeeper_version.h
+++ b/src/c/include/zookeeper_version.h
@@ -24,7 +24,7 @@ extern "C" {
 
 #define ZOO_MAJOR_VERSION 3
 #define ZOO_MINOR_VERSION 3
-#define ZOO_PATCH_VERSION 5
+#define ZOO_PATCH_VERSION 6
 
 #ifdef __cplusplus
 }
diff --git a/src/c/install-sh b/src/c/install-sh
index 6781b98..a9244eb 100755
--- a/src/c/install-sh
+++ b/src/c/install-sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 # install - install a program, script, or datafile
 
-scriptversion=2009-04-28.21; # UTC
+scriptversion=2011-01-19.21; # UTC
 
 # This originates from X11R5 (mit/util/scripts/install.sh), which was
 # later released in X11R6 (xc/config/util/install.sh) with the
@@ -156,6 +156,10 @@ while test $# -ne 0; do
     -s) stripcmd=$stripprog;;
 
     -t) dst_arg=$2
+	# Protect names problematic for `test' and other utilities.
+	case $dst_arg in
+	  -* | [=\(\)!]) dst_arg=./$dst_arg;;
+	esac
 	shift;;
 
     -T) no_target_directory=true;;
@@ -186,6 +190,10 @@ if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
     fi
     shift # arg
     dst_arg=$arg
+    # Protect names problematic for `test' and other utilities.
+    case $dst_arg in
+      -* | [=\(\)!]) dst_arg=./$dst_arg;;
+    esac
   done
 fi
 
@@ -200,7 +208,11 @@ if test $# -eq 0; then
 fi
 
 if test -z "$dir_arg"; then
-  trap '(exit $?); exit' 1 2 13 15
+  do_exit='(exit $ret); exit $ret'
+  trap "ret=129; $do_exit" 1
+  trap "ret=130; $do_exit" 2
+  trap "ret=141; $do_exit" 13
+  trap "ret=143; $do_exit" 15
 
   # Set umask so as not to create temps with too-generous modes.
   # However, 'strip' requires both read and write access to temps.
@@ -228,9 +240,9 @@ fi
 
 for src
 do
-  # Protect names starting with `-'.
+  # Protect names problematic for `test' and other utilities.
   case $src in
-    -*) src=./$src;;
+    -* | [=\(\)!]) src=./$src;;
   esac
 
   if test -n "$dir_arg"; then
@@ -252,12 +264,7 @@ do
       echo "$0: no destination specified." >&2
       exit 1
     fi
-
     dst=$dst_arg
-    # Protect names starting with `-'.
-    case $dst in
-      -*) dst=./$dst;;
-    esac
 
     # If destination is a directory, append the input filename; won't work
     # if double slashes aren't ignored.
@@ -385,7 +392,7 @@ do
 
       case $dstdir in
 	/*) prefix='/';;
-	-*) prefix='./';;
+	[-=\(\)!]*) prefix='./';;
 	*)  prefix='';;
       esac
 
@@ -403,7 +410,7 @@ do
 
       for d
       do
-	test -z "$d" && continue
+	test X"$d" = X && continue
 
 	prefix=$prefix$d
 	if test -d "$prefix"; then
diff --git a/src/c/missing b/src/c/missing
index 28055d2..86a8fc3 100755
--- a/src/c/missing
+++ b/src/c/missing
@@ -1,10 +1,10 @@
 #! /bin/sh
 # Common stub for a few missing GNU programs while installing.
 
-scriptversion=2009-04-28.21; # UTC
+scriptversion=2012-01-06.13; # UTC
 
 # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
-# 2008, 2009 Free Software Foundation, Inc.
+# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
 # Originally by Fran,cois Pinard <pinard at iro.umontreal.ca>, 1996.
 
 # This program is free software; you can redistribute it and/or modify
@@ -84,7 +84,6 @@ Supported PROGRAM values:
   help2man     touch the output file
   lex          create \`lex.yy.c', if possible, from existing .c
   makeinfo     touch the output file
-  tar          try tar, gnutar, gtar, then tar without non-portable flags
   yacc         create \`y.tab.[ch]', if possible, from existing .[ch]
 
 Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
@@ -122,15 +121,6 @@ case $1 in
     # Not GNU programs, they don't have --version.
     ;;
 
-  tar*)
-    if test -n "$run"; then
-       echo 1>&2 "ERROR: \`tar' requires --run"
-       exit 1
-    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
-       exit 1
-    fi
-    ;;
-
   *)
     if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
        # We have it, but it failed.
@@ -226,7 +216,7 @@ WARNING: \`$1' $msg.  You should only need it if
          \`Bison' from any GNU archive site."
     rm -f y.tab.c y.tab.h
     if test $# -ne 1; then
-        eval LASTARG="\${$#}"
+        eval LASTARG=\${$#}
 	case $LASTARG in
 	*.y)
 	    SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
@@ -256,7 +246,7 @@ WARNING: \`$1' is $msg.  You should only need it if
          \`Flex' from any GNU archive site."
     rm -f lex.yy.c
     if test $# -ne 1; then
-        eval LASTARG="\${$#}"
+        eval LASTARG=\${$#}
 	case $LASTARG in
 	*.l)
 	    SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
@@ -318,41 +308,6 @@ WARNING: \`$1' is $msg.  You should only need it if
     touch $file
     ;;
 
-  tar*)
-    shift
-
-    # We have already tried tar in the generic part.
-    # Look for gnutar/gtar before invocation to avoid ugly error
-    # messages.
-    if (gnutar --version > /dev/null 2>&1); then
-       gnutar "$@" && exit 0
-    fi
-    if (gtar --version > /dev/null 2>&1); then
-       gtar "$@" && exit 0
-    fi
-    firstarg="$1"
-    if shift; then
-	case $firstarg in
-	*o*)
-	    firstarg=`echo "$firstarg" | sed s/o//`
-	    tar "$firstarg" "$@" && exit 0
-	    ;;
-	esac
-	case $firstarg in
-	*h*)
-	    firstarg=`echo "$firstarg" | sed s/h//`
-	    tar "$firstarg" "$@" && exit 0
-	    ;;
-	esac
-    fi
-
-    echo 1>&2 "\
-WARNING: I can't seem to be able to run \`tar' with the given arguments.
-         You may want to install GNU tar or Free paxutils, or check the
-         command line arguments."
-    exit 1
-    ;;
-
   *)
     echo 1>&2 "\
 WARNING: \`$1' is needed, and is $msg.
diff --git a/src/c/src/cli.c b/src/c/src/cli.c
index c4538a6..e98178d 100644
--- a/src/c/src/cli.c
+++ b/src/c/src/cli.c
@@ -455,7 +455,7 @@ void processline(char *line) {
         *ptr = '\0';
         ptr++;
       }
-      zoo_add_auth(zh, line, ptr, ptr ? strlen(ptr)-1 : 0, NULL, NULL);
+      zoo_add_auth(zh, line, ptr, ptr ? strlen(ptr) : 0, NULL, NULL);
     }
 }
 
diff --git a/src/c/src/hashtable/hashtable_itr.c b/src/c/src/hashtable/hashtable_itr.c
index 5dced84..defac69 100644
--- a/src/c/src/hashtable/hashtable_itr.c
+++ b/src/c/src/hashtable/hashtable_itr.c
@@ -35,18 +35,6 @@ hashtable_iterator(struct hashtable *h)
 }
 
 /*****************************************************************************/
-/* key      - return the key of the (key,value) pair at the current position */
-/* value    - return the value of the (key,value) pair at the current position */
-
-void *
-hashtable_iterator_key(struct hashtable_itr *i)
-{ return i->e->k; }
-
-void *
-hashtable_iterator_value(struct hashtable_itr *i)
-{ return i->e->v; }
-
-/*****************************************************************************/
 /* advance - advance the iterator to the next element
  *           returns zero if advanced to end of table */
 
diff --git a/src/c/src/hashtable/hashtable_itr.h b/src/c/src/hashtable/hashtable_itr.h
index 234d3e3..30379c7 100644
--- a/src/c/src/hashtable/hashtable_itr.h
+++ b/src/c/src/hashtable/hashtable_itr.h
@@ -32,7 +32,7 @@ hashtable_iterator(struct hashtable *h);
 /* hashtable_iterator_key
  * - return the value of the (key,value) pair at the current position */
 
-extern inline void *
+static inline void *
 hashtable_iterator_key(struct hashtable_itr *i)
 {
     return i->e->k;
@@ -41,7 +41,7 @@ hashtable_iterator_key(struct hashtable_itr *i)
 /*****************************************************************************/
 /* value - return the value of the (key,value) pair at the current position */
 
-extern inline void *
+static inline void *
 hashtable_iterator_value(struct hashtable_itr *i)
 {
     return i->e->v;
diff --git a/src/c/src/zk_hashtable.c b/src/c/src/zk_hashtable.c
index 6ac8004..60cf7ac 100644
--- a/src/c/src/zk_hashtable.c
+++ b/src/c/src/zk_hashtable.c
@@ -189,8 +189,12 @@ static int do_insert_watcher_object(zk_hashtable *ht, const char *path, watcher_
         res=hashtable_insert(ht->ht,strdup(path),create_watcher_object_list(wo));
         assert(res);
     }else{
-        /* path already exists; check if the watcher already exists */
-        res = add_to_list(&wl, wo, 1);
+        /*
+         * Path already exists; check if the watcher already exists.
+         * Don't clone the watcher since it's allocated on the heap --- avoids
+         * a memory leak and saves a clone operation (calloc + copy).
+         */
+        res = add_to_list(&wl, wo, 0);
     }
     return res;    
 }
diff --git a/src/c/src/zookeeper.c b/src/c/src/zookeeper.c
index f258ef1..cbad641 100644
--- a/src/c/src/zookeeper.c
+++ b/src/c/src/zookeeper.c
@@ -818,7 +818,7 @@ void free_duplicate_path(const char *free_path, const char* path) {
 */
 static char* prepend_string(zhandle_t *zh, const char* client_path) {
     char *ret_str;
-    if (zh->chroot == NULL)
+    if (zh == NULL || zh->chroot == NULL)
         return (char *) client_path;
     // handle the chroot itself, client_path = "/"
     if (strlen(client_path) == 1) {
@@ -1949,11 +1949,9 @@ int zookeeper_process(zhandle_t *zh, int events)
             completion_list_t *cptr = dequeue_completion(&zh->sent_requests);
 
             /* [ZOOKEEPER-804] Don't assert if zookeeper_close has been called. */
-            if (zh->close_requested == 1) {
-                if (cptr) {
-                    destroy_completion_entry(cptr);
-                    cptr = NULL;
-                }
+            if (zh->close_requested == 1 && cptr == NULL) {
+                LOG_DEBUG(("Completion queue has been cleared by zookeeper_close()"));
+                close_buffer_iarchive(&ia);
                 return api_epilog(zh,ZINVALIDSTATE);
             }
             assert(cptr);
diff --git a/src/c/tests/TestClient.cc b/src/c/tests/TestClient.cc
index 1bce5bd..2e0d7d3 100644
--- a/src/c/tests/TestClient.cc
+++ b/src/c/tests/TestClient.cc
@@ -772,6 +772,10 @@ public:
         zk_ch = createchClient(&ctx_ch, "127.0.0.1:22181/testch1/mahadev");
         CPPUNIT_ASSERT(zk_ch != NULL);
         zk = createClient(&ctx);
+        // first test with a NULL zk handle, make sure client library does not
+        // dereference a null pointer, but instead returns ZBADARGUMENTS
+        rc = zoo_create(NULL, "/testch1", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+        CPPUNIT_ASSERT_EQUAL((int) ZBADARGUMENTS, rc);
         rc = zoo_create(zk, "/testch1", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
         rc = zoo_create(zk, "/testch1/mahadev", data, 7, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
diff --git a/src/contrib/zkpython/src/c/zookeeper.c b/src/contrib/zkpython/src/c/zookeeper.c
index 96d73ee..0a856bb 100644
--- a/src/contrib/zkpython/src/c/zookeeper.c
+++ b/src/contrib/zkpython/src/c/zookeeper.c
@@ -66,6 +66,8 @@ PyObject *err_to_exception(int errcode) {
     return OperationTimeoutException;
   case ZBADARGUMENTS:
     return BadArgumentsException;
+  case ZINVALIDSTATE:
+    return InvalidStateException;
   case ZAPIERROR:
     return ApiErrorException;
   case ZNONODE:
@@ -90,7 +92,6 @@ PyObject *err_to_exception(int errcode) {
     return InvalidCallbackException;
   case ZSESSIONMOVED:
     return SessionMovedException;
-      
   case ZOK:
   default:
     return NULL;
@@ -436,7 +437,8 @@ void watcher_dispatch(zhandle_t *zzh, int type, int state,
   if (PyObject_CallObject((PyObject*)callback, arglist) == NULL) {
     PyErr_Print();
   }
-  if (pyw->permanent == 0 && (type != ZOO_SESSION_EVENT || is_unrecoverable(zzh) == ZINVALIDSTATE)) {
+  Py_DECREF(arglist);
+  if (pyw->permanent == 0 && (type != ZOO_SESSION_EVENT || state < 0)) {
     free_pywatcher(pyw);
   }
   PyGILState_Release(gstate);
@@ -457,6 +459,7 @@ void void_completion_dispatch(int rc, const void *data)
   PyObject *arglist = Py_BuildValue("(i,i)", pyw->zhandle, rc);
   if (PyObject_CallObject((PyObject*)callback, arglist) == NULL)
     PyErr_Print();
+  Py_DECREF(arglist);
   free_pywatcher(pyw);
   PyGILState_Release(gstate);
 }
@@ -474,9 +477,9 @@ void stat_completion_dispatch(int rc, const struct Stat *stat, const void *data)
   PyObject *pystat = build_stat(stat);
   PyObject *arglist = Py_BuildValue("(i,i,O)", pyw->zhandle,rc, pystat);
   Py_DECREF(pystat);
-
   if (PyObject_CallObject((PyObject*)callback, arglist) == NULL)
     PyErr_Print();
+  Py_DECREF(arglist);
   free_pywatcher(pyw);
   PyGILState_Release(gstate);
 }
@@ -498,6 +501,7 @@ void data_completion_dispatch(int rc, const char *value, int value_len, const st
 
   if (PyObject_CallObject((PyObject*)callback, arglist) == NULL)
     PyErr_Print();
+  Py_DECREF(arglist);
   free_pywatcher(pyw);
   PyGILState_Release(gstate);
 }
@@ -518,6 +522,7 @@ void strings_completion_dispatch(int rc, const struct String_vector *strings, co
       PyObject *arglist = Py_BuildValue("(i,i,O)", pyw->zhandle, rc, pystrings);   
       if (arglist == NULL || PyObject_CallObject((PyObject*)callback, arglist) == NULL)
         PyErr_Print();
+      Py_DECREF(arglist);
     }
   else
     PyErr_Print();
@@ -540,6 +545,7 @@ void string_completion_dispatch(int rc, const char *value, const void *data)
   PyObject *arglist = Py_BuildValue("(i,i,s)", pyw->zhandle,rc, value);
   if (PyObject_CallObject((PyObject*)callback, arglist) == NULL)
     PyErr_Print();
+  Py_DECREF(arglist);
   free_pywatcher(pyw);
   PyGILState_Release(gstate);
 }
@@ -565,6 +571,7 @@ void acl_completion_dispatch(int rc, struct ACL_vector *acl, struct Stat *stat,
   if (PyObject_CallObject((PyObject*)callback, arglist) == NULL) {
     PyErr_Print();
   }
+  Py_DECREF(arglist);
   free_pywatcher(pyw);
   PyGILState_Release(gstate);
 }
diff --git a/src/docs/src/documentation/content/xdocs/releasenotes.xml b/src/docs/src/documentation/content/xdocs/releasenotes.xml
index 6089c03..0b7a01c 100644
--- a/src/docs/src/documentation/content/xdocs/releasenotes.xml
+++ b/src/docs/src/documentation/content/xdocs/releasenotes.xml
@@ -18,7 +18,7 @@
 <!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V1.0//EN"
 "http://www.oasis-open.org/docbook/xml/simple/1.0/sdocbook.dtd">
 <article id="ar_ReleaseNotes">
-  <title>ZooKeeper 3.3.5 Release Notes</title>
+  <title>ZooKeeper 3.3.6 Release Notes</title>
 
   <articleinfo>
     <legalnotice>
@@ -47,10 +47,10 @@ from version 2 of ZooKeeper (SourceForge) to version 3 or
 later.</para>
 
 <section id="changes">
-<title>Changes Since ZooKeeper 3.3.4</title>
+<title>Changes Since ZooKeeper 3.3.5</title>
 
 <table>
-<title>Changes Since ZooKeeper 3.3.4</title>
+<title>Changes Since ZooKeeper 3.3.5</title>
 <tgroup cols='2'>
 <colspec colname='c1'/><colspec colname='c2'/>
 <thead>
@@ -64,33 +64,47 @@ later.</para>
 <row><entry>        Bug
 </entry><entry></entry></row>
 
-<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-973'>ZOOKEEPER-973</ulink>]</entry><entry>         bind() could fail on Leader because it does not setReuseAddress on its ServerSocket 
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1048'>ZOOKEEPER-1048</ulink>]</entry><entry>         addauth command does not work in cli_mt/cli_st
 </entry></row>
-<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1089'>ZOOKEEPER-1089</ulink>]</entry><entry>         zkServer.sh status does not work due to invalid option of nc
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1163'>ZOOKEEPER-1163</ulink>]</entry><entry>         Memory leak in zk_hashtable.c:do_insert_watcher_object()
 </entry></row>
-<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1277'>ZOOKEEPER-1277</ulink>]</entry><entry>         servers stop serving when lower 32bits of zxid roll over
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1210'>ZOOKEEPER-1210</ulink>]</entry><entry>         Can't build ZooKeeper RPM with RPM >= 4.6.0 (i.e. on RHEL 6 and Fedora >= 10)
 </entry></row>
-<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1309'>ZOOKEEPER-1309</ulink>]</entry><entry>         Creating a new ZooKeeper client can leak file handles
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1305'>ZOOKEEPER-1305</ulink>]</entry><entry>         zookeeper.c:prepend_string func can dereference null ptr
 </entry></row>
-<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1352'>ZOOKEEPER-1352</ulink>]</entry><entry>         server.InvalidSnapshotTest is using connection timeouts that are too short
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1318'>ZOOKEEPER-1318</ulink>]</entry><entry>         In Python binding, get_children (and get and exists, and probably others) with expired session doesn't raise exception properly
 </entry></row>
-<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1353'>ZOOKEEPER-1353</ulink>]</entry><entry>         C client test suite fails consistently
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1339'>ZOOKEEPER-1339</ulink>]</entry><entry>         C clien doesn't build with --enable-debug
 </entry></row>
-<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1367'>ZOOKEEPER-1367</ulink>]</entry><entry>         Data inconsistencies and unexpired ephemeral nodes after cluster restart
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1395'>ZOOKEEPER-1395</ulink>]</entry><entry>         node-watcher double-free redux
 </entry></row>
-<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1386'>ZOOKEEPER-1386</ulink>]</entry><entry>         avoid flaky URL redirection in "ant javadoc" : replace "http://java.sun.com/javase/6/docs/api/" with "http://download.oracle.com/javase/6/docs/api/" 
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1403'>ZOOKEEPER-1403</ulink>]</entry><entry>         zkCli.sh script quoting issue
 </entry></row>
-<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1412'>ZOOKEEPER-1412</ulink>]</entry><entry>         java client watches inconsistently triggered on reconnect
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1431'>ZOOKEEPER-1431</ulink>]</entry><entry>         zkpython: async calls leak memory
 </entry></row>
-        
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1466'>ZOOKEEPER-1466</ulink>]</entry><entry>         QuorumCnxManager.shutdown missing synchronization
+</entry></row>
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1489'>ZOOKEEPER-1489</ulink>]</entry><entry>         Data loss after truncate on transaction log
+</entry></row>
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1493'>ZOOKEEPER-1493</ulink>]</entry><entry>         C Client: zookeeper_process doesn't invoke completion callback if zookeeper_close has been called
+</entry></row>
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1521'>ZOOKEEPER-1521</ulink>]</entry><entry>         LearnerHandler initLimit/syncLimit problems specifying follower socket timeout limits
+</entry></row>
+
 <row><entry>        Improvement
 </entry><entry></entry></row>
 
-<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1345'>ZOOKEEPER-1345</ulink>]</entry><entry>         Add a .gitignore file with general exclusions and Eclipse project files excluded
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1433'>ZOOKEEPER-1433</ulink>]</entry><entry>         improve ZxidRolloverTest (test seems flakey)
 </entry></row>
-<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1389'>ZOOKEEPER-1389</ulink>]</entry><entry>         it would be nice if start-foreground used exec $JAVA in order to get rid of the intermediate shell process
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1454'>ZOOKEEPER-1454</ulink>]</entry><entry>         Document how to run autoreconf if cppunit is installed in a non-standard directory
 </entry></row>
 
+<row><entry>        Task
+</entry><entry></entry></row>
+
+<row><entry>[<ulink url='https://issues.apache.org/jira/browse/ZOOKEEPER-1450'>ZOOKEEPER-1450</ulink>]</entry><entry>         Backport ZOOKEEPER-1294 fix to 3.4 and 3.3
+</entry></row>
+        
 </tbody></tgroup></table>
 
 </section>
diff --git a/src/java/lib/jdiff/zookeeper_3.3.5.xml b/src/java/lib/jdiff/zookeeper_3.3.6.xml
similarity index 99%
rename from src/java/lib/jdiff/zookeeper_3.3.5.xml
rename to src/java/lib/jdiff/zookeeper_3.3.6.xml
index 2b3678e..9e4692e 100644
--- a/src/java/lib/jdiff/zookeeper_3.3.5.xml
+++ b/src/java/lib/jdiff/zookeeper_3.3.6.xml
@@ -1,15 +1,15 @@
 <?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
 <!-- Generated by the JDiff Javadoc doclet -->
 <!-- (http://www.jdiff.org) -->
-<!-- on Thu Mar 15 13:09:41 PDT 2012 -->
+<!-- on Sat Jul 28 23:23:13 PDT 2012 -->
 
 <api
   xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
   xsi:noNamespaceSchemaLocation='api.xsd'
-  name="zookeeper 3.3.5"
+  name="zookeeper 3.3.6"
   jdversion="1.0.9">
 
-<!--  Command line arguments =  -doclet jdiff.JDiff -docletpath /home/phunt/dev/rels/3.3.5-rc1/branch-3.3/build/jdiff/lib/jdiff-1.0.9.jar:/home/phunt/dev/rels/3.3.5-rc1/branch-3.3/build/jdiff/lib/xerces-1.4.4.jar -classpath /home/phunt/dev/rels/3.3.5-rc1/branch-3.3/build/classes:/home/phunt/dev/rels/3.3.5-rc1/branch-3.3/src/java/lib/ivy-2.1.0.jar:/home/phunt/dev/rels/3.3.5-rc1/branch-3.3/build/lib/jline-0.9.94.jar:/home/phunt/dev/rels/3.3.5-rc1/branch-3.3/build/lib/log4j-1.2.15.jar -sourcepath /home/phunt/dev/rels/3.3.5-rc1/branch-3.3/src/java/main -apidir /home/phunt/dev/rels/3.3.5-rc1/branch-3.3/src/java/lib/jdiff -apiname zookeeper 3.3.5 -->
+<!--  Command line arguments =  -doclet jdiff.JDiff -docletpath /home/phunt/dev/rels/3.3.6/branch-3.3/build/jdiff/lib/jdiff-1.0.9.jar:/home/phunt/dev/rels/3.3.6/branch-3.3/build/jdiff/lib/xerces-1.4.4.jar -classpath /home/phunt/dev/rels/3.3.6/branch-3.3/build/classes:/home/phunt/dev/rels/3.3.6/branch-3.3/src/java/lib/ivy-2.1.0.jar:/home/phunt/dev/rels/3.3.6/branch-3.3/build/lib/jline-0.9.94.jar:/home/phunt/dev/rels/3.3.6/branch-3.3/build/lib/log4j-1.2.15.jar -sourcepath /home/phunt/dev/rels/3.3.6/branch-3.3/src/java/main -apidir /home/phunt/dev/rels/3.3.6/branch-3.3/src/java/lib/jdiff -apiname zookeeper 3.3.6 -->
 <package name="org.apache.zookeeper">
   <!-- start interface org.apache.zookeeper.AsyncCallback -->
   <interface name="AsyncCallback"    abstract="true"
diff --git a/src/java/main/org/apache/zookeeper/server/ZKDatabase.java b/src/java/main/org/apache/zookeeper/server/ZKDatabase.java
index 806141d..5eda9c1 100644
--- a/src/java/main/org/apache/zookeeper/server/ZKDatabase.java
+++ b/src/java/main/org/apache/zookeeper/server/ZKDatabase.java
@@ -425,16 +425,23 @@ public class ZKDatabase {
     }
 
     /**
-     * truncate the zkdatabase to this zxid
+     * Truncate the ZKDatabase to the specified zxid
      * @param zxid the zxid to truncate zk database to
-     * @return true if the truncate is succesful and false if not
+     * @return true if the truncate is successful and false if not
      * @throws IOException
      */
     public boolean truncateLog(long zxid) throws IOException {
         clear();
-        boolean truncated = this.snapLog.truncateLog(zxid);
+
+        // truncate the log
+        boolean truncated = snapLog.truncateLog(zxid);
+
+        if (!truncated) {
+            return false;
+        }
+
         loadDataBase();
-        return truncated;
+        return true;
     }
     
     /**
@@ -491,4 +498,4 @@ public class ZKDatabase {
         this.snapLog.close();
     }
     
-}
\ No newline at end of file
+}
diff --git a/src/java/main/org/apache/zookeeper/server/persistence/FileTxnSnapLog.java b/src/java/main/org/apache/zookeeper/server/persistence/FileTxnSnapLog.java
index 68c5264..f629783 100644
--- a/src/java/main/org/apache/zookeeper/server/persistence/FileTxnSnapLog.java
+++ b/src/java/main/org/apache/zookeeper/server/persistence/FileTxnSnapLog.java
@@ -48,12 +48,12 @@ import org.apache.zookeeper.KeeperException;
 public class FileTxnSnapLog {
     //the direcotry containing the 
     //the transaction logs
-    File dataDir; 
-    //the directory containing the 
+    private final File dataDir;
+    //the directory containing the
     //the snapshot directory
-    File snapDir;
-    TxnLog txnLog;
-    SnapShot snapLog;
+    private final File snapDir;
+    private TxnLog txnLog;
+    private SnapShot snapLog;
     public final static int VERSION = 2;
     public final static String version = "version-";
     
@@ -77,6 +77,8 @@ public class FileTxnSnapLog {
      * @param snapDir the snapshot directory
      */
     public FileTxnSnapLog(File dataDir, File snapDir) throws IOException {
+        LOG.debug("Opening datadir:" + dataDir + " snapDir:{}" + snapDir);
+
         this.dataDir = new File(dataDir, version + VERSION);
         this.snapDir = new File(snapDir, version + VERSION);
         if (!this.dataDir.exists()) {
@@ -266,8 +268,22 @@ public class FileTxnSnapLog {
      * @throws IOException
      */
     public boolean truncateLog(long zxid) throws IOException {
-        FileTxnLog txnLog = new FileTxnLog(dataDir);
-        return txnLog.truncate(zxid);
+        // close the existing txnLog and snapLog
+        close();
+
+        // truncate it
+        FileTxnLog truncLog = new FileTxnLog(dataDir);
+        boolean truncated = truncLog.truncate(zxid);
+        truncLog.close();
+
+        // re-open the txnLog and snapLog
+        // I'd rather just close/reopen this object itself, however that 
+        // would have a big impact outside ZKDatabase as there are other
+        // objects holding a reference to this object.
+        txnLog = new FileTxnLog(dataDir);
+        snapLog = new FileSnap(snapDir);
+
+        return truncated;
     }
     
     /**
diff --git a/src/java/main/org/apache/zookeeper/server/quorum/Leader.java b/src/java/main/org/apache/zookeeper/server/quorum/Leader.java
index 66fd3b7..1ce2c27 100644
--- a/src/java/main/org/apache/zookeeper/server/quorum/Leader.java
+++ b/src/java/main/org/apache/zookeeper/server/quorum/Leader.java
@@ -236,8 +236,10 @@ public class Leader {
             try {
                 while (!stop) {
                     try{
-                        Socket s = ss.accept();                        
-                        s.setSoTimeout(self.tickTime * self.syncLimit);
+                        Socket s = ss.accept();
+                        // start with the initLimit, once the ack is processed
+                        // in LearnerHandler switch to the syncLimit
+                        s.setSoTimeout(self.tickTime * self.initLimit);
                         s.setTcpNoDelay(nodelay);
                         LearnerHandler fh = new LearnerHandler(s, Leader.this);
                         fh.start();
@@ -367,15 +369,15 @@ public class Leader {
                 if (!tickSkip) {
                     self.tick++;
                 }
-                int syncedCount = 0;
                 HashSet<Long> syncedSet = new HashSet<Long>();
-                
+
                 // lock on the followers when we use it.
                 syncedSet.add(self.getId());
                 synchronized (learners) {
                     for (LearnerHandler f : learners) {
-                        if (f.synced()) {
-                            syncedCount++;
+                        // Synced set is used to check we have a supporting quorum, so only
+                        // PARTICIPANT, not OBSERVER, learners should be used
+                        if (f.synced() && f.getLearnerType() == LearnerType.PARTICIPANT) {
                             syncedSet.add(f.getSid());
                         }
                         f.ping();
@@ -385,7 +387,7 @@ public class Leader {
                 //if (!tickSkip && syncedCount < self.quorumPeers.size() / 2) {
                     // Lost quorum, shutdown
                   // TODO: message is wrong unless majority quorums used
-                    shutdown("Only " + syncedCount + " followers, need "
+                    shutdown("Only " + syncedSet.size() + " followers, need "
                             + (self.getVotingView().size() / 2));
                     // make sure the order is the same!
                     // the leader goes to looking
diff --git a/src/java/main/org/apache/zookeeper/server/quorum/LearnerHandler.java b/src/java/main/org/apache/zookeeper/server/quorum/LearnerHandler.java
index 4a9cf19..565d620 100644
--- a/src/java/main/org/apache/zookeeper/server/quorum/LearnerHandler.java
+++ b/src/java/main/org/apache/zookeeper/server/quorum/LearnerHandler.java
@@ -399,6 +399,9 @@ public class LearnerHandler extends Thread {
             }
             leader.processAck(this.sid, qp.getZxid(), sock.getLocalSocketAddress());
             
+            // now that the ack has been processed expect the syncLimit
+            sock.setSoTimeout(leader.self.tickTime * leader.self.syncLimit);
+
             /*
              * Wait until leader starts up
              */
@@ -407,7 +410,7 @@ public class LearnerHandler extends Thread {
                     leader.zk.wait(500);
                 }
             }
-            
+
             while (true) {
                 qp = new QuorumPacket();
                 ia.readRecord(qp, "packet");
diff --git a/src/java/main/org/apache/zookeeper/server/quorum/QuorumCnxManager.java b/src/java/main/org/apache/zookeeper/server/quorum/QuorumCnxManager.java
index 2e44443..239794b 100644
--- a/src/java/main/org/apache/zookeeper/server/quorum/QuorumCnxManager.java
+++ b/src/java/main/org/apache/zookeeper/server/quorum/QuorumCnxManager.java
@@ -103,7 +103,7 @@ public class QuorumCnxManager {
      * Shutdown flag
      */
 
-    boolean shutdown = false;
+    volatile boolean shutdown = false;
 
     /*
      * Listener thread
diff --git a/src/java/test/org/apache/zookeeper/server/TruncateCorruptionTest.java b/src/java/test/org/apache/zookeeper/server/TruncateCorruptionTest.java
new file mode 100644
index 0000000..8346e84
--- /dev/null
+++ b/src/java/test/org/apache/zookeeper/server/TruncateCorruptionTest.java
@@ -0,0 +1,318 @@
+/**
+ * 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 java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.TestCase;
+
+import org.apache.log4j.Logger;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.ZooKeeper.States;
+import org.apache.zookeeper.client.FourLetterWordMain;
+import org.apache.zookeeper.server.quorum.QuorumPeerTestBase.MainThread;
+import org.apache.zookeeper.server.util.PortForwarder;
+import org.apache.zookeeper.test.ClientBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Verify ZOOKEEPER-1489 - cause truncation followed by continued append to the
+ * snaplog, verify that the newly appended information (after the truncation) is
+ * readable.
+ */
+public class TruncateCorruptionTest extends TestCase {
+
+    private static final Logger LOG =
+            Logger.getLogger(TruncateCorruptionTest.class);
+
+    public interface Check {
+        boolean doCheck();
+    }
+
+    public static boolean await(Check check, long timeoutMillis)
+            throws InterruptedException {
+        long end = System.currentTimeMillis() + timeoutMillis;
+        while (end > System.currentTimeMillis()) {
+            if (check.doCheck()) {
+                LOG.debug("await succeeded after "
+                        + (System.currentTimeMillis() - end + timeoutMillis));
+                return true;
+            }
+            Thread.sleep(50);
+        }
+        LOG.debug("await failed in " + timeoutMillis);
+        return false;
+    }
+
+    @Test
+    public void testTransactionLogCorruption() throws Exception {
+        // configure the ports for that test in a way so that we can disrupt the
+        // connection for wrapper1
+        ZookeeperServerWrapper wrapper1 = new ZookeeperServerWrapper(1, 7000);
+        ZookeeperServerWrapper wrapper2 = new ZookeeperServerWrapper(2, 8000);
+        ZookeeperServerWrapper wrapper3 = new ZookeeperServerWrapper(3, 8000);
+
+        wrapper2.start();
+        wrapper3.start();
+
+        wrapper2.await(ClientBase.CONNECTION_TIMEOUT);
+        wrapper3.await(ClientBase.CONNECTION_TIMEOUT);
+        List<PortForwarder> pfs = startForwarding();
+        Thread.sleep(1000);
+        wrapper1.start();
+        wrapper1.await(ClientBase.CONNECTION_TIMEOUT);
+
+        final ZooKeeper zk1 = new ZooKeeper("localhost:8201",
+                ClientBase.CONNECTION_TIMEOUT, new ZkWatcher("zk1"));
+        waitForConnection(zk1);
+        zk1.create("/test", "testdata".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        // wait a little until stuff is synced in between servers
+        Thread.sleep(1000);
+        wrapper2.stop();
+        // wait for reconnect
+        waitForConnection(zk1);
+        zk1.create("/test2", "testdata".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+        // now we stop them to force a situation where a TRUNC event is sent to
+        // the followers
+        wrapper3.stop();
+        // simulate a short interruption in network in between
+
+        stopForwarding(pfs);
+        LOG.info("interrupted network connection ... waiting for zk1 and zk2 to realize");
+
+        Assert.assertTrue(await(new Check() {
+
+            public boolean doCheck() {
+                if (zk1.getState() == States.CONNECTING) {
+                    List<String> children;
+                    try {
+                        children = zk1.getChildren("/", false);
+
+                        return children.size() != 0;
+                    } catch (KeeperException.ConnectionLossException e) {
+                        // just to be sure
+                        return true;
+                    } catch (Exception e) {
+                        // silently fail
+                    }
+                }
+                return false;
+            }
+        }, TimeUnit.MINUTES.toMillis(2)));
+
+        // let's clean the data dir of zk3 so that an ensemble of 2 and 3 is
+        // less advanced than 1 (just to force an event where we get a TRUNCATE
+        // message)
+        wrapper3.clean();
+        wrapper2.start();
+        wrapper3.start();
+        LOG.info("Waiting for zk2 and zk3 to form a quorum");
+
+        wrapper2.await(ClientBase.CONNECTION_TIMEOUT);
+        wrapper3.await(ClientBase.CONNECTION_TIMEOUT);
+        ZooKeeper zk2 = new ZooKeeper("localhost:8202",
+                ClientBase.CONNECTION_TIMEOUT, new ZkWatcher("zk2"));
+        waitForConnection(zk2);
+
+        LOG.info("re-establishing network connection and waiting for zk1 to reconnect");
+        pfs = startForwarding();
+        waitForConnection(zk1);
+
+        // create more data ...
+        LOG.info("Creating node test3");
+        zk1.create("/test3", "testdata".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+        Thread.sleep(250);
+        LOG.info("List of children at zk2 before zk1 became master");
+        List<String> children2 = zk2.getChildren("/", false);
+        LOG.info(children2.toString());
+
+        LOG.info("List of children at zk1 before zk1 became master");
+        List<String> children1 = zk1.getChildren("/", false);
+        LOG.info(children1.toString());
+
+        // now cause zk1 to become master and test3 will be lost
+        LOG.info("restarting zk2 and zk3 while cleaning zk3 to enforce zk1 to become master");
+        wrapper2.stop();
+        wrapper3.stop();
+        wrapper3.clean();
+        wrapper3.start();
+        wrapper3.await(TimeUnit.MINUTES.toMillis(2));
+        ZooKeeper zk3 = new ZooKeeper("localhost:8203",
+                ClientBase.CONNECTION_TIMEOUT, new ZkWatcher("zk3"));
+        waitForConnection(zk3);
+        LOG.info("Zk1 and zk3 have a quorum, now starting zk2");
+        wrapper2.start();
+        waitForConnection(zk2);
+        LOG.info("List of children at zk2");
+        children2 = zk2.getChildren("/", false);
+        LOG.info(children2.toString());
+
+        waitForConnection(zk1);
+        LOG.info("List of children at zk1");
+        children1 = zk1.getChildren("/", false);
+        Assert.assertTrue("test3 node is missing on zk1",
+                children1.contains("test3"));
+        Assert.assertTrue("test3 node is missing on zk2",
+                children2.contains("test3"));
+        Assert.assertEquals(children1, children2);
+        stopForwarding(pfs);
+    }
+
+    /**
+     * @param pfs
+     * @throws Exception
+     */
+    private void stopForwarding(List<PortForwarder> pfs) throws Exception {
+        for (PortForwarder pf : pfs) {
+            pf.shutdown();
+        }
+    }
+
+    /**
+     * @return
+     * @throws IOException
+     */
+    private List<PortForwarder> startForwarding() throws IOException {
+        List<PortForwarder> res = new ArrayList<PortForwarder>();
+        res.add(new PortForwarder(8301, 7301));
+        res.add(new PortForwarder(8401, 7401));
+        res.add(new PortForwarder(7302, 8302));
+        res.add(new PortForwarder(7402, 8402));
+        res.add(new PortForwarder(7303, 8303));
+        res.add(new PortForwarder(7403, 8403));
+        return res;
+    }
+
+    /**
+     * @param zk
+     * @throws InterruptedException
+     */
+    private void waitForConnection(final ZooKeeper zk)
+            throws InterruptedException {
+        Assert.assertTrue(await(new Check() {
+
+            public boolean doCheck() {
+                if (zk.getState() == States.CONNECTED) {
+                    List<String> children;
+                    try {
+                        children = zk.getChildren("/", false);
+
+                        return children.size() != 0;
+                    } catch (Exception e) {
+                        // silently fail
+                    }
+                }
+                return false;
+            }
+        }, TimeUnit.MINUTES.toMillis(2)));
+    }
+
+    static class ZkWatcher implements Watcher {
+
+        private final String clientId;
+
+        ZkWatcher(String clientId) {
+            this.clientId = clientId;
+        }
+
+        public void process(WatchedEvent event) {
+            LOG.info("<<<EVENT>>> " + clientId + " - WatchedEvent: "
+                    + event);
+        }
+    }
+
+    public static class ZookeeperServerWrapper {
+
+        private static final Logger LOG = 
+                Logger.getLogger(ZookeeperServerWrapper.class);
+
+        private final MainThread server;
+        private final int clientPort;
+
+        public ZookeeperServerWrapper(int serverId, int portBase)
+                throws IOException {
+            clientPort = 8200 + serverId;
+
+            // start client port on 8200 + serverId
+            // start servers on portbase + 300 or + 400 (+serverId)
+            String quorumCfgSection = "server.1=127.0.0.1:" + (portBase + 301)
+                    + ":" + (portBase + 401)
+                    + "\nserver.2=127.0.0.1:" + (portBase + 302) + ":"
+                    + (portBase + 402)
+                    + "\nserver.3=127.0.0.1:" + (portBase + 303) + ":"
+                    + (portBase + 403);
+
+            server = new MainThread(serverId, clientPort, quorumCfgSection);
+        }
+
+        public void start() throws Exception {
+            server.start();
+        }
+
+        public void await(long timeout) throws Exception {
+            long deadline = System.currentTimeMillis() + timeout;
+            String result = "?";
+            while (deadline > System.currentTimeMillis()) {
+                try {
+                    result = FourLetterWordMain.send4LetterWord("127.0.0.1",
+                            clientPort, "stat");
+                    if (result.startsWith("Zookeeper version:")) {
+                        LOG.info("Started zookeeper server on port "
+                                 + clientPort);
+                        return;
+                    }
+                } catch (IOException e) {
+                    // ignore as this is expected
+                }
+                try {
+                    Thread.sleep(100);
+                } catch (InterruptedException e) {
+                    // ignore
+                }
+            }
+            LOG.info(result);
+            throw new Exception("Failed to connect to zookeeper server");
+        }
+
+        public void stop() {
+            try {
+                server.shutdown();
+            } catch (InterruptedException e) {
+                LOG.info("Interrupted while shutting down");
+            }
+        }
+
+        public void clean() throws IOException {
+            server.clean();
+        }
+    }
+}
diff --git a/src/java/test/org/apache/zookeeper/server/ZxidRolloverTest.java b/src/java/test/org/apache/zookeeper/server/ZxidRolloverTest.java
index f44cd80..281f9eb 100644
--- a/src/java/test/org/apache/zookeeper/server/ZxidRolloverTest.java
+++ b/src/java/test/org/apache/zookeeper/server/ZxidRolloverTest.java
@@ -18,12 +18,12 @@
 
 package org.apache.zookeeper.server;
 
-import java.io.IOException;
-
+import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
 import org.apache.log4j.Logger;
 import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.KeeperException.ConnectionLossException;
 import org.apache.zookeeper.ZooDefs.Ids;
 import org.apache.zookeeper.ZooKeeper;
@@ -31,6 +31,7 @@ import org.apache.zookeeper.test.ClientBase;
 import org.apache.zookeeper.test.ClientBase.CountdownWatcher;
 import org.apache.zookeeper.test.ClientTest;
 import org.apache.zookeeper.test.QuorumUtil;
+import org.apache.zookeeper.test.QuorumUtil.PeerStruct;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -64,26 +65,93 @@ public class ZxidRolloverTest extends TestCase {
 
         for (int i = 0; i < zkClients.length; i++) {
             zkClientWatchers[i] = new CountdownWatcher();
-            int followerPort = qu.getPeer(i+1).peer.getClientPort();
+            PeerStruct peer = qu.getPeer(i + 1);
             zkClients[i] = new ZooKeeper(
-                    "127.0.0.1:" + followerPort,
+                    "127.0.0.1:" + peer.clientPort,
                     ClientTest.CONNECTION_TIMEOUT, zkClientWatchers[i]);
         }
-        waitForClients();
+        waitForClientsConnected();
     }
     
-    private void waitForClients() throws Exception {
+    private void waitForClientsConnected() throws Exception {
         for (int i = 0; i < zkClients.length; i++) {
             zkClientWatchers[i].waitForConnected(ClientTest.CONNECTION_TIMEOUT);
             zkClientWatchers[i].reset();
         }
     }
 
-    private void startAll() throws IOException {
+    /**
+     * Ensure all clients are able to talk to the service.
+     */
+    private void checkClientsConnected() throws Exception {
+        for (int i = 0; i < zkClients.length; i++) {
+            checkClientConnected(i + 1);
+        }
+    }
+
+    /**
+     * Ensure the client is able to talk to the server.
+     * 
+     * @param idx the idx of the server the client is talking to
+     */
+    private void checkClientConnected(int idx) throws Exception {
+        ZooKeeper zk = getClient(idx);
+        if (zk == null) {
+            return;
+        }
+        try {
+            assertNull(zk.exists("/foofoofoo-connected", false));
+        } catch (ConnectionLossException e) {
+            // second chance...
+            // in some cases, leader change in particular, the timing is
+            // very tricky to get right in order to assure that the client has
+            // disconnected and reconnected. In some cases the client will
+            // disconnect, then attempt to reconnect before the server is
+            // back, in which case we'll see another connloss on the operation
+            // in the try, this catches that case and waits for the server
+            // to come back
+            PeerStruct peer = qu.getPeer(idx);
+            Assert.assertTrue("Waiting for server down", ClientBase.waitForServerUp(
+                    "127.0.0.1:" + peer.clientPort, ClientBase.CONNECTION_TIMEOUT));
+
+            assertNull(zk.exists("/foofoofoo-connected", false));
+        }
+    }
+
+    /**
+     * Ensure all clients are disconnected from the service.
+     */
+    private void checkClientsDisconnected() throws Exception {
+        for (int i = 0; i < zkClients.length; i++) {
+            checkClientDisconnected(i + 1);
+        }
+    }
+
+    /**
+     * Ensure the client is able to talk to the server
+     * 
+     * @param idx the idx of the server the client is talking to
+     */
+    private void checkClientDisconnected(int idx) throws Exception {
+        ZooKeeper zk = getClient(idx);
+        if (zk == null) {
+            return;
+        }
+        try {
+            assertNull(zk.exists("/foofoofoo-disconnected", false));
+            fail("expected client to be disconnected");
+        } catch (KeeperException e) {
+            // success
+        }
+    }
+
+    private void startAll() throws Exception {
         qu.startAll();
         checkLeader();
+        // all clients should be connected
+        checkClientsConnected();
     }
-    private void start(int idx) throws IOException {
+    private void start(int idx) throws Exception {
         qu.start(idx);
         for (String hp : qu.getConnString().split(",")) {
             Assert.assertTrue("waiting for server up", ClientBase.waitForServerUp(hp,
@@ -91,6 +159,8 @@ public class ZxidRolloverTest extends TestCase {
         }
 
         checkLeader();
+        // all clients should be connected
+        checkClientsConnected();
     }
 
     private void checkLeader() {
@@ -103,12 +173,34 @@ public class ZxidRolloverTest extends TestCase {
         zksLeader = qu.getPeer(idxLeader).peer.getActiveServer();
     }
 
-    private void shutdownAll() throws IOException {
+    private void shutdownAll() throws Exception {
         qu.shutdownAll();
+        // all clients should be disconnected
+        checkClientsDisconnected();
     }
     
-    private void shutdown(int idx) throws IOException {
+    private void shutdown(int idx) throws Exception {
         qu.shutdown(idx);
+
+        // leader will shutdown, remaining followers will elect a new leader
+        PeerStruct peer = qu.getPeer(idx);
+        Assert.assertTrue("Waiting for server down", ClientBase.waitForServerDown(
+                "127.0.0.1:" + peer.clientPort, ClientBase.CONNECTION_TIMEOUT));
+
+        // if idx is the the leader then everyone will get disconnected,
+        // otherwise if idx is a follower then just that client will get
+        // disconnected
+        if (idx == idxLeader) {
+            checkClientDisconnected(idx);
+            try {
+                checkClientsDisconnected();
+            } catch (AssertionFailedError e) {
+                // the clients may or may not have already reconnected
+                // to the recovered cluster, force a check, but ignore
+            }
+        } else {
+            checkClientDisconnected(idx);
+        }
     }
 
     /** Reset the next zxid to be near epoch end */
@@ -140,7 +232,7 @@ public class ZxidRolloverTest extends TestCase {
             }
         } catch (ConnectionLossException e) {
             // this is ok - the leader has dropped leadership
-            waitForClients();
+            waitForClientsConnected();
         }
         return j;
     }
diff --git a/src/java/test/org/apache/zookeeper/server/quorum/QuorumPeerTestBase.java b/src/java/test/org/apache/zookeeper/server/quorum/QuorumPeerTestBase.java
index c58d270..4a7d316 100644
--- a/src/java/test/org/apache/zookeeper/server/quorum/QuorumPeerTestBase.java
+++ b/src/java/test/org/apache/zookeeper/server/quorum/QuorumPeerTestBase.java
@@ -34,8 +34,8 @@ import org.apache.zookeeper.test.ClientBase;
 import org.apache.zookeeper.test.QuorumBase;
 
 /**
- * Has some common functionality for tests that work with QuorumPeers.
- * Override process(WatchedEvent) to implement the Watcher interface
+ * Has some common functionality for tests that work with QuorumPeers. Override
+ * process(WatchedEvent) to implement the Watcher interface
  */
 public class QuorumPeerTestBase extends TestCase implements Watcher {
     protected static final Logger LOG =
@@ -45,7 +45,7 @@ public class QuorumPeerTestBase extends TestCase implements Watcher {
         // ignore for this test
     }
 
-    public static  class TestQPMain extends QuorumPeerMain {
+    public static class TestQPMain extends QuorumPeerMain {
         public void shutdown() {
             // ensure it closes - in particular wait for thread to exit
             if (quorumPeer != null) {
@@ -54,16 +54,16 @@ public class QuorumPeerTestBase extends TestCase implements Watcher {
         }
     }
 
-    public static class MainThread extends Thread {
+    public static class MainThread implements Runnable {
         final File confFile;
         volatile TestQPMain main;
 
         public MainThread(int myid, int clientPort, String quorumCfgSection)
             throws IOException
         {
-            super("QuorumPeer with myid:" + myid
-                    + " and clientPort:" + clientPort);
             File tmpDir = ClientBase.createTmpDir();
+            LOG.info("id = " + myid + " tmpDir = " + tmpDir + " clientPort = "
+                    + clientPort);
             confFile = new File(tmpDir, "zoo.cfg");
 
             FileWriter fwriter = new FileWriter(confFile);
@@ -99,11 +99,13 @@ public class QuorumPeerTestBase extends TestCase implements Watcher {
         }
 
         Thread currentThread;
+
         synchronized public void start() {
             main = new TestQPMain();
             currentThread = new Thread(this);
             currentThread.start();
         }
+
         public void run() {
             String args[] = new String[1];
             args[0] = confFile.toString();
@@ -125,5 +127,21 @@ public class QuorumPeerTestBase extends TestCase implements Watcher {
             }
         }
 
+        public void join(long timeout) throws InterruptedException {
+            Thread t = currentThread;
+            if (t != null) {
+                t.join(timeout);
+            }
+        }
+
+        public boolean isAlive() {
+            Thread t = currentThread;
+            return t != null && t.isAlive();
+        }
+
+        public void clean() {
+            ClientBase.recursiveDelete(main.quorumPeer.getTxnFactory()
+                    .getDataDir());
+        }
     }
 }
diff --git a/src/java/test/org/apache/zookeeper/server/util/PortForwarder.java b/src/java/test/org/apache/zookeeper/server/util/PortForwarder.java
new file mode 100644
index 0000000..8ee51c4
--- /dev/null
+++ b/src/java/test/org/apache/zookeeper/server/util/PortForwarder.java
@@ -0,0 +1,203 @@
+/**
+ * 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.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ConnectException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.log4j.Logger;
+
+public class PortForwarder extends Thread {
+    private static final Logger LOG = Logger.getLogger(PortForwarder.class);
+
+    private static class PortForwardWorker implements Runnable {
+
+        private final InputStream in;
+        private final OutputStream out;
+        private final Socket toClose;
+        private final Socket toClose2;
+
+        PortForwardWorker(Socket toClose, Socket toClose2, InputStream in,
+                OutputStream out) throws IOException {
+            this.toClose = toClose;
+            this.toClose2 = toClose2;
+            this.in = in;
+            this.out = out;
+            // LOG.info("starting forward for "+toClose);
+        }
+
+        public void run() {
+            Thread.currentThread().setName(toClose.toString() + "-->"
+                    + toClose2.toString());
+            byte[] buf = new byte[1024];
+            try {
+                while (true) {
+                    try {
+                        int read = this.in.read(buf);
+                        if (read > 0) {
+                            try {
+                                this.out.write(buf, 0, read);
+                            } catch (IOException e) {
+                                LOG.warn("exception during write", e);
+                                try {
+                                    toClose.close();
+                                } catch (IOException ex) {
+                                    // ignore
+                                }
+                                try {
+                                    toClose2.close();
+                                } catch (IOException ex) {
+                                    // ignore
+                                }
+                                break;
+                            }
+                        }
+                    } catch (SocketTimeoutException e) {
+                        LOG.error("socket timeout", e);
+                    }
+                    Thread.sleep(1);
+                }
+            } catch (InterruptedException e) {
+                LOG.warn("Interrupted", e);
+                try {
+                    toClose.close();
+                } catch (IOException ex) {
+                    // ignore
+                }
+                try {
+                    toClose2.close();
+                } catch (IOException ex) {
+                    // ignore silently
+                }
+            } catch (SocketException e) {
+                if (!"Socket closed".equals(e.getMessage())) {
+                    LOG.error("Unexpected exception", e);
+                }
+            } catch (IOException e) {
+                LOG.error("Unexpected exception", e);
+            }
+            LOG.info("Shutting down forward for " + toClose);
+        }
+
+    }
+
+    private volatile boolean stopped = false;
+    private ExecutorService workers = Executors.newCachedThreadPool();
+    private ServerSocket serverSocket;
+    private final int to;
+
+    public PortForwarder(int from, int to) throws IOException {
+        this.to = to;
+        serverSocket = new ServerSocket(from);
+        serverSocket.setSoTimeout(30000);
+        this.start();
+    }
+
+    @Override
+    public void run() {
+        try {
+            while (!stopped) {
+                Socket sock = null;
+                try {
+                    LOG.info("accepting socket local:"
+                            + serverSocket.getLocalPort() + " to:" + to);
+                    sock = serverSocket.accept();
+                    LOG.info("accepted: local:" + sock.getLocalPort()
+                            + " from:" + sock.getPort()
+                            + " to:" + to);
+                    Socket target = null;
+                    int retry = 10;
+                    while(sock.isConnected()) {
+                        try {
+                            target = new Socket("localhost", to);
+                            break;
+                        } catch (IOException e) {
+                            if (retry == 0) {
+                               throw e;
+                            }
+                            LOG.warn("connection failed, retrying(" + retry
+                                    + "): local:" + sock.getLocalPort()
+                                    + " from:" + sock.getPort()
+                                    + " to:" + to, e);
+                        }
+                        Thread.sleep(TimeUnit.SECONDS.toMillis(1));
+                        retry--;
+                    }
+                    LOG.info("connected: local:" + sock.getLocalPort()
+                            + " from:" + sock.getPort()
+                            + " to:" + to);
+                    sock.setSoTimeout(30000);
+                    target.setSoTimeout(30000);
+                    this.workers.execute(new PortForwardWorker(sock, target,
+                            sock.getInputStream(), target.getOutputStream()));
+                    this.workers.execute(new PortForwardWorker(target, sock,
+                            target.getInputStream(), sock.getOutputStream()));
+                } catch (SocketTimeoutException e) {
+                    LOG.warn("socket timed out local:" + sock.getLocalPort()
+                            + " from:" + sock.getPort()
+                            + " to:" + to, e);
+                } catch (ConnectException e) {
+                    LOG.warn("connection exception local:" + sock.getLocalPort()
+                            + " from:" + sock.getPort()
+                            + " to:" + to, e);
+                    sock.close();
+                } catch (IOException e) {
+                    if (!"Socket closed".equals(e.getMessage())) {
+                        LOG.warn("unexpected exception local:" + sock.getLocalPort()
+                            + " from:" + sock.getPort()
+                            + " to:" + to, e);
+                        throw e;
+                    }
+                }
+
+            }
+        } catch (IOException e) {
+            LOG.error("Unexpected exception to:" + to, e);
+        } catch (InterruptedException e) {
+            LOG.error("Interrupted to:" + to, e);
+        }
+    }
+
+    public void shutdown() throws Exception {
+        this.stopped = true;
+        this.serverSocket.close();
+        this.workers.shutdownNow();
+        try {
+            if (!this.workers.awaitTermination(5, TimeUnit.SECONDS)) {
+                throw new Exception(
+                        "Failed to stop forwarding within 5 seconds");
+            }
+        } catch (InterruptedException e) {
+            throw new Exception("Failed to stop forwarding");
+        }
+        this.join();
+    }
+}
diff --git a/src/java/test/org/apache/zookeeper/test/ClientBase.java b/src/java/test/org/apache/zookeeper/test/ClientBase.java
index a4dce5e..23be58e 100644
--- a/src/java/test/org/apache/zookeeper/test/ClientBase.java
+++ b/src/java/test/org/apache/zookeeper/test/ClientBase.java
@@ -53,6 +53,8 @@ import org.apache.zookeeper.server.NIOServerCnxn;
 import org.apache.zookeeper.server.ZKDatabase;
 import org.apache.zookeeper.server.ZooKeeperServer;
 import org.apache.zookeeper.server.persistence.FileTxnLog;
+import org.apache.zookeeper.server.quorum.QuorumPeer;
+
 import static org.apache.zookeeper.client.FourLetterWordMain.send4LetterWord;
 
 import com.sun.management.UnixOperatingSystemMXBean;
@@ -259,6 +261,23 @@ public abstract class ClientBase extends TestCase {
         return false;
     }
 
+    public static boolean waitForServerState(QuorumPeer qp, int timeout,
+            String serverState) {
+        long start = System.currentTimeMillis();
+        while (true) {
+            try {
+                Thread.sleep(250);
+            } catch (InterruptedException e) {
+                // ignore
+            }
+            if (qp.getServerState().equals(serverState))
+                return true;
+            if (System.currentTimeMillis() > start + timeout) {
+                return false;
+            }
+        }
+    }
+
     static void verifyThreadTerminated(Thread thread, long millis)
         throws InterruptedException
     {
diff --git a/src/java/test/org/apache/zookeeper/test/ObserverLETest.java b/src/java/test/org/apache/zookeeper/test/ObserverLETest.java
new file mode 100644
index 0000000..981d4bf
--- /dev/null
+++ b/src/java/test/org/apache/zookeeper/test/ObserverLETest.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
+ *
+ *     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.test;
+
+import static org.junit.Assert.*;
+
+import java.util.Arrays;
+
+import org.apache.log4j.Logger;
+import org.apache.zookeeper.server.quorum.QuorumPeer;
+import org.apache.zookeeper.server.quorum.QuorumStats;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ObserverLETest {
+    private static final Logger LOG = Logger.getLogger(ObserverLETest.class);
+    final QuorumBase qb = new QuorumBase();
+    final ClientTest ct = new ClientTest();
+
+    @Before
+    public void establishThreeParticipantOneObserverEnsemble() throws Exception {
+        qb.setUp(true);
+        ct.hostPort = qb.hostPort;
+        ct.setUpAll();
+        qb.s5.shutdown();
+    }
+
+    @After
+    public void shutdownQuorum() throws Exception {
+        ct.tearDownAll();
+        qb.tearDown();
+    }
+
+    /**
+     * See ZOOKEEPER-1294. Confirms that an observer will not support the quorum
+     * of a leader by forming a 5-node, 2-observer ensemble (so quorum size is 2).
+     * When all but the leader and one observer are shut down, the leader should
+     * enter the 'looking' state, not stay in the 'leading' state.
+     */
+    @Test
+    public void testLEWithObserver() throws Exception {
+        QuorumPeer leader = null;
+        for (QuorumPeer server : Arrays.asList(qb.s1, qb.s2, qb.s3)) {
+            if (server.getServerState().equals(
+                    QuorumStats.Provider.FOLLOWING_STATE)) {
+                server.shutdown();
+                assertTrue("Waiting for server down", ClientBase
+                        .waitForServerDown("127.0.0.1:"
+                                + server.getClientPort(),
+                                ClientBase.CONNECTION_TIMEOUT));
+            } else {
+                assertNull("More than one leader found", leader);
+                leader = server;
+            }
+        }
+        assertTrue("Leader is not in Looking state", ClientBase
+                .waitForServerState(leader, ClientBase.CONNECTION_TIMEOUT,
+                        QuorumStats.Provider.LOOKING_STATE));
+    }
+
+}
diff --git a/src/java/test/org/apache/zookeeper/test/TruncateTest.java b/src/java/test/org/apache/zookeeper/test/TruncateTest.java
index 8e44d39..7413ef8 100644
--- a/src/java/test/org/apache/zookeeper/test/TruncateTest.java
+++ b/src/java/test/org/apache/zookeeper/test/TruncateTest.java
@@ -23,8 +23,10 @@ import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.util.HashMap;
 
+import junit.framework.Assert;
 import junit.framework.TestCase;
 
+import org.apache.jute.Record;
 import org.apache.log4j.Logger;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
@@ -34,9 +36,15 @@ import org.apache.zookeeper.ZooDefs;
 import org.apache.zookeeper.ZooKeeper;
 import org.apache.zookeeper.data.Stat;
 import org.apache.zookeeper.server.NIOServerCnxn;
+import org.apache.zookeeper.server.Request;
 import org.apache.zookeeper.server.ZKDatabase;
+import org.apache.zookeeper.server.persistence.FileTxnLog;
+import org.apache.zookeeper.server.persistence.FileTxnSnapLog;
+import org.apache.zookeeper.server.persistence.TxnLog.TxnIterator;
 import org.apache.zookeeper.server.quorum.QuorumPeer;
 import org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer;
+import org.apache.zookeeper.txn.SetDataTxn;
+import org.apache.zookeeper.txn.TxnHeader;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -67,12 +75,67 @@ public class TruncateTest extends TestCase {
             connected = event.getState() == Watcher.Event.KeeperState.SyncConnected;
         }
     };
-    
+
+    @Test
+    public void testTruncationStreamReset() throws Exception {
+        File tmpdir = ClientBase.createTmpDir();
+        FileTxnSnapLog snaplog = new FileTxnSnapLog(tmpdir, tmpdir);
+        ZKDatabase zkdb = new ZKDatabase(snaplog);
+
+        for (int i = 1; i <= 100; i++) {
+            append(zkdb, i);
+        }
+
+        zkdb.truncateLog(1);
+
+        append(zkdb, 200);
+
+        zkdb.close();
+
+        // verify that the truncation and subsequent append were processed
+        // correctly
+        FileTxnLog txnlog = new FileTxnLog(new File(tmpdir, "version-2"));
+        TxnIterator iter = txnlog.read(1);
+
+        TxnHeader hdr = iter.getHeader();
+        Record txn = iter.getTxn();
+        Assert.assertEquals(1, hdr.getZxid());
+        Assert.assertTrue(txn instanceof SetDataTxn);
+
+        iter.next();
+
+        hdr = iter.getHeader();
+        txn = iter.getTxn();
+        Assert.assertEquals(200, hdr.getZxid());
+        Assert.assertTrue(txn instanceof SetDataTxn);
+    }
+
+    private void append(ZKDatabase zkdb, int i) throws IOException {
+        TxnHeader hdr = new TxnHeader(1, 1, i, 1, ZooDefs.OpCode.setData);
+        Record txn = new SetDataTxn("/foo" + i, new byte[0], 1);
+        Request req = new Request(null, 0, 0, 0, null, null);
+        req.hdr = hdr;
+        req.txn = txn;
+
+        zkdb.append(req);
+        zkdb.commit();
+    }
+
     @Test
     public void testTruncate() throws IOException, InterruptedException, KeeperException {
         // Prime the server that is going to come in late with 50 txns
-        NIOServerCnxn.Factory factory = ClientBase.createNewServerInstance(dataDir1, null, "127.0.0.1:" + baseHostPort, 100);
-        ZooKeeper zk = new ZooKeeper("127.0.0.1:" + baseHostPort, 15000, nullWatcher);
+        String hostPort = "127.0.0.1:" + baseHostPort;
+        NIOServerCnxn.Factory factory = ClientBase.createNewServerInstance(dataDir1, null, hostPort, 100);
+        ClientBase.shutdownServerInstance(factory, hostPort);
+
+        // standalone starts with 0 epoch while quorum starts with 1
+        File origfile = new File(new File(dataDir1, "version-2"), "snapshot.0");
+        File newfile = new File(new File(dataDir1, "version-2"), "snapshot.100000000");
+        origfile.renameTo(newfile);
+
+        factory = ClientBase.createNewServerInstance(dataDir1, null, hostPort, 100);
+
+        ZooKeeper zk = new ZooKeeper(hostPort, 15000, nullWatcher);
         for(int i = 0; i < 50; i++) {
             zk.create("/" + i, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
         }
@@ -129,12 +192,14 @@ public class TruncateTest extends TestCase {
         }
         zk1.getData("/9", false, new Stat());
         try {
-        	// 10 wont work because the session expiration
-        	// will match the zxid for 10 and so we wont
-        	// actually truncate the zxid for 10 creation
-        	// but for 11 we will for sure
-        	zk1.getData("/11", false, new Stat());
-            fail("Should have gotten an error");
+            // /10 wont work because the session expiration
+            // will match the zxid for /10 and so we wont
+            // actually truncate the zxid for /10 creation
+            // due to an artifact of switching the xid of the standalone
+            // /11 is the last entry in the log for the xid
+            // as a result /12 is the first of the truncated znodes to check for
+            zk1.getData("/12", false, new Stat());
+            Assert.fail("Should have gotten an error");
         } catch(KeeperException.NoNodeException e) {
             // this is what we want
         }
diff --git a/zookeeper-3.3.5.jar.asc b/zookeeper-3.3.5.jar.asc
deleted file mode 100644
index e1cee49..0000000
--- a/zookeeper-3.3.5.jar.asc
+++ /dev/null
@@ -1,7 +0,0 @@
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.11 (GNU/Linux)
-
-iEYEABECAAYFAk9iTPUACgkQ4ip0amjjJ8H6OwCeIQpBZ9SMHz9O6DWkij2OYLyL
-fVgAnjpGkDGaIwLGuwQz9E/7LFuECdFr
-=rjsG
------END PGP SIGNATURE-----
diff --git a/zookeeper-3.3.5.jar.md5 b/zookeeper-3.3.5.jar.md5
deleted file mode 100644
index 456d1f4..0000000
--- a/zookeeper-3.3.5.jar.md5
+++ /dev/null
@@ -1 +0,0 @@
-250b389920e635d921c830400e711fff
diff --git a/zookeeper-3.3.5.jar.sha1 b/zookeeper-3.3.5.jar.sha1
deleted file mode 100644
index fca69c8..0000000
--- a/zookeeper-3.3.5.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-f179a5c0bda60b7e9cd45e411eb65f7fecfb9070
diff --git a/zookeeper-3.3.6.jar.asc b/zookeeper-3.3.6.jar.asc
new file mode 100644
index 0000000..5cb47d0
--- /dev/null
+++ b/zookeeper-3.3.6.jar.asc
@@ -0,0 +1,7 @@
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.11 (GNU/Linux)
+
+iEYEABECAAYFAlAU11kACgkQ4ip0amjjJ8ESjQCfS1xFruw8RNwSIt0JVoNwGmcW
+6LkAn3+RTCY7Hin3WMckmiklCM32yRUV
+=ulpt
+-----END PGP SIGNATURE-----
diff --git a/zookeeper-3.3.6.jar.md5 b/zookeeper-3.3.6.jar.md5
new file mode 100644
index 0000000..61aeee6
--- /dev/null
+++ b/zookeeper-3.3.6.jar.md5
@@ -0,0 +1 @@
+1e02525b961fd50dbaf7c24da2d9eee4
diff --git a/zookeeper-3.3.6.jar.sha1 b/zookeeper-3.3.6.jar.sha1
new file mode 100644
index 0000000..881048b
--- /dev/null
+++ b/zookeeper-3.3.6.jar.sha1
@@ -0,0 +1 @@
+a3760ffbc36a4b5663bfb2fb42cdda12f6a722f3

-- 
Apache ZooKeeper



More information about the pkg-java-commits mailing list