zookeeper-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From an...@apache.org
Subject [08/22] zookeeper git commit: ZOOKEEPER-3031: 3.5: MAVEN MIGRATION - move client dir
Date Wed, 22 Aug 2018 06:18:47 GMT
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/8c87cc49/zookeeper-client/zookeeper-client-c/include/zookeeper_log.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/include/zookeeper_log.h b/zookeeper-client/zookeeper-client-c/include/zookeeper_log.h
new file mode 100644
index 0000000..56a9b73
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/include/zookeeper_log.h
@@ -0,0 +1,50 @@
+/**
+ * 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_LOG_H_
+#define ZK_LOG_H_
+
+#include <zookeeper.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern ZOOAPI ZooLogLevel logLevel;
+#define LOGCALLBACK(_zh) zoo_get_log_callback(_zh)
+#define LOGSTREAM NULL
+
+#define LOG_ERROR(_cb, ...) if(logLevel>=ZOO_LOG_LEVEL_ERROR) \
+    log_message(_cb, ZOO_LOG_LEVEL_ERROR, __LINE__, __func__, __VA_ARGS__)
+#define LOG_WARN(_cb, ...) if(logLevel>=ZOO_LOG_LEVEL_WARN) \
+    log_message(_cb, ZOO_LOG_LEVEL_WARN, __LINE__, __func__, __VA_ARGS__)
+#define LOG_INFO(_cb, ...) if(logLevel>=ZOO_LOG_LEVEL_INFO) \
+    log_message(_cb, ZOO_LOG_LEVEL_INFO, __LINE__, __func__, __VA_ARGS__)
+#define LOG_DEBUG(_cb, ...) if(logLevel==ZOO_LOG_LEVEL_DEBUG) \
+    log_message(_cb, ZOO_LOG_LEVEL_DEBUG, __LINE__, __func__, __VA_ARGS__)
+
+ZOOAPI void log_message(log_callback_fn callback, ZooLogLevel curLevel,
+    int line, const char* funcName, const char* format, ...);
+
+FILE* zoo_get_log_stream();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*ZK_LOG_H_*/

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/8c87cc49/zookeeper-client/zookeeper-client-c/include/zookeeper_version.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/include/zookeeper_version.h b/zookeeper-client/zookeeper-client-c/include/zookeeper_version.h
new file mode 100644
index 0000000..9ee7976
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/include/zookeeper_version.h
@@ -0,0 +1,33 @@
+/**
+ * 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 ZOOKEEPER_VERSION_H_
+#define ZOOKEEPER_VERSION_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZOO_MAJOR_VERSION 3
+#define ZOO_MINOR_VERSION 5
+#define ZOO_PATCH_VERSION 5
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZOOKEEPER_VERSION_H_ */

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/8c87cc49/zookeeper-client/zookeeper-client-c/src/addrvec.c
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/addrvec.c b/zookeeper-client/zookeeper-client-c/src/addrvec.c
new file mode 100644
index 0000000..fdfb68d
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/addrvec.c
@@ -0,0 +1,253 @@
+/**
+ * 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 <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#ifdef WIN32
+#define random rand /* replace POSIX random with Windows rand */
+#include <winsock2.h> /* must always be included before ws2tcpip.h */
+#include <ws2tcpip.h> /* for sockaddr_storage */
+#include "winport.h"
+#endif
+
+#include "addrvec.h"
+
+#define ADDRVEC_DEFAULT_GROW_AMOUNT 16
+
+void addrvec_init(addrvec_t *avec)
+{
+    assert(avec);
+    avec->next = 0;
+    avec->count = 0;
+    avec->capacity = 0;
+    avec->data = NULL;
+}
+
+void addrvec_free(addrvec_t *avec)
+{
+    if (avec == NULL)
+    {
+        return;
+    }
+
+    avec->next = 0;
+    avec->count = 0;
+    avec->capacity = 0;
+    if (avec->data) {
+        free(avec->data);
+        avec->data = NULL;
+    }
+}
+
+int addrvec_alloc(addrvec_t *avec)
+{
+    addrvec_init(avec);
+    return addrvec_grow_default(avec);
+}
+
+int addrvec_alloc_capacity(addrvec_t* avec, uint32_t capacity)
+{
+    addrvec_init(avec);
+    return addrvec_grow(avec, capacity);
+}
+
+int addrvec_grow(addrvec_t *avec, uint32_t grow_amount)
+{
+    unsigned int old_capacity = 0;
+    struct sockaddr_storage *old_data = NULL;
+    assert(avec);
+
+    if (grow_amount == 0)
+    {
+        return 0;
+    }
+
+    // Save off old data and capacity in case there is a realloc failure
+    old_capacity = avec->capacity;
+    old_data = avec->data;
+
+    avec->capacity += grow_amount;
+    avec->data = realloc(avec->data, sizeof(*avec->data) * avec->capacity);
+    if (avec->data == NULL)
+    {
+        avec->capacity = old_capacity;
+        avec->data = old_data;
+        errno = ENOMEM;
+        return 1;
+    }
+
+    return 0;
+}
+
+int addrvec_grow_default(addrvec_t *avec)
+{
+    return addrvec_grow(avec, ADDRVEC_DEFAULT_GROW_AMOUNT);
+}
+
+static int addrvec_grow_if_full(addrvec_t *avec)
+{
+    assert(avec);
+    if (avec->count == avec->capacity)
+    {
+        int rc = addrvec_grow_default(avec);
+        if (rc != 0)
+        {
+            return rc;
+        }
+    }
+
+    return 0;
+}
+
+int addrvec_contains(const addrvec_t *avec, const struct sockaddr_storage *addr)
+{
+    uint32_t i = 0;
+    if (!avec || !addr)
+    { 
+        return 0;
+    }
+
+    for (i = 0; i < avec->count; i++)
+    {
+        if(memcmp(&avec->data[i], addr, INET_ADDRSTRLEN) == 0)
+            return 1;
+    }
+
+    return 0;
+}
+
+int addrvec_append(addrvec_t *avec, const struct sockaddr_storage *addr)
+{
+    int rc = 0;
+    assert(avec);
+    assert(addr);
+
+    rc = addrvec_grow_if_full(avec);
+    if (rc != 0)
+    {
+        return rc;
+    }
+
+    // Copy addrinfo into address list
+    memcpy(avec->data + avec->count, addr, sizeof(*addr));
+    ++avec->count;
+
+    return 0;
+}
+
+int addrvec_append_addrinfo(addrvec_t *avec, const struct addrinfo *addrinfo)
+{
+    int rc = 0;
+    assert(avec);
+    assert(addrinfo);
+
+    rc = addrvec_grow_if_full(avec);
+    if (rc != 0)
+    {
+        return rc;
+    }
+
+    // Copy addrinfo into address list
+    memcpy(avec->data + avec->count, addrinfo->ai_addr, addrinfo->ai_addrlen);
+    ++avec->count;
+
+    return 0;
+}
+
+void addrvec_shuffle(addrvec_t *avec)
+{
+    int i = 0;
+    for (i = avec->count - 1; i > 0; --i) {
+        long int j = random()%(i+1);
+        if (i != j) {
+            struct sockaddr_storage t = avec->data[i];
+            avec->data[i] = avec->data[j];
+            avec->data[j] = t;
+        }
+    }
+}
+
+int addrvec_hasnext(const addrvec_t *avec)
+{
+    return avec->count > 0 && (avec->next < avec->count);
+}
+
+int addrvec_atend(const addrvec_t *avec)
+{
+    return avec->count > 0 && avec->next >= avec->count;
+}
+
+void addrvec_next(addrvec_t *avec, struct sockaddr_storage *next)
+{
+    int index;
+
+    // If we're at the end of the list, then reset index to start
+    if (addrvec_atend(avec)) {
+        avec->next = 0;
+    }
+
+    if (!addrvec_hasnext(avec)) {
+        if (next) {
+            memset(next, 0, sizeof(*next));
+        }
+
+        return;
+    }
+
+    index = avec->next++;
+
+    if (next) {
+        *next = avec->data[index];
+    }
+}
+
+void addrvec_peek(addrvec_t *avec, struct sockaddr_storage *next)
+{
+    int index = avec->next;
+
+    if (avec->count == 0) {
+        memset(next, 0, sizeof(*next));
+        return;
+    }
+
+    if (addrvec_atend(avec)) {
+        index = 0;
+    }
+
+    *next = avec->data[index];
+}
+
+
+int addrvec_eq(const addrvec_t *a1, const addrvec_t *a2)
+{
+    uint32_t i = 0;
+    if (a1->count != a2->count)
+    {
+        return 0;
+    }
+
+    for (i = 0; i < a1->count; ++i)
+    {
+        if (!addrvec_contains(a2, &a1->data[i]))
+            return 0;
+    }
+
+    return 1;
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/8c87cc49/zookeeper-client/zookeeper-client-c/src/addrvec.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/addrvec.h b/zookeeper-client/zookeeper-client-c/src/addrvec.h
new file mode 100644
index 0000000..a126429
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/addrvec.h
@@ -0,0 +1,138 @@
+/**
+ * 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 ADDRVEC_H_
+#define ADDRVEC_H_
+
+#ifndef WIN32
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#else
+#include <WinSock2.h>
+#include <stdint.h>
+#endif
+
+/**
+ * This structure represents a list of addresses. It stores the count of the
+ * number of elements that have been inserted via calls to addrvec_append and
+ * addrvec_append_addrinfo. It also has a capacity field for the number of 
+ * addresses it has the ability to hold without needing to be enlarged.
+ */
+typedef struct _addrvec {
+    unsigned int next;                        // next index to use
+    unsigned int count;                       // number of addresses in this list
+    unsigned int capacity;                    // number of address this list can hold
+    struct sockaddr_storage *data;   // list of addresses
+} addrvec_t;
+
+/**
+ * Initialize an addrvec by clearing out all its state.
+ */
+void addrvec_init(addrvec_t *avec);
+
+/**
+ * Free any memory used internally by an addrvec
+ */
+void addrvec_free(addrvec_t *avec);
+
+/**
+ * Allocate an addrvec with a default capacity (16)
+ */
+int addrvec_alloc(addrvec_t *avec);
+
+/**
+ * Allocates an addrvec with a specified capacity
+ */
+int addrvec_alloc_capacity(addrvec_t *avec, uint32_t capacity);
+
+/**
+ * Grow an addrvec by the specified amount. This will increase the capacity
+ * of the vector and not the contents.
+ */
+int addrvec_grow(addrvec_t *avec, uint32_t grow_amount);
+
+/**
+ * Similar to addrvec_grow but uses a default growth amount of 16.
+ */
+int addrvec_grow_default(addrvec_t *avec);
+
+/**
+ * Check if an addrvec contains the specificed sockaddr_storage value.
+ * \returns 1 if it contains the value and 0 otherwise.
+ */
+int addrvec_contains(const addrvec_t *avec, const struct sockaddr_storage *addr);
+
+/**
+ * Append the given sockaddr_storage pointer into the addrvec. The contents of
+ * the given 'addr' are copied into the addrvec via memcpy.
+ */
+int addrvec_append(addrvec_t *avec, const struct sockaddr_storage *addr);
+
+/**
+ * Append the given addrinfo pointer into the addrvec. The contents of the given
+ * 'addrinfo' are copied into the addrvec via memcpy.
+ */
+int addrvec_append_addrinfo(addrvec_t *avec, const struct addrinfo *addrinfo);
+
+/**
+ * Shuffle the addrvec so that it's internal list of addresses are randomized.
+ * Uses random() and assumes it has been properly seeded.
+ */
+void addrvec_shuffle(addrvec_t *avec);
+
+/**
+ * Determine if the addrvec has a next element (e.g. it's safe to call addrvec_next)
+ * 
+ * \returns 1 if it has a next element and 0 otherwise
+ */
+int addrvec_hasnext(const addrvec_t *avec);
+
+/**
+ * Determine if the addrvec is at the end or not. Specifically, this means a
+ * subsequent call to addrvec_next will loop around to the start again.
+ */
+int addrvec_atend(const addrvec_t *avec);
+
+/**
+ * Get the next entry from the addrvec and update the associated index.
+ *
+ * If next is NULL, the index will still be updated.
+ * 
+ * If the current index points at (or after) the last element in the vector then
+ * it will loop back around and start at the beginning of the list.
+ */
+void addrvec_next(addrvec_t *avec, struct sockaddr_storage *next);
+
+/**
+ * Retrieves the next entry from the addrvec but doesn't update the index.
+ */
+void addrvec_peek(addrvec_t *avec, struct sockaddr_storage *next);
+
+/**
+ * Compare two addrvecs for equality. 
+ * 
+ * \returns 1 if the contents of the two lists are identical and and 0 otherwise.
+ */
+int addrvec_eq(const addrvec_t *a1, const addrvec_t *a2);
+
+#endif // ADDRVEC_H
+
+
+

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/8c87cc49/zookeeper-client/zookeeper-client-c/src/cli.c
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/cli.c b/zookeeper-client/zookeeper-client-c/src/cli.c
new file mode 100644
index 0000000..6ca4a41
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/cli.c
@@ -0,0 +1,836 @@
+/**
+ * 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.
+ */
+
+/**
+ * cli.c is a example/sample C client shell for ZooKeeper. It contains
+ * basic shell functionality which exercises some of the features of
+ * the ZooKeeper C client API. It is not a full fledged client and is
+ * not meant for production usage - see the Java client shell for a
+ * fully featured shell.
+ */
+
+#include <zookeeper.h>
+#include <proto.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifndef WIN32
+#include <sys/time.h>
+#include <unistd.h>
+#include <sys/select.h>
+#else
+#include "winport.h"
+//#include <io.h> <-- can't include, conflicting definitions of close()
+int read(int _FileHandle, void * _DstBuf, unsigned int _MaxCharCount);
+int write(int _Filehandle, const void * _Buf, unsigned int _MaxCharCount);
+#define ctime_r(tctime, buffer) ctime_s (buffer, 40, tctime)
+#endif
+
+#include <time.h>
+#include <errno.h>
+#include <assert.h>
+
+#ifdef YCA
+#include <yca/yca.h>
+#endif
+
+#define _LL_CAST_ (long long)
+
+static zhandle_t *zh;
+static clientid_t myid;
+static const char *clientIdFile = 0;
+struct timeval startTime;
+static char cmd[1024];
+static int batchMode=0;
+
+static int to_send=0;
+static int sent=0;
+static int recvd=0;
+
+static int shutdownThisThing=0;
+
+static __attribute__ ((unused)) void
+printProfileInfo(struct timeval start, struct timeval end, int thres,
+                 const char* msg)
+{
+  int delay=(end.tv_sec*1000+end.tv_usec/1000)-
+    (start.tv_sec*1000+start.tv_usec/1000);
+  if(delay>thres)
+    fprintf(stderr,"%s: execution time=%dms\n",msg,delay);
+}
+
+static const char* state2String(int state){
+  if (state == 0)
+    return "CLOSED_STATE";
+  if (state == ZOO_CONNECTING_STATE)
+    return "CONNECTING_STATE";
+  if (state == ZOO_ASSOCIATING_STATE)
+    return "ASSOCIATING_STATE";
+  if (state == ZOO_CONNECTED_STATE)
+    return "CONNECTED_STATE";
+  if (state == ZOO_READONLY_STATE)
+    return "READONLY_STATE";
+  if (state == ZOO_EXPIRED_SESSION_STATE)
+    return "EXPIRED_SESSION_STATE";
+  if (state == ZOO_AUTH_FAILED_STATE)
+    return "AUTH_FAILED_STATE";
+
+  return "INVALID_STATE";
+}
+
+static const char* type2String(int state){
+  if (state == ZOO_CREATED_EVENT)
+    return "CREATED_EVENT";
+  if (state == ZOO_DELETED_EVENT)
+    return "DELETED_EVENT";
+  if (state == ZOO_CHANGED_EVENT)
+    return "CHANGED_EVENT";
+  if (state == ZOO_CHILD_EVENT)
+    return "CHILD_EVENT";
+  if (state == ZOO_SESSION_EVENT)
+    return "SESSION_EVENT";
+  if (state == ZOO_NOTWATCHING_EVENT)
+    return "NOTWATCHING_EVENT";
+
+  return "UNKNOWN_EVENT_TYPE";
+}
+
+void watcher(zhandle_t *zzh, int type, int state, const char *path,
+             void* context)
+{
+    /* Be careful using zh here rather than zzh - as this may be mt code
+     * the client lib may call the watcher before zookeeper_init returns */
+
+    fprintf(stderr, "Watcher %s state = %s", type2String(type), state2String(state));
+    if (path && strlen(path) > 0) {
+      fprintf(stderr, " for path %s", path);
+    }
+    fprintf(stderr, "\n");
+
+    if (type == ZOO_SESSION_EVENT) {
+        if (state == ZOO_CONNECTED_STATE) {
+            const clientid_t *id = zoo_client_id(zzh);
+            if (myid.client_id == 0 || myid.client_id != id->client_id) {
+                myid = *id;
+                fprintf(stderr, "Got a new session id: 0x%llx\n",
+                        _LL_CAST_ myid.client_id);
+                if (clientIdFile) {
+                    FILE *fh = fopen(clientIdFile, "w");
+                    if (!fh) {
+                        perror(clientIdFile);
+                    } else {
+                        int rc = fwrite(&myid, sizeof(myid), 1, fh);
+                        if (rc != sizeof(myid)) {
+                            perror("writing client id");
+                        }
+                        fclose(fh);
+                    }
+                }
+            }
+        } else if (state == ZOO_AUTH_FAILED_STATE) {
+            fprintf(stderr, "Authentication failure. Shutting down...\n");
+            zookeeper_close(zzh);
+            shutdownThisThing=1;
+            zh=0;
+        } else if (state == ZOO_EXPIRED_SESSION_STATE) {
+            fprintf(stderr, "Session expired. Shutting down...\n");
+            zookeeper_close(zzh);
+            shutdownThisThing=1;
+            zh=0;
+        }
+    }
+}
+
+void dumpStat(const struct Stat *stat) {
+    char tctimes[40];
+    char tmtimes[40];
+    time_t tctime;
+    time_t tmtime;
+
+    if (!stat) {
+        fprintf(stderr,"null\n");
+        return;
+    }
+    tctime = stat->ctime/1000;
+    tmtime = stat->mtime/1000;
+
+    ctime_r(&tmtime, tmtimes);
+    ctime_r(&tctime, tctimes);
+
+    fprintf(stderr, "\tctime = %s\tczxid=%llx\n"
+    "\tmtime=%s\tmzxid=%llx\n"
+    "\tversion=%x\taversion=%x\n"
+    "\tephemeralOwner = %llx\n",
+     tctimes, _LL_CAST_ stat->czxid, tmtimes,
+    _LL_CAST_ stat->mzxid,
+    (unsigned int)stat->version, (unsigned int)stat->aversion,
+    _LL_CAST_ stat->ephemeralOwner);
+}
+
+void my_string_completion(int rc, const char *name, const void *data) {
+    fprintf(stderr, "[%s]: rc = %d\n", (char*)(data==0?"null":data), rc);
+    if (!rc) {
+        fprintf(stderr, "\tname = %s\n", name);
+    }
+    if(batchMode)
+      shutdownThisThing=1;
+}
+
+void my_string_completion_free_data(int rc, const char *name, const void *data) {
+    my_string_completion(rc, name, data);
+    free((void*)data);
+}
+
+void my_string_stat_completion(int rc, const char *name, const struct Stat *stat,
+        const void *data)  {
+    my_string_completion(rc, name, data);
+    dumpStat(stat);
+}
+
+void my_string_stat_completion_free_data(int rc, const char *name,
+        const struct Stat *stat, const void *data)  {
+    my_string_stat_completion(rc, name, stat, data);
+    free((void*)data);
+}
+
+void my_data_completion(int rc, const char *value, int value_len,
+        const struct Stat *stat, const void *data) {
+    struct timeval tv;
+    int sec;
+    int usec;
+    gettimeofday(&tv, 0);
+    sec = tv.tv_sec - startTime.tv_sec;
+    usec = tv.tv_usec - startTime.tv_usec;
+    fprintf(stderr, "time = %d msec\n", sec*1000 + usec/1000);
+    fprintf(stderr, "%s: rc = %d\n", (char*)data, rc);
+    if (value) {
+        fprintf(stderr, " value_len = %d\n", value_len);
+        assert(write(2, value, value_len) == value_len);
+    }
+    fprintf(stderr, "\nStat:\n");
+    dumpStat(stat);
+    free((void*)data);
+    if(batchMode)
+      shutdownThisThing=1;
+}
+
+void my_silent_data_completion(int rc, const char *value, int value_len,
+        const struct Stat *stat, const void *data) {
+    recvd++;
+    fprintf(stderr, "Data completion %s rc = %d\n",(char*)data,rc);
+    free((void*)data);
+    if (recvd==to_send) {
+        fprintf(stderr,"Recvd %d responses for %d requests sent\n",recvd,to_send);
+        if(batchMode)
+          shutdownThisThing=1;
+    }
+}
+
+void my_strings_completion(int rc, const struct String_vector *strings,
+        const void *data) {
+    struct timeval tv;
+    int sec;
+    int usec;
+    int i;
+
+    gettimeofday(&tv, 0);
+    sec = tv.tv_sec - startTime.tv_sec;
+    usec = tv.tv_usec - startTime.tv_usec;
+    fprintf(stderr, "time = %d msec\n", sec*1000 + usec/1000);
+    fprintf(stderr, "%s: rc = %d\n", (char*)data, rc);
+    if (strings)
+        for (i=0; i < strings->count; i++) {
+            fprintf(stderr, "\t%s\n", strings->data[i]);
+        }
+    free((void*)data);
+    gettimeofday(&tv, 0);
+    sec = tv.tv_sec - startTime.tv_sec;
+    usec = tv.tv_usec - startTime.tv_usec;
+    fprintf(stderr, "time = %d msec\n", sec*1000 + usec/1000);
+    if(batchMode)
+      shutdownThisThing=1;
+}
+
+void my_strings_stat_completion(int rc, const struct String_vector *strings,
+        const struct Stat *stat, const void *data) {
+    my_strings_completion(rc, strings, data);
+    dumpStat(stat);
+    if(batchMode)
+      shutdownThisThing=1;
+}
+
+void my_void_completion(int rc, const void *data) {
+    fprintf(stderr, "%s: rc = %d\n", (char*)data, rc);
+    free((void*)data);
+    if(batchMode)
+      shutdownThisThing=1;
+}
+
+void my_stat_completion(int rc, const struct Stat *stat, const void *data) {
+    fprintf(stderr, "%s: rc = %d Stat:\n", (char*)data, rc);
+    dumpStat(stat);
+    free((void*)data);
+    if(batchMode)
+      shutdownThisThing=1;
+}
+
+void my_silent_stat_completion(int rc, const struct Stat *stat,
+        const void *data) {
+    //    fprintf(stderr, "State completion: [%s] rc = %d\n", (char*)data, rc);
+    sent++;
+    free((void*)data);
+}
+
+static void sendRequest(const char* data) {
+    zoo_aset(zh, "/od", data, strlen(data), -1, my_silent_stat_completion,
+            strdup("/od"));
+    zoo_aget(zh, "/od", 1, my_silent_data_completion, strdup("/od"));
+}
+
+void od_completion(int rc, const struct Stat *stat, const void *data) {
+    int i;
+    fprintf(stderr, "od command response: rc = %d Stat:\n", rc);
+    dumpStat(stat);
+    // send a whole bunch of requests
+    recvd=0;
+    sent=0;
+    to_send=200;
+    for (i=0; i<to_send; i++) {
+        char buf[4096*16];
+        memset(buf, -1, sizeof(buf)-1);
+        buf[sizeof(buf)-1]=0;
+        sendRequest(buf);
+    }
+}
+
+int startsWith(const char *line, const char *prefix) {
+    int len = strlen(prefix);
+    return strncmp(line, prefix, len) == 0;
+}
+
+static const char *hostPort;
+static int verbose = 0;
+
+void processline(char *line) {
+    int rc;
+    int async = ((line[0] == 'a') && !(startsWith(line, "addauth ")));
+    if (async) {
+        line++;
+    }
+    if (startsWith(line, "help")) {
+      fprintf(stderr, "    create [+[e|s]] <path>\n");
+      fprintf(stderr, "    create2 [+[e|s]] <path>\n");
+      fprintf(stderr, "    delete <path>\n");
+      fprintf(stderr, "    set <path> <data>\n");
+      fprintf(stderr, "    get <path>\n");
+      fprintf(stderr, "    ls <path>\n");
+      fprintf(stderr, "    ls2 <path>\n");
+      fprintf(stderr, "    sync <path>\n");
+      fprintf(stderr, "    exists <path>\n");
+      fprintf(stderr, "    wexists <path>\n");
+      fprintf(stderr, "    myid\n");
+      fprintf(stderr, "    verbose\n");
+      fprintf(stderr, "    addauth <id> <scheme>\n");
+      fprintf(stderr, "    config\n");
+      fprintf(stderr, "    reconfig [-file <path> | -members <serverId=host:port1:port2;port3>,... | "
+                          " -add <serverId=host:port1:port2;port3>,... | -remove <serverId>,...] [-version <version>]\n");
+      fprintf(stderr, "    quit\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, "    prefix the command with the character 'a' to run the command asynchronously.\n");
+      fprintf(stderr, "    run the 'verbose' command to toggle verbose logging.\n");
+      fprintf(stderr, "    i.e. 'aget /foo' to get /foo asynchronously\n");
+    } else if (startsWith(line, "verbose")) {
+      if (verbose) {
+        verbose = 0;
+        zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
+        fprintf(stderr, "logging level set to WARN\n");
+      } else {
+        verbose = 1;
+        zoo_set_debug_level(ZOO_LOG_LEVEL_DEBUG);
+        fprintf(stderr, "logging level set to DEBUG\n");
+      }
+    } else if (startsWith(line, "get ")) {
+        line += 4;
+        if (line[0] != '/') {
+            fprintf(stderr, "Path must start with /, found: %s\n", line);
+            return;
+        }
+
+        rc = zoo_aget(zh, line, 1, my_data_completion, strdup(line));
+        if (rc) {
+            fprintf(stderr, "Error %d for %s\n", rc, line);
+        }
+    } else if (strcmp(line, "config") == 0) {
+       gettimeofday(&startTime, 0);
+        rc = zoo_agetconfig(zh, 1, my_data_completion, strdup(ZOO_CONFIG_NODE));
+        if (rc) {
+            fprintf(stderr, "Error %d for %s\n", rc, line);
+        }
+   } else if (startsWith(line, "reconfig ")) {
+           int syntaxError = 0;
+           char* p = NULL;
+           char* joining = NULL;
+           char* leaving = NULL;
+           char* members = NULL;
+           size_t members_size = 0;
+
+           int mode = 0; // 0 = not set, 1 = incremental, 2 = non-incremental
+           int64_t version = -1;
+
+           line += 9;
+           p = strtok (strdup(line)," ");
+           while (p != NULL) {
+               if (strcmp(p, "-add")==0) {
+                   p = strtok (NULL," ");
+                   if (mode == 2 || p == NULL) {
+                       syntaxError = 1;
+                       break;
+                   }
+                   mode = 1;
+                   joining = strdup(p);
+               } else if (strcmp(p, "-remove")==0){
+                   p = strtok (NULL," ");
+                   if (mode == 2 || p == NULL) {
+                       syntaxError = 1;
+                       break;
+                   }
+                   mode = 1;
+                   leaving = strdup(p);
+               } else if (strcmp(p, "-members")==0) {
+                   p = strtok (NULL," ");
+                   if (mode == 1 || p == NULL) {
+                       syntaxError = 1;
+                       break;
+                   }
+                   mode = 2;
+                   members = strdup(p);
+               } else if (strcmp(p, "-file")==0){
+                   FILE *fp = NULL;
+                   p = strtok (NULL," ");
+                   if (mode == 1 || p == NULL) {
+                       syntaxError = 1;
+                       break;
+                   }
+                   mode = 2;
+                   fp = fopen(p, "r");
+                   if (fp == NULL) {
+                       fprintf(stderr, "Error reading file: %s\n", p);
+                       syntaxError = 1;
+                       break;
+                   }
+                   fseek(fp, 0L, SEEK_END);  /* Position to end of file */
+                   members_size = ftell(fp);     /* Get file length */
+                   rewind(fp);               /* Back to start of file */
+                   members = calloc(members_size + 1, sizeof(char));
+                   if(members == NULL )
+                   {
+                       fprintf(stderr, "\nInsufficient memory to read file: %s\n", p);
+                       syntaxError = 1;
+                       fclose(fp);
+                       break;
+                   }
+
+                   /* Read the entire file into members
+                    * NOTE: -- fread returns number of items successfully read
+                    * not the number of bytes. We're requesting one item of
+                    * members_size bytes. So we expect the return value here
+                    * to be 1.
+                    */
+                   if (fread(members, members_size, 1, fp) != 1){
+                       fprintf(stderr, "Error reading file: %s\n", p);
+                       syntaxError = 1;
+                       fclose(fp);
+                        break;
+                   }
+                   fclose(fp);
+               } else if (strcmp(p, "-version")==0){
+                   p = strtok (NULL," ");
+                   if (version != -1 || p == NULL){
+                       syntaxError = 1;
+                       break;
+                   }
+#ifdef WIN32
+                   version = _strtoui64(p, NULL, 16);
+#else
+                   version = strtoull(p, NULL, 16);
+#endif
+                   if (version < 0) {
+                       syntaxError = 1;
+                       break;
+                   }
+               } else {
+                   syntaxError = 1;
+                   break;
+               }
+               p = strtok (NULL," ");
+           }
+           if (syntaxError) return;
+
+           rc = zoo_areconfig(zh, joining, leaving, members, version, my_data_completion, strdup(line));
+           free(joining);
+           free(leaving);
+           free(members);
+           if (rc) {
+               fprintf(stderr, "Error %d for %s\n", rc, line);
+           }
+
+   } else if (startsWith(line, "set ")) {
+        char *ptr;
+        line += 4;
+        if (line[0] != '/') {
+            fprintf(stderr, "Path must start with /, found: %s\n", line);
+            return;
+        }
+        ptr = strchr(line, ' ');
+        if (!ptr) {
+            fprintf(stderr, "No data found after path\n");
+            return;
+        }
+        *ptr = '\0';
+        ptr++;
+        rc = zoo_aset(zh, line, ptr, strlen(ptr), -1, my_stat_completion,
+                strdup(line));
+        if (rc) {
+            fprintf(stderr, "Error %d for %s\n", rc, line);
+        }
+    } else if (startsWith(line, "ls ")) {
+        line += 3;
+        if (line[0] != '/') {
+            fprintf(stderr, "Path must start with /, found: %s\n", line);
+            return;
+        }
+        gettimeofday(&startTime, 0);
+        rc= zoo_aget_children(zh, line, 1, my_strings_completion, strdup(line));
+        if (rc) {
+            fprintf(stderr, "Error %d for %s\n", rc, line);
+        }
+    } else if (startsWith(line, "ls2 ")) {
+        line += 4;
+        if (line[0] != '/') {
+            fprintf(stderr, "Path must start with /, found: %s\n", line);
+            return;
+        }
+        gettimeofday(&startTime, 0);
+        rc= zoo_aget_children2(zh, line, 1, my_strings_stat_completion, strdup(line));
+        if (rc) {
+            fprintf(stderr, "Error %d for %s\n", rc, line);
+        }
+    } else if (startsWith(line, "create ") || startsWith(line, "create2 ")) {
+        int flags = 0;
+        int is_create2 = startsWith(line, "create2 ");
+        line += is_create2 ? 8 : 7;
+        if (line[0] == '+') {
+            line++;
+            if (line[0] == 'e') {
+                flags |= ZOO_EPHEMERAL;
+                line++;
+            }
+            if (line[0] == 's') {
+                flags |= ZOO_SEQUENCE;
+                line++;
+            }
+            line++;
+        }
+        if (line[0] != '/') {
+            fprintf(stderr, "Path must start with /, found: %s\n", line);
+            return;
+        }
+        fprintf(stderr, "Creating [%s] node\n", line);
+//        {
+//            struct ACL _CREATE_ONLY_ACL_ACL[] = {{ZOO_PERM_CREATE, ZOO_ANYONE_ID_UNSAFE}};
+//            struct ACL_vector CREATE_ONLY_ACL = {1,_CREATE_ONLY_ACL_ACL};
+//            rc = zoo_acreate(zh, line, "new", 3, &CREATE_ONLY_ACL, flags,
+//                    my_string_completion, strdup(line));
+//        }
+        if (is_create2) {
+          rc = zoo_acreate2(zh, line, "new", 3, &ZOO_OPEN_ACL_UNSAFE, flags,
+                my_string_stat_completion_free_data, strdup(line));
+        } else {
+          rc = zoo_acreate(zh, line, "new", 3, &ZOO_OPEN_ACL_UNSAFE, flags,
+                my_string_completion_free_data, strdup(line));
+        }
+        if (rc) {
+            fprintf(stderr, "Error %d for %s\n", rc, line);
+        }
+    } else if (startsWith(line, "delete ")) {
+        line += 7;
+        if (line[0] != '/') {
+            fprintf(stderr, "Path must start with /, found: %s\n", line);
+            return;
+        }
+        rc = zoo_adelete(zh, line, -1, my_void_completion, strdup(line));
+        if (rc) {
+            fprintf(stderr, "Error %d for %s\n", rc, line);
+        }
+    } else if (startsWith(line, "sync ")) {
+        line += 5;
+        if (line[0] != '/') {
+            fprintf(stderr, "Path must start with /, found: %s\n", line);
+            return;
+        }
+        rc = zoo_async(zh, line, my_string_completion_free_data, strdup(line));
+        if (rc) {
+            fprintf(stderr, "Error %d for %s\n", rc, line);
+        }
+    } else if (startsWith(line, "wexists ")) {
+#ifdef THREADED
+        struct Stat stat;
+#endif
+        line += 8;
+        if (line[0] != '/') {
+            fprintf(stderr, "Path must start with /, found: %s\n", line);
+            return;
+        }
+#ifndef THREADED
+        rc = zoo_awexists(zh, line, watcher, (void*) 0, my_stat_completion, strdup(line));
+#else
+        rc = zoo_wexists(zh, line, watcher, (void*) 0, &stat);
+#endif
+        if (rc) {
+            fprintf(stderr, "Error %d for %s\n", rc, line);
+        }
+    } else if (startsWith(line, "exists ")) {
+#ifdef THREADED
+        struct Stat stat;
+#endif
+        line += 7;
+        if (line[0] != '/') {
+            fprintf(stderr, "Path must start with /, found: %s\n", line);
+            return;
+        }
+#ifndef THREADED
+        rc = zoo_aexists(zh, line, 1, my_stat_completion, strdup(line));
+#else
+        rc = zoo_exists(zh, line, 1, &stat);
+#endif
+        if (rc) {
+            fprintf(stderr, "Error %d for %s\n", rc, line);
+        }
+    } else if (strcmp(line, "myid") == 0) {
+        printf("session Id = %llx\n", _LL_CAST_ zoo_client_id(zh)->client_id);
+    } else if (strcmp(line, "reinit") == 0) {
+        zookeeper_close(zh);
+        // we can't send myid to the server here -- zookeeper_close() removes
+        // the session on the server. We must start anew.
+        zh = zookeeper_init(hostPort, watcher, 30000, 0, 0, 0);
+    } else if (startsWith(line, "quit")) {
+        fprintf(stderr, "Quitting...\n");
+        shutdownThisThing=1;
+    } else if (startsWith(line, "od")) {
+        const char val[]="fire off";
+        fprintf(stderr, "Overdosing...\n");
+        rc = zoo_aset(zh, "/od", val, sizeof(val)-1, -1, od_completion, 0);
+        if (rc)
+            fprintf(stderr, "od command failed: %d\n", rc);
+    } else if (startsWith(line, "addauth ")) {
+      char *ptr;
+      line += 8;
+      ptr = strchr(line, ' ');
+      if (ptr) {
+        *ptr = '\0';
+        ptr++;
+      }
+      zoo_add_auth(zh, line, ptr, ptr ? strlen(ptr) : 0, NULL, NULL);
+    }
+}
+
+int main(int argc, char **argv) {
+#ifndef THREADED
+    fd_set rfds, wfds, efds;
+    int processed=0;
+#endif
+    char buffer[4096];
+    char p[2048];
+#ifdef YCA
+    char *cert=0;
+    char appId[64];
+#endif
+    int bufoff = 0;
+    int flags, i;
+    FILE *fh;
+
+    if (argc < 2) {
+        fprintf(stderr,
+                "USAGE %s zookeeper_host_list [clientid_file|cmd:(ls|ls2|create|create2|od|...)]\n", 
+                argv[0]);
+        fprintf(stderr,
+                "Version: ZooKeeper cli (c client) version %d.%d.%d\n", 
+                ZOO_MAJOR_VERSION,
+                ZOO_MINOR_VERSION,
+                ZOO_PATCH_VERSION);
+        return 2;
+    }
+    if (argc > 2) {
+      if(strncmp("cmd:",argv[2],4)==0){
+        size_t cmdlen = strlen(argv[2]);
+        if (cmdlen > sizeof(cmd)) {
+          fprintf(stderr,
+                  "Command length %zu exceeds max length of %zu\n",
+                  cmdlen,
+                  sizeof(cmd));
+          return 2;
+        }
+        strncpy(cmd, argv[2]+4, sizeof(cmd));
+        batchMode=1;
+        fprintf(stderr,"Batch mode: %s\n",cmd);
+      }else{
+        clientIdFile = argv[2];
+        fh = fopen(clientIdFile, "r");
+        if (fh) {
+            if (fread(&myid, sizeof(myid), 1, fh) != sizeof(myid)) {
+                memset(&myid, 0, sizeof(myid));
+            }
+            fclose(fh);
+        }
+      }
+    }
+
+    flags = 0;
+    for (i = 1; i < argc; ++i) {
+      if (strcmp("-r", argv[i]) == 0) {
+        flags = ZOO_READONLY;
+        break;
+      }
+    }
+
+#ifdef YCA
+    strcpy(appId,"yahoo.example.yca_test");
+    cert = yca_get_cert_once(appId);
+    if(cert!=0) {
+        fprintf(stderr,"Certificate for appid [%s] is [%s]\n",appId,cert);
+        strncpy(p,cert,sizeof(p)-1);
+        free(cert);
+    } else {
+      fprintf(stderr,"Certificate for appid [%s] not found\n",appId);
+      strcpy(p,"dummy");
+    }
+#else
+    strcpy(p, "dummy");
+#endif
+    verbose = 0;
+    zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
+    zoo_deterministic_conn_order(1); // enable deterministic order
+    hostPort = argv[1];
+    zh = zookeeper_init(hostPort, watcher, 30000, &myid, NULL, flags);
+    if (!zh) {
+        return errno;
+    }
+
+#ifdef YCA
+    if(zoo_add_auth(zh,"yca",p,strlen(p),0,0)!=ZOK)
+    return 2;
+#endif
+
+#ifdef THREADED
+    while(!shutdownThisThing) {
+        int rc;
+        int len = sizeof(buffer) - bufoff -1;
+        if (len <= 0) {
+            fprintf(stderr, "Can't handle lines that long!\n");
+            exit(2);
+        }
+        rc = read(0, buffer+bufoff, len);
+        if (rc <= 0) {
+            fprintf(stderr, "bye\n");
+            shutdownThisThing=1;
+            break;
+        }
+        bufoff += rc;
+        buffer[bufoff] = '\0';
+        while (strchr(buffer, '\n')) {
+            char *ptr = strchr(buffer, '\n');
+            *ptr = '\0';
+            processline(buffer);
+            ptr++;
+            memmove(buffer, ptr, strlen(ptr)+1);
+            bufoff = 0;
+        }
+    }
+#else
+    FD_ZERO(&rfds);
+    FD_ZERO(&wfds);
+    FD_ZERO(&efds);
+    while (!shutdownThisThing) {
+        int fd;
+        int interest;
+        int events;
+        struct timeval tv;
+        int rc;
+        zookeeper_interest(zh, &fd, &interest, &tv);
+        if (fd != -1) {
+            if (interest&ZOOKEEPER_READ) {
+                FD_SET(fd, &rfds);
+            } else {
+                FD_CLR(fd, &rfds);
+            }
+            if (interest&ZOOKEEPER_WRITE) {
+                FD_SET(fd, &wfds);
+            } else {
+                FD_CLR(fd, &wfds);
+            }
+        } else {
+            fd = 0;
+        }
+        FD_SET(0, &rfds);
+        rc = select(fd+1, &rfds, &wfds, &efds, &tv);
+        events = 0;
+        if (rc > 0) {
+            if (FD_ISSET(fd, &rfds)) {
+                events |= ZOOKEEPER_READ;
+            }
+            if (FD_ISSET(fd, &wfds)) {
+                events |= ZOOKEEPER_WRITE;
+            }
+        }
+        if(batchMode && processed==0){
+          //batch mode
+          processline(cmd);
+          processed=1;
+        }
+        if (!processed && FD_ISSET(0, &rfds)) {
+            int rc;
+            int len = sizeof(buffer) - bufoff -1;
+            if (len <= 0) {
+                fprintf(stderr, "Can't handle lines that long!\n");
+                exit(2);
+            }
+            rc = read(0, buffer+bufoff, len);
+            if (rc <= 0) {
+                fprintf(stderr, "bye\n");
+                break;
+            }
+            bufoff += rc;
+            buffer[bufoff] = '\0';
+            while (strchr(buffer, '\n')) {
+                char *ptr = strchr(buffer, '\n');
+                *ptr = '\0';
+                processline(buffer);
+                ptr++;
+                memmove(buffer, ptr, strlen(ptr)+1);
+                bufoff = 0;
+            }
+        }
+        zookeeper_process(zh, events);
+    }
+#endif
+    if (to_send!=0)
+        fprintf(stderr,"Recvd %d responses for %d requests sent\n",recvd,sent);
+    zookeeper_close(zh);
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/8c87cc49/zookeeper-client/zookeeper-client-c/src/hashtable/LICENSE.txt
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/hashtable/LICENSE.txt b/zookeeper-client/zookeeper-client-c/src/hashtable/LICENSE.txt
new file mode 100644
index 0000000..674a624
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/hashtable/LICENSE.txt
@@ -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.

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/8c87cc49/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable.c
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable.c b/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable.c
new file mode 100644
index 0000000..caa5f6c
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable.c
@@ -0,0 +1,274 @@
+/* Copyright (C) 2004 Christopher Clark <firstname.lastname@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, hashvalue);
+    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.
+*/

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/8c87cc49/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable.h b/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable.h
new file mode 100644
index 0000000..cbead18
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable.h
@@ -0,0 +1,209 @@
+/* Copyright (C) 2002 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
+
+#ifndef __HASHTABLE_CWC22_H__
+#define __HASHTABLE_CWC22_H__
+#ifdef WIN32
+#include "winconfig.h"
+#endif
+#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.
+*/

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/8c87cc49/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable_itr.c
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable_itr.c b/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable_itr.c
new file mode 100644
index 0000000..defac69
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable_itr.c
@@ -0,0 +1,176 @@
+/* Copyright (C) 2002, 2004 Christopher Clark  <firstname.lastname@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;
+}
+
+/*****************************************************************************/
+/* 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.
+*/

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/8c87cc49/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable_itr.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable_itr.h b/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable_itr.h
new file mode 100644
index 0000000..30379c7
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable_itr.h
@@ -0,0 +1,119 @@
+/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@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 */
+
+static 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 */
+
+static 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.
+*/

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/8c87cc49/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable_private.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable_private.h b/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable_private.h
new file mode 100644
index 0000000..3e95f60
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/hashtable/hashtable_private.h
@@ -0,0 +1,85 @@
+/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@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.
+*/

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/8c87cc49/zookeeper-client/zookeeper-client-c/src/load_gen.c
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/load_gen.c b/zookeeper-client/zookeeper-client-c/src/load_gen.c
new file mode 100644
index 0000000..886fe1b
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/load_gen.c
@@ -0,0 +1,282 @@
+/**
+ * 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 <zookeeper.h>
+#include "zookeeper_log.h"
+#include <errno.h>
+#ifdef THREADED 
+#include <pthread.h>
+#endif
+#include <string.h>
+#include <stdlib.h>
+
+static zhandle_t *zh;
+
+static int shutdownThisThing=0;
+
+// *****************************************************************************
+//
+static pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_cond_t counterCond=PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t counterLock=PTHREAD_MUTEX_INITIALIZER;
+static int counter; 
+
+
+
+void ensureConnected(){
+    pthread_mutex_lock(&lock);
+    while (zoo_state(zh)!=ZOO_CONNECTED_STATE) {
+        pthread_cond_wait(&cond,&lock);
+    }
+    pthread_mutex_unlock(&lock);
+}
+
+void incCounter(int delta){
+    pthread_mutex_lock(&counterLock);
+    counter+=delta;
+    pthread_cond_broadcast(&counterCond);
+    pthread_mutex_unlock(&counterLock);        
+    
+}
+void setCounter(int cnt){
+    pthread_mutex_lock(&counterLock);
+    counter=cnt;
+    pthread_cond_broadcast(&counterCond);
+    pthread_mutex_unlock(&counterLock);        
+    
+}
+void waitCounter(){
+    pthread_mutex_lock(&counterLock);
+    while (counter>0) {
+        pthread_cond_wait(&counterCond,&counterLock);
+    }
+    pthread_mutex_unlock(&counterLock);    
+}
+
+void listener(zhandle_t *zzh, int type, int state, const char *path,void* ctx) {
+    if (type == ZOO_SESSION_EVENT) {
+        if (state == ZOO_CONNECTED_STATE || state == ZOO_READONLY_STATE) {
+            pthread_mutex_lock(&lock);
+            pthread_cond_broadcast(&cond);
+            pthread_mutex_unlock(&lock);
+        }
+        setCounter(0);
+    }
+}
+
+void create_completion(int rc, const char *name, const void *data) {
+    incCounter(-1);
+    if(rc!=ZOK){
+        LOG_ERROR(LOGSTREAM, "Failed to create a node rc=%d",rc);
+    }
+}
+
+int doCreateNodes(const char* root, int count){
+    char nodeName[1024];
+    int i;
+    for(i=0; i<count;i++){
+        int rc = 0;
+        snprintf(nodeName, sizeof(nodeName),"%s/%d",root,i);
+        incCounter(1);
+        rc=zoo_acreate(zh, nodeName, "first", 5, &ZOO_OPEN_ACL_UNSAFE, 0,
+                            create_completion, 0);
+        if(i%1000==0){
+            LOG_INFO(LOGSTREAM, "Created %s", nodeName);
+        }
+        if(rc!=ZOK) return rc;        
+    }
+    return ZOK;
+}
+
+int createRoot(const char* root){
+    char realpath[1024];
+    return zoo_create(zh,root,"root",4,&ZOO_OPEN_ACL_UNSAFE,0,realpath,sizeof(realpath)-1);
+}
+
+void write_completion(int rc, const struct Stat *stat, const void *data) {
+    incCounter(-1);
+    if(rc!=ZOK){
+        LOG_ERROR(LOGSTREAM, "Failed to write a node rc=%d",rc);
+    }
+}
+
+int doWrites(const char* root, int count){
+    char nodeName[1024];
+    int i;
+    counter=0;
+    for(i=0; i<count;i++){
+        int rc = 0;
+        snprintf(nodeName, sizeof(nodeName),"%s/%d",root,i);
+        incCounter(1);
+        rc=zoo_aset(zh, nodeName, "second", 6,-1,write_completion, 0);
+        if(rc!=ZOK) return rc;        
+    }
+    return ZOK;
+}
+
+void read_completion(int rc, const char *value, int value_len,
+        const struct Stat *stat, const void *data) {
+    incCounter(-1);    
+    if(rc!=ZOK){
+        LOG_ERROR(LOGSTREAM, "Failed to read a node rc=%d",rc);
+        return;
+    }
+    if(memcmp(value,"second",6)!=0){
+        char buf[value_len+1];
+        memcpy(buf,value,value_len);buf[value_len]=0;
+        LOG_ERROR(LOGSTREAM, "Invalid read, expected [second], received [%s]\n",buf);
+        exit(1);
+    }
+}
+
+int doReads(const char* root, int count){
+    char nodeName[1024];
+    int i;
+    counter=0;
+    for(i=0; i<count;i++){
+        int rc = 0;
+        snprintf(nodeName, sizeof(nodeName),"%s/%d",root,i);
+        incCounter(1);
+        rc=zoo_aget(zh, nodeName,0,read_completion, 0);
+        if(rc!=ZOK) return rc;        
+    }
+    return ZOK;
+}
+
+void delete_completion(int rc, const void *data) {
+    incCounter(-1);    
+}
+
+int doDeletes(const char* root, int count){
+    char nodeName[1024];
+    int i;
+    counter=0;
+    for(i=0; i<count;i++){
+        int rc = 0;
+        snprintf(nodeName, sizeof(nodeName),"%s/%d",root,i);
+        incCounter(1);
+        rc=zoo_adelete(zh, nodeName,-1,delete_completion, 0);
+        if(rc!=ZOK) return rc;        
+    }
+    return ZOK;
+}
+
+static int free_String_vector(struct String_vector *v) {
+    if (v->data) {
+        int32_t i;
+        for(i=0;i<v->count; i++) {
+            free(v->data[i]);
+        }
+        free(v->data);
+        v->data = 0;
+    }
+    return 0;
+}
+
+static int deletedCounter;
+
+int recursiveDelete(const char* root){
+    struct String_vector children;
+    int i;
+    int rc=zoo_get_children(zh,root,0,&children);
+    if(rc!=ZNONODE){
+        if(rc!=ZOK){
+            LOG_ERROR(LOGSTREAM, "Failed to get children of %s, rc=%d",root,rc);
+            return rc;
+        }
+        for(i=0;i<children.count; i++){
+            int rc = 0;
+            char nodeName[2048];
+            snprintf(nodeName, sizeof(nodeName),"%s/%s",root,children.data[i]);
+            rc=recursiveDelete(nodeName);
+            if(rc!=ZOK){
+                free_String_vector(&children);
+                return rc;
+            }
+        }
+        free_String_vector(&children);
+    }
+    if(deletedCounter%1000==0)
+        LOG_INFO(LOGSTREAM, "Deleting %s",root);
+    rc=zoo_delete(zh,root,-1);
+    if(rc!=ZOK){
+        LOG_ERROR(LOGSTREAM, "Failed to delete znode %s, rc=%d",root,rc);
+    }else
+        deletedCounter++;
+    return rc;
+}
+
+void usage(char *argv[]){
+    fprintf(stderr, "USAGE:\t%s zookeeper_host_list path #children\nor", argv[0]);
+    fprintf(stderr, "\t%s zookeeper_host_list path clean\n", argv[0]);
+    exit(0);
+}
+
+int main(int argc, char **argv) {
+    int nodeCount;
+    int cleaning=0;
+    if (argc < 4) {
+        usage(argv);
+    }
+    if(strcmp("clean",argv[3])==0){
+        cleaning=1;
+    }
+    zoo_set_debug_level(ZOO_LOG_LEVEL_INFO);
+    zoo_deterministic_conn_order(1); // enable deterministic order
+
+    zh = zookeeper_init(argv[1], listener, 10000, 0, 0, 0);
+    if (!zh)
+        return errno;
+
+    LOG_INFO(LOGSTREAM, "Checking server connection...");
+    ensureConnected();
+    if(cleaning==1){
+        int rc = 0;
+        deletedCounter=0;
+        rc=recursiveDelete(argv[2]);
+        if(rc==ZOK){
+            LOG_INFO(LOGSTREAM, "Successfully deleted a subtree starting at %s (%d nodes)",
+                    argv[2],deletedCounter);
+            exit(0);
+        }
+        exit(1);
+    }
+    nodeCount=atoi(argv[3]);
+    createRoot(argv[2]);
+    while(1) {
+        ensureConnected();
+        LOG_INFO(LOGSTREAM, "Creating children for path %s",argv[2]);
+        doCreateNodes(argv[2],nodeCount);
+        waitCounter();
+        
+        LOG_INFO(LOGSTREAM, "Starting the write cycle for path %s",argv[2]);
+        doWrites(argv[2],nodeCount);
+        waitCounter();
+        LOG_INFO(LOGSTREAM, "Starting the read cycle for path %s",argv[2]);
+        doReads(argv[2],nodeCount);
+        waitCounter();
+
+        LOG_INFO(LOGSTREAM, "Starting the delete cycle for path %s",argv[2]);
+        doDeletes(argv[2],nodeCount);
+        waitCounter();
+    }
+    zookeeper_close(zh);
+    return 0;
+}


Mime
View raw message