You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by ak...@apache.org on 2008/07/24 23:46:31 UTC
svn commit: r679557 [1/3] - in /hadoop/zookeeper/trunk/src/c: ./ include/
src/ src/hashtable/ tests/
Author: akornev
Date: Thu Jul 24 14:46:30 2008
New Revision: 679557
URL: http://svn.apache.org/viewvc?rev=679557&view=rev
Log:
[ZOOKEEPER-39] Use Watcher objects rather than boolean on read operations
Added:
hadoop/zookeeper/trunk/src/c/src/hashtable/
hadoop/zookeeper/trunk/src/c/src/hashtable/LICENSE.txt (with props)
hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable.c (with props)
hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable.h (with props)
hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_itr.c (with props)
hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_itr.h (with props)
hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_private.h (with props)
hadoop/zookeeper/trunk/src/c/src/zk_hashtable.c (with props)
hadoop/zookeeper/trunk/src/c/src/zk_hashtable.h (with props)
hadoop/zookeeper/trunk/src/c/tests/CollectionUtil.h (with props)
hadoop/zookeeper/trunk/src/c/tests/TestHashtable.cc (with props)
hadoop/zookeeper/trunk/src/c/tests/TestWatchers.cc (with props)
hadoop/zookeeper/trunk/src/c/tests/Vector.h (with props)
Modified:
hadoop/zookeeper/trunk/src/c/Makefile.am
hadoop/zookeeper/trunk/src/c/include/zookeeper.h
hadoop/zookeeper/trunk/src/c/src/cli.c
hadoop/zookeeper/trunk/src/c/src/load_gen.c
hadoop/zookeeper/trunk/src/c/src/zk_adaptor.h
hadoop/zookeeper/trunk/src/c/src/zookeeper.c
hadoop/zookeeper/trunk/src/c/tests/TestOperations.cc
hadoop/zookeeper/trunk/src/c/tests/TestZookeeperClose.cc
hadoop/zookeeper/trunk/src/c/tests/TestZookeeperInit.cc
hadoop/zookeeper/trunk/src/c/tests/ZKMocks.cc
hadoop/zookeeper/trunk/src/c/tests/ZKMocks.h
hadoop/zookeeper/trunk/src/c/tests/wrappers.opt
Modified: hadoop/zookeeper/trunk/src/c/Makefile.am
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/Makefile.am?rev=679557&r1=679556&r2=679557&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/c/Makefile.am (original)
+++ hadoop/zookeeper/trunk/src/c/Makefile.am Thu Jul 24 14:46:30 2008
@@ -10,29 +10,37 @@
pkginclude_HEADERS = include/zookeeper.h include/recordio.h generated/zookeeper.jute.h
EXTRA_DIST=LICENSE
+HASHTABLE_SRC = src/hashtable/hashtable_itr.h src/hashtable/hashtable_itr.c \
+ src/hashtable/hashtable_private.h src/hashtable/hashtable.h src/hashtable/hashtable.c
+
+noinst_LTLIBRARIES = libhashtable.la
+libhashtable_la_SOURCES = $(HASHTABLE_SRC)
+
COMMON_SRC = src/zookeeper.c include/zookeeper.h \
src/recordio.c include/recordio.h include/proto.h \
src/zk_adaptor.h generated/zookeeper.jute.c \
- src/zk_log.h src/zk_log.c
+ src/zk_log.h src/zk_log.c src/zk_hashtable.h src/zk_hashtable.c
-noinst_LTLIBRARIES = libzkst.la
+noinst_LTLIBRARIES += libzkst.la
libzkst_la_SOURCES =$(COMMON_SRC) src/st_adaptor.c
+libzkst_la_LIBADD = -lm
lib_LTLIBRARIES = libzookeeper_st.la
libzookeeper_st_la_SOURCES =
-libzookeeper_st_la_LIBADD=libzkst.la
-libzookeeper_st_la_DEPENDENCIES=libzkst.la
+libzookeeper_st_la_LIBADD=libzkst.la libhashtable.la
+libzookeeper_st_la_DEPENDENCIES=libzkst.la libhashtable.la
libzookeeper_st_la_LDFLAGS = $(LIB_LDFLAGS)
if WANT_SYNCAPI
noinst_LTLIBRARIES += libzkmt.la
libzkmt_la_SOURCES =$(COMMON_SRC) src/mt_adaptor.c
libzkmt_la_CFLAGS = -DTHREADED
+libzkmt_la_LIBADD = -lm
lib_LTLIBRARIES += libzookeeper_mt.la
libzookeeper_mt_la_SOURCES =
-libzookeeper_mt_la_LIBADD=libzkmt.la -lpthread
-libzookeeper_mt_la_DEPENDENCIES=libzkmt.la
+libzookeeper_mt_la_LIBADD=libzkmt.la libhashtable.la -lpthread
+libzookeeper_mt_la_DEPENDENCIES=libzkmt.la libhashtable.la
libzookeeper_mt_la_LDFLAGS = $(LIB_LDFLAGS)
endif
@@ -62,20 +70,21 @@
TEST_SOURCES = tests/TestDriver.cc tests/LibCMocks.cc tests/LibCSymTable.cc \
tests/MocksBase.cc tests/ZKMocks.cc tests/Util.cc tests/ThreadingUtil.cc \
+ tests/TestWatchers.cc tests/TestHashtable.cc \
tests/TestOperations.cc tests/TestZookeeperInit.cc tests/TestZookeeperClose.cc
SYMBOL_WRAPPERS=$(shell cat tests/wrappers.opt)
check_PROGRAMS = zktest-st
nodist_zktest_st_SOURCES = $(TEST_SOURCES)
-zktest_st_LDADD = libzkst.la $(CPPUNIT_LIBS)
+zktest_st_LDADD = libzkst.la libhashtable.la $(CPPUNIT_LIBS)
zktest_st_CXXFLAGS = -DUSE_STATIC_LIB $(CPPUNIT_CFLAGS)
zktest_st_LDFLAGS = -static-libtool-libs $(SYMBOL_WRAPPERS)
if WANT_SYNCAPI
check_PROGRAMS += zktest-mt
nodist_zktest_mt_SOURCES = $(TEST_SOURCES) tests/PthreadMocks.cc
- zktest_mt_LDADD = libzkmt.la -lpthread $(CPPUNIT_LIBS)
+ zktest_mt_LDADD = libzkmt.la libhashtable.la -lpthread $(CPPUNIT_LIBS)
zktest_mt_CXXFLAGS = -DUSE_STATIC_LIB -DTHREADED $(CPPUNIT_CFLAGS)
SYMBOL_WRAPPERS_MT=$(SYMBOL_WRAPPERS) $(shell cat tests/wrappers-mt.opt)
zktest_mt_LDFLAGS = -static-libtool-libs $(SYMBOL_WRAPPERS_MT)
Modified: hadoop/zookeeper/trunk/src/c/include/zookeeper.h
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/include/zookeeper.h?rev=679557&r1=679556&r2=679557&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/c/include/zookeeper.h (original)
+++ hadoop/zookeeper/trunk/src/c/include/zookeeper.h Thu Jul 24 14:46:30 2008
@@ -231,10 +231,32 @@
/**
* \brief signature of a watch function.
*
- * Programs wishing to receive events from ZooKeeper need to implement a function
- * with this signature and pass a pointer to the function to \ref zookeeper_init.
+ * There are two ways to receive watch notifications: legacy and watcher object.
+ * <p>
+ * The legacy style, an application wishing to receive events from ZooKeeper must
+ * first implement a function with this signature and pass a pointer to the function
+ * to \ref zookeeper_init. Next, the application sets a watch by calling one of
+ * the getter API that accept the watch integer flag (for example, \ref zoo_aexists,
+ * \ref zoo_get, etc).
+ * <p>
+ * The watcher object style uses an instance of a "watcher object" which in
+ * the C world is represented by a pair: a pointer to a function implementing this
+ * signature and a pointer to watcher context -- handback user-specific data.
+ * When a watch is triggered this function will be called along with
+ * the watcher context. An application wishing to use this style must use
+ * the getter API functions with the "w" prefix in their names (for example, \ref
+ * zoo_awexists, \ref zoo_wget, etc).
+ *
+ * \param zh zookeeper handle
+ * \param type event type. This is one of the *_EVENT constants.
+ * \param state connection state. If the type is SESSION_EVENT, the state value
+ * will be one of the *_STATE constants, otherwise -1.
+ * \param path znode path for which the watcher is triggered. NULL if the event
+ * type is SESSION_EVENT
+ * \param watcherCtx watcher context.
*/
-typedef void (*watcher_fn)(zhandle_t *, int type, int state, const char *path);
+typedef void (*watcher_fn)(zhandle_t *zh, int type,
+ int state, const char *path,void *watcherCtx);
/**
* \brief create a handle to used communicate with zookeeper.
@@ -243,7 +265,7 @@
* to that handle.
* \param host the host name to connect to. This may be a comma separated list
* of different hosts.
- * \param fn the watcher callback function. When notifications are triggered
+ * \param fn the global watcher callback function. When notifications are triggered
* this function will be invoked.
* \param clientid the id of a previously established session that this
* client will be reconnecting to. Pass 0 if not reconnecting to a previous
@@ -579,6 +601,39 @@
stat_completion_t completion, const void *data);
/**
+ * \brief checks the existence of a node in zookeeper.
+ *
+ * This function is similar to \ref zoo_axists except it allows one specify
+ * a watcher object - a function pointer and associated context. The function
+ * will be called once the watch has fired. The associated context data will be
+ * passed to the function as the watcher context parameter.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watcher if non-null a watch will set on the specified znode on the server.
+ * The watch will be set even if the node does not exist. This allows clients
+ * to watch for nodes to appear.
+ * \param watcherCtx user specific data, will be passed to the watcher callback.
+ * Unlike the global context set by \ref zookeeper_init, this watcher context
+ * is associated with the given instance of the watcher only.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed succesfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * \param data the data that will be passed to the completion routine when the
+ * function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_awexists(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx,
+ stat_completion_t completion, const void *data);
+
+/**
* \brief gets the data associated with a node.
*
* \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
@@ -602,6 +657,36 @@
data_completion_t completion, const void *data);
/**
+ * \brief gets the data associated with a node.
+ *
+ * This function is similar to \ref zoo_aget except it allows one specify
+ * a watcher object rather than a boolean watch flag.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watcher if non-null, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param watcherCtx user specific data, will be passed to the watcher callback.
+ * Unlike the global context set by \ref zookeeper_init, this watcher context
+ * is associated with the given instance of the watcher only.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed succesfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * \param data the data that will be passed to the completion routine when
+ * the function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either in SESSION_EXPIRED_STATE or AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_awget(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx,
+ data_completion_t completion, const void *data);
+
+/**
* \brief sets the data associated with a node.
*
* \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
@@ -654,6 +739,36 @@
strings_completion_t completion, const void *data);
/**
+ * \brief lists the children of a node.
+ *
+ * This function is similar to \ref zoo_aget_children except it allows one specify
+ * a watcher object rather than a boolean watch flag.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watcher if non-null, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param watcherCtx user specific data, will be passed to the watcher callback.
+ * Unlike the global context set by \ref zookeeper_init, this watcher context
+ * is associated with the given instance of the watcher only.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed succesfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * \param data the data that will be passed to the completion routine when
+ * the function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_awget_children(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx,
+ strings_completion_t completion, const void *data);
+
+/**
* \brief Flush leader channel.
*
* \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
@@ -672,7 +787,8 @@
* ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
*/
-ZOOAPI int zoo_async(zhandle_t *zh, const char *path, string_completion_t completion, const void *data);
+ZOOAPI int zoo_async(zhandle_t *zh, const char *path,
+ string_completion_t completion, const void *data);
/**
@@ -825,7 +941,6 @@
* ZINVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE
* ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
*/
-
ZOOAPI int zoo_create(zhandle_t *zh, const char *path, const char *value,
int valuelen, const struct ACL_vector *acl, int flags, char *realpath,
int max_realpath_len);
@@ -849,7 +964,6 @@
* ZINVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE
* ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
*/
-
ZOOAPI int zoo_delete(zhandle_t *zh, const char *path, int version);
@@ -871,10 +985,36 @@
* ZINVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE
* ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
*/
-
ZOOAPI int zoo_exists(zhandle_t *zh, const char *path, int watch, struct Stat *stat);
/**
+ * \brief checks the existence of a node in zookeeper synchronously.
+ *
+ * This function is similar to \ref zoo_exists except it allows one specify
+ * a watcher object rather than a boolean watch flag.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watcher if non-null a watch will set on the specified znode on the server.
+ * The watch will be set even if the node does not exist. This allows clients
+ * to watch for nodes to appear.
+ * \param watcherCtx user specific data, will be passed to the watcher callback.
+ * Unlike the global context set by \ref zookeeper_init, this watcher context
+ * is associated with the given instance of the watcher only.
+ * \param the return stat value of the node.
+ * \return return code of the function call.
+ * ZOK operation completed succesfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_wexists(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx, struct Stat *stat);
+
+/**
* \brief gets the data associated with a node synchronously.
*
* \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
@@ -894,10 +1034,38 @@
* ZINVALIDSTATE - zhandle state is either in SESSION_EXPIRED_STATE or AUTH_FAILED_STATE
* ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
*/
-
ZOOAPI int zoo_get(zhandle_t *zh, const char *path, int watch, char *buffer,
int* buffer_len, struct Stat *stat);
+/**
+ * \brief gets the data associated with a node synchronously.
+ *
+ * This function is similar to \ref zoo_get except it allows one specify
+ * a watcher object rather than a boolean watch flag.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watcher if non-null, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param watcherCtx user specific data, will be passed to the watcher callback.
+ * Unlike the global context set by \ref zookeeper_init, this watcher context
+ * is associated with the given instance of the watcher only.
+ * \param buffer the buffer holding the node data returned by the server
+ * \param buffer_len is the size of the buffer pointed to by the buffer parameter.
+ * It'll be set to the actual data length upon return.
+ * \param stat if not NULL, will hold the value of stat for the path on return.
+ * \return return value of the function call.
+ * ZOK operation completed succesfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either in SESSION_EXPIRED_STATE or AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_wget(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx,
+ char *buffer, int* buffer_len, struct Stat *stat);
/**
* \brief sets the data associated with a node.
@@ -919,7 +1087,6 @@
* ZINVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE
* ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
*/
-
ZOOAPI int zoo_set(zhandle_t *zh, const char *path, const char *buffer, int buflen,
int version);
@@ -941,9 +1108,36 @@
* ZINVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE
* ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
*/
-
ZOOAPI int zoo_get_children(zhandle_t *zh, const char *path, int watch,
struct String_vector *strings);
+
+/**
+ * \brief lists the children of a node synchronously.
+ *
+ * This function is similar to \ref zoo_get_children except it allows one specify
+ * a watcher object rather than a boolean watch flag.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watcher if non-null, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param watcherCtx user specific data, will be passed to the watcher callback.
+ * Unlike the global context set by \ref zookeeper_init, this watcher context
+ * is associated with the given instance of the watcher only.
+ * \param strings return value of children paths.
+ * \return the return code of the function.
+ * ZOK operation completed succesfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_wget_children(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx,
+ struct String_vector *strings);
+
/**
* \brief gets the acl associated with a node synchronously.
*
@@ -960,7 +1154,6 @@
* ZINVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE
* ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
*/
-
ZOOAPI int zoo_get_acl(zhandle_t *zh, const char *path, struct ACL_vector *acl,
struct Stat *stat);
@@ -982,7 +1175,6 @@
* ZINVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE
* ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
*/
-
ZOOAPI int zoo_set_acl(zhandle_t *zh, const char *path, int version,
const struct ACL_vector *acl);
Modified: hadoop/zookeeper/trunk/src/c/src/cli.c
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/src/cli.c?rev=679557&r1=679556&r2=679557&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/c/src/cli.c (original)
+++ hadoop/zookeeper/trunk/src/c/src/cli.c Thu Jul 24 14:46:30 2008
@@ -55,7 +55,7 @@
fprintf(stderr,"%s: execution time=%dms\n",msg,delay);
}
-void watcher(zhandle_t *zzh, int type, int state, const char *path) {
+void watcher(zhandle_t *zzh, int type, int state, const char *path,void* context) {
fprintf(stderr,"Watcher %d state = %d for %s\n", type, state, (path ? path: "null"));
if (type == SESSION_EVENT) {
if (state == CONNECTED_STATE) {
Added: hadoop/zookeeper/trunk/src/c/src/hashtable/LICENSE.txt
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/src/hashtable/LICENSE.txt?rev=679557&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/c/src/hashtable/LICENSE.txt (added)
+++ hadoop/zookeeper/trunk/src/c/src/hashtable/LICENSE.txt Thu Jul 24 14:46:30 2008
@@ -0,0 +1,30 @@
+Copyright (c) 2002, 2004, Christopher Clark
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the original author; nor the names of any contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Propchange: hadoop/zookeeper/trunk/src/c/src/hashtable/LICENSE.txt
------------------------------------------------------------------------------
svn:eol-style = native
Added: hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable.c
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable.c?rev=679557&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable.c (added)
+++ hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable.c Thu Jul 24 14:46:30 2008
@@ -0,0 +1,274 @@
+/* Copyright (C) 2004 Christopher Clark <fi...@cl.cam.ac.uk> */
+
+#include "hashtable.h"
+#include "hashtable_private.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+/*
+Credit for primes table: Aaron Krowne
+ http://br.endernet.org/~akrowne/
+ http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
+*/
+static const unsigned int primes[] = {
+53, 97, 193, 389,
+769, 1543, 3079, 6151,
+12289, 24593, 49157, 98317,
+196613, 393241, 786433, 1572869,
+3145739, 6291469, 12582917, 25165843,
+50331653, 100663319, 201326611, 402653189,
+805306457, 1610612741
+};
+const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
+const float max_load_factor = 0.65;
+
+/*****************************************************************************/
+struct hashtable *
+create_hashtable(unsigned int minsize,
+ unsigned int (*hashf) (void*),
+ int (*eqf) (void*,void*))
+{
+ struct hashtable *h;
+ unsigned int pindex, size = primes[0];
+ /* Check requested hashtable isn't too large */
+ if (minsize > (1u << 30)) return NULL;
+ /* Enforce size as prime */
+ for (pindex=0; pindex < prime_table_length; pindex++) {
+ if (primes[pindex] > minsize) { size = primes[pindex]; break; }
+ }
+ h = (struct hashtable *)malloc(sizeof(struct hashtable));
+ if (NULL == h) return NULL; /*oom*/
+ h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
+ if (NULL == h->table) { free(h); return NULL; } /*oom*/
+ memset(h->table, 0, size * sizeof(struct entry *));
+ h->tablelength = size;
+ h->primeindex = pindex;
+ h->entrycount = 0;
+ h->hashfn = hashf;
+ h->eqfn = eqf;
+ h->loadlimit = (unsigned int) ceil(size * max_load_factor);
+ return h;
+}
+
+/*****************************************************************************/
+unsigned int
+hash(struct hashtable *h, void *k)
+{
+ /* Aim to protect against poor hash functions by adding logic here
+ * - logic taken from java 1.4 hashtable source */
+ unsigned int i = h->hashfn(k);
+ i += ~(i << 9);
+ i ^= ((i >> 14) | (i << 18)); /* >>> */
+ i += (i << 4);
+ i ^= ((i >> 10) | (i << 22)); /* >>> */
+ return i;
+}
+
+/*****************************************************************************/
+static int
+hashtable_expand(struct hashtable *h)
+{
+ /* Double the size of the table to accomodate more entries */
+ struct entry **newtable;
+ struct entry *e;
+ struct entry **pE;
+ unsigned int newsize, i, index;
+ /* Check we're not hitting max capacity */
+ if (h->primeindex == (prime_table_length - 1)) return 0;
+ newsize = primes[++(h->primeindex)];
+
+ newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
+ if (NULL != newtable)
+ {
+ memset(newtable, 0, newsize * sizeof(struct entry *));
+ /* This algorithm is not 'stable'. ie. it reverses the list
+ * when it transfers entries between the tables */
+ for (i = 0; i < h->tablelength; i++) {
+ while (NULL != (e = h->table[i])) {
+ h->table[i] = e->next;
+ index = indexFor(newsize,e->h);
+ e->next = newtable[index];
+ newtable[index] = e;
+ }
+ }
+ free(h->table);
+ h->table = newtable;
+ }
+ /* Plan B: realloc instead */
+ else
+ {
+ newtable = (struct entry **)
+ realloc(h->table, newsize * sizeof(struct entry *));
+ if (NULL == newtable) { (h->primeindex)--; return 0; }
+ h->table = newtable;
+ memset(newtable[h->tablelength], 0, newsize - h->tablelength);
+ for (i = 0; i < h->tablelength; i++) {
+ for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
+ index = indexFor(newsize,e->h);
+ if (index == i)
+ {
+ pE = &(e->next);
+ }
+ else
+ {
+ *pE = e->next;
+ e->next = newtable[index];
+ newtable[index] = e;
+ }
+ }
+ }
+ }
+ h->tablelength = newsize;
+ h->loadlimit = (unsigned int) ceil(newsize * max_load_factor);
+ return -1;
+}
+
+/*****************************************************************************/
+unsigned int
+hashtable_count(struct hashtable *h)
+{
+ return h->entrycount;
+}
+
+/*****************************************************************************/
+int
+hashtable_insert(struct hashtable *h, void *k, void *v)
+{
+ /* This method allows duplicate keys - but they shouldn't be used */
+ unsigned int index;
+ struct entry *e;
+ if (++(h->entrycount) > h->loadlimit)
+ {
+ /* Ignore the return value. If expand fails, we should
+ * still try cramming just this value into the existing table
+ * -- we may not have memory for a larger table, but one more
+ * element may be ok. Next time we insert, we'll try expanding again.*/
+ hashtable_expand(h);
+ }
+ e = (struct entry *)malloc(sizeof(struct entry));
+ if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
+ e->h = hash(h,k);
+ index = indexFor(h->tablelength,e->h);
+ e->k = k;
+ e->v = v;
+ e->next = h->table[index];
+ h->table[index] = e;
+ return -1;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_search(struct hashtable *h, void *k)
+{
+ struct entry *e;
+ unsigned int hashvalue, index;
+ hashvalue = hash(h,k);
+ index = indexFor(h->tablelength,hashvalue);
+ e = h->table[index];
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
+ e = e->next;
+ }
+ return NULL;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_remove(struct hashtable *h, void *k)
+{
+ /* TODO: consider compacting the table when the load factor drops enough,
+ * or provide a 'compact' method. */
+
+ struct entry *e;
+ struct entry **pE;
+ void *v;
+ unsigned int hashvalue, index;
+
+ hashvalue = hash(h,k);
+ index = indexFor(h->tablelength,hash(h,k));
+ pE = &(h->table[index]);
+ e = *pE;
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+ {
+ *pE = e->next;
+ h->entrycount--;
+ v = e->v;
+ freekey(e->k);
+ free(e);
+ return v;
+ }
+ pE = &(e->next);
+ e = e->next;
+ }
+ return NULL;
+}
+
+/*****************************************************************************/
+/* destroy */
+void
+hashtable_destroy(struct hashtable *h, int free_values)
+{
+ unsigned int i;
+ struct entry *e, *f;
+ struct entry **table = h->table;
+ if (free_values)
+ {
+ for (i = 0; i < h->tablelength; i++)
+ {
+ e = table[i];
+ while (NULL != e)
+ { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
+ }
+ }
+ else
+ {
+ for (i = 0; i < h->tablelength; i++)
+ {
+ e = table[i];
+ while (NULL != e)
+ { f = e; e = e->next; freekey(f->k); free(f); }
+ }
+ }
+ free(h->table);
+ free(h);
+}
+
+/*
+ * Copyright (c) 2002, Christopher Clark
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
Propchange: hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable.h
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable.h?rev=679557&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable.h (added)
+++ hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable.h Thu Jul 24 14:46:30 2008
@@ -0,0 +1,207 @@
+/* Copyright (C) 2002 Christopher Clark <fi...@cl.cam.ac.uk> */
+
+#ifndef __HASHTABLE_CWC22_H__
+#define __HASHTABLE_CWC22_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct hashtable;
+
+/* Example of use:
+ *
+ * struct hashtable *h;
+ * struct some_key *k;
+ * struct some_value *v;
+ *
+ * static unsigned int hash_from_key_fn( void *k );
+ * static int keys_equal_fn ( void *key1, void *key2 );
+ *
+ * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
+ * k = (struct some_key *) malloc(sizeof(struct some_key));
+ * v = (struct some_value *) malloc(sizeof(struct some_value));
+ *
+ * (initialise k and v to suitable values)
+ *
+ * if (! hashtable_insert(h,k,v) )
+ * { exit(-1); }
+ *
+ * if (NULL == (found = hashtable_search(h,k) ))
+ * { printf("not found!"); }
+ *
+ * if (NULL == (found = hashtable_remove(h,k) ))
+ * { printf("Not found\n"); }
+ *
+ */
+
+/* Macros may be used to define type-safe(r) hashtable access functions, with
+ * methods specialized to take known key and value types as parameters.
+ *
+ * Example:
+ *
+ * Insert this at the start of your file:
+ *
+ * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
+ *
+ * This defines the functions 'insert_some', 'search_some' and 'remove_some'.
+ * These operate just like hashtable_insert etc., with the same parameters,
+ * but their function signatures have 'struct some_key *' rather than
+ * 'void *', and hence can generate compile time errors if your program is
+ * supplying incorrect data as a key (and similarly for value).
+ *
+ * Note that the hash and key equality functions passed to create_hashtable
+ * still take 'void *' parameters instead of 'some key *'. This shouldn't be
+ * a difficult issue as they're only defined and passed once, and the other
+ * functions will ensure that only valid keys are supplied to them.
+ *
+ * The cost for this checking is increased code size and runtime overhead
+ * - if performance is important, it may be worth switching back to the
+ * unsafe methods once your program has been debugged with the safe methods.
+ * This just requires switching to some simple alternative defines - eg:
+ * #define insert_some hashtable_insert
+ *
+ */
+
+/*****************************************************************************
+ * create_hashtable
+
+ * @name create_hashtable
+ * @param minsize minimum initial size of hashtable
+ * @param hashfunction function for hashing keys
+ * @param key_eq_fn function for determining key equality
+ * @return newly created hashtable or NULL on failure
+ */
+
+struct hashtable *
+create_hashtable(unsigned int minsize,
+ unsigned int (*hashfunction) (void*),
+ int (*key_eq_fn) (void*,void*));
+
+/*****************************************************************************
+ * hashtable_insert
+
+ * @name hashtable_insert
+ * @param h the hashtable to insert into
+ * @param k the key - hashtable claims ownership and will free on removal
+ * @param v the value - does not claim ownership
+ * @return non-zero for successful insertion
+ *
+ * This function will cause the table to expand if the insertion would take
+ * the ratio of entries to table size over the maximum load factor.
+ *
+ * This function does not check for repeated insertions with a duplicate key.
+ * The value returned when using a duplicate key is undefined -- when
+ * the hashtable changes size, the order of retrieval of duplicate key
+ * entries is reversed.
+ * If in doubt, remove before insert.
+ */
+
+int
+hashtable_insert(struct hashtable *h, void *k, void *v);
+
+#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
+int fnname (struct hashtable *h, keytype *k, valuetype *v) \
+{ \
+ return hashtable_insert(h,k,v); \
+}
+
+/*****************************************************************************
+ * hashtable_search
+
+ * @name hashtable_search
+ * @param h the hashtable to search
+ * @param k the key to search for - does not claim ownership
+ * @return the value associated with the key, or NULL if none found
+ */
+
+void *
+hashtable_search(struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
+valuetype * fnname (struct hashtable *h, keytype *k) \
+{ \
+ return (valuetype *) (hashtable_search(h,k)); \
+}
+
+/*****************************************************************************
+ * hashtable_remove
+
+ * @name hashtable_remove
+ * @param h the hashtable to remove the item from
+ * @param k the key to search for - does not claim ownership
+ * @return the value associated with the key, or NULL if none found
+ */
+
+void * /* returns value */
+hashtable_remove(struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
+valuetype * fnname (struct hashtable *h, keytype *k) \
+{ \
+ return (valuetype *) (hashtable_remove(h,k)); \
+}
+
+
+/*****************************************************************************
+ * hashtable_count
+
+ * @name hashtable_count
+ * @param h the hashtable
+ * @return the number of items stored in the hashtable
+ */
+unsigned int
+hashtable_count(struct hashtable *h);
+
+
+/*****************************************************************************
+ * hashtable_destroy
+
+ * @name hashtable_destroy
+ * @param h the hashtable
+ * @param free_values whether to call 'free' on the remaining values
+ */
+
+void
+hashtable_destroy(struct hashtable *h, int free_values);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HASHTABLE_CWC22_H__ */
+
+/*
+ * Copyright (c) 2002, Christopher Clark
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
Propchange: hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_itr.c
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_itr.c?rev=679557&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_itr.c (added)
+++ hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_itr.c Thu Jul 24 14:46:30 2008
@@ -0,0 +1,188 @@
+/* Copyright (C) 2002, 2004 Christopher Clark <fi...@cl.cam.ac.uk> */
+
+#include "hashtable.h"
+#include "hashtable_private.h"
+#include "hashtable_itr.h"
+#include <stdlib.h> /* defines NULL */
+
+/*****************************************************************************/
+/* hashtable_iterator - iterator constructor */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h)
+{
+ unsigned int i, tablelength;
+ struct hashtable_itr *itr = (struct hashtable_itr *)
+ malloc(sizeof(struct hashtable_itr));
+ if (NULL == itr) return NULL;
+ itr->h = h;
+ itr->e = NULL;
+ itr->parent = NULL;
+ tablelength = h->tablelength;
+ itr->index = tablelength;
+ if (0 == h->entrycount) return itr;
+
+ for (i = 0; i < tablelength; i++)
+ {
+ if (NULL != h->table[i])
+ {
+ itr->e = h->table[i];
+ itr->index = i;
+ break;
+ }
+ }
+ return itr;
+}
+
+/*****************************************************************************/
+/* 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 */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr)
+{
+ unsigned int j,tablelength;
+ struct entry **table;
+ struct entry *next;
+ if (NULL == itr->e) return 0; /* stupidity check */
+
+ next = itr->e->next;
+ if (NULL != next)
+ {
+ itr->parent = itr->e;
+ itr->e = next;
+ return -1;
+ }
+ tablelength = itr->h->tablelength;
+ itr->parent = NULL;
+ if (tablelength <= (j = ++(itr->index)))
+ {
+ itr->e = NULL;
+ return 0;
+ }
+ table = itr->h->table;
+ while (NULL == (next = table[j]))
+ {
+ if (++j >= tablelength)
+ {
+ itr->index = tablelength;
+ itr->e = NULL;
+ return 0;
+ }
+ }
+ itr->index = j;
+ itr->e = next;
+ return -1;
+}
+
+/*****************************************************************************/
+/* remove - remove the entry at the current iterator position
+ * and advance the iterator, if there is a successive
+ * element.
+ * If you want the value, read it before you remove:
+ * beware memory leaks if you don't.
+ * Returns zero if end of iteration. */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr)
+{
+ struct entry *remember_e, *remember_parent;
+ int ret;
+
+ /* Do the removal */
+ if (NULL == (itr->parent))
+ {
+ /* element is head of a chain */
+ itr->h->table[itr->index] = itr->e->next;
+ } else {
+ /* element is mid-chain */
+ itr->parent->next = itr->e->next;
+ }
+ /* itr->e is now outside the hashtable */
+ remember_e = itr->e;
+ itr->h->entrycount--;
+ freekey(remember_e->k);
+
+ /* Advance the iterator, correcting the parent */
+ remember_parent = itr->parent;
+ ret = hashtable_iterator_advance(itr);
+ if (itr->parent == remember_e) { itr->parent = remember_parent; }
+ free(remember_e);
+ return ret;
+}
+
+/*****************************************************************************/
+int /* returns zero if not found */
+hashtable_iterator_search(struct hashtable_itr *itr,
+ struct hashtable *h, void *k)
+{
+ struct entry *e, *parent;
+ unsigned int hashvalue, index;
+
+ hashvalue = hash(h,k);
+ index = indexFor(h->tablelength,hashvalue);
+
+ e = h->table[index];
+ parent = NULL;
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+ {
+ itr->index = index;
+ itr->e = e;
+ itr->parent = parent;
+ itr->h = h;
+ return -1;
+ }
+ parent = e;
+ e = e->next;
+ }
+ return 0;
+}
+
+
+/*
+ * Copyright (c) 2002, 2004, Christopher Clark
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
Propchange: hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_itr.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_itr.h
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_itr.h?rev=679557&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_itr.h (added)
+++ hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_itr.h Thu Jul 24 14:46:30 2008
@@ -0,0 +1,119 @@
+/* Copyright (C) 2002, 2004 Christopher Clark <fi...@cl.cam.ac.uk> */
+
+#ifndef __HASHTABLE_ITR_CWC22__
+#define __HASHTABLE_ITR_CWC22__
+#include "hashtable.h"
+#include "hashtable_private.h" /* needed to enable inlining */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************/
+/* This struct is only concrete here to allow the inlining of two of the
+ * accessor functions. */
+struct hashtable_itr
+{
+ struct hashtable *h;
+ struct entry *e;
+ struct entry *parent;
+ unsigned int index;
+};
+
+
+/*****************************************************************************/
+/* hashtable_iterator
+ */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h);
+
+/*****************************************************************************/
+/* hashtable_iterator_key
+ * - return the value of the (key,value) pair at the current position */
+
+extern inline void *
+hashtable_iterator_key(struct hashtable_itr *i)
+{
+ return i->e->k;
+}
+
+/*****************************************************************************/
+/* value - return the value of the (key,value) pair at the current position */
+
+extern inline 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 */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* remove - remove current element and advance the iterator to the next element
+ * NB: if you need the value to free it, read it before
+ * removing. ie: beware memory leaks!
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* search - overwrite the supplied iterator, to point to the entry
+ * matching the supplied key.
+ h points to the hashtable to be searched.
+ * returns zero if not found. */
+int
+hashtable_iterator_search(struct hashtable_itr *itr,
+ struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \
+int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \
+{ \
+ return (hashtable_iterator_search(i,h,k)); \
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HASHTABLE_ITR_CWC22__*/
+
+/*
+ * Copyright (c) 2002, 2004, Christopher Clark
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
Propchange: hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_itr.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_private.h
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_private.h?rev=679557&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_private.h (added)
+++ hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_private.h Thu Jul 24 14:46:30 2008
@@ -0,0 +1,85 @@
+/* Copyright (C) 2002, 2004 Christopher Clark <fi...@cl.cam.ac.uk> */
+
+#ifndef __HASHTABLE_PRIVATE_CWC22_H__
+#define __HASHTABLE_PRIVATE_CWC22_H__
+
+#include "hashtable.h"
+
+/*****************************************************************************/
+struct entry
+{
+ void *k, *v;
+ unsigned int h;
+ struct entry *next;
+};
+
+struct hashtable {
+ unsigned int tablelength;
+ struct entry **table;
+ unsigned int entrycount;
+ unsigned int loadlimit;
+ unsigned int primeindex;
+ unsigned int (*hashfn) (void *k);
+ int (*eqfn) (void *k1, void *k2);
+};
+
+/*****************************************************************************/
+unsigned int
+hash(struct hashtable *h, void *k);
+
+/*****************************************************************************/
+/* indexFor */
+static inline unsigned int
+indexFor(unsigned int tablelength, unsigned int hashvalue) {
+ return (hashvalue % tablelength);
+};
+
+/* Only works if tablelength == 2^N */
+/*static inline unsigned int
+indexFor(unsigned int tablelength, unsigned int hashvalue)
+{
+ return (hashvalue & (tablelength - 1u));
+}
+*/
+
+/*****************************************************************************/
+#define freekey(X) free(X)
+/*define freekey(X) ; */
+
+
+/*****************************************************************************/
+
+#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/
+
+/*
+ * Copyright (c) 2002, Christopher Clark
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
Propchange: hadoop/zookeeper/trunk/src/c/src/hashtable/hashtable_private.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: hadoop/zookeeper/trunk/src/c/src/load_gen.c
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/src/load_gen.c?rev=679557&r1=679556&r2=679557&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/c/src/load_gen.c (original)
+++ hadoop/zookeeper/trunk/src/c/src/load_gen.c Thu Jul 24 14:46:30 2008
@@ -68,7 +68,7 @@
pthread_mutex_unlock(&counterLock);
}
-void listener(zhandle_t *zzh, int type, int state, const char *path) {
+void listener(zhandle_t *zzh, int type, int state, const char *path,void* ctx) {
if(type == SESSION_EVENT){
if(state == CONNECTED_STATE){
pthread_mutex_lock(&lock);
Modified: hadoop/zookeeper/trunk/src/c/src/zk_adaptor.h
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/src/zk_adaptor.h?rev=679557&r1=679556&r2=679557&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/c/src/zk_adaptor.h (original)
+++ hadoop/zookeeper/trunk/src/c/src/zk_adaptor.h Thu Jul 24 14:46:30 2008
@@ -23,12 +23,28 @@
#include <pthread.h>
#endif
#include "zookeeper.h"
+#include "zk_hashtable.h"
/* predefined xid's values recognized as special by the server */
#define WATCHER_EVENT_XID -1
#define PING_XID -2
#define AUTH_XID -4
+/* zookeeper state constants */
+#define EXPIRED_SESSION_STATE_DEF -112
+#define AUTH_FAILED_STATE_DEF -113
+#define CONNECTING_STATE_DEF 1
+#define ASSOCIATING_STATE_DEF 2
+#define CONNECTED_STATE_DEF 3
+
+/* zookeeper event type constants */
+#define CREATED_EVENT_DEF 1
+#define DELETED_EVENT_DEF 2
+#define CHANGED_EVENT_DEF 3
+#define CHILD_EVENT_DEF 4
+#define SESSION_EVENT_DEF -1
+#define NOTWATCHING_EVENT_DEF -2
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -174,9 +190,12 @@
volatile int close_requested;
void *adaptor_priv;
/* Used for debugging only: non-zero value indicates the time when the zookeeper_process
- * call returned while there was at least one server response
- * unprocessed available in the socket recv buffer */
+ * call returned while there was at least one unprocessed server response
+ * available in the socket recv buffer */
struct timeval socket_readable;
+
+ zk_hashtable* active_node_watchers;
+ zk_hashtable* active_child_watchers;
};
int adaptor_init(zhandle_t *zh);
@@ -209,7 +228,7 @@
#define PROCESS_SESSION_EVENT(zh,newstate) queue_session_event(zh,newstate)
#else
// in single-threaded mode process session event immediately
-#define PROCESS_SESSION_EVENT(zh,newstate) zh->watcher(zh,SESSION_EVENT,newstate,0)
+#define PROCESS_SESSION_EVENT(zh,newstate) deliverWatchers(zh,SESSION_EVENT,newstate,0)
#endif
#ifdef __cplusplus
Added: hadoop/zookeeper/trunk/src/c/src/zk_hashtable.c
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/src/zk_hashtable.c?rev=679557&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/c/src/zk_hashtable.c (added)
+++ hadoop/zookeeper/trunk/src/c/src/zk_hashtable.c Thu Jul 24 14:46:30 2008
@@ -0,0 +1,444 @@
+/**
+ * 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.
+ */
+
+#include "zk_hashtable.h"
+#include "zk_adaptor.h"
+#include "hashtable/hashtable.h"
+#include "hashtable/hashtable_itr.h"
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#ifdef THREADED
+#include <pthread.h>
+#endif
+
+struct _zk_hashtable {
+ struct hashtable* ht;
+#ifdef THREADED
+ pthread_mutex_t lock;
+#endif
+};
+
+hashtable_impl* getImpl(zk_hashtable* ht){
+ return ht->ht;
+}
+
+typedef struct _watcher_object_list_t {
+ watcher_object_t* head;
+} watcher_object_list_t;
+
+watcher_object_t* getFirstWatcher(zk_hashtable* ht,const char* path)
+{
+ watcher_object_list_t* wl=hashtable_search(ht->ht,(void*)path);
+ if(wl!=0)
+ return wl->head;
+ return 0;
+}
+
+watcher_object_t* clone_watcher_object(watcher_object_t* wo)
+{
+ watcher_object_t* res=calloc(1,sizeof(watcher_object_t));
+ res->watcher=wo->watcher;
+ res->context=wo->context;
+ return res;
+}
+
+static unsigned int string_hash_djb2(void *str)
+{
+ unsigned int hash = 5381;
+ int c;
+
+ while ((c = *(const char*)str++))
+ hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
+
+ return hash;
+}
+
+static int string_equal(void *key1,void *key2)
+{
+ return strcmp((const char*)key1,(const char*)key2)==0;
+}
+
+watcher_object_t* create_watcher_object(watcher_fn watcher,void* ctx)
+{
+ watcher_object_t* wo=calloc(1,sizeof(watcher_object_t));
+ wo->watcher=watcher;
+ wo->context=ctx;
+ return wo;
+}
+
+static watcher_object_list_t* create_watcher_object_list(watcher_object_t* head)
+{
+ watcher_object_list_t* wl=calloc(1,sizeof(watcher_object_list_t));
+ wl->head=head;
+ return wl;
+}
+
+static void destroy_watcher_object_list(watcher_object_list_t* list)
+{
+ if(list==0)
+ return;
+ watcher_object_t* e=list->head;
+ while(e!=0){
+ watcher_object_t* this=e;
+ e=e->next;
+ free(this);
+ }
+ free(list);
+}
+
+zk_hashtable* create_zk_hashtable()
+{
+ struct _zk_hashtable *ht=calloc(1,sizeof(struct _zk_hashtable));
+#ifdef THREADED
+ pthread_mutex_init(&ht->lock, 0);
+#endif
+ ht->ht=create_hashtable(32,string_hash_djb2,string_equal);
+ return ht;
+}
+
+int get_element_count(zk_hashtable *ht)
+{
+ int res;
+#ifdef THREADED
+ pthread_mutex_lock(&ht->lock);
+#endif
+ res=hashtable_count(ht->ht);
+#ifdef THREADED
+ pthread_mutex_unlock(&ht->lock);
+#endif
+ return res;
+}
+
+int get_watcher_count(zk_hashtable* ht,const char* path)
+{
+ int res=0;
+ watcher_object_list_t* wl;
+ watcher_object_t* wo;
+#ifdef THREADED
+ pthread_mutex_lock(&ht->lock);
+#endif
+ wl=hashtable_search(ht->ht,(void*)path);
+ if(wl==0)
+ goto done;
+ wo=wl->head;
+ while(wo!=0){
+ res++;
+ wo=wo->next;
+ }
+done:
+#ifdef THREADED
+ pthread_mutex_unlock(&ht->lock);
+#endif
+ return res;
+}
+
+static void do_clean_hashtable(zk_hashtable* ht)
+{
+ struct hashtable_itr *it;
+ int hasMore;
+ if(hashtable_count(ht->ht)==0)
+ return;
+ it=hashtable_iterator(ht->ht);
+ do{
+ watcher_object_list_t* w=hashtable_iterator_value(it);
+ destroy_watcher_object_list(w);
+ hasMore=hashtable_iterator_remove(it);
+ }while(hasMore);
+ free(it);
+}
+
+void clean_zk_hashtable(zk_hashtable* ht)
+{
+#ifdef THREADED
+ pthread_mutex_lock(&ht->lock);
+#endif
+ do_clean_hashtable(ht);
+#ifdef THREADED
+ pthread_mutex_unlock(&ht->lock);
+#endif
+}
+
+void destroy_zk_hashtable(zk_hashtable* ht)
+{
+ if(ht!=0){
+ do_clean_hashtable(ht);
+ hashtable_destroy(ht->ht,0);
+#ifdef THREADED
+ pthread_mutex_destroy(&ht->lock);
+#endif
+ free(ht);
+ }
+}
+
+// searches for a watcher object instance in a watcher object list;
+// two watcher objects are equal if their watcher function and context pointers
+// are equal
+static watcher_object_t* search_watcher(watcher_object_list_t* wl,watcher_object_t* wo)
+{
+ watcher_object_t* wobj=wl->head;
+ while(wobj!=0){
+ if(wobj->watcher==wo->watcher && wobj->context==wo->context)
+ return wobj;
+ wobj=wobj->next;
+ }
+ return 0;
+}
+
+static int do_insert_watcher_object(zk_hashtable *ht, const char *path, watcher_object_t* wo)
+{
+ int res=1;
+ watcher_object_list_t* wl;
+ wl=hashtable_search(ht->ht,(void*)path);
+ if(wl==0){
+ int res;
+ /* inserting a new path element */
+ res=hashtable_insert(ht->ht,strdup(path),create_watcher_object_list(wo));
+ assert(res);
+ }else{
+ /* path already exists; check if the watcher already exists */
+ if(search_watcher(wl,wo)==0){
+ wo->next=wl->head;
+ wl->head=wo; // insert the new watcher at the head
+ }else
+ res=0; // the watcher already exists -- do not insert!
+ }
+ return res;
+}
+
+int insert_watcher_object(zk_hashtable *ht, const char *path, watcher_object_t* wo)
+{
+ int res;
+#ifdef THREADED
+ pthread_mutex_lock(&ht->lock);
+#endif
+ res=do_insert_watcher_object(ht,path,wo);
+#ifdef THREADED
+ pthread_mutex_unlock(&ht->lock);
+#endif
+ return res;
+}
+
+static void copy_watchers(zk_hashtable* dst,const char* path,watcher_object_list_t* wl)
+{
+ if(wl==0)
+ return;
+ watcher_object_t* wo=wl->head;
+ while(wo!=0){
+ int res;
+ watcher_object_t* cloned=clone_watcher_object(wo);
+ res=do_insert_watcher_object(dst,path,cloned);
+ // was it a duplicate?
+ if(res==0)
+ free(cloned); // yes, didn't get inserted
+ wo=wo->next;
+ }
+}
+
+static void copy_table(zk_hashtable* dst,zk_hashtable* src)
+{
+ struct hashtable_itr *it;
+ int hasMore;
+ if(hashtable_count(src->ht)==0)
+ return;
+ it=hashtable_iterator(src->ht);
+ do{
+ copy_watchers(dst,hashtable_iterator_key(it),hashtable_iterator_value(it));
+ hasMore=hashtable_iterator_advance(it);
+ }while(hasMore);
+ free(it);
+}
+
+zk_hashtable* combine_hashtables(zk_hashtable *ht1,zk_hashtable *ht2)
+{
+ zk_hashtable* newht=create_zk_hashtable();
+#ifdef THREADED
+ pthread_mutex_lock(&ht1->lock);
+ pthread_mutex_lock(&ht2->lock);
+#endif
+ copy_table(newht,ht1);
+ copy_table(newht,ht2);
+#ifdef THREADED
+ pthread_mutex_unlock(&ht2->lock);
+ pthread_mutex_unlock(&ht1->lock);
+#endif
+ return newht;
+}
+
+zk_hashtable* move_merge_watchers(zk_hashtable *ht1,zk_hashtable *ht2,const char *path)
+{
+ watcher_object_list_t* wl;
+ zk_hashtable* newht=create_zk_hashtable();
+#ifdef THREADED
+ pthread_mutex_lock(&ht1->lock);
+ pthread_mutex_lock(&ht2->lock);
+#endif
+ // copy watchers from table 1
+ wl=hashtable_remove(ht1->ht,(void*)path);
+ copy_watchers(newht,path,wl);
+ destroy_watcher_object_list(wl);
+ // merge all watchers from tabe 2
+ wl=hashtable_remove(ht2->ht,(void*)path);
+ copy_watchers(newht,path,wl);
+ destroy_watcher_object_list(wl);
+
+#ifdef THREADED
+ pthread_mutex_unlock(&ht2->lock);
+ pthread_mutex_unlock(&ht1->lock);
+#endif
+ return newht;
+}
+
+int contains_watcher(zk_hashtable *ht,watcher_object_t* wo)
+{
+ struct hashtable_itr *it=0;
+ int res=0;
+ int hasMore;
+#ifdef THREADED
+ pthread_mutex_lock(&ht->lock);
+#endif
+ if(hashtable_count(ht->ht)==0)
+ goto done;
+ it=hashtable_iterator(ht->ht);
+ do{
+ watcher_object_list_t* w=hashtable_iterator_value(it);
+ if(search_watcher(w,wo)!=0){
+ res=1;
+ goto done;
+ }
+ hasMore=hashtable_iterator_advance(it);
+ }while(hasMore);
+done:
+ if(it!=0)
+ free(it);
+#ifdef THREADED
+ pthread_mutex_unlock(&ht->lock);
+#endif
+ return res;
+}
+
+static void do_foreach_watcher(watcher_object_t* wo,zhandle_t* zh,
+ const char* path,int type,int state)
+{
+ while(wo!=0){
+ wo->watcher(zh,type,state,path,wo->context);
+ wo=wo->next;
+ }
+}
+
+void deliver_session_event(zk_hashtable* ht,zhandle_t* zh,int type,int state)
+{
+ struct hashtable_itr *it;
+ int hasMore;
+#ifdef THREADED
+ pthread_mutex_lock(&ht->lock);
+#endif
+ if(hashtable_count(ht->ht)==0)
+ goto done;
+ it=hashtable_iterator(ht->ht);
+ do{
+ watcher_object_t* wo=((watcher_object_list_t*)hashtable_iterator_value(it))->head;
+ // session events are delivered with the path set to null
+ do_foreach_watcher(wo,zh,0,type,state);
+ hasMore=hashtable_iterator_advance(it);
+ }while(hasMore);
+ free(it);
+done:
+#ifdef THREADED
+ pthread_mutex_unlock(&ht->lock);
+#endif
+ return;
+}
+
+void deliver_znode_event(zk_hashtable* ht,zhandle_t* zh,const char* path,int type,int state)
+{
+ watcher_object_list_t* wl;
+#ifdef THREADED
+ pthread_mutex_lock(&ht->lock);
+#endif
+ wl=hashtable_remove(ht->ht,(void*)path);
+#ifdef THREADED
+ pthread_mutex_unlock(&ht->lock);
+#endif
+ if(wl!=0){
+ do_foreach_watcher(wl->head,zh,path,type,state);
+ destroy_watcher_object_list(wl);
+ }
+}
+
+void deliverWatchers(zhandle_t* zh,int type,int state, const char* path)
+{
+ zk_hashtable *ht;
+ if(type==SESSION_EVENT){
+ watcher_object_t defWatcher;
+ if(state==CONNECTED_STATE){
+ clean_zk_hashtable(zh->active_node_watchers);
+ clean_zk_hashtable(zh->active_child_watchers);
+ // unconditionally call back the default watcher only
+ zh->watcher(zh,type,state,0,zh->context);
+ return;
+ }
+ // process a disconnect/expiration
+ // must merge node and child watchers first
+ ht=combine_hashtables(zh->active_node_watchers,
+ zh->active_child_watchers);
+ // check if the default watcher is already present on the combined map
+ defWatcher.watcher=zh->watcher;
+ defWatcher.context=zh->context;
+ if(contains_watcher(ht,&defWatcher)==0)
+ insert_watcher_object(ht,"",clone_watcher_object(&defWatcher));
+ // deliver watcher callback to all registered watchers
+ deliver_session_event(ht,zh,type,state);
+ destroy_zk_hashtable(ht);
+ // in anticipation of the watcher auto-reset feature we keep
+ // the watcher maps intact.
+ // (for now, we simply clean the maps on reconnect, see above)
+ return;
+ }
+ switch(type){
+ case CREATED_EVENT_DEF:
+ case CHANGED_EVENT_DEF:
+ // look up the watchers for the path and deliver them
+ deliver_znode_event(zh->active_node_watchers,zh,path,type,state);
+ break;
+ case CHILD_EVENT_DEF:
+ // look up the watchers for the path and deliver them
+ deliver_znode_event(zh->active_child_watchers,zh,path,type,state);
+ break;
+ case DELETED_EVENT_DEF:
+ // combine node and child watchers for the path and deliver them
+ ht=move_merge_watchers(zh->active_child_watchers,
+ zh->active_node_watchers,path);
+ deliver_znode_event(ht,zh,path,type,state);
+ destroy_zk_hashtable(ht);
+ break;
+ }
+}
+
+void activateWatcher(watcher_registration_t* reg, int rc)
+{
+ if(reg!=0){
+ /* in multithreaded lib, this code is executed
+ * by the completion thread */
+ if(reg->checker(rc)){
+ insert_watcher_object(reg->activeMap,reg->path,
+ create_watcher_object(reg->watcher,reg->context));
+ }
+ }
+}
Propchange: hadoop/zookeeper/trunk/src/c/src/zk_hashtable.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: hadoop/zookeeper/trunk/src/c/src/zk_hashtable.h
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/src/zk_hashtable.h?rev=679557&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/c/src/zk_hashtable.h (added)
+++ hadoop/zookeeper/trunk/src/c/src/zk_hashtable.h Thu Jul 24 14:46:30 2008
@@ -0,0 +1,115 @@
+/**
+ * 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 ZK_HASHTABLE_H_
+#define ZK_HASHTABLE_H_
+
+#include <zookeeper.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _zk_hashtable zk_hashtable;
+
+/**
+ * The function must return a non-zero value if the watcher object can be activated
+ * as a result of the server response. Normally, a watch can only be activated
+ * if the server returns a success code (ZOK). However in the case when zoo_exists()
+ * returns a ZNONODE code the watcher should be activated nevertheless.
+ */
+typedef int (*result_checker_fn)(int rc);
+
+/**
+ * A watcher object gets temporarily stored with the completion entry until
+ * the server response comes back at which moment the watcher object is moved
+ * to the active watchers map.
+ */
+typedef struct _watcher_registration {
+ watcher_fn watcher;
+ result_checker_fn checker;
+ void* context;
+ zk_hashtable* activeMap; // the map to add the watcher to upon activation
+ const char* path;
+} watcher_registration_t;
+
+
+typedef struct _watcher_object {
+ watcher_fn watcher;
+ void* context;
+ struct _watcher_object* next;
+} watcher_object_t;
+
+watcher_object_t* create_watcher_object(watcher_fn watcher,void* ctx);
+watcher_object_t* clone_watcher_object(watcher_object_t* wo);
+
+zk_hashtable* create_zk_hashtable();
+void clean_zk_hashtable(zk_hashtable* ht);
+void destroy_zk_hashtable(zk_hashtable* ht);
+zk_hashtable* combine_hashtables(zk_hashtable* ht1,zk_hashtable* ht2);
+/**
+ * \brief first, merges all watchers for path from ht1 and ht2 to a new hashtable and
+ * then removes the path entries from ht1 and ht2
+ */
+zk_hashtable* move_merge_watchers(zk_hashtable* ht1,zk_hashtable* ht2,const char* path);
+
+/**
+ * The hashtable takes ownership of the watcher object instance.
+ *
+ * \return 1 if the watcher object was succesfully inserted, 0 otherwise
+ */
+int insert_watcher_object(zk_hashtable* ht, const char* path, watcher_object_t* wo);
+/**
+ * \brief searches the entire hashtable for the watcher object
+ *
+ * \return 1 if the watcher object found in the table, 0 otherwise
+ */
+int contains_watcher(zk_hashtable* ht,watcher_object_t* wo);
+int get_element_count(zk_hashtable* ht);
+int get_watcher_count(zk_hashtable* ht,const char* path);
+/**
+ * \brief delivers all watchers in the hashtable
+ */
+void deliver_session_event(zk_hashtable* ht,zhandle_t* zh,int type,int state);
+/**
+ * \brief delivers all watchers for path and then removes the path entry
+ * from the hashtable
+ */
+void deliver_znode_event(zk_hashtable* ht,zhandle_t* zh,const char* path,int type,int state);
+
+/**
+ * zookeeper uses this function to deliver watcher callbacks
+ */
+void deliverWatchers(zhandle_t* zh,int type,int state, const char* path);
+/**
+ * check if the completion has a watcher object associated
+ * with it. If it does, move the watcher object to the map of
+ * active watchers (only if the checker allows to do so)
+ */
+void activateWatcher(watcher_registration_t* reg, int rc);
+
+/* the following functions are for testing only */
+typedef struct hashtable hashtable_impl;
+hashtable_impl* getImpl(zk_hashtable* ht);
+watcher_object_t* getFirstWatcher(zk_hashtable* ht,const char* path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*ZK_HASHTABLE_H_*/
Propchange: hadoop/zookeeper/trunk/src/c/src/zk_hashtable.h
------------------------------------------------------------------------------
svn:eol-style = native