You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by ma...@apache.org on 2009/06/16 00:54:48 UTC

svn commit: r785018 - in /hadoop/zookeeper/trunk: ./ src/contrib/zkpython/ src/contrib/zkpython/src/c/ src/contrib/zkpython/src/python/ src/contrib/zkpython/src/test/

Author: mahadev
Date: Mon Jun 15 22:54:48 2009
New Revision: 785018

URL: http://svn.apache.org/viewvc?rev=785018&view=rev
Log:
ZOOKEEPER-432. Various improvements to zkpython bindings. (henry via mahadev)

Added:
    hadoop/zookeeper/trunk/src/contrib/zkpython/src/c/pyzk_docstrings.h
    hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/clientid_test.py   (with props)
    hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/delete_test.py   (with props)
Modified:
    hadoop/zookeeper/trunk/CHANGES.txt
    hadoop/zookeeper/trunk/src/contrib/zkpython/README
    hadoop/zookeeper/trunk/src/contrib/zkpython/src/c/zookeeper.c
    hadoop/zookeeper/trunk/src/contrib/zkpython/src/python/setup.py   (contents, props changed)
    hadoop/zookeeper/trunk/src/contrib/zkpython/src/python/zk.py   (props changed)
    hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/connection_test.py
    hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/create_test.py
    hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/exists_test.py
    hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/get_set_test.py
    hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/zktestbase.py

Modified: hadoop/zookeeper/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/CHANGES.txt?rev=785018&r1=785017&r2=785018&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/CHANGES.txt (original)
+++ hadoop/zookeeper/trunk/CHANGES.txt Mon Jun 15 22:54:48 2009
@@ -209,6 +209,9 @@
   ZOOKEEPER-443. trace logging in watch notification not wrapped with
 istraceneabled - inefficient (pat via mahadev)
 
+  ZOOKEEPER-432. Various improvements to zkpython bindings. (henry via
+mahadev)
+
 NEW FEATURES:
 
   ZOOKEEPER-371. jdiff documentation included in build/release (giri via phunt)

Modified: hadoop/zookeeper/trunk/src/contrib/zkpython/README
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/zkpython/README?rev=785018&r1=785017&r2=785018&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/zkpython/README (original)
+++ hadoop/zookeeper/trunk/src/contrib/zkpython/README Mon Jun 15 22:54:48 2009
@@ -1,4 +1,6 @@
-Very early version of ZooKeeper bindings for Python. All functions are imported as methods into the zookeeper module.
+Early version of ZooKeeper bindings for Python. All functions are imported as methods into the zookeeper module.
+
+Please do not rely on APIs staying constant in the short term. The handling of exceptions and failure modes is one area that is subject to change. 
 
 DEPENDENCIES:
 -------------
@@ -23,7 +25,7 @@
 NAMING CONVENTIONS:
 --------------------
 
-All methods that in the C library are zoo_fn_name have been implemented as zookeeper.fn_name. The exception is any function that has a watch function argument is named without the 'w' prefix (for example, zoo_wexists becomes zookeeper.exists). The variants of these functions without the watch argument (i.e. zoo_exists) have not been implemented on the understanding that they are superceded by the zoo_w* API. 
+All methods that in the C library are zoo_fn_name have been implemented as zookeeper.fn_name. The exception is any function that has a watch function argument is named without the 'w' prefix (for example, zoo_wexists becomes zookeeper.exists). The variants of these functions without the watch argument (i.e. zoo_exists) have not been implemented on the understanding that they are superseded by the zoo_w* API. 
 
 Enums and integer constants that begin ZOO_int_name are named as zookeeper.int_name.
 
@@ -48,6 +50,26 @@
 
 Callbacks signify failure by having the integer response code passed in. 
 
