You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by an...@apache.org on 2018/08/21 05:31:08 UTC
[08/22] zookeeper git commit: ZOOKEEPER-3031: MAVEN MIGRATION - Step
1.4 - move client dir
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/176bd682/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/176bd682/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..1633cab
--- /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 6
+#define ZOO_PATCH_VERSION 0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZOOKEEPER_VERSION_H_ */
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/176bd682/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/176bd682/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/176bd682/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/176bd682/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/176bd682/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 <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, 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/176bd682/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 <fi...@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/176bd682/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 <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;
+}
+
+/*****************************************************************************/
+/* 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/176bd682/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 <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 */
+
+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/176bd682/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 <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.
+*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/176bd682/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;
+}