+WHAT'S NEW IN 0.4:
+------------------
+
+More test coverage. 
+
+Better reference counting, fixing at least two serious bugs.
+
+Out-of-range zhandles are now checked, fixing a potential security hole.
+
+Docstrings! Editing and cleanup required, but most of the text is there.
+
+zookeeper.set_watcher is now implemented correctly.
+
+zookeeper.client_id is now implemented correctly. zookeeper.init now respects the client_id parameter.
+
+get_context and set_context have been removed from the API. The context mechanism is used by PyZK to store the callables that are dispatched by C-side watchers. Messing with this from Python-side causes bugs very quickly. You should wrap all desired context up in a callable and then use zookeeper.set_watcher to attach it to the global watcher. 
+
+Many methods now have optional parameters (usually if you can specify a watch, it's optional). The only time where genuinely optional parameters are still mandatory is when a required parameters comes after it. Currently we still respect the ZK C client parameter ordering. For example, you can simply connect with zookeeper.init("host:port") and ignore the other three parameters.
+
+
 WHAT'S NEW IN 0.3:
 ------------------
 
@@ -68,15 +90,13 @@
 
 A reference count error was tracked down and killed. More probably lurk in there!
 
-WHAT'S NOT DONE / KNOWN ISSUES:
--------------------------------
+WHAT'S NOT DONE / KNOWN ISSUES / FUTURE WORK:
+---------------------------------------------
 
-1. There may well be memory leaks / reference count issues; I need to do a complete audit.
+1. There may well be more memory leaks / reference count issues; however I am more confident that common paths are relatively safe. 
 2. There probably needs to be a more Pythonic Python-side wrapper for these functions (e.g. a zookeeper object, the ability to iterate through a tree of zk nodes)
-3. set_watcher is not implemented. 
-4. If you pass an invalid handle, the library will do anything from silent failure to segfaulting. This will be fixed and an exception will be raised in future versions.
-5. More tests aren't written yet, but should be. 
-6. Similarly for documentation, other than this README (in particular, docstrings)
+3. Docstrings need a cleanup.
+4. The way exceptions and error codes are returned needs looking at. Currently synchronous calls throw exceptions on everything but ZOK return, but asynchronous completions are simply passed the error code. Async. functions should never throw an exception on the C-side as they are practically impossible to catch. For the sync. functions, exceptions seem more reasonable, but some cases are certainly not exceptional. 
 
 Bug reports / comments very welcome!
 

Added: hadoop/zookeeper/trunk/src/contrib/zkpython/src/c/pyzk_docstrings.h
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/zkpython/src/c/pyzk_docstrings.h?rev=785018&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/zkpython/src/c/pyzk_docstrings.h (added)
+++ hadoop/zookeeper/trunk/src/contrib/zkpython/src/c/pyzk_docstrings.h Mon Jun 15 22:54:48 2009
@@ -0,0 +1,592 @@
+/**
+ * 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.
+ */
+
+#ifndef PYZK_DOCSTRINGS_H
+#define PYZK_DOCSTRINGS_H
+
+const char pyzk_acreate_doc[] = 
+"Create a node asynchronously.\n"
+"\n"
+"This method will create a node in ZooKeeper. A node can only be created if\n"
+"it does not already exists. The Create Flags affect the creation of nodes.\n"
+"If EPHEMERAL flag is set, the node will automatically get removed if the\n"
+"client session goes away. If the SEQUENCE flag is set, a unique\n"
+"monotonically increasing sequence number is appended to the path name.\n"
+"\n"
+" zh: the zookeeper handle obtained by a call to zookeeper.init\n"
+" path: The name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+" value: The data to be stored in the node.\n"
+" acl: The initial ACL of the node. If None, the ACL of the parent will be\n"
+"   used.\n"
+"\n"
+" (Subsequent parameters are optional)\n"
+" flags: this parameter can be set to 0 for normal create or an OR\n"
+"   of the Create Flags\n"
+" completion: the routine to invoke when the request completes. The completion\n"
+"will be triggered with one of the following codes passed in as the rc argument:\n"
+"OK operation completed succesfully\n"
+"NONODE the parent node does not exist.\n"
+"NODEEXISTS the node already exists\n"
+"NOAUTH the client does not have permission.\n"
+"NOCHILDRENFOREPHEMERALS cannot create children of ephemeral nodes.\n"
+"\n"
+"RETURNS:\n"
+"Returns OK on success or throws of the following errcodes on failure:\n"
+"EXCEPTIONS:\n"
+"BADARGUMENTS - invalid input parameters\n"
+"INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+"MARSHALLINGERROR - failed to marshall a request; possibly, out of memory";
+
+static const char pyzk_client_id_doc[] = 
+"Return the client session id, only valid if the connections\n"
+" is currently connected (ie. last watcher state is CONNECTED_STATE)";
+
+static const char pyzk_state_doc[] = 
+"Get the state of the zookeeper connection.\n"
+  "The return value will be one of the State Consts.";
+  
+static const char pyzk_adelete_doc[] = 
+" Delete a node in zookeeper.\n"
+"\n"
+" zh: the zookeeper handle obtained by a call to zookeeper.init\n"
+" path: the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+"\n"
+"(Subsequent parameters are optional)\n"
+" version: the expected version of the node. The function will fail if the\n"
+"   actual version of the node does not match the expected version.\n"
+" If -1 is used the version check will not take place. \n"
+" completion: the routine to invoke when the request completes. The completion\n"
+"will be triggered with one of the following codes passed in as the rc argument:\n"
+"OK operation completed succesfully\n"
+"NONODE the node does not exist.\n"
+"NOAUTH the client does not have permission.\n"
+"BADVERSION expected version does not match actual version.\n"
+"NOTEMPTY children are present; node cannot be deleted.\n"
+"Returns OK on success or one of the following errcodes on failure:\n"
+"BADARGUMENTS - invalid input parameters\n"
+"INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+  "MARSHALLINGERROR - failed to marshall a request; possibly, out of memory";
+
+static const char pyzk_aexists_doc[] = 
+" checks the existence of a node in zookeeper.\n"
+"\n"
+" zh the zookeeper handle obtained by a call to zookeeper.init\n"
+" path the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+"\n"
+"(Subsequent parameters are optional)\n"
+" watch: if not None, a watch will be set at the server to notify the \n"
+"client if the node changes. The watch will be set even if the node does not \n"
+"exist. This allows clients to watch for nodes to appear.\n"
+"\n"
+" completion: the routine to invoke when the request completes. The completion\n"
+"will be triggered with one of the following codes passed in as the rc argument:\n"
+" OK operation completed succesfully\n"
+" NONODE the node does not exist.\n"
+" NOAUTH the client does not have permission.\n"
+" data the data that will be passed to the completion routine when the \n"
+"function completes.\n"
+" OK on success or one of the following errcodes on failure:\n"
+" BADARGUMENTS - invalid input parameters\n"
+" INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+" MARSHALLINGERROR - failed to marshall a request; possibly, out of memory";
+
+static const char pyzk_aget_doc[] = 
+"Gets the data associated with a node.\n"
+"\n"
+" zh the zookeeper handle obtained by a call to zookeeper.init\n"
+" path the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+"\n"
+"(Subsequent parameters are optional)\n"
+" watcher if not None, a watch will be set at the server to notify \n"
+"the client if the node changes.\n"
+" completion: the routine to invoke when the request completes. The completion\n"
+"will be triggered with one of the following codes passed in as the rc argument:\n"
+" OK operation completed succesfully\n"
+" NONODE the node does not exist.\n"
+" NOAUTH the client does not have permission.\n"
+" data the data that will be passed to the completion routine when \n"
+"the function completes.\n"
+"Returns OK on success or one of the following errcodes on failure:\n"
+" BADARGUMENTS - invalid input parameters\n"
+" INVALIDSTATE - zhandle state is either in SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+  " MARSHALLINGERROR - failed to marshall a request; possibly, out of memory";
+
+static const char pyzk_aset_doc[] = 
+" Sets the data associated with a node.\n"
+"\n"
+" zh the zookeeper handle obtained by a call to zookeeper.init\n"
+" path the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+" buffer the buffer holding data to be written to the node.\n"
+" buflen the number of bytes from buffer to write.\n"
+"\n"
+"(Subsequent parameters are optional)\n"
+" version the expected version of the node. The function will fail if \n"
+"the actual version of the node does not match the expected version. If -1 is \n"
+"used the version check will not take place.\n"
+"completion: If None, \n"
+"the function will execute synchronously. Otherwise, the function will return \n"
+"immediately and invoke the completion routine when the request completes.\n"
+" completion the routine to invoke when the request completes. The completion\n"
+"will be triggered with one of the following codes passed in as the rc argument:\n"
+"OK operation completed succesfully\n"
+"NONODE the node does not exist.\n"
+"NOAUTH the client does not have permission.\n"
+"BADVERSION expected version does not match actual version.\n"
+" data the data that will be passed to the completion routine when \n"
+"the function completes.\n"
+"Returns OK on success or one of the following errcodes on failure:\n"
+"BADARGUMENTS - invalid input parameters\n"
+"INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+"MARSHALLINGERROR - failed to marshall a request; possibly, out of memory";
+
+static const char pyzk_aget_children_doc[] = 
+" Lists the children of a node.\n"
+"\n"
+"This function is similar to zoo_aget_children except it allows one specify \n"
+"a watcher object rather than a boolean watch flag.\n"
+" \n"
+" zh the zookeeper handle obtained by a call to zookeeper.init\n"
+" path the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+"\n"
+"(Subsequent parameters are optional)\n"
+" watcher if non-null, a watch will be set at the server to notify \n"
+"the client if the node changes.\n"
+"\n"
+" completion the routine to invoke when the request completes. The completion\n"
+"will be triggered with one of the following codes passed in as the rc argument:\n"
+"OK operation completed succesfully\n"
+"NONODE the node does not exist.\n"
+"NOAUTH the client does not have permission.\n"
+"\n"
+"Returns OK on success or one of the following errcodes on failure:\n"
+"BADARGUMENTS - invalid input parameters\n"
+"INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+"MARSHALLINGERROR - failed to marshall a request; possibly, out of memory";
+
+static const char pyzk_async_doc[] = 
+" Flush leader channel.\n"
+"\n"
+" zh the zookeeper handle obtained by a call to zookeeper.init\n"
+" path the name of the node. Expressed as a file name with slashes\n"
+"separating ancestors of the node.\n"
+" completion the routine to invoke when the request completes. The completion\n"
+"will be triggered with one of the following codes passed in as the rc argument:\n"
+"OK operation completed succesfully\n"
+"NONODE the node does not exist.\n"
+"NOAUTH the client does not have permission.\n"
+"\n"
+"Returns OK on success or one of the following errcodes on failure:\n"
+"BADARGUMENTS - invalid input parameters\n"
+"INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+  "MARSHALLINGERROR - failed to marshall a request; possibly, out of memory";
+
+const static char pyzk_aget_acl_doc[] = 
+" Gets the acl associated with a node.\n"
+"\n"
+" zh: the zookeeper handle obtained by a call to zookeeper.init\n"
+" path: the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+"\n"
+"(Subsequent parameters are optional)\n"
+" completion: the routine to invoke when the request completes. The completion\n"
+"will be triggered with one of the following codes passed in as the rc argument:\n"
+"OK operation completed succesfully\n"
+"NONODE the node does not exist.\n"
+"NOAUTH the client does not have permission.\n"
+"\n"
+"Returns:\n"
+" OK on success or one of the following errcodes on failure:\n"
+" BADARGUMENTS - invalid input parameters\n"
+" INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+" MARSHALLINGERROR - failed to marshall a request; possibly, out of memory";
+
+const char pyzk_aset_acl_doc[] = 
+" Sets the acl associated with a node.\n"
+"\n"
+"PARAMETERS:\n"
+" zh: the zookeeper handle obtained by a call to zookeeper.init\n"
+" path: the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+" buffer: the buffer holding the acls to be written to the node.\n"
+" completion: the routine to invoke when the request completes. The completion\n"
+"will be triggered with one of the following codes passed in as the rc argument:\n"
+"OK operation completed succesfully\n"
+"NONODE the node does not exist.\n"
+"NOAUTH the client does not have permission.\n"
+"INVALIDACL invalid ACL specified\n"
+"BADVERSION expected version does not match actual version.\n"
+""
+" Returns OK on success or one of the following errcodes on failure:\n"
+" BADARGUMENTS - invalid input parameters\n"
+" INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+" MARSHALLINGERROR - failed to marshall a request; possibly, out of memory";
+
+const char pyzk_zerror_doc[] = 
+"Returns an error string corresponding to an integer error code.\n"
+"\n"
+"PARAMETERS:\n"
+" err: Error code\n"
+"RETURNS:\n"
+  " string corresponding to the return code\n";
+
+const char pyzk_add_auth_doc[] = 
+" specify application credentials.\n"
+"\n"
+"The application calls this function to specify its credentials for purposes\n"
+"of authentication. The server will use the security provider specified by \n"
+"the scheme parameter to authenticate the client connection. If the \n"
+"authentication request has failed:\n"
+"- the server connection is dropped\n"
+"- the watcher is called with the AUTH_FAILED_STATE value as the state \n"
+"parameter.\n"
+"\n"
+"PARAMETERS:\n"
+" zh: the zookeeper handle obtained by a call to zookeeper.init\n"
+" scheme the id of authentication scheme. Natively supported:\n"
+"'digest' password-based authentication\n"
+" cert: application credentials. The actual value depends on the scheme.\n"
+" completion: the routine to invoke when the request completes. One of \n"
+"the following result codes may be passed into the completion callback:\n"
+"OK operation completed successfully\n"
+"AUTHFAILED authentication failed \n"
+"\n"
+"RETURNS:\n"
+"OK on success or one of the following errcodes on failure:\n"
+"BADARGUMENTS - invalid input parameters\n"
+"INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+"MARSHALLINGERROR - failed to marshall a request; possibly, out of memory\n"
+  "SYSTEMERROR - a system error occured\n";
+
+const char pyzk_is_unrecoverable_doc[] = 
+" checks if the current zookeeper connection state can't be recovered.\n"
+"\n"
+" The application must close the zhandle and try to reconnect.\n"
+"\n"
+"PARAMETERS:\n"
+" zh the zookeeper handle (see zookeeper.init)\n"
+"\n"
+"RETURNS:\n"
+  "INVALIDSTATE if connection is unrecoverable\n";
+
+const char pyzk_set_debug_level_doc[] = 
+"\brief sets the debugging level for the library \n"
+"\n"
+"PARAMETERS:\n"
+" logLevel: One of LOG_LEVEL_ERROR, LOG_LEVEL_WARN, LOG_LEVEL_INFO or LOG_LEVEL_DEBUG\n"
+"\n"
+"RETURNS:\n"
+  " None\n";
+
+static const char pyzk_set_log_stream_doc[] = 
+" sets the stream to be used by the library for logging \n"
+"\n"
+"The zookeeper library uses stderr as its default log stream. Applications\n"
+"must make sure the stream is writable. Passing in NULL resets the stream \n"
+  "to its default value (stderr).\n"
+"\n"
+"PARAMETERS:\n"
+" logStream: a writable file object\n"
+"RETURNS:\n"
+" None\n";
+
+static const char pyzk_deterministic_conn_order_doc[] = 
+" enable/disable quorum endpoint order randomization\n"
+"\n"
+"If passed a non-zero value, will make the client connect to quorum peers\n"
+"in the order as specified in the zookeeper.init() call.\n"
+"A zero value causes zookeeper.init() to permute the peer endpoints\n"
+"which is good for more even client connection distribution among the \n"
+"quorum peers.\n"
+"PARAMETERS:\n"
+" yesOrNo\n"
+"\n"
+"RETURNS:\n"
+  " None\n";
+
+static const char pyzk_create_doc[] = 
+" create a node synchronously.\n"
+"\n"
+"This method will create a node in ZooKeeper. A node can only be created if\n"
+"it does not already exists. The Create Flags affect the creation of nodes.\n"
+"If the EPHEMERAL flag is set, the node will automatically get removed if the\n"
+"client session goes away. If the SEQUENCE flag is set, a unique\n"
+"monotonically increasing sequence number is appended to the path name.\n"
+"\n"
+"PARAMETERS:\n"
+" zh: the zookeeper handle obtained by a call to zookeeper.init\n"
+" path: The name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+" value: The data to be stored in the node.\n"
+" acl: The initial ACL of the node. If null, the ACL of the parent will be\n"
+"   used.\n"
+" flags: this parameter can be set to 0 for normal create or an OR\n"
+"   of the Create Flags\n"
+" realpath: the real path that is created (this might be different than the\n"
+"   path to create because of the SEQUENCE flag.\n"
+" the maximum length of real path you would want.\n"
+"\n"
+"RETURNS:\n"
+" The actual znode path that was created (may be different from path due to use of SEQUENTIAL\n" 
+" flag).\n"
+"EXCEPTIONS:\n"
+" NONODE the parent node does not exist.\n"
+" NODEEXISTS the node already exists\n"
+" NOAUTH the client does not have permission.\n"
+" NOCHILDRENFOREPHEMERALS cannot create children of ephemeral nodes.\n"
+" BADARGUMENTS - invalid input parameters\n"
+" INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+  " MARSHALLINGERROR - failed to marshall a request; possibly, out of memory\n";
+
+static const char pyzk_delete_doc[] = 
+" delete a node in zookeeper synchronously.\n"
+"\n"
+"PARAMETERS:\n"
+" zh the zookeeper handle obtained by a call to zookeeper.init\n"
+" path the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+"\n"
+"(Subsequent parameters are optional)\n"
+" version: the expected version of the node. The function will fail if the\n"
+"   actual version of the node does not match the expected version.\n"
+" If -1 (the default) is used the version check will not take place. \n"
+"\n"
+"RETURNS:\n"
+"One of the following values is returned.\n"
+"OK operation completed succesfully\n"
+"NONODE the node does not exist.\n"
+"NOAUTH the client does not have permission.\n"
+"BADVERSION expected version does not match actual version.\n"
+"NOTEMPTY children are present; node cannot be deleted.\n"
+"BADARGUMENTS - invalid input parameters\n"
+"INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+  "MARSHALLINGERROR - failed to marshall a request; possibly, out of memory\n";
+
+static const char pyzk_exists_doc[] = 
+" checks the existence of a node in zookeeper synchronously.\n"
+"\n"
+"PARAMETERS:\n"
+" zh: the zookeeper handle obtained by a call to zookeeper.init\n"
+" path: the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+"\n"
+"(Subsequent parameters are optional)\n"
+" watch: if nonzero, a watch will be set at the server to notify the \n"
+"client if the node changes. The watch will be set even if the node does not \n"
+"exist. This allows clients to watch for nodes to appear.\n"
+"\n"
+"RETURNS:\n"
+" the return stat value of the node.\n"
+"EXCEPTIONS:\n"
+"OK operation completed succesfully\n"
+"NONODE the node does not exist.\n"
+"NOAUTH the client does not have permission.\n"
+"BADARGUMENTS - invalid input parameters\n"
+"INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+  "MARSHALLINGERROR - failed to marshall a request; possibly, out of memory\n";
+
+
+static const char pyzk_get_children_doc[] =
+" lists the children of a node synchronously.\n"
+"\n"
+"PARAMETERS:\n"
+" zh: the zookeeper handle obtained by a call to zookeeper.init\n"
+" path: the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+"\n"
+"(subsequent parameters are optional)\n"
+" watcher: if non-null, a watch will be set at the server to notify \n"
+"the client if the node changes.\n"
+"\n"
+"RETURNS:\n"
+" A list of znode names\n"
+"EXCEPTIONS:\n"
+"NONODE the node does not exist.\n"
+"NOAUTH the client does not have permission.\n"
+"BADARGUMENTS - invalid input parameters\n"
+"INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+  "MARSHALLINGERROR - failed to marshall a request; possibly, out of memory\n";
+
+static const char pyzk_set_doc[] = 
+"\n"
+" sets the data associated with a node. See set2 function if\n"
+"you require access to the stat information associated with the znode.\n"
+"\n"
+"PARAMETERS:\n"
+" zh: the zookeeper handle obtained by a call to zookeeper.init\n"
+" path: the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+" buffer: the buffer holding data to be written to the node.\n"
+"\n"
+"(subsequent parameters are optional)\n"
+" version: the expected version of the node. The function will fail if \n"
+"the actual version of the node does not match the expected version. If -1 is \n"
+"used the version check will not take place. \n"
+"\n"
+"RETURNS:\n"
+" the return code for the function call.\n"
+"OK operation completed succesfully\n"
+"EXCEPTIONS:\n"
+"NONODE the node does not exist.\n"
+"NOAUTH the client does not have permission.\n"
+"BADVERSION expected version does not match actual version.\n"
+"BADARGUMENTS - invalid input parameters\n"
+"INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+  "MARSHALLINGERROR - failed to marshall a request; possibly, out of memory\n";
+
+static const char pyzk_get_acl_doc[] = 
+" gets the acl associated with a node synchronously.\n"
+"\n"
+"PARAMETERS:\n"
+" zh: the zookeeper handle obtained by a call to zookeeper.init\n"
+" path: the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+" acl: the return value of acls on the path.\n"
+"RETURNS:"
+" returns the stat of the path specified.\n"
+"EXCEPTIONS:"
+"NONODE the node does not exist.\n"
+"NOAUTH the client does not have permission.\n"
+"BADARGUMENTS - invalid input parameters\n"
+"INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+  "MARSHALLINGERROR - failed to marshall a request; possibly, out of memory\n";
+
+
+static const char pyzk_set_acl_doc[] = 
+" sets the acl associated with a node synchronously.\n"
+"\n"
+"PARAMETERS:\n"
+" zh: the zookeeper handle obtained by a call to zookeeper.init\n"
+" path: the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+" version: the expected version of the path.\n"
+" acl: the acl to be set on the path. \n"
+"\n"
+"RETURNS:\n"
+"OK operation completed succesfully\n"
+"EXCEPTIONS:\n"
+"NONODE the node does not exist.\n"
+"NOAUTH the client does not have permission.\n"
+"INVALIDACL invalid ACL specified\n"
+"BADVERSION expected version does not match actual version.\n"
+"BADARGUMENTS - invalid input parameters\n"
+"INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+  "MARSHALLINGERROR - failed to marshall a request; possibly, out of memory\n";
+
+static const char pyzk_close_doc[] = 
+" close the zookeeper handle and free up any resources.\n"
+"\n"
+"After this call, the client session will no longer be valid. The function\n"
+"will flush any outstanding send requests before return. As a result it may \n"
+"block.\n"
+"\n"
+"This method should only be called only once on a zookeeper handle. Calling\n"
+"twice will cause undefined (and probably undesirable behavior).\n"
+"\n"
+"PARAMETERS:\n"
+" zh: the zookeeper handle obtained by a call to zookeeper.init\n"
+"RETURNS:\n"
+"Regardless of the error code returned, the zhandle \n"
+"will be destroyed and all resources freed. \n"
+"OK - success\n"
+"EXCEPTIONS:\n"
+"BADARGUMENTS - invalid input parameters\n"
+"MARSHALLINGERROR - failed to marshall a request; possibly, out of memory\n"
+"OPERATIONTIMEOUT - failed to flush the buffers within the specified timeout.\n"
+"CONNECTIONLOSS - a network error occured while attempting to send request to server\n"
+  "SYSTEMERROR -- a system (OS) error occured; it's worth checking errno to get details\n";
+
+static const char pyzk_set2_doc[] = 
+"\n"
+" sets the data associated with a node, and returns the associated stat structure.\n" 
+"\n"
+"PARAMETERS:\n"
+" zh: the zookeeper handle obtained by a call to zookeeper.init\n"
+" path: the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+" buffer: the buffer holding data to be written to the node.\n"
+"\n"
+"(subsequent parameters are optional)\n"
+" version: the expected version of the node. The function will fail if \n"
+"the actual version of the node does not match the expected version. If -1 is \n"
+"used the version check will not take place. \n"
+"\n"
+"RETURNS:\n"
+" the stat structure for the target znode\n"
+"OK operation completed succesfully\n"
+"EXCEPTIONS:\n"
+"NONODE the node does not exist.\n"
+"NOAUTH the client does not have permission.\n"
+"BADVERSION expected version does not match actual version.\n"
+"BADARGUMENTS - invalid input parameters\n"
+"INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+  "MARSHALLINGERROR - failed to marshall a request; possibly, out of memory\n";
+
+static const char pyzk_init_doc[] = 
+"This method creates a new handle and a zookeeper session that corresponds\n"
+"to that handle. Session establishment is asynchronous, meaning that the\n"
+"session should not be considered established until (and unless) an\n"
+"event of state CONNECTED_STATE is received.\n"
+"PARAMETERS:\n"
+" host: comma separated host:port pairs, each corresponding to a zk\n"
+"  server. e.g. '127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002'\n"
+"\n"
+"(subsequent parameters are optional)\n"
+" fn: the global watcher callback function. When notifications are\n"
+"  triggered this function will be invoked.\n"
+" recv_timeout: \n"
+" (clientid, passwd)\n"
+" clientid the id of a previously established session that this\n"
+"  client will be reconnecting to. Clients can access the session id of an established, valid,\n"
+"  connection by calling zoo_client_id. If\n"
+"  the specified clientid has expired, or if the clientid is invalid for \n"
+"  any reason, the returned zhandle_t will be invalid -- the zhandle_t \n"
+"  state will indicate the reason for failure (typically\n"
+"  EXPIRED_SESSION_STATE).\n"
+"\n"
+"RETURNS:\n"
+" an integer handle. If it fails to create \n"
+" a new zhandle the function throws an exception.\n";
+
+static const char pyzk_get_doc[] = 
+" gets the data associated with a node synchronously.\n"
+"\n"
+"\n"
+"PARAMETERS:\n"
+" zh the zookeeper handle obtained by a call to zookeeper.init\n"
+" path the name of the node. Expressed as a file name with slashes \n"
+"separating ancestors of the node.\n"
+"\n"
+"(subsequent parameters are optional)\n"
+" watcher if not None, a watch will be set at the server to notify \n"
+"the client if the node changes.\n"
+"RETURNS:\n"
+" the data associated with the node\n"
+"OK operation completed succesfully\n"
+"NONODE the node does not exist.\n"
+"NOAUTH the client does not have permission.\n"
+"BADARGUMENTS - invalid input parameters\n"
+"INVALIDSTATE - zhandle state is either in SESSION_EXPIRED_STATE or AUTH_FAILED_STATE\n"
+  "MARSHALLINGERROR - failed to marshall a request; possibly, out of memory\n";
+
+#endif

Modified: hadoop/zookeeper/trunk/src/contrib/zkpython/src/c/zookeeper.c
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/zkpython/src/c/zookeeper.c?rev=785018&r1=785017&r2=785018&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/zkpython/src/c/zookeeper.c (original)
+++ hadoop/zookeeper/trunk/src/contrib/zkpython/src/c/zookeeper.c Mon Jun 15 22:54:48 2009
@@ -24,18 +24,30 @@
 static zhandle_t* zhandles[MAX_ZHANDLES];
 static int num_zhandles = 0;
 
+#define CHECK_ZHANDLE(z) if ( (z) < 0 || (z) >= num_zhandles ) { \
+  PyErr_SetString( PyExc_ValueError, "zhandle out of range" ); \
+  return NULL; \
+  }
+
 /////////////////////////////////////////////
 // HELPER FUNCTIONS
 typedef struct {
   int zhandle;
   PyObject *callback;
+  int permanent;
 }pywatcher_t;
 
-pywatcher_t *create_pywatcher(int zh, PyObject* cb)
+// This array exists because we need to ref. count 
+// the global watchers for each connection - but they're 
+// inaccessible without pulling in zk_adaptor.h, which I'm
+// trying to avoid. 
+static pywatcher_t *watchers[MAX_ZHANDLES];
+
+pywatcher_t *create_pywatcher(int zh, PyObject* cb, int permanent)
 {
   pywatcher_t *ret = (pywatcher_t*)calloc(sizeof(pywatcher_t),1);
   Py_INCREF(cb);
-  ret->zhandle = zh; ret->callback = cb;
+  ret->zhandle = zh; ret->callback = cb; ret->permanent = permanent;
   return ret;
 }
 
@@ -124,7 +136,7 @@
    a) acquires the global interpreter lock
    b) unpacks the PyObject to call from the passed context pointer, which
       handily includes the index of the relevant zookeeper handle to pass back to Python.
-   c) Makes the call into Python, checking for error conditions which we are responsible fro
+   c) Makes the call into Python, checking for error conditions which we are responsible for
       detecting and doing something about (we just print the error and plough right on)
    d) releases the lock after freeing up the context object, which is only used for one
       watch invocation (watches are one-shot)
@@ -138,24 +150,42 @@
   PyObject *arglist = Py_BuildValue("(i,i,i,s)", pyw->zhandle,type, state, path);
   if (PyObject_CallObject((PyObject*)callback, arglist) == NULL)
     PyErr_Print();
-  free_pywatcher(pyw);
+  if (pyw->permanent == 0)
+    free_pywatcher(pyw);
   PyGILState_Release(gstate);
 }
 
 static PyObject *pyzookeeper_init(PyObject *self, PyObject *args)
 {
-  // TODO: Unpack clientid
   const char *host;
-  PyObject *watcherfn;
-  int recv_timeout;
-  PyObject *clientid;
+  PyObject *watcherfn = Py_None;
+  int recv_timeout = 10000;
+  //  int clientid = -1;
+  clientid_t cid;
+  cid.client_id = -1;
+  const char *passwd;
+
+  if (num_zhandles >= MAX_ZHANDLES) {
+    PyErr_SetString( PyExc_ValueError, "Too many ZooKeeper handles created, max is 256" );
+    return NULL;
+  }
 
-  if (!PyArg_ParseTuple(args, "sOii", &host, &watcherfn, &recv_timeout, &clientid)) 
+  if (!PyArg_ParseTuple(args, "s|Oi(Ls)", &host, &watcherfn, &recv_timeout, &cid.client_id, &passwd)) 
     return NULL;
+  
 
+  if (cid.client_id != -1) {
+    strncpy(cid.passwd, passwd, 16*sizeof(char));
+  }
+  pywatcher_t *pyw = NULL;
+  if (watcherfn != Py_None) {
+    pyw = create_pywatcher(num_zhandles, watcherfn,1);
+  }
+  watchers[num_zhandles] = pyw;
   zhandle_t *zh = zookeeper_init( host, watcherfn != Py_None ? watcher_dispatch : NULL, 
-				  recv_timeout, NULL, 
-				  create_pywatcher(num_zhandles,watcherfn), 0 ); 
+				  recv_timeout, cid.client_id == -1 ? 0 : &cid, 
+				  pyw,
+				  0 ); 
 
   if (zh == NULL)
     {
@@ -251,25 +281,26 @@
 
 ///////////////////////////////////////////////////////
 // Asynchronous API
-
 PyObject *pyzoo_acreate(PyObject *self, PyObject *args)
 {
   int zkhid; char *path; char *value; int valuelen;
-  struct ACL_vector acl; int flags;
-  PyObject *completion_callback;
-  PyObject *pyacls;
-  if (!PyArg_ParseTuple(args, "iss#OiO", &zkhid, &path, &value, &valuelen, &pyacls, &flags, &completion_callback))
+  struct ACL_vector acl; int flags = 0;
+  PyObject *completion_callback = Py_None;
+  PyObject *pyacls = Py_None;
+  if (!PyArg_ParseTuple(args, "iss#O|iO", &zkhid, &path, &value, &valuelen, &pyacls, &flags, &completion_callback))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
 
-  parse_acls(&acl, pyacls);
+  if (pyacls != Py_None)
+    parse_acls(&acl, pyacls);
   int err = zoo_acreate( zhandles[zkhid],
 			 path,
 			 value,
 			 valuelen,
-			 &acl,
+			 pyacls == Py_None ? NULL : &acl,
 			 flags,
 			 completion_callback != Py_None ? string_completion_dispatch : NULL,
-			 completion_callback != Py_None ? create_pywatcher(zkhid, completion_callback ) : NULL );
+			 completion_callback != Py_None ? create_pywatcher(zkhid, completion_callback,0 ) : NULL );
     
   free_acls(&acl);
   if (err != ZOK)
@@ -282,40 +313,44 @@
 
 PyObject *pyzoo_adelete(PyObject *self, PyObject *args)
 {
-  int zkhid; char *path; int version;
-  PyObject *completion_callback;
-  if (!PyArg_ParseTuple(args, "isiO", &zkhid, &path, &version, &completion_callback))
+  int zkhid; char *path; int version = -1;
+  PyObject *completion_callback = Py_None;
+  if (!PyArg_ParseTuple(args, "is|iO", &zkhid, &path, &version, &completion_callback))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
 
   int err = zoo_adelete( zhandles[zkhid],
 			 path,
 			 version,
 			 completion_callback != Py_None ? void_completion_dispatch : NULL,
 			 completion_callback != Py_None ? create_pywatcher(zkhid, 
-									   completion_callback ) : NULL );
+									   completion_callback,
+									   0 ) : NULL );
     
   if (err != ZOK)
     {
       PyErr_SetString( PyExc_IOError, zerror(err));
       return NULL;
     }
-  return Py_BuildValue("i", err);;
+  return Py_BuildValue("i", err);
 }
 
 PyObject *pyzoo_aexists(PyObject *self, PyObject *args)
 {
   int zkhid; char *path; 
-  PyObject *completion_callback;
-  PyObject *exists_watch;
-  if (!PyArg_ParseTuple(args, "isOO", &zkhid, &path, 
+  PyObject *completion_callback = Py_None;
+  PyObject *exists_watch = Py_None;
+  if (!PyArg_ParseTuple(args, "is|OO", &zkhid, &path, 
 			&exists_watch, &completion_callback))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
+
   int err = zoo_awexists( zhandles[zkhid],
 			  path,
 			  exists_watch != Py_None ? watcher_dispatch : NULL,
-			  exists_watch != Py_None ? create_pywatcher(zkhid, exists_watch) : NULL,
+			  exists_watch != Py_None ? create_pywatcher(zkhid, exists_watch,0) : NULL,
 			  (completion_callback != Py_None) ? stat_completion_dispatch : NULL,
-			  (completion_callback != Py_None) ? create_pywatcher(zkhid, completion_callback) : NULL );
+			  (completion_callback != Py_None) ? create_pywatcher(zkhid, completion_callback,0) : NULL );
     
   if (err != ZOK)
     {
@@ -328,19 +363,20 @@
 PyObject *pyzoo_aget(PyObject *self, PyObject *args)
 {
   int zkhid; char *path; 
-  PyObject *completion_callback;
-  PyObject *get_watch;
-  if (!PyArg_ParseTuple(args, "isOO", &zkhid, &path, 
+  PyObject *completion_callback = Py_None;
+  PyObject *get_watch = Py_None;
+  if (!PyArg_ParseTuple(args, "is|OO", &zkhid, &path, 
 			&get_watch, &completion_callback))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
 
   int err = zoo_awget( zhandles[zkhid],
 		       path,
 		       get_watch != Py_None ? watcher_dispatch : NULL,
-		       get_watch != Py_None ? create_pywatcher(zkhid, get_watch) : NULL,
+		       get_watch != Py_None ? create_pywatcher(zkhid, get_watch,0) : NULL,
 		       completion_callback != Py_None ? data_completion_dispatch : NULL,
 		       completion_callback != Py_None ? 
-		       create_pywatcher(zkhid, completion_callback ) : NULL );
+		       create_pywatcher(zkhid, completion_callback,0 ) : NULL );
     
   if (err != ZOK)
     {
@@ -352,10 +388,11 @@
 
 PyObject *pyzoo_aset(PyObject *self, PyObject *args)
 {
-  int zkhid; char *path; char *buffer; int buflen; int version;
-  PyObject *completion_callback;
-  if (!PyArg_ParseTuple(args, "iss#iO", &zkhid, &path, &buffer, &buflen, &version, &completion_callback))
+  int zkhid; char *path; char *buffer; int buflen; int version=-1;
+  PyObject *completion_callback = Py_None;
+  if (!PyArg_ParseTuple(args, "iss#|iO", &zkhid, &path, &buffer, &buflen, &version, &completion_callback))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
 
   int err = zoo_aset( zhandles[zkhid],
 		      path,
@@ -364,7 +401,8 @@
 		      version,
 		      completion_callback != Py_None ? stat_completion_dispatch : NULL,
 		      completion_callback != Py_None ? create_pywatcher(zkhid, 
-									completion_callback ) : NULL );
+									completion_callback,
+									0 ) : NULL );
     
   if (err != ZOK)
     {
@@ -377,19 +415,20 @@
 PyObject *pyzoo_aget_children(PyObject *self, PyObject *args)
 {
   int zkhid; char *path; 
-  PyObject *completion_callback;
+  PyObject *completion_callback = Py_None;
   PyObject *get_watch;
-  if (!PyArg_ParseTuple(args, "isOO", &zkhid,  &path,
+  if (!PyArg_ParseTuple(args, "is|OO", &zkhid,  &path,
 			&get_watch, &completion_callback))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
 
   int err = zoo_awget_children( zhandles[zkhid],
 				path,
 				get_watch != Py_None ? watcher_dispatch : NULL,
-				get_watch != Py_None ? create_pywatcher(zkhid, get_watch) : NULL,
+				get_watch != Py_None ? create_pywatcher(zkhid, get_watch,0) : NULL,
 				completion_callback != Py_None ? strings_completion_dispatch : NULL,
 				completion_callback != Py_None ? 
-				create_pywatcher(zkhid, completion_callback ) : NULL );    
+				create_pywatcher(zkhid, completion_callback,0) : NULL );    
   if (err != ZOK)
     {
       PyErr_SetString( PyExc_IOError, zerror(err));
@@ -401,16 +440,17 @@
 PyObject *pyzoo_async(PyObject *self, PyObject *args)
 {
   int zkhid; char *path; 
-  PyObject *completion_callback;
-  if (!PyArg_ParseTuple(args, "isO", &zkhid, &path, 
+  PyObject *completion_callback = Py_None;
+  if (!PyArg_ParseTuple(args, "is|O", &zkhid, &path, 
 			&completion_callback))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
 
   int err = zoo_async( zhandles[zkhid],
 		       path,
 		       completion_callback != Py_None ? string_completion_dispatch : NULL,
 		       completion_callback != Py_None ? 
-		       create_pywatcher(zkhid, completion_callback ) : NULL );    
+		       create_pywatcher(zkhid, completion_callback,0) : NULL );    
   if (err != ZOK)
     {
       PyErr_SetString( PyExc_IOError, zerror(err));
@@ -422,16 +462,17 @@
 PyObject *pyzoo_aget_acl(PyObject *self, PyObject *args)
 {
   int zkhid; char *path; 
-  PyObject *completion_callback;
-  if (!PyArg_ParseTuple(args, "isiOO", &zkhid, &path, 
+  PyObject *completion_callback = Py_None;
+  if (!PyArg_ParseTuple(args, "is|O", &zkhid, &path, 
 			&completion_callback))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
 
   int err = zoo_aget_acl( zhandles[zkhid],
 			  path,
 			  completion_callback != Py_None ? acl_completion_dispatch : NULL,
 			  completion_callback != Py_None ? 
-			  create_pywatcher(zkhid, completion_callback ) : NULL );
+			  create_pywatcher(zkhid, completion_callback,0) : NULL );
     
   if (err != ZOK)
     {
@@ -444,11 +485,13 @@
 PyObject *pyzoo_aset_acl(PyObject *self, PyObject *args)
 {
   int zkhid; char *path; int version; 
-  PyObject *completion_callback, *pyacl;
+  PyObject *completion_callback = Py_None, *pyacl;
   struct ACL_vector aclv;
-  if (!PyArg_ParseTuple(args, "isiOO", &zkhid, &path, &version, 
+  if (!PyArg_ParseTuple(args, "isiO|O", &zkhid, &path, &version, 
 			&pyacl, &completion_callback))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
+
   parse_acls( &aclv, pyacl );
   int err = zoo_aset_acl( zhandles[zkhid],
 			  path,
@@ -456,7 +499,7 @@
 			  &aclv,
 			  completion_callback != Py_None ? void_completion_dispatch : NULL,
 			  completion_callback != Py_None ? 
-			  create_pywatcher(zkhid, completion_callback ) : NULL );
+			  create_pywatcher(zkhid, completion_callback,0) : NULL );
   free_acls(&aclv);
   if (err != ZOK)
     {
@@ -466,31 +509,6 @@
   return Py_BuildValue("i", err);;
 }
 
-/*PyObject *pyzoo_aget(PyObject *self, PyObject *args)
-{
-  int zkhid; char *path; 
-  PyObject *completion_callback;
-  PyObject *get_watch;
-  if (!PyArg_ParseTuple(args, "isiOO", &zkhid, &path, 
-			&get_watch, &completion_callback))
-    return NULL;
-
-  int err = zoo_awget( zhandles[zkhid],
-		       path,
-		       get_watch != Py_None ? watcher_dispatch : NULL,
-		       get_watch != Py_None ? create_pywatcher(zkhid, get_watch) : NULL,
-		       completion_callback != Py_None ? void_completion_dispatch : NULL,
-		       completion_callback != Py_None ? 
-		       create_pywatcher(zkhid, completion_callback ) : NULL );
-    
-  if (err != ZOK)
-    {
-      PyErr_SetString( PyExc_IOError, zerror(err));
-      return NULL;
-    }
-  return Py_BuildValue("i", err);;
-  }*/
-
 PyObject *pyzoo_add_auth(PyObject *self, PyObject *args)
 {
   int zkhid;
@@ -500,19 +518,20 @@
 
   if (!PyArg_ParseTuple(args, "iss#O", &zkhid, &scheme, &cert, &certLen, &completion_callback))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
   
   int err = zoo_add_auth( zhandles[zkhid],
 			  scheme,
 			  cert,
 			  certLen,
 			  completion_callback != Py_None ? void_completion_dispatch : NULL,
-			  completion_callback != Py_None ? create_pywatcher(zkhid, completion_callback) : NULL );
+			  completion_callback != Py_None ? create_pywatcher(zkhid, completion_callback,0) : NULL );
   if (err != ZOK)
     {
       PyErr_SetString( PyExc_IOError, zerror(err));
       return NULL;
     }
-  return Py_BuildValue("i", err);;
+  return Py_BuildValue("i", err);
 }
 
 ///////////////////////////////////////////////////////
@@ -528,8 +547,9 @@
   int flags = 0;
   char realbuf[256];
   const int maxbuf_len = 256;
-  if (!PyArg_ParseTuple(args, "iss#Oi",&zkhid, &path, &values, &valuelen,&acl,&flags))
+  if (!PyArg_ParseTuple(args, "iss#O|i",&zkhid, &path, &values, &valuelen,&acl,&flags))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
   struct ACL_vector aclv;
   parse_acls(&aclv,acl);
   zhandle_t *zh = zhandles[zkhid];
@@ -540,16 +560,17 @@
       return NULL;
     }
 
-  return Py_BuildValue("i", err);;
+  return Py_BuildValue("s", realbuf);
 }
 
 static PyObject *pyzoo_delete(PyObject *self, PyObject *args)
 {
   int zkhid;
   char *path;
-  int version;
-  if (!PyArg_ParseTuple(args, "isi",&zkhid,&path,&version))
+  int version = -1;
+  if (!PyArg_ParseTuple(args, "is|i",&zkhid,&path,&version))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
   zhandle_t *zh = zhandles[zkhid];
   int err = zoo_delete(zh, path, version);
   if (err != ZOK)
@@ -557,19 +578,20 @@
       PyErr_SetString( PyExc_IOError, zerror(err));
       return NULL;
     }
-  return Py_BuildValue("i", err);;
+  return Py_BuildValue("i", err);
 }
 
 static PyObject *pyzoo_exists(PyObject *self, PyObject *args)
 {
-  int zkhid; char *path; PyObject *watcherfn = NULL;
+  int zkhid; char *path; PyObject *watcherfn = Py_None;
   struct Stat stat;
-  if (!PyArg_ParseTuple(args, "isO", &zkhid, &path, &watcherfn))
+  if (!PyArg_ParseTuple(args, "is|O", &zkhid, &path, &watcherfn))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
   zhandle_t *zh = zhandles[zkhid];
   pywatcher_t *pw = NULL;
   if (watcherfn != Py_None) 
-    pw = create_pywatcher(zkhid, watcherfn);
+    pw = create_pywatcher(zkhid, watcherfn,0);
   int err = zoo_wexists(zh,  path, watcherfn != Py_None ? watcher_dispatch : NULL, pw, &stat);
   if (err != ZOK && err != ZNONODE)
     {
@@ -590,13 +612,14 @@
   // we should free the String_vector
   int zkhid;
   char *path;
-  PyObject *watcherfn = NULL;
+  PyObject *watcherfn = Py_None;
   struct String_vector strings; 
-  if (!PyArg_ParseTuple(args, "isO", &zkhid, &path, &watcherfn))
+  if (!PyArg_ParseTuple(args, "is|O", &zkhid, &path, &watcherfn))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
   pywatcher_t *pw = NULL;
   if (watcherfn != Py_None)
-    pw = create_pywatcher( zkhid, watcherfn );
+    pw = create_pywatcher( zkhid, watcherfn, 0 );
   int err = zoo_wget_children( zhandles[zkhid], path, 
 			       watcherfn != Py_None ? watcher_dispatch : NULL, 
 			       pw, &strings );
@@ -623,11 +646,11 @@
   char *path;
   char *buffer;
   int buflen;
-  int version; 
-  if (!PyArg_ParseTuple(args, "iss#i", &zkhid, &path, &buffer, &buflen, &version))
+  int version = -1; 
+  if (!PyArg_ParseTuple(args, "iss#|i", &zkhid, &path, &buffer, &buflen, &version))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
 
-  assert(zkhid < num_zhandles);
   int err = zoo_set(zhandles[zkhid], path, buffer, buflen, version);
   if (err != ZOK)
     {
@@ -644,9 +667,10 @@
   char *path;
   char *buffer;
   int buflen;
-  int version; 
-  if (!PyArg_ParseTuple(args, "iss#i", &zkhid, &path, &buffer, &buflen, &version))
+  int version = -1; 
+  if (!PyArg_ParseTuple(args, "iss#|i", &zkhid, &path, &buffer, &buflen, &version))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
   struct Stat *stat = NULL;
   int err = zoo_set2(zhandles[zkhid], path, buffer, buflen, version, stat);
   if (err != ZOK)
@@ -666,13 +690,13 @@
   memset(buffer,0,sizeof(char)*512);
   int buffer_len=512;
   struct Stat stat;
-  PyObject *watcherfn = NULL;
+  PyObject *watcherfn = Py_None;
   pywatcher_t *pw = NULL;
-  if (!PyArg_ParseTuple(args, "isO", &zkhid, &path, &watcherfn))
+  if (!PyArg_ParseTuple(args, "is|O", &zkhid, &path, &watcherfn))
     return NULL;
-
+  CHECK_ZHANDLE(zkhid);
   if (watcherfn != Py_None)
-    pw = create_pywatcher( zkhid, watcherfn );
+    pw = create_pywatcher( zkhid, watcherfn,0 );
   int err = zoo_wget(zhandles[zkhid], path, 
 		     watcherfn != Py_None ? watcher_dispatch : NULL, 
 		     pw, buffer, 
@@ -695,6 +719,7 @@
   struct Stat stat;
   if (!PyArg_ParseTuple(args, "is", &zkhid, &path))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
   int err = zoo_get_acl( zhandles[zkhid], path, &acl, &stat );
   if (err != ZOK) 
     { 
@@ -715,7 +740,7 @@
   struct ACL_vector acl;
   if (!PyArg_ParseTuple(args, "isiO", &zkhid, &path, &version, &pyacls))
     return NULL;
-
+  CHECK_ZHANDLE(zkhid);
   parse_acls(&acl, pyacls);
   int err = zoo_set_acl(zhandles[zkhid], path, version, &acl );
   free_acls(&acl);
@@ -734,6 +759,7 @@
   int zkhid;
   if (!PyArg_ParseTuple(args, "i", &zkhid))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
   int ret = zookeeper_close(zhandles[zkhid]);
   return Py_BuildValue("i", ret);
 }
@@ -743,8 +769,9 @@
   int zkhid;
   if (!PyArg_ParseTuple(args, "i", &zkhid))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
   const clientid_t *cid = zoo_client_id(zhandles[zkhid]);
-  return Py_BuildValue("(L,s)", cid->client_id, cid->passwd);
+  return Py_BuildValue("(Ls)", cid->client_id, cid->passwd);
 }
 
 PyObject *pyzoo_get_context(PyObject *self, PyObject *args)
@@ -752,6 +779,7 @@
   int zkhid;
   if (!PyArg_ParseTuple(args, "i", &zkhid))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
   PyObject *context = NULL;
   context = (PyObject*)zoo_get_context(zhandles[zkhid]);
   if (context) return context;
@@ -764,27 +792,36 @@
   PyObject *context;
   if (!PyArg_ParseTuple(args, "iO", &zkhid, &context))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
+  PyObject *py_context = (PyObject*)zoo_get_context(zhandles[zkhid]);
+  if (py_context != NULL) {
+    Py_DECREF(py_context);
+  }
+  Py_INCREF(context);
   zoo_set_context(zhandles[zkhid], (void*)context);
   return Py_None;
 }
 ///////////////////////////////////////////////////////
 // misc
-// static PyObject *generic_python_callback = NULL;
-// void generic_watcher(zhandle_t *zh, int type, int state, const char *path, void *watcherCtx)
-// {
-//   if (generic_python_callback == NULL)
-//     return;  
-// }
 
 PyObject *pyzoo_set_watcher(PyObject *self, PyObject *args)
 {
-  /*  int zkhid;
+  int zkhid;
   PyObject *watcherfn;
   if (!PyArg_ParseTuple(args, "iO", &zkhid, &watcherfn))
     return NULL;
-  watcher_fn cwatcher = zoo_set_watcher(
-  */
-  return NULL; // TODO
+  CHECK_ZHANDLE(zkhid);
+  pywatcher_t *pyw = watchers[zkhid];
+  if (pyw != NULL) {
+    free_pywatcher( pyw );
+  }
+  
+  pyw = create_pywatcher(zkhid, watcherfn,1);
+  watchers[zkhid] = pyw;
+  zoo_set_watcher(zhandles[zkhid], watcher_dispatch);
+  zoo_set_context(zhandles[zkhid], pyw);
+  
+  return Py_None; 
 }
 
 PyObject *pyzoo_state(PyObject *self, PyObject *args)
@@ -792,7 +829,7 @@
   int zkhid;
   if (!PyArg_ParseTuple(args,"i",&zkhid))
     return NULL;
-
+  CHECK_ZHANDLE(zkhid);
   int state = zoo_state(zhandles[zkhid]);
   return Py_BuildValue("i",state);
 }
@@ -813,7 +850,7 @@
   int zkhid;
   if (!PyArg_ParseTuple(args,"i",&zkhid))
     return NULL;
-
+  CHECK_ZHANDLE(zkhid);
   int recv_timeout = zoo_recv_timeout(zhandles[zkhid]);
   return Py_BuildValue("i",recv_timeout);  
 }
@@ -823,6 +860,7 @@
   int zkhid;
   if (!PyArg_ParseTuple(args,"i",&zkhid))
     return NULL;
+  CHECK_ZHANDLE(zkhid);
   int ret = is_unrecoverable(zhandles[zkhid]);
   return Py_BuildValue("i",ret); // TODO: make this a boolean
 }
@@ -865,38 +903,44 @@
 
 ///////////////////////////////////////////////////
 
+#include "pyzk_docstrings.h"
+
 static PyMethodDef ZooKeeperMethods[] = {
-  {"init", pyzookeeper_init, METH_VARARGS },
-  {"create",pyzoo_create, METH_VARARGS },
-  {"delete",pyzoo_delete, METH_VARARGS },
-  {"get_children", pyzoo_get_children, METH_VARARGS },
-  {"set", pyzoo_set, METH_VARARGS },
-  {"set2", pyzoo_set2, METH_VARARGS },
-  {"get",pyzoo_get, METH_VARARGS },
-  {"exists",pyzoo_exists, METH_VARARGS },
-  {"get_acl", pyzoo_get_acl, METH_VARARGS },
-  {"set_acl", pyzoo_set_acl, METH_VARARGS },
-  {"close", pyzoo_close, METH_VARARGS },
-  {"client_id", pyzoo_client_id, METH_VARARGS },
-  {"get_context", pyzoo_get_context, METH_VARARGS },
-  {"set_context", pyzoo_set_context, METH_VARARGS },
-  //  {"set_watcher", pyzoo_set_watcher, METH_VARARGS }, // Not yet implemented
-  {"state", pyzoo_state, METH_VARARGS },
+  {"init", pyzookeeper_init, METH_VARARGS, pyzk_init_doc },
+  {"create",pyzoo_create, METH_VARARGS, pyzk_create_doc },
+  {"delete",pyzoo_delete, METH_VARARGS, pyzk_delete_doc },
+  {"get_children", pyzoo_get_children, METH_VARARGS, pyzk_get_children_doc },
+  {"set", pyzoo_set, METH_VARARGS, pyzk_set_doc },
+  {"set2", pyzoo_set2, METH_VARARGS, pyzk_set2_doc },
+  {"get",pyzoo_get, METH_VARARGS, pyzk_get_doc },
+  {"exists",pyzoo_exists, METH_VARARGS, pyzk_exists_doc },
+  {"get_acl", pyzoo_get_acl, METH_VARARGS, pyzk_get_acl_doc },
+  {"set_acl", pyzoo_set_acl, METH_VARARGS, pyzk_set_acl_doc },
+  {"close", pyzoo_close, METH_VARARGS, pyzk_close_doc },
+  {"client_id", pyzoo_client_id, METH_VARARGS, pyzk_client_id_doc },
+  // DO NOT USE get / set_context. Context is used internally
+  // to pass the python watcher to a dispatch function. If you want 
+  // context, set it through set_watcher. 
+  //  {"get_context", pyzoo_get_context, METH_VARARGS, "" },
+  // {"set_context", pyzoo_set_context, METH_VARARGS, "" },
+  {"set_watcher", pyzoo_set_watcher, METH_VARARGS }, 
+  {"state", pyzoo_state, METH_VARARGS, pyzk_state_doc },
   {"recv_timeout",pyzoo_recv_timeout, METH_VARARGS },
-  {"is_unrecoverable",pyis_unrecoverable, METH_VARARGS },
-  {"set_debug_level",pyzoo_set_debug_level, METH_VARARGS }, 
-  {"set_log_stream",pyzoo_set_log_stream, METH_VARARGS },
-  {"deterministic_conn_order",pyzoo_deterministic_conn_order, METH_VARARGS },
-  {"acreate", pyzoo_acreate, METH_VARARGS },
-  {"adelete", pyzoo_adelete, METH_VARARGS },
-  {"aexists", pyzoo_aexists, METH_VARARGS },
-  {"aget", pyzoo_aget, METH_VARARGS },
-  {"aset", pyzoo_aset, METH_VARARGS },
-  {"aget_children", pyzoo_aget_children, METH_VARARGS },
-  {"async", pyzoo_async, METH_VARARGS },
-  {"aget_acl", pyzoo_aget_acl, METH_VARARGS },
-  {"aset_acl", pyzoo_aset_acl, METH_VARARGS },
-  {"zerror", pyzerror, METH_VARARGS },
+  {"is_unrecoverable",pyis_unrecoverable, METH_VARARGS, pyzk_is_unrecoverable_doc },
+  {"set_debug_level",pyzoo_set_debug_level, METH_VARARGS, pyzk_set_debug_level_doc }, 
+  {"set_log_stream",pyzoo_set_log_stream, METH_VARARGS, pyzk_set_log_stream_doc },
+  {"deterministic_conn_order",pyzoo_deterministic_conn_order, METH_VARARGS, pyzk_deterministic_conn_order_doc },
+  {"acreate", pyzoo_acreate, METH_VARARGS, pyzk_acreate_doc },
+  {"adelete", pyzoo_adelete, METH_VARARGS,pyzk_adelete_doc },
+  {"aexists", pyzoo_aexists, METH_VARARGS,pyzk_aexists_doc },
+  {"aget", pyzoo_aget, METH_VARARGS, pyzk_aget_doc },
+  {"aset", pyzoo_aset, METH_VARARGS, pyzk_aset_doc },
+  {"aget_children", pyzoo_aget_children, METH_VARARGS, pyzk_aget_children_doc },
+  {"async", pyzoo_async, METH_VARARGS, pyzk_async_doc },
+  {"aget_acl", pyzoo_aget_acl, METH_VARARGS, pyzk_aget_acl_doc },
+  {"aset_acl", pyzoo_aset_acl, METH_VARARGS, pyzk_aset_acl_doc },
+  {"zerror", pyzerror, METH_VARARGS, pyzk_zerror_doc },
+  {"add_auth", pyzoo_add_auth, METH_VARARGS, pyzk_add_auth_doc },
   {NULL, NULL}
 };
 

Modified: hadoop/zookeeper/trunk/src/contrib/zkpython/src/python/setup.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/zkpython/src/python/setup.py?rev=785018&r1=785017&r2=785018&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/zkpython/src/python/setup.py (original)
+++ hadoop/zookeeper/trunk/src/contrib/zkpython/src/python/setup.py Mon Jun 15 22:54:48 2009
@@ -26,6 +26,6 @@
                             library_dirs=["/usr/local/lib"])
 
 setup( name="ZooKeeper",
-       version = "0.3",
+       version = "0.4",
        description = "ZooKeeper Python bindings",
        ext_modules=[zookeepermodule] )

Propchange: hadoop/zookeeper/trunk/src/contrib/zkpython/src/python/setup.py
------------------------------------------------------------------------------
    svn:executable = *

Propchange: hadoop/zookeeper/trunk/src/contrib/zkpython/src/python/zk.py
------------------------------------------------------------------------------
    svn:executable = *

Added: hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/clientid_test.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/clientid_test.py?rev=785018&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/clientid_test.py (added)
+++ hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/clientid_test.py Mon Jun 15 22:54:48 2009
@@ -0,0 +1,48 @@
+#!/usr/bin/python
+#
+#  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.
+
+import unittest, threading
+
+import zookeeper, zktestbase
+
+class ClientidTest(zktestbase.TestBase):
+    """Test whether clientids work"""
+    def setUp(self):
+        pass
+            
+    def testclientid(self):
+        cv = threading.Condition()
+        self.connected = False
+        def connection_watcher(handle, type, state, path):
+            cv.acquire()
+            self.connected = True
+            cv.notify()
+            cv.release()
+
+        cv.acquire()
+        self.handle = zookeeper.init(self.host, connection_watcher,10000,(123456,"mypassword"))
+        self.assertEqual(self.handle, zookeeper.OK)
+        cv.wait(15.0)
+        cv.release()
+        self.assertEqual(self.connected, True, "Connection timed out to " + self.host)
+        (cid,passwd) = zookeeper.client_id(self.handle)
+        self.assertEqual(cid,123456)
+        self.assertEqual(passwd,"mypassword")   
+
+if __name__ == '__main__':
+    unittest.main()

Propchange: hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/clientid_test.py
------------------------------------------------------------------------------
    svn:executable = *

Modified: hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/connection_test.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/connection_test.py?rev=785018&r1=785017&r2=785018&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/connection_test.py (original)
+++ hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/connection_test.py Mon Jun 15 22:54:48 2009
@@ -26,6 +26,7 @@
         pass
     
     def testconnection(self):
+        print "testconnection"
         cv = threading.Condition()
         self.connected = False
         def connection_watcher(handle, type, state, path):
@@ -35,12 +36,13 @@
             cv.release()
 
         cv.acquire()
-        ret = zookeeper.init( self.host, connection_watcher, 10000, 0)
-        self.assertEqual(ret, zookeeper.OK)
+        ret = zookeeper.init(self.host, connection_watcher)
         cv.wait(15.0)
         cv.release()
-
         self.assertEqual(self.connected, True, "Connection timed out to " + self.host)
-
+        
+    def tearDown(self):
+        pass
+        
 if __name__ == '__main__':
     unittest.main()

Modified: hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/create_test.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/create_test.py?rev=785018&r1=785017&r2=785018&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/create_test.py (original)
+++ hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/create_test.py Mon Jun 15 22:54:48 2009
@@ -18,13 +18,14 @@
 
 import zookeeper, zktestbase, unittest, threading
 
-class SyncCreationTest(zktestbase.TestBase):
+class CreationTest(zktestbase.TestBase):
     """Test whether we can create znodes"""
     # to do: startup and teardown via scripts?
     def setUp( self ):
         zktestbase.TestBase.setUp(self)
         try:
-            zookeeper.delete(self.handle, "/zk-python-createtest",-1)
+            zookeeper.delete(self.handle, "/zk-python-createtest")
+            zookeeper.delete(self.handle, "/zk-python-acreatetest")
         except:
             pass
 
@@ -32,28 +33,21 @@
         ZOO_OPEN_ACL_UNSAFE = {"perms":0x1f, "scheme":"world", "id" :"anyone"}
         self.assertEqual(self.connected, True)
         ret = zookeeper.create(self.handle, "/zk-python-createtest", "nodecontents", [ZOO_OPEN_ACL_UNSAFE], zookeeper.EPHEMERAL)
-        self.assertEqual(ret, zookeeper.OK)
-
-class AsyncCreationTest(zktestbase.TestBase):
-    def setUp( self ):
-        zktestbase.TestBase.setUp(self)
-        try:
-            zookeeper.delete(self.handle, "/zk-python-acreatetest",-1)
-        except:
-            pass
+        self.assertEqual(ret, "/zk-python-createtest")
         
     def test_async_create(self):
         self.cv = threading.Condition()
         def callback(handle, rc, value):
             self.cv.acquire()
-            self.callback_flag = True            
+            self.callback_flag = True   
+            self.rc = rc         
             self.cv.notify()
             self.cv.release()
-            
+
         ZOO_OPEN_ACL_UNSAFE = {"perms":0x1f, "scheme":"world", "id" :"anyone"}
         self.assertEqual(self.connected, True, "Not connected!")
         self.cv.acquire()
-        
+
         ret = zookeeper.acreate(self.handle, "/zk-python-acreatetest", "nodecontents",
                                 [ZOO_OPEN_ACL_UNSAFE], zookeeper.EPHEMERAL,
                                 callback )
@@ -63,6 +57,7 @@
         self.cv.release()
 
         self.assertEqual(self.callback_flag, True, "acreate timed out")
+        self.assertEqual(self.rc, zookeeper.OK)
 
         
 if __name__ == '__main__':

Added: hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/delete_test.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/delete_test.py?rev=785018&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/delete_test.py (added)
+++ hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/delete_test.py Mon Jun 15 22:54:48 2009
@@ -0,0 +1,62 @@
+#!/usr/bin/python
+#
+#  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.
+
+import zookeeper, zktestbase, unittest, threading
+
+class DeletionTest(zktestbase.TestBase):
+    """Test whether we can delete znodes"""
+
+    def test_sync_delete(self):
+        ZOO_OPEN_ACL_UNSAFE = {"perms":0x1f, "scheme":"world", "id" :"anyone"}
+        self.assertEqual(self.connected, True)
+        ret = zookeeper.create(self.handle, "/zk-python-deletetest", "nodecontents", [ZOO_OPEN_ACL_UNSAFE], zookeeper.EPHEMERAL)
+        self.assertEqual(ret, "/zk-python-deletetest")
+        ret = zookeeper.delete(self.handle,"/zk-python-deletetest")
+        self.assertEqual(ret, zookeeper.OK)
+        children = zookeeper.get_children(self.handle, "/")
+        self.assertEqual(False, "zk-python-deletetest" in children)
+    
+    def test_async_delete(self):
+        ZOO_OPEN_ACL_UNSAFE = {"perms":0x1f, "scheme":"world", "id" :"anyone"}
+        self.assertEqual(self.connected, True)
+        ret = zookeeper.create(self.handle, "/zk-python-adeletetest", "nodecontents", [ZOO_OPEN_ACL_UNSAFE], zookeeper.EPHEMERAL)
+        self.assertEqual(ret, "/zk-python-adeletetest")
+        
+        self.cv = threading.Condition()
+        self.callback_flag = False
+        self.rc = -1
+        def callback(handle, rc):
+            self.cv.acquire()
+            self.callback_flag = True            
+            self.cv.notify()
+            self.rc = rc # don't assert this here, as if the assertion fails, the test will block
+            self.cv.release()
+
+        self.cv.acquire()
+        ret = zookeeper.adelete(self.handle,"/zk-python-adeletetest",-1,callback)
+        self.assertEqual(ret, zookeeper.OK, "adelete failed")
+        while not self.callback_flag:
+            self.cv.wait(15)
+        self.cv.release()
+
+        self.assertEqual(self.callback_flag, True, "adelete timed out")
+        self.assertEqual(self.rc, zookeeper.OK)
+
+        
+if __name__ == '__main__':
+    unittest.main()

Propchange: hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/delete_test.py
------------------------------------------------------------------------------
    svn:executable = *

Modified: hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/exists_test.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/exists_test.py?rev=785018&r1=785017&r2=785018&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/exists_test.py (original)
+++ hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/exists_test.py Mon Jun 15 22:54:48 2009
@@ -19,11 +19,12 @@
 import zookeeper, zktestbase, unittest, threading
 
 ZOO_OPEN_ACL_UNSAFE = {"perms":0x1f, "scheme":"world", "id" :"anyone"}
-class SyncExistsTest(zktestbase.TestBase):
+class ExistsTest(zktestbase.TestBase):
     def setUp( self ):
         zktestbase.TestBase.setUp(self)
         try:
             zookeeper.create(self.handle, "/zk-python-existstest","existstest", [ZOO_OPEN_ACL_UNSAFE],zookeeper.EPHEMERAL)
+            zookeeper.create(self.handle, "/zk-python-aexiststest","existstest",[ZOO_OPEN_ACL_UNSAFE],zookeeper.EPHEMERAL)
         except:
             pass
 
@@ -31,14 +32,6 @@
         self.assertEqual(self.connected, True)
         ret = zookeeper.exists(self.handle, "/zk-python-existstest", None)
         self.assertNotEqual(ret, None, "/zk-python-existstest does not exist (possibly means creation failure)")
-
-class AsyncExistsTest(zktestbase.TestBase):
-    def setUp( self ):
-        zktestbase.TestBase.setUp(self)
-        try:
-            zookeeper.create(self.handle, "/zk-python-aexiststest","existstest",[ZOO_OPEN_ACL_UNSAFE],zookeeper.EPHEMERAL)
-        except:
-            pass
         
     def test_async_exists(self):
         self.cv = threading.Condition()

Modified: hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/get_set_test.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/get_set_test.py?rev=785018&r1=785017&r2=785018&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/get_set_test.py (original)
+++ hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/get_set_test.py Mon Jun 15 22:54:48 2009
@@ -19,11 +19,13 @@
 import zookeeper, zktestbase, unittest, threading
 ZOO_OPEN_ACL_UNSAFE = {"perms":0x1f, "scheme":"world", "id" :"anyone"}
 
-class SyncGetSetTest(zktestbase.TestBase):
+class GetSetTest(zktestbase.TestBase):
     def setUp( self ):
         zktestbase.TestBase.setUp(self)
         try:
             zookeeper.create(self.handle, "/zk-python-getsettest", "on",[ZOO_OPEN_ACL_UNSAFE], zookeeper.EPHEMERAL)
+            zookeeper.create(self.handle, "/zk-python-agetsettest",
+                             "on",[ZOO_OPEN_ACL_UNSAFE], zookeeper.EPHEMERAL)
         except:
             pass
 
@@ -31,18 +33,11 @@
         self.assertEqual(self.connected, True, "Not connected!")
         (data,stat) = zookeeper.get(self.handle, "/zk-python-getsettest", None)
         self.assertEqual(data, "on", "Data is not 'on' as expected: " + data)
-        ret = zookeeper.set(self.handle, "/zk-python-getsettest", "off", stat["version"])
+        ret = zookeeper.set(self.handle, "/zk-python-getsettest",
+                            "off", stat["version"])
         (data,stat) = zookeeper.get(self.handle, "/zk-python-getsettest", None)
         self.assertEqual(data, "off", "Data is not 'off' as expected: " + data)        
 
-class AsyncGetSetTest(zktestbase.TestBase):
-    def setUp( self ):
-        zktestbase.TestBase.setUp(self)
-        try:
-            zookeeper.create(self.handle, "/zk-python-agetsettest", "on",[ZOO_OPEN_ACL_UNSAFE], zookeeper.EPHEMERAL)            
-        except:
-            pass
-        
     def test_async_getset(self):
         self.cv = threading.Condition()        
         def get_callback(handle, rc, value, stat):
@@ -81,9 +76,6 @@
         self.cv.release()
         self.assertEqual(self.callback_flag, True, "aget timed out")
         self.assertEqual(self.value[0], "off", "Data is not 'off' as expected: " + self.value[0])
-
-            
-
         
 if __name__ == '__main__':
     unittest.main()

Modified: hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/zktestbase.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/zktestbase.py?rev=785018&r1=785017&r2=785018&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/zktestbase.py (original)
+++ hadoop/zookeeper/trunk/src/contrib/zkpython/src/test/zktestbase.py Mon Jun 15 22:54:48 2009
@@ -42,12 +42,32 @@
             self.cv.release()
 
         self.cv.acquire()
-        self.handle = zookeeper.init( self.host, connection_watcher, 10000, 0)
+        self.handle = zookeeper.init(self.host, connection_watcher)
         self.cv.wait(15.0)
         self.cv.release()
 
         if not self.connected:
             raise Exception("Couldn't connect to host -", self.host)
+            
+    def newConnection(self):
+        cv = threading.Condition()
+        self.pending_connection = False
+        def connection_watcher(handle, type, state, path):
+            print "CONNECTION WATCHER"
+            cv.acquire()
+            self.pending_connection = True
+            cv.notify()
+            cv.release()
+
+        cv.acquire()
+        handle = zookeeper.init(self.host, connection_watcher)
+        cv.wait(15.0)
+        cv.release()
+
+        if not self.pending_connection:
+            raise Exception("Couldn't connect to host -", self.host)
+        return handle
+    
         
     def tearDown(self):
         if self.connected: