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/23 14:11:53 UTC
[01/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Repository: zookeeper
Updated Branches:
refs/heads/branch-3.4 f90e4a4de -> 5694559d7
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/TestZookeeperInit.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/TestZookeeperInit.cc b/zookeeper-client/zookeeper-client-c/tests/TestZookeeperInit.cc
new file mode 100644
index 0000000..eadf41d
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/TestZookeeperInit.cc
@@ -0,0 +1,301 @@
+/**
+ * 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 <cppunit/extensions/HelperMacros.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <errno.h>
+
+#include "Util.h"
+#include "LibCMocks.h"
+#include "ZKMocks.h"
+
+#ifdef THREADED
+#include "PthreadMocks.h"
+#else
+class MockPthreadsNull;
+#endif
+
+using namespace std;
+
+class Zookeeper_init : public CPPUNIT_NS::TestFixture
+{
+ CPPUNIT_TEST_SUITE(Zookeeper_init);
+ CPPUNIT_TEST(testBasic);
+ CPPUNIT_TEST(testAddressResolution);
+ CPPUNIT_TEST(testMultipleAddressResolution);
+ CPPUNIT_TEST(testNullAddressString);
+ CPPUNIT_TEST(testEmptyAddressString);
+ CPPUNIT_TEST(testOneSpaceAddressString);
+ CPPUNIT_TEST(testTwoSpacesAddressString);
+ CPPUNIT_TEST(testInvalidAddressString1);
+ CPPUNIT_TEST(testInvalidAddressString2);
+ CPPUNIT_TEST(testNonexistentHost);
+ CPPUNIT_TEST(testOutOfMemory_init);
+ CPPUNIT_TEST(testOutOfMemory_getaddrs1);
+#if !defined(__CYGWIN__) // not valid for cygwin
+ CPPUNIT_TEST(testOutOfMemory_getaddrs2);
+#endif
+ CPPUNIT_TEST(testPermuteAddrsList);
+ CPPUNIT_TEST_SUITE_END();
+ zhandle_t *zh;
+ MockPthreadsNull* pthreadMock;
+ static void watcher(zhandle_t *, int , int , const char *,void*){}
+ FILE *logfile;
+public:
+ Zookeeper_init():zh(0),pthreadMock(0){
+ logfile = openlogfile("Zookeeper_init");
+ }
+
+ ~Zookeeper_init() {
+ if (logfile) {
+ fflush(logfile);
+ fclose(logfile);
+ logfile = 0;
+ }
+ }
+
+ void setUp()
+ {
+ zoo_set_log_stream(logfile);
+
+ zoo_deterministic_conn_order(0);
+#ifdef THREADED
+ // disable threading
+ pthreadMock=new MockPthreadZKNull;
+#endif
+ zh=0;
+ }
+
+ void tearDown()
+ {
+ zookeeper_close(zh);
+#ifdef THREADED
+ delete pthreadMock;
+#endif
+ }
+
+ void testBasic()
+ {
+ const string EXPECTED_HOST("127.0.0.1:2121");
+ const int EXPECTED_ADDRS_COUNT =1;
+ const int EXPECTED_RECV_TIMEOUT=10000;
+ clientid_t cid;
+ memset(&cid,0xFE,sizeof(cid));
+
+ zh=zookeeper_init(EXPECTED_HOST.c_str(),watcher,EXPECTED_RECV_TIMEOUT,
+ &cid,(void*)1,0);
+
+ CPPUNIT_ASSERT(zh!=0);
+ CPPUNIT_ASSERT(zh->fd == -1);
+ CPPUNIT_ASSERT(zh->hostname!=0);
+ CPPUNIT_ASSERT_EQUAL(EXPECTED_ADDRS_COUNT,zh->addrs_count);
+ CPPUNIT_ASSERT_EQUAL(EXPECTED_HOST,string(zh->hostname));
+ CPPUNIT_ASSERT(zh->state == NOTCONNECTED_STATE_DEF);
+ CPPUNIT_ASSERT(zh->context == (void*)1);
+ CPPUNIT_ASSERT_EQUAL(EXPECTED_RECV_TIMEOUT,zh->recv_timeout);
+ CPPUNIT_ASSERT(zh->watcher == watcher);
+ CPPUNIT_ASSERT(zh->connect_index==0);
+ CPPUNIT_ASSERT(zh->primer_buffer.buffer==zh->primer_storage_buffer);
+ CPPUNIT_ASSERT(zh->primer_buffer.curr_offset ==0);
+ CPPUNIT_ASSERT(zh->primer_buffer.len == sizeof(zh->primer_storage_buffer));
+ CPPUNIT_ASSERT(zh->primer_buffer.next == 0);
+ CPPUNIT_ASSERT(zh->last_zxid ==0);
+ CPPUNIT_ASSERT(memcmp(&zh->client_id,&cid,sizeof(cid))==0);
+
+#ifdef THREADED
+ // thread specific checks
+ adaptor_threads* adaptor=(adaptor_threads*)zh->adaptor_priv;
+ CPPUNIT_ASSERT(adaptor!=0);
+ CPPUNIT_ASSERT(pthreadMock->pthread_createCounter==2);
+ CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(adaptor->io));
+ CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(adaptor->completion));
+ CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(&zh->to_process.lock));
+ CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(&zh->to_send.lock));
+ CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(&zh->sent_requests.lock));
+ CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(&zh->completions_to_process.lock));
+ CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(&zh->sent_requests.cond));
+ CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(&zh->completions_to_process.cond));
+#endif
+ }
+ void testAddressResolution()
+ {
+ const char EXPECTED_IPS[][4]={{127,0,0,1}};
+ const int EXPECTED_ADDRS_COUNT =COUNTOF(EXPECTED_IPS);
+
+ zoo_deterministic_conn_order(1);
+ zh=zookeeper_init("127.0.0.1:2121",0,10000,0,0,0);
+
+ CPPUNIT_ASSERT(zh!=0);
+ CPPUNIT_ASSERT_EQUAL(EXPECTED_ADDRS_COUNT,zh->addrs_count);
+ for(int i=0;i<zh->addrs_count;i++){
+ sockaddr_in* addr=(struct sockaddr_in*)&zh->addrs[i];
+ CPPUNIT_ASSERT(memcmp(EXPECTED_IPS[i],&addr->sin_addr,sizeof(addr->sin_addr))==0);
+ CPPUNIT_ASSERT_EQUAL(2121,(int)ntohs(addr->sin_port));
+ }
+ }
+ void testMultipleAddressResolution()
+ {
+ const string EXPECTED_HOST("127.0.0.1:2121,127.0.0.2:3434");
+ const char EXPECTED_IPS[][4]={{127,0,0,1},{127,0,0,2}};
+ const int EXPECTED_ADDRS_COUNT =COUNTOF(EXPECTED_IPS);
+
+ zoo_deterministic_conn_order(1);
+ zh=zookeeper_init(EXPECTED_HOST.c_str(),0,1000,0,0,0);
+
+ CPPUNIT_ASSERT(zh!=0);
+ CPPUNIT_ASSERT_EQUAL(EXPECTED_ADDRS_COUNT,zh->addrs_count);
+
+ for(int i=0;i<zh->addrs_count;i++){
+ sockaddr_in* addr=(struct sockaddr_in*)&zh->addrs[i];
+ CPPUNIT_ASSERT(memcmp(EXPECTED_IPS[i],&addr->sin_addr,sizeof(addr->sin_addr))==0);
+ if(i<1)
+ CPPUNIT_ASSERT_EQUAL(2121,(int)ntohs(addr->sin_port));
+ else
+ CPPUNIT_ASSERT_EQUAL(3434,(int)ntohs(addr->sin_port));
+ }
+ }
+ void testMultipleAddressWithSpace()
+ {
+ const string EXPECTED_HOST("127.0.0.1:2121, 127.0.0.2:3434");
+ const char EXPECTED_IPS[][4]={{127,0,0,1},{127,0,0,2}};
+ const int EXPECTED_ADDRS_COUNT =COUNTOF(EXPECTED_IPS);
+
+ zoo_deterministic_conn_order(1);
+ zh=zookeeper_init(EXPECTED_HOST.c_str(),0,1000,0,0,0);
+
+ CPPUNIT_ASSERT(zh!=0);
+ CPPUNIT_ASSERT_EQUAL(EXPECTED_ADDRS_COUNT,zh->addrs_count);
+
+ for(int i=0;i<zh->addrs_count;i++){
+ sockaddr_in* addr=(struct sockaddr_in*)&zh->addrs[i];
+ CPPUNIT_ASSERT(memcmp(EXPECTED_IPS[i],&addr->sin_addr,sizeof(addr->sin_addr))==0);
+ if(i<1)
+ CPPUNIT_ASSERT_EQUAL(2121,(int)ntohs(addr->sin_port));
+ else
+ CPPUNIT_ASSERT_EQUAL(3434,(int)ntohs(addr->sin_port));
+ }
+ }
+ void testNullAddressString()
+ {
+ zh=zookeeper_init(NULL,0,0,0,0,0);
+ CPPUNIT_ASSERT(zh==0);
+ CPPUNIT_ASSERT_EQUAL(EINVAL,errno);
+ }
+ void testEmptyAddressString()
+ {
+ const string INVALID_HOST("");
+ zh=zookeeper_init(INVALID_HOST.c_str(),0,0,0,0,0);
+ CPPUNIT_ASSERT(zh==0);
+ CPPUNIT_ASSERT_EQUAL(EINVAL,errno);
+ }
+ void testOneSpaceAddressString()
+ {
+ const string INVALID_HOST(" ");
+ zh=zookeeper_init(INVALID_HOST.c_str(),0,0,0,0,0);
+ CPPUNIT_ASSERT(zh==0);
+ CPPUNIT_ASSERT_EQUAL(EINVAL,errno);
+ }
+ void testTwoSpacesAddressString()
+ {
+ const string INVALID_HOST(" ");
+ zh=zookeeper_init(INVALID_HOST.c_str(),0,0,0,0,0);
+ CPPUNIT_ASSERT(zh==0);
+ CPPUNIT_ASSERT_EQUAL(EINVAL,errno);
+ }
+ void testInvalidAddressString1()
+ {
+ const string INVALID_HOST("host1");
+ zh=zookeeper_init(INVALID_HOST.c_str(),0,0,0,0,0);
+ CPPUNIT_ASSERT(zh==0);
+ CPPUNIT_ASSERT_EQUAL(EINVAL,errno);
+ }
+ void testInvalidAddressString2()
+ {
+ const string INVALID_HOST("host1:1111+host:123");
+ zh=zookeeper_init(INVALID_HOST.c_str(),0,0,0,0,0);
+ CPPUNIT_ASSERT(zh==0);
+ CPPUNIT_ASSERT((ENOENT|EINVAL) & errno);
+ }
+ void testNonexistentHost()
+ {
+ const string EXPECTED_HOST("host1.blabadibla.bla.:1111");
+
+ zh=zookeeper_init(EXPECTED_HOST.c_str(),0,0,0,0,0);
+
+ CPPUNIT_ASSERT(zh==0);
+ //With the switch to thread safe getaddrinfo, we don't get
+ //these global variables
+ //CPPUNIT_ASSERT_EQUAL(EINVAL,errno);
+ //CPPUNIT_ASSERT_EQUAL(HOST_NOT_FOUND,h_errno);
+ }
+ void testOutOfMemory_init()
+ {
+ Mock_calloc mock;
+ mock.callsBeforeFailure=0; // fail first calloc in init()
+
+ zh=zookeeper_init("ahost:123",watcher,10000,0,0,0);
+
+ CPPUNIT_ASSERT(zh==0);
+ CPPUNIT_ASSERT_EQUAL(ENOMEM,errno);
+ }
+ void testOutOfMemory_getaddrs1()
+ {
+ Mock_realloc reallocMock;
+ reallocMock.callsBeforeFailure=0; // fail on first call to realloc
+
+ zh=zookeeper_init("127.0.0.1:123",0,0,0,0,0);
+
+ CPPUNIT_ASSERT(zh==0);
+ CPPUNIT_ASSERT_EQUAL(ENOMEM,errno);
+ }
+ void testOutOfMemory_getaddrs2()
+ {
+ Mock_realloc reallocMock;
+ reallocMock.callsBeforeFailure=1; // fail on the second call to realloc
+
+ zh=zookeeper_init("127.0.0.1:123,127.0.0.2:123,127.0.0.3:123,127.0.0.4:123,127.0.0.5:123,127.0.0.6:123,127.0.0.7:123,127.0.0.8:123,127.0.0.9:123,127.0.0.10:123,127.0.0.11:123,127.0.0.12:123,127.0.0.13:123,127.0.0.14:123,127.0.0.15:123,127.0.0.16:123,127.0.0.17:123",0,0,0,0,0);
+
+ CPPUNIT_ASSERT(zh==0);
+ CPPUNIT_ASSERT_EQUAL(ENOMEM,errno);
+ }
+ void testPermuteAddrsList()
+ {
+ const char EXPECTED[][5]={"\0\0\0\0","\1\1\1\1","\2\2\2\2","\3\3\3\3"};
+ const int EXPECTED_ADDR_COUNT=COUNTOF(EXPECTED);
+
+ const int RAND_SEQ[]={0,1,1,-1};
+ const int RAND_SIZE=COUNTOF(RAND_SEQ);
+ Mock_random randomMock;
+ randomMock.randomReturns.assign(RAND_SEQ,RAND_SEQ+RAND_SIZE-1);
+ zh=zookeeper_init("0.0.0.0:123,1.1.1.1:123,2.2.2.2:123,3.3.3.3:123",0,1000,0,0,0);
+
+ CPPUNIT_ASSERT(zh!=0);
+ CPPUNIT_ASSERT_EQUAL(EXPECTED_ADDR_COUNT,zh->addrs_count);
+ const string EXPECTED_SEQ("3210");
+ char ACTUAL_SEQ[EXPECTED_ADDR_COUNT+1]; ACTUAL_SEQ[EXPECTED_ADDR_COUNT]=0;
+ for(int i=0;i<zh->addrs_count;i++){
+ sockaddr_in* addr=(struct sockaddr_in*)&zh->addrs[i];
+ // match the first byte of the EXPECTED and of the actual address
+ ACTUAL_SEQ[i]=((char*)&addr->sin_addr)[0]+'0';
+ }
+ CPPUNIT_ASSERT_EQUAL(EXPECTED_SEQ,string(ACTUAL_SEQ));
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_init);
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/ThreadingUtil.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/ThreadingUtil.cc b/zookeeper-client/zookeeper-client-c/tests/ThreadingUtil.cc
new file mode 100644
index 0000000..3b5170a
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/ThreadingUtil.cc
@@ -0,0 +1,87 @@
+/**
+ * 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 <sys/types.h>
+#include "ThreadingUtil.h"
+#include "LibCSymTable.h"
+
+#ifdef THREADED
+
+// ****************************************************************************
+// Mutex wrapper
+struct Mutex::Impl{
+ Impl(){
+ LIBC_SYMBOLS.pthread_mutex_init(&mut_, 0);
+ }
+ ~Impl(){
+ LIBC_SYMBOLS.pthread_mutex_destroy(&mut_);
+ }
+ pthread_mutex_t mut_;
+};
+
+Mutex::Mutex():impl_(new Impl) {}
+Mutex::~Mutex() { delete impl_;}
+void Mutex::acquire() {
+ LIBC_SYMBOLS.pthread_mutex_lock(&impl_->mut_);
+}
+void Mutex::release() {
+ LIBC_SYMBOLS.pthread_mutex_unlock(&impl_->mut_);
+}
+
+// ****************************************************************************
+// Atomics
+int32_t atomic_post_incr(volatile int32_t* operand, int32_t incr)
+{
+#if defined(__GNUC__)
+ return __sync_fetch_and_add(operand,incr);
+#else
+ int32_t result;
+ __asm__ __volatile__(
+ "lock xaddl %0,%1\n"
+ : "=r"(result), "=m"(*operand)
+ : "0"(incr)
+ : "memory");
+ return result;
+#endif
+}
+int32_t atomic_fetch_store(volatile int32_t *ptr, int32_t value)
+{
+#if defined(__GNUC__)
+ return __sync_lock_test_and_set(ptr,value);
+#else
+ int32_t result;
+ __asm__ __volatile__("lock xchgl %0,%1\n"
+ : "=r"(result), "=m"(*ptr)
+ : "0"(value)
+ : "memory");
+ return result;
+#endif
+}
+#else
+int32_t atomic_post_incr(volatile int32_t* operand, int32_t incr){
+ int32_t v=*operand;
+ *operand+=incr;
+ return v;
+}
+int32_t atomic_fetch_store(volatile int32_t *ptr, int32_t value)
+{
+ int32_t result=*ptr;
+ *ptr=value;
+ return result;
+}
+#endif // THREADED
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/ThreadingUtil.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/ThreadingUtil.h b/zookeeper-client/zookeeper-client-c/tests/ThreadingUtil.h
new file mode 100644
index 0000000..9165412
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/ThreadingUtil.h
@@ -0,0 +1,261 @@
+/**
+ * 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 THREADINGUTIL_H_
+#define THREADINGUTIL_H_
+
+#include <vector>
+
+#ifdef THREADED
+#include "pthread.h"
+#endif
+
+// *****************************************************************************
+// Threading primitives
+
+// atomic post-increment; returns the previous value of the operand
+int32_t atomic_post_incr(volatile int32_t* operand, int32_t incr);
+// atomic fetch&store; returns the previous value of the operand
+int32_t atomic_fetch_store(volatile int32_t *operand, int32_t value);
+
+// a partial implementation of an atomic integer type
+class AtomicInt{
+public:
+ explicit AtomicInt(int32_t init=0):v_(init){}
+ AtomicInt(const AtomicInt& other):v_(other){}
+ // assigment
+ AtomicInt& operator=(const AtomicInt& lhs){
+ atomic_fetch_store(&v_,lhs);
+ return *this;
+ }
+ AtomicInt& operator=(int32_t i){
+ atomic_fetch_store(&v_,i);
+ return *this;
+ }
+ // pre-increment
+ AtomicInt& operator++() {
+ atomic_post_incr(&v_,1);
+ return *this;
+ }
+ // pre-decrement
+ AtomicInt& operator--() {
+ atomic_post_incr(&v_,-1);
+ return *this;
+ }
+ // post-increment
+ AtomicInt operator++(int){
+ return AtomicInt(atomic_post_incr(&v_,1));
+ }
+ // post-decrement
+ AtomicInt operator--(int){
+ return AtomicInt(atomic_post_incr(&v_,-1));
+ }
+
+ operator int() const{
+ return atomic_post_incr(&v_,0);
+ }
+ int get() const{
+ return atomic_post_incr(&v_,0);
+ }
+private:
+ mutable int32_t v_;
+};
+
+#ifdef THREADED
+// ****************************************************************************
+#define VALIDATE_JOBS(jm) jm.validateJobs(__FILE__,__LINE__)
+#define VALIDATE_JOB(j) j.validate(__FILE__,__LINE__)
+
+class Mutex{
+public:
+ Mutex();
+ ~Mutex();
+ void acquire();
+ void release();
+private:
+ Mutex(const Mutex&);
+ Mutex& operator=(const Mutex&);
+ struct Impl;
+ Impl* impl_;
+};
+
+class MTLock{
+public:
+ MTLock(Mutex& m):m_(m){m.acquire();}
+ ~MTLock(){m_.release();}
+ Mutex& m_;
+};
+
+#define synchronized(m) MTLock __lock(m)
+
+// ****************************************************************************
+class Latch {
+public:
+ virtual ~Latch() {}
+ virtual void await() const =0;
+ virtual void signalAndWait() =0;
+ virtual void signal() =0;
+};
+
+class CountDownLatch: public Latch {
+public:
+ CountDownLatch(int count):count_(count) {
+ pthread_cond_init(&cond_,0);
+ pthread_mutex_init(&mut_,0);
+ }
+ virtual ~CountDownLatch() {
+ pthread_mutex_lock(&mut_);
+ if(count_!=0) {
+ count_=0;
+ pthread_cond_broadcast(&cond_);
+ }
+ pthread_mutex_unlock(&mut_);
+
+ pthread_cond_destroy(&cond_);
+ pthread_mutex_destroy(&mut_);
+ }
+
+ virtual void await() const {
+ pthread_mutex_lock(&mut_);
+ awaitImpl();
+ pthread_mutex_unlock(&mut_);
+ }
+ virtual void signalAndWait() {
+ pthread_mutex_lock(&mut_);
+ signalImpl();
+ awaitImpl();
+ pthread_mutex_unlock(&mut_);
+ }
+ virtual void signal() {
+ pthread_mutex_lock(&mut_);
+ signalImpl();
+ pthread_mutex_unlock(&mut_);
+ }
+private:
+ void awaitImpl() const{
+ while(count_!=0)
+ pthread_cond_wait(&cond_,&mut_);
+ }
+ void signalImpl() {
+ if(count_>0) {
+ count_--;
+ pthread_cond_broadcast(&cond_);
+ }
+ }
+ int count_;
+ mutable pthread_mutex_t mut_;
+ mutable pthread_cond_t cond_;
+};
+
+class TestJob {
+public:
+ typedef long JobId;
+ TestJob():hasRun_(false),startLatch_(0),endLatch_(0) {}
+ virtual ~TestJob() {
+ join();
+ }
+ virtual TestJob* clone() const =0;
+
+ virtual void run() =0;
+ virtual void validate(const char* file, int line) const =0;
+
+ virtual void start(Latch* startLatch=0,Latch* endLatch=0) {
+ startLatch_=startLatch;endLatch_=endLatch;
+ hasRun_=true;
+ pthread_create(&thread_, 0, thread, this);
+ }
+ virtual JobId getJobId() const {
+ return (JobId)thread_;
+ }
+ virtual void join() {
+ if(!hasRun_)
+ return;
+ if(!pthread_equal(thread_,pthread_self()))
+ pthread_join(thread_,0);
+ else
+ pthread_detach(thread_);
+ }
+private:
+ void awaitStart() {
+ if(startLatch_==0) return;
+ startLatch_->signalAndWait();
+ }
+ void signalFinished() {
+ if(endLatch_==0) return;
+ endLatch_->signal();
+ }
+ static void* thread(void* p) {
+ TestJob* j=(TestJob*)p;
+ j->awaitStart(); // wait for the start command
+ j->run();
+ j->signalFinished();
+ return 0;
+ }
+ bool hasRun_;
+ Latch* startLatch_;
+ Latch* endLatch_;
+ pthread_t thread_;
+};
+
+class TestJobManager {
+ typedef std::vector<TestJob*> JobList;
+public:
+ TestJobManager(const TestJob& tj,int threadCount=1):
+ startLatch_(threadCount),endLatch_(threadCount)
+ {
+ for(int i=0;i<threadCount;++i)
+ jobs_.push_back(tj.clone());
+ }
+ virtual ~TestJobManager(){
+ for(unsigned i=0;i<jobs_.size();++i)
+ delete jobs_[i];
+ }
+
+ virtual void startAllJobs() {
+ for(unsigned i=0;i<jobs_.size();++i)
+ jobs_[i]->start(&startLatch_,&endLatch_);
+ }
+ virtual void startJobsImmediately() {
+ for(unsigned i=0;i<jobs_.size();++i)
+ jobs_[i]->start(0,&endLatch_);
+ }
+ virtual void wait() const {
+ endLatch_.await();
+ }
+ virtual void validateJobs(const char* file, int line) const{
+ for(unsigned i=0;i<jobs_.size();++i)
+ jobs_[i]->validate(file,line);
+ }
+private:
+ JobList jobs_;
+ CountDownLatch startLatch_;
+ CountDownLatch endLatch_;
+};
+
+#else // THREADED
+// single THREADED
+class Mutex{
+public:
+ void acquire(){}
+ void release(){}
+};
+#define synchronized(m)
+
+#endif // THREADED
+
+#endif /*THREADINGUTIL_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/Util.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/Util.cc b/zookeeper-client/zookeeper-client-c/tests/Util.cc
new file mode 100644
index 0000000..2b9da84
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/Util.cc
@@ -0,0 +1,51 @@
+/**
+ * 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 "Util.h"
+#include "string.h"
+
+const std::string EMPTY_STRING;
+
+TestConfig globalTestConfig;
+
+void millisleep(int ms){
+ timespec ts;
+ ts.tv_sec=ms/1000;
+ ts.tv_nsec=(ms%1000)*1000000; // to nanoseconds
+ nanosleep(&ts,0);
+}
+
+FILE *openlogfile(const char* testname) {
+ char name[1024];
+ strcpy(name, "TEST-");
+ strncpy(name + 5, testname, sizeof(name) - 5);
+#ifdef THREADED
+ strcpy(name + strlen(name), "-mt.txt");
+#else
+ strcpy(name + strlen(name), "-st.txt");
+#endif
+
+ FILE *logfile = fopen(name, "a");
+
+ if (logfile == 0) {
+ fprintf(stderr, "Can't open log file %s!\n", name);
+ return 0;
+ }
+
+ return logfile;
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/Util.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/Util.h b/zookeeper-client/zookeeper-client-c/tests/Util.h
new file mode 100644
index 0000000..01e21ce
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/Util.h
@@ -0,0 +1,137 @@
+/**
+ * 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 UTIL_H_
+#define UTIL_H_
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include "zookeeper_log.h"
+
+// number of elements in array
+#define COUNTOF(array) sizeof(array)/sizeof(array[0])
+
+#define DECLARE_WRAPPER(ret,sym,sig) \
+ extern "C" ret __real_##sym sig; \
+ extern "C" ret __wrap_##sym sig
+
+#define CALL_REAL(sym,params) \
+ __real_##sym params
+
+// must include "src/zookeeper_log.h" to be able to use this macro
+#define TEST_TRACE(x) \
+ log_message(ZOO_LOG_LEVEL_DEBUG,__LINE__,__func__,format_log_message x)
+
+extern const std::string EMPTY_STRING;
+
+// *****************************************************************************
+// A bit of wizardry to get to the bare type from a reference or a pointer
+// to the type
+template <class T>
+struct TypeOp {
+ typedef T BareT;
+ typedef T ArgT;
+};
+
+// partial specialization for reference types
+template <class T>
+struct TypeOp<T&>{
+ typedef T& ArgT;
+ typedef typename TypeOp<T>::BareT BareT;
+};
+
+// partial specialization for pointers
+template <class T>
+struct TypeOp<T*>{
+ typedef T* ArgT;
+ typedef typename TypeOp<T>::BareT BareT;
+};
+
+// *****************************************************************************
+// Container utilities
+
+template <class K, class V>
+void putValue(std::map<K,V>& map,const K& k, const V& v){
+ typedef std::map<K,V> Map;
+ typename Map::const_iterator it=map.find(k);
+ if(it==map.end())
+ map.insert(typename Map::value_type(k,v));
+ else
+ map[k]=v;
+}
+
+template <class K, class V>
+bool getValue(const std::map<K,V>& map,const K& k,V& v){
+ typedef std::map<K,V> Map;
+ typename Map::const_iterator it=map.find(k);
+ if(it==map.end())
+ return false;
+ v=it->second;
+ return true;
+}
+
+// *****************************************************************************
+// misc utils
+
+// millisecond sleep
+void millisleep(int ms);
+FILE *openlogfile(const char* name);
+// evaluate given predicate until it returns true or the timeout
+// (in millis) has expired
+template<class Predicate>
+int ensureCondition(const Predicate& p,int timeout){
+ int elapsed=0;
+ while(!p() && elapsed<timeout){
+ millisleep(2);
+ elapsed+=2;
+ }
+ return elapsed;
+};
+
+// *****************************************************************************
+// test global configuration data
+class TestConfig{
+ typedef std::vector<std::string> CmdLineOptList;
+public:
+ typedef CmdLineOptList::const_iterator const_iterator;
+ TestConfig(){}
+ ~TestConfig(){}
+ void addConfigFromCmdLine(int argc, char* argv[]){
+ if(argc>=2)
+ testName_=argv[1];
+ for(int i=2; i<argc;++i)
+ cmdOpts_.push_back(argv[i]);
+ }
+ const_iterator getExtraOptBegin() const {return cmdOpts_.begin();}
+ const_iterator getExtraOptEnd() const {return cmdOpts_.end();}
+ size_t getExtraOptCount() const {
+ return cmdOpts_.size();
+ }
+ const std::string& getTestName() const {
+ return testName_=="all"?EMPTY_STRING:testName_;
+ }
+private:
+ CmdLineOptList cmdOpts_;
+ std::string testName_;
+};
+
+extern TestConfig globalTestConfig;
+
+#endif /*UTIL_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/Vector.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/Vector.h b/zookeeper-client/zookeeper-client-c/tests/Vector.h
new file mode 100644
index 0000000..d75fe07
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/Vector.h
@@ -0,0 +1,37 @@
+/**
+ * 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 _VECTOR_UTIL_H
+#define _VECTOR_UTIL_H
+
+#include <vector>
+
+// function to conveniently stream vectors
+template <class U>
+std::ostream& operator<<(std::ostream& os,const std::vector<U>& c){
+ typedef std::vector<U> V;
+ os<<"[";
+ if(c.size()>0){
+ for(typename V::const_iterator it=c.begin();it!=c.end();++it)
+ os<<*it<<",";
+ os.seekp(-1,std::ios::cur);
+ }
+ os<<"]";
+ return os;
+}
+
+#endif // _VECTOR_UTIL_H
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/ZKMocks.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/ZKMocks.cc b/zookeeper-client/zookeeper-client-c/tests/ZKMocks.cc
new file mode 100644
index 0000000..69bea16
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/ZKMocks.cc
@@ -0,0 +1,519 @@
+/**
+ * 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 <arpa/inet.h> // for htonl
+#include <memory>
+
+#include <zookeeper.h>
+#include <proto.h>
+
+#ifdef THREADED
+#include "PthreadMocks.h"
+#endif
+#include "ZKMocks.h"
+
+using namespace std;
+
+TestClientId testClientId;
+const char* TestClientId::PASSWD="1234567890123456";
+
+HandshakeRequest* HandshakeRequest::parse(const std::string& buf){
+ auto_ptr<HandshakeRequest> req(new HandshakeRequest);
+
+ memcpy(&req->protocolVersion,buf.data(), sizeof(req->protocolVersion));
+ req->protocolVersion = htonl(req->protocolVersion);
+
+ int offset=sizeof(req->protocolVersion);
+
+ memcpy(&req->lastZxidSeen,buf.data()+offset,sizeof(req->lastZxidSeen));
+ req->lastZxidSeen = zoo_htonll(req->lastZxidSeen);
+ offset+=sizeof(req->lastZxidSeen);
+
+ memcpy(&req->timeOut,buf.data()+offset,sizeof(req->timeOut));
+ req->timeOut = htonl(req->timeOut);
+ offset+=sizeof(req->timeOut);
+
+ memcpy(&req->sessionId,buf.data()+offset,sizeof(req->sessionId));
+ req->sessionId = zoo_htonll(req->sessionId);
+ offset+=sizeof(req->sessionId);
+
+ memcpy(&req->passwd_len,buf.data()+offset,sizeof(req->passwd_len));
+ req->passwd_len = htonl(req->passwd_len);
+ offset+=sizeof(req->passwd_len);
+
+ memcpy(req->passwd,buf.data()+offset,sizeof(req->passwd));
+ if(testClientId.client_id==req->sessionId &&
+ !memcmp(testClientId.passwd,req->passwd,sizeof(req->passwd)))
+ return req.release();
+ // the request didn't match -- may not be a handshake request after all
+ return 0;
+}
+
+// *****************************************************************************
+// watcher action implementation
+void activeWatcher(zhandle_t *zh, int type, int state, const char *path,void* ctx){
+ if(zh==0 || ctx==0) return;
+ WatcherAction* action=(WatcherAction*)ctx;
+
+ if(type==ZOO_SESSION_EVENT){
+ if(state==ZOO_EXPIRED_SESSION_STATE)
+ action->onSessionExpired(zh);
+ else if(state==ZOO_CONNECTING_STATE)
+ action->onConnectionLost(zh);
+ else if(state==ZOO_CONNECTED_STATE)
+ action->onConnectionEstablished(zh);
+ }else if(type==ZOO_CHANGED_EVENT)
+ action->onNodeValueChanged(zh,path);
+ else if(type==ZOO_DELETED_EVENT)
+ action->onNodeDeleted(zh,path);
+ else if(type==ZOO_CHILD_EVENT)
+ action->onChildChanged(zh,path);
+ // TODO: implement for the rest of the event types
+ // ...
+ action->setWatcherTriggered();
+}
+SyncedBoolCondition WatcherAction::isWatcherTriggered() const{
+ return SyncedBoolCondition(triggered_,mx_);
+}
+
+// *****************************************************************************
+// a set of async completion signatures
+void asyncCompletion(int rc, ACL_vector *acl,Stat *stat, const void *data){
+ assert("Completion data is NULL"&&data);
+ static_cast<AsyncCompletion*>((void*)data)->aclCompl(rc,acl,stat);
+}
+void asyncCompletion(int rc, const char *value, int len, const Stat *stat,
+ const void *data){
+ assert("Completion data is NULL"&&data);
+ static_cast<AsyncCompletion*>((void*)data)->dataCompl(rc,value,len,stat);
+}
+void asyncCompletion(int rc, const Stat *stat, const void *data){
+ assert("Completion data is NULL"&&data);
+ static_cast<AsyncCompletion*>((void*)data)->statCompl(rc,stat);
+}
+void asyncCompletion(int rc, const char *value, const void *data){
+ assert("Completion data is NULL"&&data);
+ static_cast<AsyncCompletion*>((void*)data)->stringCompl(rc,value);
+}
+void asyncCompletion(int rc,const String_vector *strings, const void *data){
+ assert("Completion data is NULL"&&data);
+ static_cast<AsyncCompletion*>((void*)data)->stringsCompl(rc,strings);
+}
+void asyncCompletion(int rc, const void *data){
+ assert("Completion data is NULL"&&data);
+ static_cast<AsyncCompletion*>((void*)data)->voidCompl(rc);
+}
+
+// *****************************************************************************
+// a predicate implementation
+bool IOThreadStopped::operator()() const{
+#ifdef THREADED
+ adaptor_threads* adaptor=(adaptor_threads*)zh_->adaptor_priv;
+ return CheckedPthread::isTerminated(adaptor->io);
+#else
+ assert("IOThreadStopped predicate is only for use with THREADED client"&& false);
+ return false;
+#endif
+}
+
+//******************************************************************************
+//
+DECLARE_WRAPPER(int,flush_send_queue,(zhandle_t*zh, int timeout))
+{
+ if(!Mock_flush_send_queue::mock_)
+ return CALL_REAL(flush_send_queue,(zh,timeout));
+ return Mock_flush_send_queue::mock_->call(zh,timeout);
+}
+
+Mock_flush_send_queue* Mock_flush_send_queue::mock_=0;
+
+//******************************************************************************
+//
+DECLARE_WRAPPER(int32_t,get_xid,())
+{
+ if(!Mock_get_xid::mock_)
+ return CALL_REAL(get_xid,());
+ return Mock_get_xid::mock_->call();
+}
+
+Mock_get_xid* Mock_get_xid::mock_=0;
+
+//******************************************************************************
+// activateWatcher mock
+
+DECLARE_WRAPPER(void,activateWatcher,(zhandle_t *zh, watcher_registration_t* reg, int rc))
+{
+ if(!Mock_activateWatcher::mock_){
+ CALL_REAL(activateWatcher,(zh, reg,rc));
+ }else{
+ Mock_activateWatcher::mock_->call(zh, reg,rc);
+ }
+}
+Mock_activateWatcher* Mock_activateWatcher::mock_=0;
+
+class ActivateWatcherWrapper: public Mock_activateWatcher{
+public:
+ ActivateWatcherWrapper():ctx_(0),activated_(false){}
+
+ virtual void call(zhandle_t *zh, watcher_registration_t* reg, int rc){
+ CALL_REAL(activateWatcher,(zh, reg,rc));
+ synchronized(mx_);
+ if(reg->context==ctx_){
+ activated_=true;
+ ctx_=0;
+ }
+ }
+
+ void setContext(void* ctx){
+ synchronized(mx_);
+ ctx_=ctx;
+ activated_=false;
+ }
+
+ SyncedBoolCondition isActivated() const{
+ return SyncedBoolCondition(activated_,mx_);
+ }
+ mutable Mutex mx_;
+ void* ctx_;
+ bool activated_;
+};
+
+WatcherActivationTracker::WatcherActivationTracker():
+ wrapper_(new ActivateWatcherWrapper)
+{
+}
+
+WatcherActivationTracker::~WatcherActivationTracker(){
+ delete wrapper_;
+}
+
+void WatcherActivationTracker::track(void* ctx){
+ wrapper_->setContext(ctx);
+}
+
+SyncedBoolCondition WatcherActivationTracker::isWatcherActivated() const{
+ return wrapper_->isActivated();
+}
+
+//******************************************************************************
+//
+DECLARE_WRAPPER(void,deliverWatchers,(zhandle_t* zh,int type,int state, const char* path, watcher_object_list_t **list))
+{
+ if(!Mock_deliverWatchers::mock_){
+ CALL_REAL(deliverWatchers,(zh,type,state,path, list));
+ }else{
+ Mock_deliverWatchers::mock_->call(zh,type,state,path, list);
+ }
+}
+
+Mock_deliverWatchers* Mock_deliverWatchers::mock_=0;
+
+struct RefCounterValue{
+ RefCounterValue(zhandle_t* const& zh,int32_t expectedCounter,Mutex& mx):
+ zh_(zh),expectedCounter_(expectedCounter),mx_(mx){}
+ bool operator()() const{
+ {
+ synchronized(mx_);
+ if(zh_==0)
+ return false;
+ }
+ return inc_ref_counter(zh_,0)==expectedCounter_;
+ }
+ zhandle_t* const& zh_;
+ int32_t expectedCounter_;
+ Mutex& mx_;
+};
+
+
+class DeliverWatchersWrapper: public Mock_deliverWatchers{
+public:
+ DeliverWatchersWrapper(int type,int state,bool terminate):
+ type_(type),state_(state),
+ allDelivered_(false),terminate_(terminate),zh_(0),deliveryCounter_(0){}
+ virtual void call(zhandle_t* zh,int type,int state, const char* path, watcher_object_list **list){
+ {
+ synchronized(mx_);
+ zh_=zh;
+ allDelivered_=false;
+ }
+ CALL_REAL(deliverWatchers,(zh,type,state,path, list));
+ if(type_==type && state_==state){
+ if(terminate_){
+ // prevent zhandle_t from being prematurely distroyed;
+ // this will also ensure that zookeeper_close() cleanups the thread
+ // resources by calling finish_adaptor()
+ inc_ref_counter(zh,1);
+ terminateZookeeperThreads(zh);
+ }
+ synchronized(mx_);
+ allDelivered_=true;
+ deliveryCounter_++;
+ }
+ }
+ SyncedBoolCondition isDelivered() const{
+ if(terminate_){
+ int i=ensureCondition(RefCounterValue(zh_,1,mx_),1000);
+ assert(i<1000);
+ }
+ return SyncedBoolCondition(allDelivered_,mx_);
+ }
+ void resetDeliveryCounter(){
+ synchronized(mx_);
+ deliveryCounter_=0;
+ }
+ SyncedIntegerEqual deliveryCounterEquals(int expected) const{
+ if(terminate_){
+ int i=ensureCondition(RefCounterValue(zh_,1,mx_),1000);
+ assert(i<1000);
+ }
+ return SyncedIntegerEqual(deliveryCounter_,expected,mx_);
+ }
+ int type_;
+ int state_;
+ mutable Mutex mx_;
+ bool allDelivered_;
+ bool terminate_;
+ zhandle_t* zh_;
+ int deliveryCounter_;
+};
+
+WatcherDeliveryTracker::WatcherDeliveryTracker(
+ int type,int state,bool terminateCompletionThread):
+ deliveryWrapper_(new DeliverWatchersWrapper(
+ type,state,terminateCompletionThread)){
+}
+
+WatcherDeliveryTracker::~WatcherDeliveryTracker(){
+ delete deliveryWrapper_;
+}
+
+SyncedBoolCondition WatcherDeliveryTracker::isWatcherProcessingCompleted() const{
+ return deliveryWrapper_->isDelivered();
+}
+
+void WatcherDeliveryTracker::resetDeliveryCounter(){
+ deliveryWrapper_->resetDeliveryCounter();
+}
+
+SyncedIntegerEqual WatcherDeliveryTracker::deliveryCounterEquals(int expected) const{
+ return deliveryWrapper_->deliveryCounterEquals(expected);
+}
+
+//******************************************************************************
+//
+string HandshakeResponse::toString() const {
+ string buf;
+ int32_t tmp=htonl(protocolVersion);
+ buf.append((char*)&tmp,sizeof(tmp));
+ tmp=htonl(timeOut);
+ buf.append((char*)&tmp,sizeof(tmp));
+ int64_t tmp64=zoo_htonll(sessionId);
+ buf.append((char*)&tmp64,sizeof(sessionId));
+ tmp=htonl(passwd_len);
+ buf.append((char*)&tmp,sizeof(tmp));
+ buf.append(passwd,sizeof(passwd));
+ // finally set the buffer length
+ tmp=htonl(buf.size()+sizeof(tmp));
+ buf.insert(0,(char*)&tmp, sizeof(tmp));
+ return buf;
+}
+
+string ZooGetResponse::toString() const{
+ oarchive* oa=create_buffer_oarchive();
+
+ ReplyHeader h = {xid_,1,ZOK};
+ serialize_ReplyHeader(oa, "hdr", &h);
+
+ GetDataResponse resp;
+ char buf[1024];
+ assert("GetDataResponse is too long"&&data_.size()<=sizeof(buf));
+ resp.data.len=data_.size();
+ resp.data.buff=buf;
+ data_.copy(resp.data.buff, data_.size());
+ resp.stat=stat_;
+ serialize_GetDataResponse(oa, "reply", &resp);
+ int32_t len=htonl(get_buffer_len(oa));
+ string res((char*)&len,sizeof(len));
+ res.append(get_buffer(oa),get_buffer_len(oa));
+
+ close_buffer_oarchive(&oa,1);
+ return res;
+}
+
+string ZooStatResponse::toString() const{
+ oarchive* oa=create_buffer_oarchive();
+
+ ReplyHeader h = {xid_,1,rc_};
+ serialize_ReplyHeader(oa, "hdr", &h);
+
+ SetDataResponse resp;
+ resp.stat=stat_;
+ serialize_SetDataResponse(oa, "reply", &resp);
+ int32_t len=htonl(get_buffer_len(oa));
+ string res((char*)&len,sizeof(len));
+ res.append(get_buffer(oa),get_buffer_len(oa));
+
+ close_buffer_oarchive(&oa,1);
+ return res;
+}
+
+string ZooGetChildrenResponse::toString() const{
+ oarchive* oa=create_buffer_oarchive();
+
+ ReplyHeader h = {xid_,1,rc_};
+ serialize_ReplyHeader(oa, "hdr", &h);
+
+ GetChildrenResponse resp;
+ // populate the string vector
+ allocate_String_vector(&resp.children,strings_.size());
+ for(int i=0;i<(int)strings_.size();++i)
+ resp.children.data[i]=strdup(strings_[i].c_str());
+ serialize_GetChildrenResponse(oa, "reply", &resp);
+ deallocate_GetChildrenResponse(&resp);
+
+ int32_t len=htonl(get_buffer_len(oa));
+ string res((char*)&len,sizeof(len));
+ res.append(get_buffer(oa),get_buffer_len(oa));
+
+ close_buffer_oarchive(&oa,1);
+ return res;
+}
+
+string ZNodeEvent::toString() const{
+ oarchive* oa=create_buffer_oarchive();
+ struct WatcherEvent evt = {type_,0,(char*)path_.c_str()};
+ struct ReplyHeader h = {WATCHER_EVENT_XID,0,ZOK };
+
+ serialize_ReplyHeader(oa, "hdr", &h);
+ serialize_WatcherEvent(oa, "event", &evt);
+
+ int32_t len=htonl(get_buffer_len(oa));
+ string res((char*)&len,sizeof(len));
+ res.append(get_buffer(oa),get_buffer_len(oa));
+
+ close_buffer_oarchive(&oa,1);
+ return res;
+}
+
+string PingResponse::toString() const{
+ oarchive* oa=create_buffer_oarchive();
+
+ ReplyHeader h = {PING_XID,1,ZOK};
+ serialize_ReplyHeader(oa, "hdr", &h);
+
+ int32_t len=htonl(get_buffer_len(oa));
+ string res((char*)&len,sizeof(len));
+ res.append(get_buffer(oa),get_buffer_len(oa));
+
+ close_buffer_oarchive(&oa,1);
+ return res;
+}
+
+//******************************************************************************
+// Zookeeper server simulator
+//
+bool ZookeeperServer::hasMoreRecv() const{
+ return recvHasMore.get()!=0 || connectionLost;
+}
+
+ssize_t ZookeeperServer::callRecv(int s,void *buf,size_t len,int flags){
+ if(connectionLost){
+ recvReturnBuffer.erase();
+ return 0;
+ }
+ // done transmitting the current buffer?
+ if(recvReturnBuffer.size()==0){
+ synchronized(recvQMx);
+ if(recvQueue.empty()){
+ recvErrno=EAGAIN;
+ return Mock_socket::callRecv(s,buf,len,flags);
+ }
+ --recvHasMore;
+ Element& el=recvQueue.front();
+ if(el.first!=0){
+ recvReturnBuffer=el.first->toString();
+ delete el.first;
+ }
+ recvErrno=el.second;
+ recvQueue.pop_front();
+ }
+ return Mock_socket::callRecv(s,buf,len,flags);
+}
+
+void ZookeeperServer::onMessageReceived(const RequestHeader& rh, iarchive* ia){
+ // no-op by default
+}
+
+void ZookeeperServer::notifyBufferSent(const std::string& buffer){
+ if(HandshakeRequest::isValid(buffer)){
+ // could be a connect request
+ auto_ptr<HandshakeRequest> req(HandshakeRequest::parse(buffer));
+ if(req.get()!=0){
+ // handle the handshake
+ int64_t sessId=sessionExpired?req->sessionId+1:req->sessionId;
+ sessionExpired=false;
+ addRecvResponse(new HandshakeResponse(sessId));
+ return;
+ }
+ // not a connect request -- fall thru
+ }
+ // parse the buffer to extract the request type and its xid
+ iarchive *ia=create_buffer_iarchive((char*)buffer.data(), buffer.size());
+ RequestHeader rh;
+ deserialize_RequestHeader(ia,"hdr",&rh);
+ // notify the "server" a client request has arrived
+ if (rh.xid == -8) {
+ Element e = Element(new ZooStatResponse,0);
+ e.first->setXID(-8);
+ addRecvResponse(e);
+ close_buffer_iarchive(&ia);
+ return;
+ } else {
+ onMessageReceived(rh,ia);
+ }
+ close_buffer_iarchive(&ia);
+ if(rh.type==ZOO_CLOSE_OP){
+ ++closeSent;
+ return; // no reply for close requests
+ }
+ // get the next response from the response queue and append it to the receive list
+ Element e;
+ {
+ synchronized(respQMx);
+ if(respQueue.empty())
+ return;
+ e=respQueue.front();
+ respQueue.pop_front();
+ }
+ e.first->setXID(rh.xid);
+ addRecvResponse(e);
+}
+
+void forceConnected(zhandle_t* zh){
+ // simulate connected state
+ zh->state=ZOO_CONNECTED_STATE;
+ zh->fd=ZookeeperServer::FD;
+ zh->input_buffer=0;
+ gettimeofday(&zh->last_recv,0);
+ gettimeofday(&zh->last_send,0);
+}
+
+void terminateZookeeperThreads(zhandle_t* zh){
+ // this will cause the zookeeper threads to terminate
+ zh->close_requested=1;
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/ZKMocks.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/ZKMocks.h b/zookeeper-client/zookeeper-client-c/tests/ZKMocks.h
new file mode 100644
index 0000000..fbcfc4f
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/ZKMocks.h
@@ -0,0 +1,509 @@
+/**
+ * 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 ZKMOCKS_H_
+#define ZKMOCKS_H_
+
+#include <zookeeper.h>
+#include "src/zk_adaptor.h"
+
+#include "Util.h"
+#include "LibCMocks.h"
+#include "MocksBase.h"
+
+// *****************************************************************************
+// sets internal zhandle_t members to certain values to simulate the client
+// connected state. This function should only be used with the single-threaded
+// Async API tests!
+void forceConnected(zhandle_t* zh);
+
+/**
+ * Gracefully terminates zookeeper I/O and completion threads.
+ */
+void terminateZookeeperThreads(zhandle_t* zh);
+
+// *****************************************************************************
+// Abstract watcher action
+struct SyncedBoolCondition;
+
+class WatcherAction{
+public:
+ WatcherAction():triggered_(false){}
+ virtual ~WatcherAction(){}
+
+ virtual void onSessionExpired(zhandle_t*){}
+ virtual void onConnectionEstablished(zhandle_t*){}
+ virtual void onConnectionLost(zhandle_t*){}
+ virtual void onNodeValueChanged(zhandle_t*,const char* path){}
+ virtual void onNodeDeleted(zhandle_t*,const char* path){}
+ virtual void onChildChanged(zhandle_t*,const char* path){}
+
+ SyncedBoolCondition isWatcherTriggered() const;
+ void setWatcherTriggered(){
+ synchronized(mx_);
+ triggered_=true;
+ }
+
+protected:
+ mutable Mutex mx_;
+ bool triggered_;
+};
+// zh->context is a pointer to a WatcherAction instance
+// based on the event type and state, the watcher calls a specific watcher
+// action method
+void activeWatcher(zhandle_t *zh, int type, int state, const char *path,void* ctx);
+
+// *****************************************************************************
+// a set of async completion signatures
+class AsyncCompletion{
+public:
+ virtual ~AsyncCompletion(){}
+ virtual void aclCompl(int rc, ACL_vector *acl,Stat *stat){}
+ virtual void dataCompl(int rc, const char *value, int len, const Stat *stat){}
+ virtual void statCompl(int rc, const Stat *stat){}
+ virtual void stringCompl(int rc, const char *value){}
+ virtual void stringsCompl(int rc,const String_vector *strings){}
+ virtual void voidCompl(int rc){}
+};
+void asyncCompletion(int rc, ACL_vector *acl,Stat *stat, const void *data);
+void asyncCompletion(int rc, const char *value, int len, const Stat *stat,
+ const void *data);
+void asyncCompletion(int rc, const Stat *stat, const void *data);
+void asyncCompletion(int rc, const char *value, const void *data);
+void asyncCompletion(int rc,const String_vector *strings, const void *data);
+void asyncCompletion(int rc, const void *data);
+
+// *****************************************************************************
+// some common predicates to use with ensureCondition():
+// checks if the connection is established
+struct ClientConnected{
+ ClientConnected(zhandle_t* zh):zh_(zh){}
+ bool operator()() const{
+ return zoo_state(zh_)==ZOO_CONNECTED_STATE;
+ }
+ zhandle_t* zh_;
+};
+// check in the session expired
+struct SessionExpired{
+ SessionExpired(zhandle_t* zh):zh_(zh){}
+ bool operator()() const{
+ return zoo_state(zh_)==ZOO_EXPIRED_SESSION_STATE;
+ }
+ zhandle_t* zh_;
+};
+// checks if the IO thread has stopped; CheckedPthread must be active
+struct IOThreadStopped{
+ IOThreadStopped(zhandle_t* zh):zh_(zh){}
+ bool operator()() const;
+ zhandle_t* zh_;
+};
+
+// a synchronized boolean condition
+struct SyncedBoolCondition{
+ SyncedBoolCondition(const bool& cond,Mutex& mx):cond_(cond),mx_(mx){}
+ bool operator()() const{
+ synchronized(mx_);
+ return cond_;
+ }
+ const bool& cond_;
+ Mutex& mx_;
+};
+
+// a synchronized integer comparison
+struct SyncedIntegerEqual{
+ SyncedIntegerEqual(const int& cond,int expected,Mutex& mx):
+ cond_(cond),expected_(expected),mx_(mx){}
+ bool operator()() const{
+ synchronized(mx_);
+ return cond_==expected_;
+ }
+ const int& cond_;
+ const int expected_;
+ Mutex& mx_;
+};
+
+// *****************************************************************************
+// make sure to call zookeeper_close() even in presence of exceptions
+struct CloseFinally{
+ CloseFinally(zhandle_t** zh):zh_(zh){}
+ ~CloseFinally(){
+ execute();
+ }
+ int execute(){
+ if(zh_==0)return ZOK;
+ zhandle_t* lzh=*zh_;
+ *zh_=0;
+ disarm();
+ return zookeeper_close(lzh);
+ }
+ void disarm(){zh_=0;}
+ zhandle_t ** zh_;
+};
+
+struct TestClientId: clientid_t{
+ static const int SESSION_ID=123456789;
+ static const char* PASSWD;
+ TestClientId(){
+ client_id=SESSION_ID;
+ memcpy(passwd,PASSWD,sizeof(passwd));
+ }
+};
+
+// *****************************************************************************
+// special client id recongnized by the ZK server simulator
+extern TestClientId testClientId;
+#define TEST_CLIENT_ID &testClientId
+
+// *****************************************************************************
+//
+struct HandshakeRequest: public connect_req
+{
+ static HandshakeRequest* parse(const std::string& buf);
+ static bool isValid(const std::string& buf){
+ // this is just quick and dirty check before we go and parse the request
+ return buf.size()==HANDSHAKE_REQ_SIZE;
+ }
+};
+
+// *****************************************************************************
+// flush_send_queue
+class Mock_flush_send_queue: public Mock
+{
+public:
+ Mock_flush_send_queue():counter(0),callReturns(ZOK){mock_=this;}
+ ~Mock_flush_send_queue(){mock_=0;}
+
+ int counter;
+ int callReturns;
+ virtual int call(zhandle_t* zh, int timeout){
+ counter++;
+ return callReturns;
+ }
+
+ static Mock_flush_send_queue* mock_;
+};
+
+// *****************************************************************************
+// get_xid
+class Mock_get_xid: public Mock
+{
+public:
+ static const int32_t XID=123456;
+ Mock_get_xid(int retValue=XID):callReturns(retValue){mock_=this;}
+ ~Mock_get_xid(){mock_=0;}
+
+ int callReturns;
+ virtual int call(){
+ return callReturns;
+ }
+
+ static Mock_get_xid* mock_;
+};
+
+// *****************************************************************************
+// activateWatcher
+class Mock_activateWatcher: public Mock{
+public:
+ Mock_activateWatcher(){mock_=this;}
+ virtual ~Mock_activateWatcher(){mock_=0;}
+
+ virtual void call(zhandle_t *zh, watcher_registration_t* reg, int rc){}
+ static Mock_activateWatcher* mock_;
+};
+
+class ActivateWatcherWrapper;
+class WatcherActivationTracker{
+public:
+ WatcherActivationTracker();
+ ~WatcherActivationTracker();
+
+ void track(void* ctx);
+ SyncedBoolCondition isWatcherActivated() const;
+private:
+ ActivateWatcherWrapper* wrapper_;
+};
+
+// *****************************************************************************
+// deliverWatchers
+class Mock_deliverWatchers: public Mock{
+public:
+ Mock_deliverWatchers(){mock_=this;}
+ virtual ~Mock_deliverWatchers(){mock_=0;}
+
+ virtual void call(zhandle_t* zh,int type,int state, const char* path, watcher_object_list **){}
+ static Mock_deliverWatchers* mock_;
+};
+
+class DeliverWatchersWrapper;
+class WatcherDeliveryTracker{
+public:
+ // filters deliveries by state and type
+ WatcherDeliveryTracker(int type,int state,bool terminateCompletionThread=true);
+ ~WatcherDeliveryTracker();
+
+ // if the thread termination requested (see the ctor params)
+ // this function will wait for the I/O and completion threads to
+ // terminate before returning a SyncBoolCondition instance
+ SyncedBoolCondition isWatcherProcessingCompleted() const;
+ void resetDeliveryCounter();
+ SyncedIntegerEqual deliveryCounterEquals(int expected) const;
+private:
+ DeliverWatchersWrapper* deliveryWrapper_;
+};
+
+// *****************************************************************************
+// a zookeeper Stat wrapper
+struct NodeStat: public Stat
+{
+ NodeStat(){
+ czxid=0;
+ mzxid=0;
+ ctime=0;
+ mtime=0;
+ version=1;
+ cversion=0;
+ aversion=0;
+ ephemeralOwner=0;
+ }
+ NodeStat(const Stat& other){
+ memcpy(this,&other,sizeof(*this));
+ }
+};
+
+// *****************************************************************************
+// Abstract server Response
+class Response
+{
+public:
+ virtual ~Response(){}
+
+ virtual void setXID(int32_t xid){}
+ // this method is used by the ZookeeperServer class to serialize
+ // the instance of Response
+ virtual std::string toString() const =0;
+};
+
+// *****************************************************************************
+// Handshake response
+class HandshakeResponse: public Response
+{
+public:
+ HandshakeResponse(int64_t sessId=1)
+ :protocolVersion(1),timeOut(10000),sessionId(sessId),passwd_len(sizeof(passwd))
+ {
+ memcpy(passwd,"1234567890123456",sizeof(passwd));
+ }
+ int32_t protocolVersion;
+ int32_t timeOut;
+ int64_t sessionId;
+ int32_t passwd_len;
+ char passwd[16];
+ virtual std::string toString() const ;
+};
+
+// zoo_get() response
+class ZooGetResponse: public Response
+{
+public:
+ ZooGetResponse(const char* data, int len,int32_t xid=0,int rc=ZOK,const Stat& stat=NodeStat())
+ :xid_(xid),data_(data,len),rc_(rc),stat_(stat)
+ {
+ }
+ virtual std::string toString() const;
+ virtual void setXID(int32_t xid) {xid_=xid;}
+
+private:
+ int32_t xid_;
+ std::string data_;
+ int rc_;
+ Stat stat_;
+};
+
+// zoo_exists(), zoo_set() response
+class ZooStatResponse: public Response
+{
+public:
+ ZooStatResponse(int32_t xid=0,int rc=ZOK,const Stat& stat=NodeStat())
+ :xid_(xid),rc_(rc),stat_(stat)
+ {
+ }
+ virtual std::string toString() const;
+ virtual void setXID(int32_t xid) {xid_=xid;}
+
+private:
+ int32_t xid_;
+ int rc_;
+ Stat stat_;
+};
+
+// zoo_get_children()
+class ZooGetChildrenResponse: public Response
+{
+public:
+ typedef std::vector<std::string> StringVector;
+ ZooGetChildrenResponse(const StringVector& v,int rc=ZOK):
+ xid_(0),strings_(v),rc_(rc)
+ {
+ }
+
+ virtual std::string toString() const;
+ virtual void setXID(int32_t xid) {xid_=xid;}
+
+ int32_t xid_;
+ StringVector strings_;
+ int rc_;
+};
+
+// PING response
+class PingResponse: public Response
+{
+public:
+ virtual std::string toString() const;
+};
+
+// watcher znode event
+class ZNodeEvent: public Response
+{
+public:
+ ZNodeEvent(int type,const char* path):type_(type),path_(path){}
+
+ virtual std::string toString() const;
+
+private:
+ int type_;
+ std::string path_;
+};
+
+// ****************************************************************************
+// Zookeeper server simulator
+
+class ZookeeperServer: public Mock_socket
+{
+public:
+ ZookeeperServer():
+ serverDownSkipCount_(-1),sessionExpired(false),connectionLost(false)
+ {
+ connectReturns=-1;
+ connectErrno=EWOULDBLOCK;
+ }
+ virtual ~ZookeeperServer(){
+ clearRecvQueue();
+ clearRespQueue();
+ }
+ virtual int callClose(int fd){
+ if(fd!=FD)
+ return LIBC_SYMBOLS.close(fd);
+ clearRecvQueue();
+ clearRespQueue();
+ return Mock_socket::callClose(fd);
+ }
+ // connection handling
+ // what to do when the handshake request comes in?
+ int serverDownSkipCount_;
+ // this will cause getsockopt(zh->fd,SOL_SOCKET,SO_ERROR,&error,&len) return
+ // a failure after skipCount dropped to zero, thus simulating a server down
+ // condition
+ // passing skipCount==-1 will make every connect attempt succeed
+ void setServerDown(int skipCount=0){
+ serverDownSkipCount_=skipCount;
+ optvalSO_ERROR=0;
+ }
+ virtual void setSO_ERROR(void *optval,socklen_t len){
+ if(serverDownSkipCount_!=-1){
+ if(serverDownSkipCount_==0)
+ optvalSO_ERROR=ECONNREFUSED;
+ else
+ serverDownSkipCount_--;
+ }
+ Mock_socket::setSO_ERROR(optval,len);
+ }
+
+ // this is a trigger that gets reset back to false
+ // a connect request will return a non-matching session id thus causing
+ // the client throw SESSION_EXPIRED
+ volatile bool sessionExpired;
+ void returnSessionExpired(){ sessionExpired=true; }
+
+ // this is a one shot trigger that gets reset back to false
+ // next recv call will return 0 length, thus simulating a connecton loss
+ volatile bool connectionLost;
+ void setConnectionLost() {connectionLost=true;}
+
+ // recv
+ // this queue is used for server responses: client's recv() system call
+ // returns next available message from this queue
+ typedef std::pair<Response*,int> Element;
+ typedef std::deque<Element> ResponseList;
+ ResponseList recvQueue;
+ mutable Mutex recvQMx;
+ AtomicInt recvHasMore;
+ ZookeeperServer& addRecvResponse(Response* resp, int errnum=0){
+ synchronized(recvQMx);
+ recvQueue.push_back(Element(resp,errnum));
+ ++recvHasMore;
+ return *this;
+ }
+ ZookeeperServer& addRecvResponse(int errnum){
+ synchronized(recvQMx);
+ recvQueue.push_back(Element(0,errnum));
+ ++recvHasMore;
+ return *this;
+ }
+ ZookeeperServer& addRecvResponse(const Element& e){
+ synchronized(recvQMx);
+ recvQueue.push_back(e);
+ ++recvHasMore;
+ return *this;
+ }
+ void clearRecvQueue(){
+ synchronized(recvQMx);
+ recvHasMore=0;
+ for(unsigned i=0; i<recvQueue.size();i++)
+ delete recvQueue[i].first;
+ recvQueue.clear();
+ }
+
+ virtual ssize_t callRecv(int s,void *buf,size_t len,int flags);
+ virtual bool hasMoreRecv() const;
+
+ // the operation response queue holds zookeeper operation responses till the
+ // operation request has been sent to the server. After that, the operation
+ // response gets moved on to the recv queue (see above) ready to be read by
+ // the next recv() system call
+ // send operation doesn't try to match request to the response
+ ResponseList respQueue;
+ mutable Mutex respQMx;
+ ZookeeperServer& addOperationResponse(Response* resp, int errnum=0){
+ synchronized(respQMx);
+ respQueue.push_back(Element(resp,errnum));
+ return *this;
+ }
+ void clearRespQueue(){
+ synchronized(respQMx);
+ for(unsigned i=0; i<respQueue.size();i++)
+ delete respQueue[i].first;
+ respQueue.clear();
+ }
+ AtomicInt closeSent;
+ virtual void notifyBufferSent(const std::string& buffer);
+ // simulates an arrival of a client request
+ // a callback to be implemented by subclasses (no-op by default)
+ virtual void onMessageReceived(const RequestHeader& rh, iarchive* ia);
+};
+
+#endif /*ZKMOCKS_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/wrappers-mt.opt
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/wrappers-mt.opt b/zookeeper-client/zookeeper-client-c/tests/wrappers-mt.opt
new file mode 100644
index 0000000..01046fb
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/wrappers-mt.opt
@@ -0,0 +1,3 @@
+-Wl,--wrap -Wl,pthread_mutex_lock
+-Wl,--wrap -Wl,pthread_mutex_trylock
+-Wl,--wrap -Wl,pthread_mutex_unlock
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/wrappers.opt
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/wrappers.opt b/zookeeper-client/zookeeper-client-c/tests/wrappers.opt
new file mode 100644
index 0000000..bce192f
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/wrappers.opt
@@ -0,0 +1,7 @@
+-Wl,--wrap -Wl,calloc
+-Wl,--wrap -Wl,free
+-Wl,--wrap -Wl,flush_send_queue
+-Wl,--wrap -Wl,get_xid
+-Wl,--wrap -Wl,deliverWatchers
+-Wl,--wrap -Wl,activateWatcher
+-Wl,--wrap -Wl,realloc
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/zkServer.sh
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/zkServer.sh b/zookeeper-client/zookeeper-client-c/tests/zkServer.sh
new file mode 100755
index 0000000..4872fba
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/zkServer.sh
@@ -0,0 +1,161 @@
+#!/bin/bash
+#
+# 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.
+
+# This is the port where zookeeper server runs on.
+ZOOPORT=22181
+
+if [ "x$1" == "x" ]
+then
+ echo "USAGE: $0 startClean|start|stop hostPorts"
+ exit 2
+fi
+
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ *) cygwin=false ;;
+esac
+
+if [ "x$1" == "xstartClean" ]
+then
+ if [ "x${base_dir}" == "x" ]
+ then
+ rm -rf /tmp/zkdata
+ else
+ rm -rf "${base_dir}/build/tmp"
+ fi
+fi
+
+if $cygwin
+then
+ # cygwin has a "kill" in the shell itself, gets confused
+ KILL=/bin/kill
+else
+ KILL=kill
+fi
+
+# Make sure nothing is left over from before
+if [ -r "/tmp/zk.pid" ]
+then
+pid=`cat /tmp/zk.pid`
+$KILL -9 $pid
+rm -f /tmp/zk.pid
+fi
+
+if [ -r "${base_dir}/build/tmp/zk.pid" ]
+then
+pid=`cat "${base_dir}/build/tmp/zk.pid"`
+$KILL -9 $pid
+rm -f "${base_dir}/build/tmp/zk.pid"
+fi
+
+# [ZOOKEEPER-820] If lsof command is present, look for a process listening
+# on ZOOPORT and kill it.
+which lsof &> /dev/null
+if [ $? -eq 0 ]
+then
+ pid=`lsof -i :$ZOOPORT | grep LISTEN | awk '{print $2}'`
+ if [ -n "$pid" ]
+ then
+ $KILL -9 $pid
+ fi
+fi
+
+if [ "x${base_dir}" == "x" ]
+then
+zk_base="../../"
+else
+zk_base="${base_dir}"
+fi
+
+CLASSPATH="$CLASSPATH:${zk_base}/build/classes"
+CLASSPATH="$CLASSPATH:${zk_base}/conf"
+
+for i in "${zk_base}"/build/lib/*.jar
+do
+ CLASSPATH="$CLASSPATH:$i"
+done
+
+for i in "${zk_base}"/src/java/lib/*.jar
+do
+ CLASSPATH="$CLASSPATH:$i"
+done
+
+CLASSPATH="$CLASSPATH:${CLOVER_HOME}/lib/clover.jar"
+
+if $cygwin
+then
+ CLASSPATH=`cygpath -wp "$CLASSPATH"`
+fi
+
+case $1 in
+start|startClean)
+ if [ "x${base_dir}" == "x" ]
+ then
+ mkdir -p /tmp/zkdata
+ java -cp "$CLASSPATH" org.apache.zookeeper.server.ZooKeeperServerMain $ZOOPORT /tmp/zkdata 3000 $ZKMAXCNXNS &> /tmp/zk.log &
+ pid=$!
+ echo -n $! > /tmp/zk.pid
+ else
+ mkdir -p "${base_dir}/build/tmp/zkdata"
+ java -cp "$CLASSPATH" org.apache.zookeeper.server.ZooKeeperServerMain $ZOOPORT "${base_dir}/build/tmp/zkdata" 3000 $ZKMAXCNXNS &> "${base_dir}/build/tmp/zk.log" &
+ pid=$!
+ echo -n $pid > "${base_dir}/build/tmp/zk.pid"
+ fi
+
+ # wait max 120 seconds for server to be ready to server clients
+ # this handles testing on slow hosts
+ success=false
+ for i in {1..120}
+ do
+ if ps -p $pid > /dev/null
+ then
+ java -cp "$CLASSPATH" org.apache.zookeeper.ZooKeeperMain -server localhost:$ZOOPORT ls / > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ # server not up yet - wait
+ sleep 1
+ else
+ # server is up and serving client connections
+ success=true
+ break
+ fi
+ else
+ # server died - exit now
+ echo -n " ZooKeeper server process failed"
+ break
+ fi
+ done
+
+ if $success
+ then
+ ## in case for debug, but generally don't use as it messes up the
+ ## console test output
+ echo -n " ZooKeeper server started"
+ else
+ echo -n " ZooKeeper server NOT started"
+ fi
+
+ ;;
+stop)
+ # Already killed above
+ ;;
+*)
+ echo "Unknown command " + $1
+ exit 2
+esac
+
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-contrib/zookeeper-contrib-zkpython/src/python/setup.py
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zkpython/src/python/setup.py b/zookeeper-contrib/zookeeper-contrib-zkpython/src/python/setup.py
index c6a1cee..d9fa36b 100755
--- a/zookeeper-contrib/zookeeper-contrib-zkpython/src/python/setup.py
+++ b/zookeeper-contrib/zookeeper-contrib-zkpython/src/python/setup.py
@@ -19,12 +19,12 @@ from distutils.core import setup, Extension
zookeeper_basedir = "../../../"
zookeepermodule = Extension("zookeeper",
- sources=["src/c/zookeeper.c"],
- include_dirs=[zookeeper_basedir + "/src/c/include",
+ sources=["zookeeper-client/zookeeper-client-c/zookeeper.c"],
+ include_dirs=[zookeeper_basedir + "/zookeeper-client/zookeeper-client-c/include",
zookeeper_basedir + "/build/c",
- zookeeper_basedir + "/src/c/generated"],
+ zookeeper_basedir + "/zookeeper-client/zookeeper-client-c/generated"],
libraries=["zookeeper_mt"],
- library_dirs=[zookeeper_basedir + "/src/c/.libs/",
+ library_dirs=[zookeeper_basedir + "/zookeeper-client/zookeeper-client-c/.libs/",
zookeeper_basedir + "/build/c/.libs/",
zookeeper_basedir + "/build/test/test-cppunit/.libs",
"/usr/local/lib"
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-docs/src/documentation/content/xdocs/zookeeperProgrammers.xml
----------------------------------------------------------------------
diff --git a/zookeeper-docs/src/documentation/content/xdocs/zookeeperProgrammers.xml b/zookeeper-docs/src/documentation/content/xdocs/zookeeperProgrammers.xml
index 8fbd679..aaf21c4 100644
--- a/zookeeper-docs/src/documentation/content/xdocs/zookeeperProgrammers.xml
+++ b/zookeeper-docs/src/documentation/content/xdocs/zookeeperProgrammers.xml
@@ -941,7 +941,7 @@
<note><para>This is a very simple example which is intended to show
how to interact with ZooKeeper ACLs
- specifically. See <filename>.../trunk/src/c/src/cli.c</filename>
+ specifically. See <filename>.../trunk/zookeeper-client/zookeeper-client-c/src/cli.c</filename>
for an example of a C client implementation</para>
</note>
@@ -1329,11 +1329,11 @@ authProvider.2=com.f.MyAuth2
<para>Run <command>ant compile_jute</command> from the ZooKeeper
top level directory (<filename>.../trunk</filename>).
This will create a directory named "generated" under
- <filename>.../trunk/src/c</filename>.</para>
+ <filename>.../trunk/zookeeper-client/zookeeper-client-c</filename>.</para>
</listitem>
<listitem>
- <para>Change directory to the<filename>.../trunk/src/c</filename>
+ <para>Change directory to the<filename>.../trunk/zookeeper-client/zookeeper-client-c</filename>
and run <command>autoreconf -if</command> to bootstrap <emphasis
role="bold">autoconf</emphasis>, <emphasis
role="bold">automake</emphasis> and <emphasis
@@ -1345,7 +1345,7 @@ authProvider.2=com.f.MyAuth2
<listitem>
<para>If you are building from a project source package,
unzip/untar the source tarball and cd to the<filename>
- zookeeper-x.x.x/src/c</filename> directory.</para>
+ zookeeper-x.x.x/zookeeper-client/zookeeper-client-c</filename> directory.</para>
</listitem>
<listitem>
@@ -1429,7 +1429,7 @@ authProvider.2=com.f.MyAuth2
</orderedlist>
<note><para>
- See <filename>.../trunk/src/c/src/cli.c</filename>
+ See <filename>.../trunk/zookeeper-client/zookeeper-client-c/src/cli.c</filename>
for an example of a C client implementation</para>
</note>
</section>
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-recipes/zookeeper-recipes-lock/src/main/c/configure.ac
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-lock/src/main/c/configure.ac b/zookeeper-recipes/zookeeper-recipes-lock/src/main/c/configure.ac
index 3954123..31c5406 100644
--- a/zookeeper-recipes/zookeeper-recipes-lock/src/main/c/configure.ac
+++ b/zookeeper-recipes/zookeeper-recipes-lock/src/main/c/configure.ac
@@ -48,8 +48,8 @@ DX_PS_FEATURE(OFF)
DX_INIT_DOXYGEN([zookeeper-locks],[c-doc.Doxyfile],[docs])
-ZOOKEEPER_PATH=${BUILD_PATH}/../../../../../src/c
-ZOOKEEPER_LD=-L${BUILD_PATH}/../../../../../src/c\ -lzookeeper_mt
+ZOOKEEPER_PATH=${BUILD_PATH}/../../../../zookeeper-client/zookeeper-client-c
+ZOOKEEPER_LD=-L${BUILD_PATH}/../../../../zookeeper-client/zookeeper-client-c\ -lzookeeper_mt
AC_SUBST(ZOOKEEPER_PATH)
AC_SUBST(ZOOKEEPER_LD)
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-recipes/zookeeper-recipes-queue/src/main/c/configure.ac
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-queue/src/main/c/configure.ac b/zookeeper-recipes/zookeeper-recipes-queue/src/main/c/configure.ac
index a9fb7b1..23fa8c9 100644
--- a/zookeeper-recipes/zookeeper-recipes-queue/src/main/c/configure.ac
+++ b/zookeeper-recipes/zookeeper-recipes-queue/src/main/c/configure.ac
@@ -48,8 +48,8 @@ DX_PS_FEATURE(OFF)
DX_INIT_DOXYGEN([zookeeper-queues],[c-doc.Doxyfile],[docs])
-ZOOKEEPER_PATH=${BUILD_PATH}/../../../../../src/c
-ZOOKEEPER_LD=-L${BUILD_PATH}/../../../../../src/c\ -lzookeeper_mt
+ZOOKEEPER_PATH=${BUILD_PATH}/../../../../zookeeper-client/zookeeper-client-c
+ZOOKEEPER_LD=-L${BUILD_PATH}/../../../../zookeeper-client/zookeeper-client-c\ -lzookeeper_mt
AC_SUBST(ZOOKEEPER_PATH)
AC_SUBST(ZOOKEEPER_LD)
[18/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/include/zookeeper.h
----------------------------------------------------------------------
diff --git a/src/c/include/zookeeper.h b/src/c/include/zookeeper.h
deleted file mode 100644
index aee865b..0000000
--- a/src/c/include/zookeeper.h
+++ /dev/null
@@ -1,1589 +0,0 @@
-/**
- * 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_H_
-#define ZOOKEEPER_H_
-
-#include <stdlib.h>
-
-/* we must not include config.h as a public header */
-#ifndef WIN32
-#include <sys/socket.h>
-#include <sys/time.h>
-#endif
-
-#ifdef WIN32
-#include <winsock2.h> /* must always be included before ws2tcpip.h */
-#include <ws2tcpip.h> /* for struct sock_addr and socklen_t */
-#endif
-
-#include <stdio.h>
-#include <ctype.h>
-
-#include "proto.h"
-#include "zookeeper_version.h"
-#include "recordio.h"
-#include "zookeeper.jute.h"
-
-/**
- * \file zookeeper.h
- * \brief ZooKeeper functions and definitions.
- *
- * ZooKeeper is a network service that may be backed by a cluster of
- * synchronized servers. The data in the service is represented as a tree
- * of data nodes. Each node has data, children, an ACL, and status information.
- * The data for a node is read and write in its entirety.
- *
- * ZooKeeper clients can leave watches when they queries the data or children
- * of a node. If a watch is left, that client will be notified of the change.
- * The notification is a one time trigger. Subsequent chances to the node will
- * not trigger a notification unless the client issues a query with the watch
- * flag set. If the client is ever disconnected from the service, the watches do
- * not need to be reset. The client automatically resets the watches.
- *
- * When a node is created, it may be flagged as an ephemeral node. Ephemeral
- * nodes are automatically removed when a client session is closed or when
- * a session times out due to inactivity (the ZooKeeper runtime fills in
- * periods of inactivity with pings). Ephemeral nodes cannot have children.
- *
- * ZooKeeper clients are identified by a server assigned session id. For
- * security reasons The server
- * also generates a corresponding password for a session. A client may save its
- * id and corresponding password to persistent storage in order to use the
- * session across program invocation boundaries.
- */
-
-/* Support for building on various platforms */
-
-// on cygwin we should take care of exporting/importing symbols properly
-#ifdef DLL_EXPORT
-# define ZOOAPI __declspec(dllexport)
-#else
-# if (defined(__CYGWIN__) || defined(WIN32)) && !defined(USE_STATIC_LIB)
-# define ZOOAPI __declspec(dllimport)
-# else
-# define ZOOAPI
-# endif
-#endif
-
-/** zookeeper return constants **/
-
-enum ZOO_ERRORS {
- ZOK = 0, /*!< Everything is OK */
-
- /** System and server-side errors.
- * This is never thrown by the server, it shouldn't be used other than
- * to indicate a range. Specifically error codes greater than this
- * value, but lesser than {@link #ZAPIERROR}, are system errors. */
- ZSYSTEMERROR = -1,
- ZRUNTIMEINCONSISTENCY = -2, /*!< A runtime inconsistency was found */
- ZDATAINCONSISTENCY = -3, /*!< A data inconsistency was found */
- ZCONNECTIONLOSS = -4, /*!< Connection to the server has been lost */
- ZMARSHALLINGERROR = -5, /*!< Error while marshalling or unmarshalling data */
- ZUNIMPLEMENTED = -6, /*!< Operation is unimplemented */
- ZOPERATIONTIMEOUT = -7, /*!< Operation timeout */
- ZBADARGUMENTS = -8, /*!< Invalid arguments */
- ZINVALIDSTATE = -9, /*!< Invliad zhandle state */
-
- /** API errors.
- * This is never thrown by the server, it shouldn't be used other than
- * to indicate a range. Specifically error codes greater than this
- * value are API errors (while values less than this indicate a
- * {@link #ZSYSTEMERROR}).
- */
- ZAPIERROR = -100,
- ZNONODE = -101, /*!< Node does not exist */
- ZNOAUTH = -102, /*!< Not authenticated */
- ZBADVERSION = -103, /*!< Version conflict */
- ZNOCHILDRENFOREPHEMERALS = -108, /*!< Ephemeral nodes may not have children */
- ZNODEEXISTS = -110, /*!< The node already exists */
- ZNOTEMPTY = -111, /*!< The node has children */
- ZSESSIONEXPIRED = -112, /*!< The session has been expired by the server */
- ZINVALIDCALLBACK = -113, /*!< Invalid callback specified */
- ZINVALIDACL = -114, /*!< Invalid ACL specified */
- ZAUTHFAILED = -115, /*!< Client authentication failed */
- ZCLOSING = -116, /*!< ZooKeeper is closing */
- ZNOTHING = -117, /*!< (not error) no server responses to process */
- ZSESSIONMOVED = -118 /*!<session moved to another server, so operation is ignored */
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
-* @name Debug levels
-*/
-typedef enum {ZOO_LOG_LEVEL_ERROR=1,ZOO_LOG_LEVEL_WARN=2,ZOO_LOG_LEVEL_INFO=3,ZOO_LOG_LEVEL_DEBUG=4} ZooLogLevel;
-
-/**
- * @name ACL Consts
- */
-extern ZOOAPI const int ZOO_PERM_READ;
-extern ZOOAPI const int ZOO_PERM_WRITE;
-extern ZOOAPI const int ZOO_PERM_CREATE;
-extern ZOOAPI const int ZOO_PERM_DELETE;
-extern ZOOAPI const int ZOO_PERM_ADMIN;
-extern ZOOAPI const int ZOO_PERM_ALL;
-
-/** This Id represents anyone. */
-extern ZOOAPI struct Id ZOO_ANYONE_ID_UNSAFE;
-/** This Id is only usable to set ACLs. It will get substituted with the
- * Id's the client authenticated with.
- */
-extern ZOOAPI struct Id ZOO_AUTH_IDS;
-
-/** This is a completely open ACL*/
-extern ZOOAPI struct ACL_vector ZOO_OPEN_ACL_UNSAFE;
-/** This ACL gives the world the ability to read. */
-extern ZOOAPI struct ACL_vector ZOO_READ_ACL_UNSAFE;
-/** This ACL gives the creators authentication id's all permissions. */
-extern ZOOAPI struct ACL_vector ZOO_CREATOR_ALL_ACL;
-
-/**
- * @name Interest Consts
- * These constants are used to express interest in an event and to
- * indicate to zookeeper which events have occurred. They can
- * be ORed together to express multiple interests. These flags are
- * used in the interest and event parameters of
- * \ref zookeeper_interest and \ref zookeeper_process.
- */
-// @{
-extern ZOOAPI const int ZOOKEEPER_WRITE;
-extern ZOOAPI const int ZOOKEEPER_READ;
-// @}
-
-/**
- * @name Create Flags
- *
- * These flags are used by zoo_create to affect node create. They may
- * be ORed together to combine effects.
- */
-// @{
-extern ZOOAPI const int ZOO_EPHEMERAL;
-extern ZOOAPI const int ZOO_SEQUENCE;
-// @}
-
-/**
- * @name State Consts
- * These constants represent the states of a zookeeper connection. They are
- * possible parameters of the watcher callback.
- */
-// @{
-extern ZOOAPI const int ZOO_EXPIRED_SESSION_STATE;
-extern ZOOAPI const int ZOO_AUTH_FAILED_STATE;
-extern ZOOAPI const int ZOO_CONNECTING_STATE;
-extern ZOOAPI const int ZOO_ASSOCIATING_STATE;
-extern ZOOAPI const int ZOO_CONNECTED_STATE;
-// @}
-
-/**
- * @name Watch Types
- * These constants indicate the event that caused the watch event. They are
- * possible values of the first parameter of the watcher callback.
- */
-// @{
-/**
- * \brief a node has been created.
- *
- * This is only generated by watches on non-existent nodes. These watches
- * are set using \ref zoo_exists.
- */
-extern ZOOAPI const int ZOO_CREATED_EVENT;
-/**
- * \brief a node has been deleted.
- *
- * This is only generated by watches on nodes. These watches
- * are set using \ref zoo_exists and \ref zoo_get.
- */
-extern ZOOAPI const int ZOO_DELETED_EVENT;
-/**
- * \brief a node has changed.
- *
- * This is only generated by watches on nodes. These watches
- * are set using \ref zoo_exists and \ref zoo_get.
- */
-extern ZOOAPI const int ZOO_CHANGED_EVENT;
-/**
- * \brief a change as occurred in the list of children.
- *
- * This is only generated by watches on the child list of a node. These watches
- * are set using \ref zoo_get_children or \ref zoo_get_children2.
- */
-extern ZOOAPI const int ZOO_CHILD_EVENT;
-/**
- * \brief a session has been lost.
- *
- * This is generated when a client loses contact or reconnects with a server.
- */
-extern ZOOAPI const int ZOO_SESSION_EVENT;
-
-/**
- * \brief a watch has been removed.
- *
- * This is generated when the server for some reason, probably a resource
- * constraint, will no longer watch a node for a client.
- */
-extern ZOOAPI const int ZOO_NOTWATCHING_EVENT;
-// @}
-
-/**
- * \brief ZooKeeper handle.
- *
- * This is the handle that represents a connection to the ZooKeeper service.
- * It is needed to invoke any ZooKeeper function. A handle is obtained using
- * \ref zookeeper_init.
- */
-typedef struct _zhandle zhandle_t;
-
-/**
- * \brief client id structure.
- *
- * This structure holds the id and password for the session. This structure
- * should be treated as opaque. It is received from the server when a session
- * is established and needs to be sent back as-is when reconnecting a session.
- */
-typedef struct {
- int64_t client_id;
- char passwd[16];
-} clientid_t;
-
-/**
- * \brief zoo_op structure.
- *
- * This structure holds all the arguments necessary for one op as part
- * of a containing multi_op via \ref zoo_multi or \ref zoo_amulti.
- * This structure should be treated as opaque and initialized via
- * \ref zoo_create_op_init, \ref zoo_delete_op_init, \ref zoo_set_op_init
- * and \ref zoo_check_op_init.
- */
-typedef struct zoo_op {
- int type;
- union {
- // CREATE
- struct {
- const char *path;
- const char *data;
- int datalen;
- char *buf;
- int buflen;
- const struct ACL_vector *acl;
- int flags;
- } create_op;
-
- // DELETE
- struct {
- const char *path;
- int version;
- } delete_op;
-
- // SET
- struct {
- const char *path;
- const char *data;
- int datalen;
- int version;
- struct Stat *stat;
- } set_op;
-
- // CHECK
- struct {
- const char *path;
- int version;
- } check_op;
- };
-} zoo_op_t;
-
-/**
- * \brief zoo_create_op_init.
- *
- * This function initializes a zoo_op_t with the arguments for a ZOO_CREATE_OP.
- *
- * \param op A pointer to the zoo_op_t to be initialized.
- * \param path The name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param value The data to be stored in the node.
- * \param valuelen The number of bytes in data. To set the data to be NULL use
- * value as NULL and valuelen as -1.
- * \param acl The initial ACL of the node. The ACL must not be null or empty.
- * \param flags this parameter can be set to 0 for normal create or an OR
- * of the Create Flags
- * \param path_buffer Buffer which will be filled with the path of the
- * new node (this might be different than the supplied path
- * because of the ZOO_SEQUENCE flag). The path string will always be
- * null-terminated. This parameter may be NULL if path_buffer_len = 0.
- * \param path_buffer_len Size of path buffer; if the path of the new
- * node (including space for the null terminator) exceeds the buffer size,
- * the path string will be truncated to fit. The actual path of the
- * new node in the server will not be affected by the truncation.
- * The path string will always be null-terminated.
- */
-void zoo_create_op_init(zoo_op_t *op, const char *path, const char *value,
- int valuelen, const struct ACL_vector *acl, int flags,
- char *path_buffer, int path_buffer_len);
-
-/**
- * \brief zoo_delete_op_init.
- *
- * This function initializes a zoo_op_t with the arguments for a ZOO_DELETE_OP.
- *
- * \param op A pointer to the zoo_op_t to be initialized.
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param version the expected version of the node. The function will fail if the
- * actual version of the node does not match the expected version.
- * If -1 is used the version check will not take place.
- */
-void zoo_delete_op_init(zoo_op_t *op, const char *path, int version);
-
-/**
- * \brief zoo_set_op_init.
- *
- * This function initializes an zoo_op_t with the arguments for a ZOO_SETDATA_OP.
- *
- * \param op A pointer to the zoo_op_t to be initialized.
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param buffer the buffer holding data to be written to the node.
- * \param buflen the number of bytes from buffer to write. To set NULL as data
- * use buffer as NULL and buflen as -1.
- * \param version the expected version of the node. The function will fail if
- * the actual version of the node does not match the expected version. If -1 is
- * used the version check will not take place.
- */
-void zoo_set_op_init(zoo_op_t *op, const char *path, const char *buffer,
- int buflen, int version, struct Stat *stat);
-
-/**
- * \brief zoo_check_op_init.
- *
- * This function initializes an zoo_op_t with the arguments for a ZOO_CHECK_OP.
- *
- * \param op A pointer to the zoo_op_t to be initialized.
- * \param path The name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param version the expected version of the node. The function will fail if the
- * actual version of the node does not match the expected version.
- */
-void zoo_check_op_init(zoo_op_t *op, const char *path, int version);
-
-/**
- * \brief zoo_op_result structure.
- *
- * This structure holds the result for an op submitted as part of a multi_op
- * via \ref zoo_multi or \ref zoo_amulti.
- */
-typedef struct zoo_op_result {
- int err;
- char *value;
- int valuelen;
- struct Stat *stat;
-} zoo_op_result_t;
-
-/**
- * \brief signature of a watch function.
- *
- * There are two ways to receive watch notifications: legacy and watcher object.
- * <p>
- * The legacy style, an application wishing to receive events from ZooKeeper must
- * first implement a function with this signature and pass a pointer to the function
- * to \ref zookeeper_init. Next, the application sets a watch by calling one of
- * the getter API that accept the watch integer flag (for example, \ref zoo_aexists,
- * \ref zoo_get, etc).
- * <p>
- * The watcher object style uses an instance of a "watcher object" which in
- * the C world is represented by a pair: a pointer to a function implementing this
- * signature and a pointer to watcher context -- handback user-specific data.
- * When a watch is triggered this function will be called along with
- * the watcher context. An application wishing to use this style must use
- * the getter API functions with the "w" prefix in their names (for example, \ref
- * zoo_awexists, \ref zoo_wget, etc).
- *
- * \param zh zookeeper handle
- * \param type event type. This is one of the *_EVENT constants.
- * \param state connection state. The state value will be one of the *_STATE constants.
- * \param path znode path for which the watcher is triggered. NULL if the event
- * type is ZOO_SESSION_EVENT
- * \param watcherCtx watcher context.
- */
-typedef void (*watcher_fn)(zhandle_t *zh, int type,
- int state, const char *path,void *watcherCtx);
-
-/**
- * \brief create a handle to used communicate with zookeeper.
- *
- * This method creates a new handle and a zookeeper session that corresponds
- * to that handle. Session establishment is asynchronous, meaning that the
- * session should not be considered established until (and unless) an
- * event of state ZOO_CONNECTED_STATE is received.
- * \param host comma separated host:port pairs, each corresponding to a zk
- * server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002"
- * \param fn the global watcher callback function. When notifications are
- * triggered this function will be invoked.
- * \param clientid the id of a previously established session that this
- * client will be reconnecting to. Pass 0 if not reconnecting to a previous
- * session. Clients can access the session id of an established, valid,
- * connection by calling \ref zoo_client_id. If the session corresponding to
- * the specified clientid has expired, or if the clientid is invalid for
- * any reason, the returned zhandle_t will be invalid -- the zhandle_t
- * state will indicate the reason for failure (typically
- * ZOO_EXPIRED_SESSION_STATE).
- * \param context the handback object that will be associated with this instance
- * of zhandle_t. Application can access it (for example, in the watcher
- * callback) using \ref zoo_get_context. The object is not used by zookeeper
- * internally and can be null.
- * \param flags reserved for future use. Should be set to zero.
- * \return a pointer to the opaque zhandle structure. If it fails to create
- * a new zhandle the function returns NULL and the errno variable
- * indicates the reason.
- */
-ZOOAPI zhandle_t *zookeeper_init(const char *host, watcher_fn fn,
- int recv_timeout, const clientid_t *clientid, void *context, int flags);
-
-/**
- * \brief close the zookeeper handle and free up any resources.
- *
- * After this call, the client session will no longer be valid. The function
- * will flush any outstanding send requests before return. As a result it may
- * block.
- *
- * This method should only be called only once on a zookeeper handle. Calling
- * twice will cause undefined (and probably undesirable behavior). Calling any other
- * zookeeper method after calling close is undefined behaviour and should be avoided.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \return a result code. Regardless of the error code returned, the zhandle
- * will be destroyed and all resources freed.
- *
- * ZOK - success
- * ZBADARGUMENTS - invalid input parameters
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- * ZOPERATIONTIMEOUT - failed to flush the buffers within the specified timeout.
- * ZCONNECTIONLOSS - a network error occurred while attempting to send request to server
- * ZSYSTEMERROR -- a system (OS) error occurred; it's worth checking errno to get details
- */
-ZOOAPI int zookeeper_close(zhandle_t *zh);
-
-/**
- * \brief return the client session id, only valid if the connections
- * is currently connected (ie. last watcher state is ZOO_CONNECTED_STATE)
- */
-ZOOAPI const clientid_t *zoo_client_id(zhandle_t *zh);
-
-/**
- * \brief return the timeout for this session, only valid if the connections
- * is currently connected (ie. last watcher state is ZOO_CONNECTED_STATE). This
- * value may change after a server re-connect.
- */
-ZOOAPI int zoo_recv_timeout(zhandle_t *zh);
-
-/**
- * \brief return the context for this handle.
- */
-ZOOAPI const void *zoo_get_context(zhandle_t *zh);
-
-/**
- * \brief set the context for this handle.
- */
-ZOOAPI void zoo_set_context(zhandle_t *zh, void *context);
-
-/**
- * \brief set a watcher function
- * \return previous watcher function
- */
-ZOOAPI watcher_fn zoo_set_watcher(zhandle_t *zh,watcher_fn newFn);
-
-/**
- * \brief returns the socket address for the current connection
- * \return socket address of the connected host or NULL on failure, only valid if the
- * connection is current connected
- */
-ZOOAPI struct sockaddr* zookeeper_get_connected_host(zhandle_t *zh,
- struct sockaddr *addr, socklen_t *addr_len);
-
-#ifndef THREADED
-/**
- * \brief Returns the events that zookeeper is interested in.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param fd is the file descriptor of interest
- * \param interest is an or of the ZOOKEEPER_WRITE and ZOOKEEPER_READ flags to
- * indicate the I/O of interest on fd.
- * \param tv a timeout value to be used with select/poll system call
- * \return a result code.
- * ZOK - success
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZCONNECTIONLOSS - a network error occurred while attempting to establish
- * a connection to the server
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- * ZOPERATIONTIMEOUT - hasn't received anything from the server for 2/3 of the
- * timeout value specified in zookeeper_init()
- * ZSYSTEMERROR -- a system (OS) error occurred; it's worth checking errno to get details
- */
-#ifdef WIN32
-ZOOAPI int zookeeper_interest(zhandle_t *zh, SOCKET *fd, int *interest,
- struct timeval *tv);
-#else
-ZOOAPI int zookeeper_interest(zhandle_t *zh, int *fd, int *interest,
- struct timeval *tv);
-#endif
-
-/**
- * \brief Notifies zookeeper that an event of interest has happened.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param events will be an OR of the ZOOKEEPER_WRITE and ZOOKEEPER_READ flags.
- * \return a result code.
- * ZOK - success
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZCONNECTIONLOSS - a network error occurred while attempting to send request to server
- * ZSESSIONEXPIRED - connection attempt failed -- the session's expired
- * ZAUTHFAILED - authentication request failed, e.i. invalid credentials
- * ZRUNTIMEINCONSISTENCY - a server response came out of order
- * ZSYSTEMERROR -- a system (OS) error occurred; it's worth checking errno to get details
- * ZNOTHING -- not an error; simply indicates that there no more data from the server
- * to be processed (when called with ZOOKEEPER_READ flag).
- */
-ZOOAPI int zookeeper_process(zhandle_t *zh, int events);
-#endif
-
-/**
- * \brief signature of a completion function for a call that returns void.
- *
- * This method will be invoked at the end of a asynchronous call and also as
- * a result of connection loss or timeout.
- * \param rc the error code of the call. Connection loss/timeout triggers
- * the completion with one of the following error codes:
- * ZCONNECTIONLOSS -- lost connection to the server
- * ZOPERATIONTIMEOUT -- connection timed out
- * Data related events trigger the completion with error codes listed the
- * Exceptions section of the documentation of the function that initiated the
- * call. (Zero indicates call was successful.)
- * \param data the pointer that was passed by the caller when the function
- * that this completion corresponds to was invoked. The programmer
- * is responsible for any memory freeing associated with the data
- * pointer.
- */
-typedef void (*void_completion_t)(int rc, const void *data);
-
-/**
- * \brief signature of a completion function that returns a Stat structure.
- *
- * This method will be invoked at the end of a asynchronous call and also as
- * a result of connection loss or timeout.
- * \param rc the error code of the call. Connection loss/timeout triggers
- * the completion with one of the following error codes:
- * ZCONNECTIONLOSS -- lost connection to the server
- * ZOPERATIONTIMEOUT -- connection timed out
- * Data related events trigger the completion with error codes listed the
- * Exceptions section of the documentation of the function that initiated the
- * call. (Zero indicates call was successful.)
- * \param stat a pointer to the stat information for the node involved in
- * this function. If a non zero error code is returned, the content of
- * stat is undefined. The programmer is NOT responsible for freeing stat.
- * \param data the pointer that was passed by the caller when the function
- * that this completion corresponds to was invoked. The programmer
- * is responsible for any memory freeing associated with the data
- * pointer.
- */
-typedef void (*stat_completion_t)(int rc, const struct Stat *stat,
- const void *data);
-
-/**
- * \brief signature of a completion function that returns data.
- *
- * This method will be invoked at the end of a asynchronous call and also as
- * a result of connection loss or timeout.
- * \param rc the error code of the call. Connection loss/timeout triggers
- * the completion with one of the following error codes:
- * ZCONNECTIONLOSS -- lost connection to the server
- * ZOPERATIONTIMEOUT -- connection timed out
- * Data related events trigger the completion with error codes listed the
- * Exceptions section of the documentation of the function that initiated the
- * call. (Zero indicates call was successful.)
- * \param value the value of the information returned by the asynchronous call.
- * If a non zero error code is returned, the content of value is undefined.
- * The programmer is NOT responsible for freeing value.
- * \param value_len the number of bytes in value.
- * \param stat a pointer to the stat information for the node involved in
- * this function. If a non zero error code is returned, the content of
- * stat is undefined. The programmer is NOT responsible for freeing stat.
- * \param data the pointer that was passed by the caller when the function
- * that this completion corresponds to was invoked. The programmer
- * is responsible for any memory freeing associated with the data
- * pointer.
- */
-typedef void (*data_completion_t)(int rc, const char *value, int value_len,
- const struct Stat *stat, const void *data);
-
-/**
- * \brief signature of a completion function that returns a list of strings.
- *
- * This method will be invoked at the end of a asynchronous call and also as
- * a result of connection loss or timeout.
- * \param rc the error code of the call. Connection loss/timeout triggers
- * the completion with one of the following error codes:
- * ZCONNECTIONLOSS -- lost connection to the server
- * ZOPERATIONTIMEOUT -- connection timed out
- * Data related events trigger the completion with error codes listed the
- * Exceptions section of the documentation of the function that initiated the
- * call. (Zero indicates call was successful.)
- * \param strings a pointer to the structure containng the list of strings of the
- * names of the children of a node. If a non zero error code is returned,
- * the content of strings is undefined. The programmer is NOT responsible
- * for freeing strings.
- * \param data the pointer that was passed by the caller when the function
- * that this completion corresponds to was invoked. The programmer
- * is responsible for any memory freeing associated with the data
- * pointer.
- */
-typedef void (*strings_completion_t)(int rc,
- const struct String_vector *strings, const void *data);
-
-/**
- * \brief signature of a completion function that returns a list of strings and stat.
- * .
- *
- * This method will be invoked at the end of a asynchronous call and also as
- * a result of connection loss or timeout.
- * \param rc the error code of the call. Connection loss/timeout triggers
- * the completion with one of the following error codes:
- * ZCONNECTIONLOSS -- lost connection to the server
- * ZOPERATIONTIMEOUT -- connection timed out
- * Data related events trigger the completion with error codes listed the
- * Exceptions section of the documentation of the function that initiated the
- * call. (Zero indicates call was successful.)
- * \param strings a pointer to the structure containng the list of strings of the
- * names of the children of a node. If a non zero error code is returned,
- * the content of strings is undefined. The programmer is NOT responsible
- * for freeing strings.
- * \param stat a pointer to the stat information for the node involved in
- * this function. If a non zero error code is returned, the content of
- * stat is undefined. The programmer is NOT responsible for freeing stat.
- * \param data the pointer that was passed by the caller when the function
- * that this completion corresponds to was invoked. The programmer
- * is responsible for any memory freeing associated with the data
- * pointer.
- */
-typedef void (*strings_stat_completion_t)(int rc,
- const struct String_vector *strings, const struct Stat *stat,
- const void *data);
-
-/**
- * \brief signature of a completion function that returns a list of strings.
- *
- * This method will be invoked at the end of a asynchronous call and also as
- * a result of connection loss or timeout.
- * \param rc the error code of the call. Connection loss/timeout triggers
- * the completion with one of the following error codes:
- * ZCONNECTIONLOSS -- lost connection to the server
- * ZOPERATIONTIMEOUT -- connection timed out
- * Data related events trigger the completion with error codes listed the
- * Exceptions section of the documentation of the function that initiated the
- * call. (Zero indicates call was successful.)
- * \param value the value of the string returned.
- * \param data the pointer that was passed by the caller when the function
- * that this completion corresponds to was invoked. The programmer
- * is responsible for any memory freeing associated with the data
- * pointer.
- */
-typedef void
- (*string_completion_t)(int rc, const char *value, const void *data);
-
-/**
- * \brief signature of a completion function that returns an ACL.
- *
- * This method will be invoked at the end of a asynchronous call and also as
- * a result of connection loss or timeout.
- * \param rc the error code of the call. Connection loss/timeout triggers
- * the completion with one of the following error codes:
- * ZCONNECTIONLOSS -- lost connection to the server
- * ZOPERATIONTIMEOUT -- connection timed out
- * Data related events trigger the completion with error codes listed the
- * Exceptions section of the documentation of the function that initiated the
- * call. (Zero indicates call was successful.)
- * \param acl a pointer to the structure containng the ACL of a node. If a non
- * zero error code is returned, the content of strings is undefined. The
- * programmer is NOT responsible for freeing acl.
- * \param stat a pointer to the stat information for the node involved in
- * this function. If a non zero error code is returned, the content of
- * stat is undefined. The programmer is NOT responsible for freeing stat.
- * \param data the pointer that was passed by the caller when the function
- * that this completion corresponds to was invoked. The programmer
- * is responsible for any memory freeing associated with the data
- * pointer.
- */
-typedef void (*acl_completion_t)(int rc, struct ACL_vector *acl,
- struct Stat *stat, const void *data);
-
-/**
- * \brief get the state of the zookeeper connection.
- *
- * The return value will be one of the \ref State Consts.
- */
-ZOOAPI int zoo_state(zhandle_t *zh);
-
-/**
- * \brief create a node.
- *
- * This method will create a node in ZooKeeper. A node can only be created if
- * it does not already exists. The Create Flags affect the creation of nodes.
- * If ZOO_EPHEMERAL flag is set, the node will automatically get removed if the
- * client session goes away. If the ZOO_SEQUENCE flag is set, a unique
- * monotonically increasing sequence number is appended to the path name. The
- * sequence number is always fixed length of 10 digits, 0 padded.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path The name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param value The data to be stored in the node.
- * \param valuelen The number of bytes in data.
- * \param acl The initial ACL of the node. The ACL must not be null or empty.
- * \param flags this parameter can be set to 0 for normal create or an OR
- * of the Create Flags
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with one of the following codes passed in as the rc argument:
- * ZOK operation completed successfully
- * ZNONODE the parent node does not exist.
- * ZNODEEXISTS the node already exists
- * ZNOAUTH the client does not have permission.
- * ZNOCHILDRENFOREPHEMERALS cannot create children of ephemeral nodes.
- * \param data The data that will be passed to the completion routine when the
- * function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_acreate(zhandle_t *zh, const char *path, const char *value,
- int valuelen, const struct ACL_vector *acl, int flags,
- string_completion_t completion, const void *data);
-
-/**
- * \brief delete a node in zookeeper.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param version the expected version of the node. The function will fail if the
- * actual version of the node does not match the expected version.
- * If -1 is used the version check will not take place.
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with one of the following codes passed in as the rc argument:
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZBADVERSION expected version does not match actual version.
- * ZNOTEMPTY children are present; node cannot be deleted.
- * \param data the data that will be passed to the completion routine when
- * the function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_adelete(zhandle_t *zh, const char *path, int version,
- void_completion_t completion, const void *data);
-
-/**
- * \brief checks the existence of a node in zookeeper.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watch if nonzero, a watch will be set at the server to notify the
- * client if the node changes. The watch will be set even if the node does not
- * exist. This allows clients to watch for nodes to appear.
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with one of the following codes passed in as the rc argument:
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * \param data the data that will be passed to the completion routine when the
- * function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_aexists(zhandle_t *zh, const char *path, int watch,
- stat_completion_t completion, const void *data);
-
-/**
- * \brief checks the existence of a node in zookeeper.
- *
- * This function is similar to \ref zoo_axists except it allows one specify
- * a watcher object - a function pointer and associated context. The function
- * will be called once the watch has fired. The associated context data will be
- * passed to the function as the watcher context parameter.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watcher if non-null a watch will set on the specified znode on the server.
- * The watch will be set even if the node does not exist. This allows clients
- * to watch for nodes to appear.
- * \param watcherCtx user specific data, will be passed to the watcher callback.
- * Unlike the global context set by \ref zookeeper_init, this watcher context
- * is associated with the given instance of the watcher only.
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with one of the following codes passed in as the rc argument:
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * \param data the data that will be passed to the completion routine when the
- * function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_awexists(zhandle_t *zh, const char *path,
- watcher_fn watcher, void* watcherCtx,
- stat_completion_t completion, const void *data);
-
-/**
- * \brief gets the data associated with a node.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watch if nonzero, a watch will be set at the server to notify
- * the client if the node changes.
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with one of the following codes passed in as the rc argument:
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * \param data the data that will be passed to the completion routine when
- * the function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either in ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_aget(zhandle_t *zh, const char *path, int watch,
- data_completion_t completion, const void *data);
-
-/**
- * \brief gets the data associated with a node.
- *
- * This function is similar to \ref zoo_aget except it allows one specify
- * a watcher object rather than a boolean watch flag.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watcher if non-null, a watch will be set at the server to notify
- * the client if the node changes.
- * \param watcherCtx user specific data, will be passed to the watcher callback.
- * Unlike the global context set by \ref zookeeper_init, this watcher context
- * is associated with the given instance of the watcher only.
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with one of the following codes passed in as the rc argument:
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * \param data the data that will be passed to the completion routine when
- * the function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either in ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_awget(zhandle_t *zh, const char *path,
- watcher_fn watcher, void* watcherCtx,
- data_completion_t completion, const void *data);
-
-/**
- * \brief sets the data associated with a node.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param buffer the buffer holding data to be written to the node.
- * \param buflen the number of bytes from buffer to write.
- * \param version the expected version of the node. The function will fail if
- * the actual version of the node does not match the expected version. If -1 is
- * used the version check will not take place. * completion: If null,
- * the function will execute synchronously. Otherwise, the function will return
- * immediately and invoke the completion routine when the request completes.
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with one of the following codes passed in as the rc argument:
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZBADVERSION expected version does not match actual version.
- * \param data the data that will be passed to the completion routine when
- * the function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_aset(zhandle_t *zh, const char *path, const char *buffer, int buflen,
- int version, stat_completion_t completion, const void *data);
-
-/**
- * \brief lists the children of a node.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watch if nonzero, a watch will be set at the server to notify
- * the client if the node changes.
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with one of the following codes passed in as the rc argument:
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * \param data the data that will be passed to the completion routine when
- * the function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_aget_children(zhandle_t *zh, const char *path, int watch,
- strings_completion_t completion, const void *data);
-
-/**
- * \brief lists the children of a node.
- *
- * This function is similar to \ref zoo_aget_children except it allows one specify
- * a watcher object rather than a boolean watch flag.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watcher if non-null, a watch will be set at the server to notify
- * the client if the node changes.
- * \param watcherCtx user specific data, will be passed to the watcher callback.
- * Unlike the global context set by \ref zookeeper_init, this watcher context
- * is associated with the given instance of the watcher only.
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with one of the following codes passed in as the rc argument:
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * \param data the data that will be passed to the completion routine when
- * the function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_awget_children(zhandle_t *zh, const char *path,
- watcher_fn watcher, void* watcherCtx,
- strings_completion_t completion, const void *data);
-
-/**
- * \brief lists the children of a node, and get the parent stat.
- *
- * This function is new in version 3.3.0
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watch if nonzero, a watch will be set at the server to notify
- * the client if the node changes.
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with one of the following codes passed in as the rc argument:
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * \param data the data that will be passed to the completion routine when
- * the function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_aget_children2(zhandle_t *zh, const char *path, int watch,
- strings_stat_completion_t completion, const void *data);
-
-/**
- * \brief lists the children of a node, and get the parent stat.
- *
- * This function is similar to \ref zoo_aget_children2 except it allows one specify
- * a watcher object rather than a boolean watch flag.
- *
- * This function is new in version 3.3.0
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watcher if non-null, a watch will be set at the server to notify
- * the client if the node changes.
- * \param watcherCtx user specific data, will be passed to the watcher callback.
- * Unlike the global context set by \ref zookeeper_init, this watcher context
- * is associated with the given instance of the watcher only.
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with one of the following codes passed in as the rc argument:
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * \param data the data that will be passed to the completion routine when
- * the function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_awget_children2(zhandle_t *zh, const char *path,
- watcher_fn watcher, void* watcherCtx,
- strings_stat_completion_t completion, const void *data);
-
-/**
- * \brief Flush leader channel.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with one of the following codes passed in as the rc argument:
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * \param data the data that will be passed to the completion routine when
- * the function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-
-ZOOAPI int zoo_async(zhandle_t *zh, const char *path,
- string_completion_t completion, const void *data);
-
-
-/**
- * \brief gets the acl associated with a node.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with one of the following codes passed in as the rc argument:
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * \param data the data that will be passed to the completion routine when
- * the function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_aget_acl(zhandle_t *zh, const char *path, acl_completion_t completion,
- const void *data);
-
-/**
- * \brief sets the acl associated with a node.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param buffer the buffer holding the acls to be written to the node.
- * \param buflen the number of bytes from buffer to write.
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with one of the following codes passed in as the rc argument:
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZINVALIDACL invalid ACL specified
- * ZBADVERSION expected version does not match actual version.
- * \param data the data that will be passed to the completion routine when
- * the function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_aset_acl(zhandle_t *zh, const char *path, int version,
- struct ACL_vector *acl, void_completion_t, const void *data);
-
-/**
- * \brief atomically commits multiple zookeeper operations.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param count the number of operations
- * \param ops an array of operations to commit
- * \param results an array to hold the results of the operations
- * \param completion the routine to invoke when the request completes. The completion
- * will be triggered with any of the error codes that can that can be returned by the
- * ops supported by a multi op (see \ref zoo_acreate, \ref zoo_adelete, \ref zoo_aset).
- * \param data the data that will be passed to the completion routine when
- * the function completes.
- * \return the return code for the function call. This can be any of the
- * values that can be returned by the ops supported by a multi op (see
- * \ref zoo_acreate, \ref zoo_adelete, \ref zoo_aset).
- */
-ZOOAPI int zoo_amulti(zhandle_t *zh, int count, const zoo_op_t *ops,
- zoo_op_result_t *results, void_completion_t, const void *data);
-
-/**
- * \brief return an error string.
- *
- * \param return code
- * \return string corresponding to the return code
- */
-ZOOAPI const char* zerror(int c);
-
-/**
- * \brief specify application credentials.
- *
- * The application calls this function to specify its credentials for purposes
- * of authentication. The server will use the security provider specified by
- * the scheme parameter to authenticate the client connection. If the
- * authentication request has failed:
- * - the server connection is dropped
- * - the watcher is called with the ZOO_AUTH_FAILED_STATE value as the state
- * parameter.
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param scheme the id of authentication scheme. Natively supported:
- * "digest" password-based authentication
- * \param cert application credentials. The actual value depends on the scheme.
- * \param certLen the length of the data parameter
- * \param completion the routine to invoke when the request completes. One of
- * the following result codes may be passed into the completion callback:
- * ZOK operation completed successfully
- * ZAUTHFAILED authentication failed
- * \param data the data that will be passed to the completion routine when the
- * function completes.
- * \return ZOK on success or one of the following errcodes on failure:
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- * ZSYSTEMERROR - a system error occurred
- */
-ZOOAPI int zoo_add_auth(zhandle_t *zh,const char* scheme,const char* cert,
- int certLen, void_completion_t completion, const void *data);
-
-/**
- * \brief checks if the current zookeeper connection state can't be recovered.
- *
- * The application must close the zhandle and try to reconnect.
- *
- * \param zh the zookeeper handle (see \ref zookeeper_init)
- * \return ZINVALIDSTATE if connection is unrecoverable
- */
-ZOOAPI int is_unrecoverable(zhandle_t *zh);
-
-/**
- * \brief sets the debugging level for the library
- */
-ZOOAPI void zoo_set_debug_level(ZooLogLevel logLevel);
-
-/**
- * \brief sets the stream to be used by the library for logging
- *
- * The zookeeper library uses stderr as its default log stream. Application
- * must make sure the stream is writable. Passing in NULL resets the stream
- * to its default value (stderr).
- */
-ZOOAPI void zoo_set_log_stream(FILE* logStream);
-
-/**
- * \brief enable/disable quorum endpoint order randomization
- *
- * Note: typically this method should NOT be used outside of testing.
- *
- * If passed a non-zero value, will make the client connect to quorum peers
- * in the order as specified in the zookeeper_init() call.
- * A zero value causes zookeeper_init() to permute the peer endpoints
- * which is good for more even client connection distribution among the
- * quorum peers.
- */
-ZOOAPI void zoo_deterministic_conn_order(int yesOrNo);
-
-/**
- * \brief create a node synchronously.
- *
- * This method will create a node in ZooKeeper. A node can only be created if
- * it does not already exists. The Create Flags affect the creation of nodes.
- * If ZOO_EPHEMERAL flag is set, the node will automatically get removed if the
- * client session goes away. If the ZOO_SEQUENCE flag is set, a unique
- * monotonically increasing sequence number is appended to the path name.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path The name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param value The data to be stored in the node.
- * \param valuelen The number of bytes in data. To set the data to be NULL use
- * value as NULL and valuelen as -1.
- * \param acl The initial ACL of the node. The ACL must not be null or empty.
- * \param flags this parameter can be set to 0 for normal create or an OR
- * of the Create Flags
- * \param path_buffer Buffer which will be filled with the path of the
- * new node (this might be different than the supplied path
- * because of the ZOO_SEQUENCE flag). The path string will always be
- * null-terminated. This parameter may be NULL if path_buffer_len = 0.
- * \param path_buffer_len Size of path buffer; if the path of the new
- * node (including space for the null terminator) exceeds the buffer size,
- * the path string will be truncated to fit. The actual path of the
- * new node in the server will not be affected by the truncation.
- * The path string will always be null-terminated.
- * \return one of the following codes are returned:
- * ZOK operation completed successfully
- * ZNONODE the parent node does not exist.
- * ZNODEEXISTS the node already exists
- * ZNOAUTH the client does not have permission.
- * ZNOCHILDRENFOREPHEMERALS cannot create children of ephemeral nodes.
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_create(zhandle_t *zh, const char *path, const char *value,
- int valuelen, const struct ACL_vector *acl, int flags,
- char *path_buffer, int path_buffer_len);
-
-/**
- * \brief delete a node in zookeeper synchronously.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param version the expected version of the node. The function will fail if the
- * actual version of the node does not match the expected version.
- * If -1 is used the version check will not take place.
- * \return one of the following values is returned.
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZBADVERSION expected version does not match actual version.
- * ZNOTEMPTY children are present; node cannot be deleted.
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_delete(zhandle_t *zh, const char *path, int version);
-
-
-/**
- * \brief checks the existence of a node in zookeeper synchronously.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watch if nonzero, a watch will be set at the server to notify the
- * client if the node changes. The watch will be set even if the node does not
- * exist. This allows clients to watch for nodes to appear.
- * \param the return stat value of the node.
- * \return return code of the function call.
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_exists(zhandle_t *zh, const char *path, int watch, struct Stat *stat);
-
-/**
- * \brief checks the existence of a node in zookeeper synchronously.
- *
- * This function is similar to \ref zoo_exists except it allows one specify
- * a watcher object rather than a boolean watch flag.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watcher if non-null a watch will set on the specified znode on the server.
- * The watch will be set even if the node does not exist. This allows clients
- * to watch for nodes to appear.
- * \param watcherCtx user specific data, will be passed to the watcher callback.
- * Unlike the global context set by \ref zookeeper_init, this watcher context
- * is associated with the given instance of the watcher only.
- * \param the return stat value of the node.
- * \return return code of the function call.
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_wexists(zhandle_t *zh, const char *path,
- watcher_fn watcher, void* watcherCtx, struct Stat *stat);
-
-/**
- * \brief gets the data associated with a node synchronously.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watch if nonzero, a watch will be set at the server to notify
- * the client if the node changes.
- * \param buffer the buffer holding the node data returned by the server
- * \param buffer_len is the size of the buffer pointed to by the buffer parameter.
- * It'll be set to the actual data length upon return. If the data is NULL, length is -1.
- * \param stat if not NULL, will hold the value of stat for the path on return.
- * \return return value of the function call.
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either in ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_get(zhandle_t *zh, const char *path, int watch, char *buffer,
- int* buffer_len, struct Stat *stat);
-
-/**
- * \brief gets the data associated with a node synchronously.
- *
- * This function is similar to \ref zoo_get except it allows one specify
- * a watcher object rather than a boolean watch flag.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watcher if non-null, a watch will be set at the server to notify
- * the client if the node changes.
- * \param watcherCtx user specific data, will be passed to the watcher callback.
- * Unlike the global context set by \ref zookeeper_init, this watcher context
- * is associated with the given instance of the watcher only.
- * \param buffer the buffer holding the node data returned by the server
- * \param buffer_len is the size of the buffer pointed to by the buffer parameter.
- * It'll be set to the actual data length upon return. If the data is NULL, length is -1.
- * \param stat if not NULL, will hold the value of stat for the path on return.
- * \return return value of the function call.
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either in ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_wget(zhandle_t *zh, const char *path,
- watcher_fn watcher, void* watcherCtx,
- char *buffer, int* buffer_len, struct Stat *stat);
-
-/**
- * \brief sets the data associated with a node. See zoo_set2 function if
- * you require access to the stat information associated with the znode.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param buffer the buffer holding data to be written to the node.
- * \param buflen the number of bytes from buffer to write. To set NULL as data
- * use buffer as NULL and buflen as -1.
- * \param version the expected version of the node. The function will fail if
- * the actual version of the node does not match the expected version. If -1 is
- * used the version check will not take place.
- * \return the return code for the function call.
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZBADVERSION expected version does not match actual version.
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_set(zhandle_t *zh, const char *path, const char *buffer,
- int buflen, int version);
-
-/**
- * \brief sets the data associated with a node. This function is the same
- * as zoo_set except that it also provides access to stat information
- * associated with the znode.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param buffer the buffer holding data to be written to the node.
- * \param buflen the number of bytes from buffer to write. To set NULL as data
- * use buffer as NULL and buflen as -1.
- * \param version the expected version of the node. The function will fail if
- * the actual version of the node does not match the expected version. If -1 is
- * used the version check will not take place.
- * \param stat if not NULL, will hold the value of stat for the path on return.
- * \return the return code for the function call.
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZBADVERSION expected version does not match actual version.
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_set2(zhandle_t *zh, const char *path, const char *buffer,
- int buflen, int version, struct Stat *stat);
-
-/**
- * \brief lists the children of a node synchronously.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watch if nonzero, a watch will be set at the server to notify
- * the client if the node changes.
- * \param strings return value of children paths.
- * \return the return code of the function.
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_get_children(zhandle_t *zh, const char *path, int watch,
- struct String_vector *strings);
-
-/**
- * \brief lists the children of a node synchronously.
- *
- * This function is similar to \ref zoo_get_children except it allows one specify
- * a watcher object rather than a boolean watch flag.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watcher if non-null, a watch will be set at the server to notify
- * the client if the node changes.
- * \param watcherCtx user specific data, will be passed to the watcher callback.
- * Unlike the global context set by \ref zookeeper_init, this watcher context
- * is associated with the given instance of the watcher only.
- * \param strings return value of children paths.
- * \return the return code of the function.
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_wget_children(zhandle_t *zh, const char *path,
- watcher_fn watcher, void* watcherCtx,
- struct String_vector *strings);
-
-/**
- * \brief lists the children of a node and get its stat synchronously.
- *
- * This function is new in version 3.3.0
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watch if nonzero, a watch will be set at the server to notify
- * the client if the node changes.
- * \param strings return value of children paths.
- * \param stat return value of node stat.
- * \return the return code of the function.
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_get_children2(zhandle_t *zh, const char *path, int watch,
- struct String_vector *strings, struct Stat *stat);
-
-/**
- * \brief lists the children of a node and get its stat synchronously.
- *
- * This function is similar to \ref zoo_get_children except it allows one specify
- * a watcher object rather than a boolean watch flag.
- *
- * This function is new in version 3.3.0
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param watcher if non-null, a watch will be set at the server to notify
- * the client if the node changes.
- * \param watcherCtx user specific data, will be passed to the watcher callback.
- * Unlike the global context set by \ref zookeeper_init, this watcher context
- * is associated with the given instance of the watcher only.
- * \param strings return value of children paths.
- * \param stat return value of node stat.
- * \return the return code of the function.
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_wget_children2(zhandle_t *zh, const char *path,
- watcher_fn watcher, void* watcherCtx,
- struct String_vector *strings, struct Stat *stat);
-
-/**
- * \brief gets the acl associated with a node synchronously.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param acl the return value of acls on the path.
- * \param stat returns the stat of the path specified.
- * \return the return code for the function call.
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_get_acl(zhandle_t *zh, const char *path, struct ACL_vector *acl,
- struct Stat *stat);
-
-/**
- * \brief sets the acl associated with a node synchronously.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param path the name of the node. Expressed as a file name with slashes
- * separating ancestors of the node.
- * \param version the expected version of the path.
- * \param acl the acl to be set on the path.
- * \return the return code for the function call.
- * ZOK operation completed successfully
- * ZNONODE the node does not exist.
- * ZNOAUTH the client does not have permission.
- * ZINVALIDACL invalid ACL specified
- * ZBADVERSION expected version does not match actual version.
- * ZBADARGUMENTS - invalid input parameters
- * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
- * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
- */
-ZOOAPI int zoo_set_acl(zhandle_t *zh, const char *path, int version,
- const struct ACL_vector *acl);
-
-/**
- * \brief atomically commits multiple zookeeper operations synchronously.
- *
- * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
- * \param count the number of operations
- * \param ops an array of operations to commit
- * \param results an array to hold the results of the operations
- * \return the return code for the function call. This can be any of the
- * values that can be returned by the ops supported by a multi op (see
- * \ref zoo_acreate, \ref zoo_adelete, \ref zoo_aset).
- */
-ZOOAPI int zoo_multi(zhandle_t *zh, int count, const zoo_op_t *ops, zoo_op_result_t *results);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*ZOOKEEPER_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/include/zookeeper_log.h
----------------------------------------------------------------------
diff --git a/src/c/include/zookeeper_log.h b/src/c/include/zookeeper_log.h
deleted file mode 100644
index e5917cb..0000000
--- a/src/c/include/zookeeper_log.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * 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 LOGSTREAM getLogStream()
-
-#define LOG_ERROR(x) if(logLevel>=ZOO_LOG_LEVEL_ERROR) \
- log_message(ZOO_LOG_LEVEL_ERROR,__LINE__,__func__,format_log_message x)
-#define LOG_WARN(x) if(logLevel>=ZOO_LOG_LEVEL_WARN) \
- log_message(ZOO_LOG_LEVEL_WARN,__LINE__,__func__,format_log_message x)
-#define LOG_INFO(x) if(logLevel>=ZOO_LOG_LEVEL_INFO) \
- log_message(ZOO_LOG_LEVEL_INFO,__LINE__,__func__,format_log_message x)
-#define LOG_DEBUG(x) if(logLevel==ZOO_LOG_LEVEL_DEBUG) \
- log_message(ZOO_LOG_LEVEL_DEBUG,__LINE__,__func__,format_log_message x)
-
-ZOOAPI void log_message(ZooLogLevel curLevel, int line,const char* funcName,
- const char* message);
-
-ZOOAPI const char* format_log_message(const char* format,...);
-
-FILE* getLogStream();
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*ZK_LOG_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/include/zookeeper_version.h
----------------------------------------------------------------------
diff --git a/src/c/include/zookeeper_version.h b/src/c/include/zookeeper_version.h
deleted file mode 100644
index 518f7e6..0000000
--- a/src/c/include/zookeeper_version.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * 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 4
-#define ZOO_PATCH_VERSION 12
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ZOOKEEPER_VERSION_H_ */
[14/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/CollectionUtil.h
----------------------------------------------------------------------
diff --git a/src/c/tests/CollectionUtil.h b/src/c/tests/CollectionUtil.h
deleted file mode 100644
index dd34811..0000000
--- a/src/c/tests/CollectionUtil.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/**
- * 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 _COLLECTION_UTIL_H_
-#define _COLLECTION_UTIL_H_
-
-/**
- * \file
- * CollectionBuilder and DictionaryBuilder classes and collection utility functions
- */
-
-namespace Util
-{
-
-// *********************************************************
-/** A shortcut to use for building collections.
- * This class is a wrapper around standard STL collection containers such as vector.
- * It allows one to conveniently build collections at the variable initialization time:
- * \code
- * #include "CollectionUtil.h"
- * #include "Vector.h" // for ostream << operator overload for STL vector
- * using Util;
- *
- * int main()
- * {
- * typedef vector<string> MyVector;
- * MyVector myVector=CollectionBuilder<MyVector>()("str1")("str2")("str3");
- * cout<<myVector;
- * // the following output will be produced:
- * // [str1,str2,str3]
- * }
- * \endcode
- */
-template <class CONT>
-class CollectionBuilder
-{
-public:
- /// Type of the collection container.
- typedef CONT CollectionType;
- /// Container's value type.
- typedef typename CollectionType::value_type value_type;
- /// Container's constant iterator type.
- typedef typename CollectionType::const_iterator const_iterator;
- /// Container's size type.
- typedef typename CollectionType::size_type size_type;
-
- /** Operator function call overload to allow call chaining.
- * \param value the value to be inserted into the container
- */
- CollectionBuilder<CONT>& operator()(const value_type& value){
- return push_back(value);
- }
- /** Same as regular STL push_back() but allows call chaining.
- * \param value the value to be inserted into the container
- */
- CollectionBuilder<CONT>& push_back(const value_type& value){
- collection_.push_back(value);
- return *this;
- }
- /// \name Standard STL container interface
- /// @{
- const_iterator begin() const{return collection_.begin();}
- const_iterator end() const{return collection_.end();}
- size_type size() const{return collection_.size();}
- void clear() {collection_.clear();}
- ///@}
- /// Explicit typecast operator.
- operator const CollectionType&() const {return collection_;}
-private:
- /// \cond PRIVATE
- CollectionType collection_;
- /// \endcond
-};
-
-
-// *********************************************************
-/** A shortcut to use for building dictionaries.
- * This class is a wrapper around standard STL associative containers such as map.
- * It allows one to conveniently build dictionaries at the variable initialization time:
- * \code
- * #include "CollectionUtil.h"
- * #include "Map.h" // for ostream << operator overload for STL map
- * using Util;
- *
- * int main()
- * {
- * typedef map<string,int> MyMap;
- * MyMap myMap=DictionaryBuilder<MyMap>()("str1",1)("str2",2)("str3",3);
- * cout<<myMap;
- * // the following output will be produced:
- * // [str1=1,str2=2,str3=3]
- * }
- * \endcode
- */
-template <class CONT>
-class DictionaryBuilder
-{
-public:
- /// The type of the associative container
- typedef CONT DictionaryType;
- /// Container's element type (usually a pair<key_type,mapped_type>)
- typedef typename DictionaryType::value_type value_type;
- /// Container's key type
- typedef typename DictionaryType::key_type key_type;
- /// Container's value type
- typedef typename DictionaryType::mapped_type mapped_type;
- /// Container's constant iterator type
- typedef typename DictionaryType::const_iterator const_iterator;
- /// Container's writable iterator type
- typedef typename DictionaryType::iterator iterator;
- /// Container's size type
- typedef typename DictionaryType::size_type size_type;
-
- /** Operator function call overload to allow call chaining.
- * \param key the value key to be inserted
- * \param value the value to be inserted into the container
- * \return a non-const reference to self
- */
- DictionaryBuilder<CONT>& operator()(const key_type& key,const mapped_type& value){
- dict_.insert(value_type(key,value));
- return *this;
- }
- /** Lookup value by key.
- * \param key the key associated with the value.
- * \return a non-const iterator pointing to the element whose key matched the \a key parameter
- */
- iterator find(const key_type& key){
- return dict_.find(key);
- }
- /** Lookup value by key.
- * \param key the key associated with the value.
- * \return a const iterator pointing to the element whose key matched the \a key parameter
- */
- const_iterator find(const key_type& key) const{
- return dict_.find(key);
- }
-
- /// \name Standard STL container interface
- /// @{
- const_iterator begin() const{return dict_.begin();}
- const_iterator end() const{return dict_.end();}
- size_type size() const{return dict_.size();}
- void clear() {dict_.clear();}
- ///@}
- /// Explicit typecast operator.
- operator const DictionaryType&() const {return dict_;}
-private:
- DictionaryType dict_;
-};
-
-
-// ***********************************************************
-/** Deletes all dynamically allocated elements of a collection.
- * C::value_type is expected to be a pointer to a dynamically allocated object, or it won't compile.
- * The function will iterate over all container elements and call delete for each of them.
- * \param c a collection (vector,set) whose elements are being deleted.
- */
-template <class C>
-void clearCollection(C& c){
- for(typename C::const_iterator it=c.begin();it!=c.end();++it)
- delete *it;
- c.clear();
-}
-
-/** Deletes all dynamically allocated values of the assotiative container.
- * The function expects the M::value_type to be a pair<..., ptr_to_type>, or it won't compile.
- * It first deletes the objects pointed to by ptr_to_type
- * and then clears (calls m.clear()) the container.
- * \param m an associative container (map,hash_map) whose elements are being deleted.
- */
-template <class M>
-void clearMap(M& m){
- for(typename M::const_iterator it=m.begin();it!=m.end();++it)
- delete it->second;
- m.clear();
-}
-
-} // namespace Util
-
-
-#endif // _COLLECTION_UTIL_H_
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/CppAssertHelper.h
----------------------------------------------------------------------
diff --git a/src/c/tests/CppAssertHelper.h b/src/c/tests/CppAssertHelper.h
deleted file mode 100644
index 3926f51..0000000
--- a/src/c/tests/CppAssertHelper.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * 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 CPPASSERTHELPER_H_
-#define CPPASSERTHELPER_H_
-
-#include <cppunit/TestAssert.h>
-
-// make it possible to specify location of the ASSERT call
-#define CPPUNIT_ASSERT_EQUAL_LOC(expected,actual,file,line) \
- ( CPPUNIT_NS::assertEquals( (expected), \
- (actual), \
- CPPUNIT_NS::SourceLine(file,line), \
- "" ) )
-
-#define CPPUNIT_ASSERT_EQUAL_MESSAGE_LOC(message,expected,actual,file,line) \
- ( CPPUNIT_NS::assertEquals( (expected), \
- (actual), \
- CPPUNIT_NS::SourceLine(file,line), \
- (message) ) )
-
-#endif /*CPPASSERTHELPER_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/LibCMocks.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/LibCMocks.cc b/src/c/tests/LibCMocks.cc
deleted file mode 100644
index 5db4553..0000000
--- a/src/c/tests/LibCMocks.cc
+++ /dev/null
@@ -1,333 +0,0 @@
-/**
- * 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 <cstdlib>
-#include <cstdarg>
-#include <iostream>
-#include <stdarg.h>
-
-#include "Util.h"
-#include "LibCMocks.h"
-
-#undef USING_DUMA
-
-using namespace std;
-
-// *****************************************************************************
-// gethostbyname
-
-struct hostent* gethostbyname(const char *name) {
- if(!Mock_gethostbyname::mock_)
- return LIBC_SYMBOLS.gethostbyname(name);
- return Mock_gethostbyname::mock_->call(name);
-}
-
-Mock_gethostbyname* Mock_gethostbyname::mock_=0;
-
-Mock_gethostbyname::~Mock_gethostbyname(){
- mock_=0;
- for(unsigned int i=0;i<gethostbynameReturns.size();i++)
- delete gethostbynameReturns[i];
-}
-
-Mock_gethostbyname::HostEntry& Mock_gethostbyname::addHostEntry(
- const char* hostName, short addrtype) {
- gethostbynameReturns.push_back(new HostEntry(hostName, addrtype));
- return *gethostbynameReturns.back();
-}
-
-hostent* Mock_gethostbyname::call(const char* name) {
- assert("Must add one or more mock hostent entries first"&&
- (gethostbynameReturns.size()!=0));
- return gethostbynameReturns[current++ % gethostbynameReturns.size()];
-}
-
-static char** appendString(char **list,const char* str,int len=0){
- const int SIZE_INCREMENT=16;
- if(list==0)
- list=(char**)LIBC_SYMBOLS.calloc(SIZE_INCREMENT,sizeof(char*));
- // find the first available slot
- int count=0;
- for(char** ptr=list; *ptr!=0; ptr++,count++);
- if(((count+1)%SIZE_INCREMENT)==0){
- list=(char**)LIBC_SYMBOLS.realloc(list,(count+1+SIZE_INCREMENT)*sizeof(char*));
- memset(list+count+1,0,SIZE_INCREMENT*sizeof(char*));
- }
- if(len==0){
- len=strlen(str)+1;
- }
- char* ptr=(char*)malloc(len);
- memcpy(ptr,str,len);
- list[count]=ptr;
- return list;
-}
-
-static void freeList(char **list){
- if(list==0) return;
- for(char** ptr=list; *ptr!=0; ptr++)
- LIBC_SYMBOLS.free((void*)*ptr);
- LIBC_SYMBOLS.free((void*)list);
-}
-
-Mock_gethostbyname::HostEntry::HostEntry(const char* hostName, short addrtype) {
- h_name=strdup(hostName);
- h_addrtype=addrtype;
- if(addrtype==AF_INET)
- h_length=4;
- else{
-#ifdef AF_INET6
- h_length=6; // TODO: not really sure, verify!
-#else
- assert("AF_INET6 not supported yet"&&false);
-#endif
- }
- h_aliases=h_addr_list=0;
-}
-
-Mock_gethostbyname::HostEntry::~HostEntry(){
- if(h_name) LIBC_SYMBOLS.free((void*)h_name);
- freeList(h_aliases); h_aliases=0;
- freeList(h_addr_list); h_addr_list=0;
-}
-
-Mock_gethostbyname::HostEntry& Mock_gethostbyname::HostEntry::addAlias(
- const char* alias) {
- h_aliases=appendString(h_aliases,alias);
- return *this;
-}
-
-Mock_gethostbyname::HostEntry& Mock_gethostbyname::HostEntry::addAddress(
- const char* addr4) {
- h_addr_list=appendString(h_addr_list,addr4,4);
- return *this;
-}
-
-
-// *****************************************************************************
-// calloc
-#ifndef USING_DUMA
-DECLARE_WRAPPER(void*,calloc,(size_t p1, size_t p2)){
- if(!Mock_calloc::mock_)
- return CALL_REAL(calloc,(p1,p2));
- return Mock_calloc::mock_->call(p1,p2);
-}
-#endif
-
-void* Mock_calloc::call(size_t p1, size_t p2){
-#ifndef USING_DUMA
- if(counter++ ==callsBeforeFailure){
- counter=0;
- errno=errnoOnFailure;
- return 0;
- }
- return CALL_REAL(calloc,(p1,p2));
-#else
- return 0;
-#endif
-}
-
-Mock_calloc* Mock_calloc::mock_=0;
-
-// *****************************************************************************
-// realloc
-
-#ifndef USING_DUMA
-DECLARE_WRAPPER(void*,realloc,(void* p, size_t s)){
- if(!Mock_realloc::mock_)
- return LIBC_SYMBOLS.realloc(p,s);
- return Mock_realloc::mock_->call(p,s);
-}
-#endif
-
-Mock_realloc* Mock_realloc::mock_=0;
-
-void* Mock_realloc::call(void* p, size_t s){
- if(counter++ ==callsBeforeFailure){
- counter=0;
- errno=errnoOnFailure;
- return 0;
- }
- return LIBC_SYMBOLS.realloc(p,s);
-}
-
-// *****************************************************************************
-// random
-RANDOM_RET_TYPE random(){
- if(!Mock_random::mock_)
- return LIBC_SYMBOLS.random();
- return Mock_random::mock_->call();
-}
-
-void srandom(unsigned long seed){
- if (!Mock_random::mock_)
- LIBC_SYMBOLS.srandom(seed);
- else
- Mock_random::mock_->setSeed(seed);
-}
-
-Mock_random* Mock_random::mock_=0;
-
-int Mock_random::call(){
- assert("Must specify one or more random integers"&&(randomReturns.size()!=0));
- return randomReturns[currentIdx++ % randomReturns.size()];
-}
-
-// *****************************************************************************
-// free
-#ifndef USING_DUMA
-DECLARE_WRAPPER(void,free,(void* p)){
- if(Mock_free_noop::mock_ && !Mock_free_noop::mock_->nested)
- Mock_free_noop::mock_->call(p);
- else
- CALL_REAL(free,(p));
-}
-#endif
-
-void Mock_free_noop::call(void* p){
- // on cygwin libc++ is linked statically
- // push_back() may call free(), hence the nesting guards
- synchronized(mx);
- nested++;
- callCounter++;
- requested.push_back(p);
- nested--;
-}
-void Mock_free_noop::freeRequested(){
-#ifndef USING_DUMA
- synchronized(mx);
- for(unsigned i=0; i<requested.size();i++)
- CALL_REAL(free,(requested[i]));
-#endif
-}
-
-int Mock_free_noop::getFreeCount(void* p){
- int cnt=0;
- synchronized(mx);
- for(unsigned i=0;i<requested.size();i++)
- if(requested[i]==p)cnt++;
- return cnt;
-}
-
-bool Mock_free_noop::isFreed(void* p){
- synchronized(mx);
- for(unsigned i=0;i<requested.size();i++)
- if(requested[i]==p)return true;
- return false;
-}
-
-Mock_free_noop* Mock_free_noop::mock_=0;
-
-// *****************************************************************************
-// socket
-int socket(int domain, int type, int protocol){
- if (!Mock_socket::mock_)
- return LIBC_SYMBOLS.socket(domain,type,protocol);
- return Mock_socket::mock_->callSocket(domain,type,protocol);
-}
-
-int close(int fd){
- if (!Mock_socket::mock_)
- return LIBC_SYMBOLS.close(fd);
- return Mock_socket::mock_->callClose(fd);
-}
-
-int getsockopt(int s,int level,int optname,void *optval,socklen_t *optlen){
- if (!Mock_socket::mock_)
- return LIBC_SYMBOLS.getsockopt(s,level,optname,optval,optlen);
- return Mock_socket::mock_->callGet(s,level,optname,optval,optlen);
-}
-
-int setsockopt(int s,int level,int optname,const void *optval,socklen_t optlen){
- if (!Mock_socket::mock_)
- return LIBC_SYMBOLS.setsockopt(s,level,optname,optval,optlen);
- return Mock_socket::mock_->callSet(s,level,optname,optval,optlen);
-}
-int connect(int s,const struct sockaddr *addr,socklen_t len){
- if (!Mock_socket::mock_)
- return LIBC_SYMBOLS.connect(s,addr,len);
- return Mock_socket::mock_->callConnect(s,addr,len);
-}
-ssize_t send(int s,const void *buf,size_t len,int flags){
- if (!Mock_socket::mock_)
- return LIBC_SYMBOLS.send(s,buf,len,flags);
- return Mock_socket::mock_->callSend(s,buf,len,flags);
-}
-
-ssize_t recv(int s,void *buf,size_t len,int flags){
- if (!Mock_socket::mock_)
- return LIBC_SYMBOLS.recv(s,buf,len,flags);
- return Mock_socket::mock_->callRecv(s,buf,len,flags);
-}
-
-Mock_socket* Mock_socket::mock_=0;
-
-// *****************************************************************************
-// fcntl
-extern "C" int fcntl(int fd,int cmd,...){
- va_list va;
- va_start(va,cmd);
- void* arg = va_arg(va, void *);
- va_end (va);
- if (!Mock_fcntl::mock_)
- return LIBC_SYMBOLS.fcntl(fd,cmd,arg);
- return Mock_fcntl::mock_->call(fd,cmd,arg);
-}
-
-Mock_fcntl* Mock_fcntl::mock_=0;
-
-// *****************************************************************************
-// select
-int select(int nfds,fd_set *rfds,fd_set *wfds,fd_set *efds,struct timeval *timeout){
- if (!Mock_select::mock_)
- return LIBC_SYMBOLS.select(nfds,rfds,wfds,efds,timeout);
- return Mock_select::mock_->call(nfds,rfds,wfds,efds,timeout);
-}
-
-Mock_select* Mock_select::mock_=0;
-
-// *****************************************************************************
-// poll
-Mock_poll* Mock_poll::mock_=0;
-int poll(struct pollfd *fds, POLL_NFDS_TYPE nfds, int timeout){
- if (!Mock_poll::mock_)
- return LIBC_SYMBOLS.poll(fds,nfds,timeout);
- return Mock_poll::mock_->call(fds,nfds,timeout);
-
-}
-
-/*
- * Recent gcc with -O2 and glibc FORTIFY feature may cause our poll
- * mock to be ignored.
- */
-#if __USE_FORTIFY_LEVEL > 0
-int __poll_chk (struct pollfd *__fds, nfds_t __nfds, int __timeout,
- __SIZE_TYPE__ __fdslen) {
- return poll(__fds, __nfds, __timeout);
-}
-#endif
-
-// *****************************************************************************
-// gettimeofday
-int gettimeofday(struct timeval *tp, GETTIMEOFDAY_ARG2_TYPE tzp){
- if (!Mock_gettimeofday::mock_)
- return LIBC_SYMBOLS.gettimeofday(tp,tzp);
- return Mock_gettimeofday::mock_->call(tp,tzp);
-}
-
-Mock_gettimeofday* Mock_gettimeofday::mock_=0;
-
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/LibCMocks.h
----------------------------------------------------------------------
diff --git a/src/c/tests/LibCMocks.h b/src/c/tests/LibCMocks.h
deleted file mode 100644
index 5b07cda..0000000
--- a/src/c/tests/LibCMocks.h
+++ /dev/null
@@ -1,408 +0,0 @@
-/**
- * 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 LIBCMOCKS_H_
-#define LIBCMOCKS_H_
-
-#include <string>
-#include <vector>
-#include <deque>
-
-#include <errno.h>
-#include <string.h>
-
-#include "MocksBase.h"
-#include "LibCSymTable.h"
-#include "ThreadingUtil.h"
-
-// *****************************************************************************
-// gethostbyname
-
-class Mock_gethostbyname: public Mock
-{
-public:
- struct HostEntry: public hostent {
- HostEntry(const char* hostName,short addrtype);
- ~HostEntry();
- HostEntry& addAlias(const char* alias);
- HostEntry& addAddress(const char* addr4);
- };
-
- Mock_gethostbyname():current(0){mock_=this;}
- virtual ~Mock_gethostbyname();
- HostEntry& addHostEntry(const char* hostName,short addrtype=AF_INET);
- virtual hostent* call(const char* name);
-
- typedef std::vector<HostEntry*> HostEntryCollection;
- HostEntryCollection gethostbynameReturns;
- int current;
- static Mock_gethostbyname* mock_;
-};
-
-class MockFailed_gethostbyname: public Mock_gethostbyname
-{
-public:
- MockFailed_gethostbyname():h_errnoReturn(HOST_NOT_FOUND) {}
-
- int h_errnoReturn;
- virtual hostent* call(const char* name) {
- h_errno=h_errnoReturn;
- return 0;
- }
-};
-
-// *****************************************************************************
-// calloc
-
-class Mock_calloc: public Mock
-{
-public:
- Mock_calloc():errnoOnFailure(ENOMEM),callsBeforeFailure(-1),counter(0) {
- mock_=this;
- }
- virtual ~Mock_calloc() {mock_=0;}
-
- int errnoOnFailure;
- int callsBeforeFailure;
- int counter;
- virtual void* call(size_t p1, size_t p2);
-
- static Mock_calloc* mock_;
-};
-
-// *****************************************************************************
-// realloc
-
-class Mock_realloc: public Mock
-{
-public:
- Mock_realloc():errnoOnFailure(ENOMEM),callsBeforeFailure(-1),counter(0) {
- mock_=this;
- }
- virtual ~Mock_realloc() {mock_=0;}
-
- int errnoOnFailure;
- int callsBeforeFailure;
- int counter;
- virtual void* call(void* p, size_t s);
-
- static Mock_realloc* mock_;
-};
-
-// *****************************************************************************
-// random
-
-class Mock_random: public Mock
-{
-public:
- Mock_random():currentIdx(0) {mock_=this;}
- virtual ~Mock_random() {mock_=0;}
-
- int currentIdx;
- std::vector<int> randomReturns;
- virtual int call();
- void setSeed(unsigned long){currentIdx=0;}
-
- static Mock_random* mock_;
-};
-
-// *****************************************************************************
-// no-op free; keeps track of all deallocation requests
-class Mock_free_noop: public Mock
-{
- Mutex mx;
- std::vector<void*> requested;
-public:
- Mock_free_noop():nested(0),callCounter(0){mock_=this;}
- virtual ~Mock_free_noop(){
- mock_=0;
- freeRequested();
- }
-
- int nested;
- int callCounter;
- virtual void call(void* p);
- void freeRequested();
- void disable(){mock_=0;}
- // returns number of times the pointer was freed
- int getFreeCount(void*);
- bool isFreed(void*);
-
- static Mock_free_noop* mock_;
-};
-
-// *****************************************************************************
-// socket and related system calls
-
-class Mock_socket: public Mock
-{
-public:
- static const int FD=63;
- Mock_socket():socketReturns(FD),closeReturns(0),getsocketoptReturns(0),
- optvalSO_ERROR(0),
- setsockoptReturns(0),connectReturns(0),connectErrno(0),
- sendErrno(0),recvErrno(0)
- {
- mock_=this;
- }
- virtual ~Mock_socket(){mock_=0;}
-
- int socketReturns;
- virtual int callSocket(int domain, int type, int protocol){
- return socketReturns;
- }
- int closeReturns;
- virtual int callClose(int fd){
- return closeReturns;
- }
- int getsocketoptReturns;
- int optvalSO_ERROR;
- virtual int callGet(int s,int level,int optname,void *optval,socklen_t *len){
- if(level==SOL_SOCKET && optname==SO_ERROR){
- setSO_ERROR(optval,*len);
- }
- return getsocketoptReturns;
- }
- virtual void setSO_ERROR(void *optval,socklen_t len){
- memcpy(optval,&optvalSO_ERROR,len);
- }
-
- int setsockoptReturns;
- virtual int callSet(int s,int level,int optname,const void *optval,socklen_t len){
- return setsockoptReturns;
- }
- int connectReturns;
- int connectErrno;
- virtual int callConnect(int s,const struct sockaddr *addr,socklen_t len){
- errno=connectErrno;
- return connectReturns;
- }
-
- virtual void notifyBufferSent(const std::string& buffer){}
-
- int sendErrno;
- std::string sendBuffer;
- virtual ssize_t callSend(int s,const void *buf,size_t len,int flags){
- if(sendErrno!=0){
- errno=sendErrno;
- return -1;
- }
- // first call to send() is always the length of the buffer to follow
- bool sendingLength=sendBuffer.size()==0;
- // overwrite the length bytes
- sendBuffer.assign((const char*)buf,len);
- if(!sendingLength){
- notifyBufferSent(sendBuffer);
- sendBuffer.erase();
- }
- return len;
- }
-
- int recvErrno;
- std::string recvReturnBuffer;
- virtual ssize_t callRecv(int s,void *buf,size_t len,int flags){
- if(recvErrno!=0){
- errno=recvErrno;
- return -1;
- }
- int k=std::min(len,recvReturnBuffer.length());
- if(k==0)
- return 0;
- memcpy(buf,recvReturnBuffer.data(),k);
- recvReturnBuffer.erase(0,k);
- return k;
- }
- virtual bool hasMoreRecv() const{
- return recvReturnBuffer.size()!=0;
- }
- static Mock_socket* mock_;
-};
-
-// *****************************************************************************
-// fcntl
-class Mock_fcntl: public Mock
-{
-public:
- Mock_fcntl():callReturns(0),trapFD(-1){mock_=this;}
- ~Mock_fcntl(){mock_=0;}
-
- int callReturns;
- int trapFD;
- virtual int call(int fd, int cmd, void* arg){
- if(trapFD==-1)
- return LIBC_SYMBOLS.fcntl(fd,cmd,arg);
- return callReturns;
- }
-
- static Mock_fcntl* mock_;
-};
-
-// *****************************************************************************
-// select
-class Mock_select: public Mock
-{
-public:
- Mock_select(Mock_socket* s,int fd):sock(s),
- callReturns(0),myFD(fd),timeout(50)
- {
- mock_=this;
- }
- ~Mock_select(){mock_=0;}
-
- Mock_socket* sock;
- int callReturns;
- int myFD;
- int timeout; //in millis
- virtual int call(int nfds,fd_set *rfds,fd_set *wfds,fd_set *efds,struct timeval *tv){
- bool isWritableRequested=(wfds && FD_ISSET(myFD,wfds));
- if(rfds) FD_CLR(myFD,rfds);
- if(wfds) FD_CLR(myFD,wfds);
- // this timeout is only to prevent a tight loop
- timeval myTimeout={0,0};
- if(!isWritableRequested && !isFDReadable()){
- myTimeout.tv_sec=timeout/1000;
- myTimeout.tv_usec=(timeout%1000)*1000;
- }
- LIBC_SYMBOLS.select(nfds,rfds,wfds,efds,&myTimeout);
- // myFD is always writable
- if(isWritableRequested) FD_SET(myFD,wfds);
- // myFD is only readable if the socket has anything to read
- if(isFDReadable() && rfds) FD_SET(myFD,rfds);
- return callReturns;
- }
-
- virtual bool isFDReadable() const {
- return sock->hasMoreRecv();
- }
-
- static Mock_select* mock_;
-};
-
-// *****************************************************************************
-// poll
-// the last element of the pollfd array is expected to be test FD
-class Mock_poll: public Mock
-{
-public:
- Mock_poll(Mock_socket* s,int fd):sock(s),
- callReturns(1),myFD(fd),timeout(50)
- {
- mock_=this;
- }
- ~Mock_poll(){mock_=0;}
-
- Mock_socket* sock;
- int callReturns;
- int myFD;
- int timeout; //in millis
- virtual int call(struct pollfd *fds, POLL_NFDS_TYPE nfds, int to) {
- pollfd* myPoll=0;
- if(fds[nfds-1].fd==myFD)
- myPoll=&fds[nfds-1];
- bool isWritableRequested=false;
- if(myPoll!=0){
- isWritableRequested=myPoll->events&POLLOUT;
- nfds--;
- }
- LIBC_SYMBOLS.poll(fds,nfds,(!isWritableRequested&&!isFDReadable())?timeout:0);
- if(myPoll!=0){
- // myFD is always writable if requested
- myPoll->revents=isWritableRequested?POLLOUT:0;
- // myFD is only readable if the socket has anything to read
- myPoll->revents|=isFDReadable()?POLLIN:0;
- }
- return callReturns;
- }
-
- virtual bool isFDReadable() const {
- return sock->hasMoreRecv();
- }
-
- static Mock_poll* mock_;
-};
-
-// *****************************************************************************
-// gettimeofday
-class Mock_gettimeofday: public Mock
-{
-public:
- Mock_gettimeofday(){
- LIBC_SYMBOLS.gettimeofday(&tv,0);
- mock_=this;
- }
- Mock_gettimeofday(const Mock_gettimeofday& other):tv(other.tv){}
- Mock_gettimeofday(int32_t sec,int32_t usec){
- tv.tv_sec=sec;
- tv.tv_usec=usec;
- }
- ~Mock_gettimeofday(){mock_=0;}
-
- timeval tv;
- virtual int call(struct timeval *tp, GETTIMEOFDAY_ARG2_TYPE tzp){
- *tp=tv;
- return 0;
- }
- operator timeval() const{
- return tv;
- }
- // advance secs
- virtual void tick(int howmuch=1){tv.tv_sec+=howmuch;}
- // advance milliseconds
- // can move the clock forward as well as backward by providing a negative
- // number
- virtual void millitick(int howmuch=1){
- int ms=tv.tv_usec/1000+howmuch;
- tv.tv_sec+=ms/1000;
- // going backward?
- if(ms<0){
- ms=1000-(-ms%1000); //wrap millis around
- }
- tv.tv_usec=(ms%1000)*1000;
- }
- virtual void tick(const timeval& howmuch){
- // add milliseconds (discarding microsecond portion)
- long ms=tv.tv_usec/1000+howmuch.tv_usec/1000;
- tv.tv_sec+=howmuch.tv_sec+ms/1000;
- tv.tv_usec=(ms%1000)*1000;
- }
- static Mock_gettimeofday* mock_;
-};
-
-// discard microseconds!
-inline bool operator==(const timeval& lhs, const timeval& rhs){
- return rhs.tv_sec==lhs.tv_sec && rhs.tv_usec/1000==lhs.tv_usec/1000;
-}
-
-// simplistic implementation: no normalization, assume lhs >= rhs,
-// discarding microseconds
-inline timeval operator-(const timeval& lhs, const timeval& rhs){
- timeval res;
- res.tv_sec=lhs.tv_sec-rhs.tv_sec;
- res.tv_usec=(lhs.tv_usec/1000-rhs.tv_usec/1000)*1000;
- if(res.tv_usec<0){
- res.tv_sec--;
- res.tv_usec=1000000+res.tv_usec%1000000; // wrap the millis around
- }
- return res;
-}
-
-inline int32_t toMilliseconds(const timeval& tv){
- return tv.tv_sec*1000+tv.tv_usec/1000;
-}
-
-#endif /*LIBCMOCKS_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/LibCSymTable.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/LibCSymTable.cc b/src/c/tests/LibCSymTable.cc
deleted file mode 100644
index 5378579..0000000
--- a/src/c/tests/LibCSymTable.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * 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 "LibCSymTable.h"
-
-#define LOAD_SYM(sym) \
- sym=(sym##_sig)dlsym(handle,#sym); \
- assert("Unable to load "#sym" from libc"&&sym)
-
-
-LibCSymTable& LibCSymTable::instance(){
- static LibCSymTable tbl;
- return tbl;
-}
-
-//******************************************************************************
-// preload original libc symbols
-LibCSymTable::LibCSymTable()
-{
- void* handle=getHandle();
- LOAD_SYM(gethostbyname);
- LOAD_SYM(calloc);
- LOAD_SYM(realloc);
- LOAD_SYM(free);
- LOAD_SYM(random);
- LOAD_SYM(srandom);
- LOAD_SYM(printf);
- LOAD_SYM(socket);
- LOAD_SYM(close);
- LOAD_SYM(getsockopt);
- LOAD_SYM(setsockopt);
- LOAD_SYM(fcntl);
- LOAD_SYM(connect);
- LOAD_SYM(send);
- LOAD_SYM(recv);
- LOAD_SYM(select);
- LOAD_SYM(poll);
- LOAD_SYM(gettimeofday);
-#ifdef THREADED
- LOAD_SYM(pthread_create);
- LOAD_SYM(pthread_detach);
- LOAD_SYM(pthread_cond_broadcast);
- LOAD_SYM(pthread_cond_destroy);
- LOAD_SYM(pthread_cond_init);
- LOAD_SYM(pthread_cond_signal);
- LOAD_SYM(pthread_cond_timedwait);
- LOAD_SYM(pthread_cond_wait);
- LOAD_SYM(pthread_join);
- LOAD_SYM(pthread_mutex_destroy);
- LOAD_SYM(pthread_mutex_init);
- LOAD_SYM(pthread_mutex_lock);
- LOAD_SYM(pthread_mutex_trylock);
- LOAD_SYM(pthread_mutex_unlock);
-#endif
-}
-
-void* LibCSymTable::getHandle(){
- static void* handle=0;
- if(!handle){
-#ifdef __CYGWIN__
- handle=dlopen("cygwin1.dll",RTLD_LAZY);
- assert("Unable to dlopen global sym table"&&handle);
-#else
- handle=RTLD_NEXT;
-#endif
- }
- return handle;
-}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/LibCSymTable.h
----------------------------------------------------------------------
diff --git a/src/c/tests/LibCSymTable.h b/src/c/tests/LibCSymTable.h
deleted file mode 100644
index 2f7e0c2..0000000
--- a/src/c/tests/LibCSymTable.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * 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 LIBCSYMTABLE_H_
-#define LIBCSYMTABLE_H_
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <stddef.h>
-#include <dlfcn.h>
-#include <cassert>
-#include <poll.h>
-
-#ifdef THREADED
-#include <pthread.h>
-#endif
-
-#include "config.h"
-
-// TODO: move all these macros to config.h (generated by autoconf)
-#ifdef __CYGWIN__
-#if (CYGWIN_VERSION_DLL_MAJOR < 1007)
-#define RANDOM_RET_TYPE int
-#else
-#define RANDOM_RET_TYPE long int
-#endif
-#define GETTIMEOFDAY_ARG2_TYPE void*
-#else
-#define RANDOM_RET_TYPE long int
-#define GETTIMEOFDAY_ARG2_TYPE struct timezone*
-#endif
-
-#define DECLARE_SYM(ret,sym,sig) \
- typedef ret (*sym##_sig)sig; \
- static sym##_sig preload_##sym () { \
- static sym##_sig ptr=0;\
- if(!ptr){ void* h=getHandle(); ptr=(sym##_sig)dlsym(h,#sym); } \
- assert("Unable to load "#sym" from libc"&&ptr); \
- return ptr; \
- } \
- sym##_sig sym
-
-#define LIBC_SYMBOLS LibCSymTable::instance()
-
-//******************************************************************************
-// preload original libc symbols
-struct LibCSymTable
-{
- DECLARE_SYM(hostent*,gethostbyname,(const char*));
- DECLARE_SYM(void*,calloc,(size_t, size_t));
- DECLARE_SYM(void*,realloc,(void*, size_t));
- DECLARE_SYM(void,free,(void*));
- DECLARE_SYM(RANDOM_RET_TYPE,random,(void));
- DECLARE_SYM(void,srandom,(unsigned long));
- DECLARE_SYM(int,printf,(const char*, ...));
- DECLARE_SYM(int,socket,(int,int,int));
- DECLARE_SYM(int,close,(int));
- DECLARE_SYM(int,getsockopt,(int,int,int,void*,socklen_t*));
- DECLARE_SYM(int,setsockopt,(int,int,int,const void*,socklen_t));
- DECLARE_SYM(int,fcntl,(int,int,...));
- DECLARE_SYM(int,connect,(int,const struct sockaddr*,socklen_t));
- DECLARE_SYM(ssize_t,send,(int,const void*,size_t,int));
- DECLARE_SYM(ssize_t,recv,(int,const void*,size_t,int));
- DECLARE_SYM(int,select,(int,fd_set*,fd_set*,fd_set*,struct timeval*));
- DECLARE_SYM(int,poll,(struct pollfd*,POLL_NFDS_TYPE,int));
- DECLARE_SYM(int,gettimeofday,(struct timeval*,GETTIMEOFDAY_ARG2_TYPE));
-#ifdef THREADED
- DECLARE_SYM(int,pthread_create,(pthread_t *, const pthread_attr_t *,
- void *(*)(void *), void *));
- DECLARE_SYM(int,pthread_detach,(pthread_t));
- DECLARE_SYM(int,pthread_cond_broadcast,(pthread_cond_t *));
- DECLARE_SYM(int,pthread_cond_destroy,(pthread_cond_t *));
- DECLARE_SYM(int,pthread_cond_init,(pthread_cond_t *, const pthread_condattr_t *));
- DECLARE_SYM(int,pthread_cond_signal,(pthread_cond_t *));
- DECLARE_SYM(int,pthread_cond_timedwait,(pthread_cond_t *,
- pthread_mutex_t *, const struct timespec *));
- DECLARE_SYM(int,pthread_cond_wait,(pthread_cond_t *, pthread_mutex_t *));
- DECLARE_SYM(int,pthread_join,(pthread_t, void **));
- DECLARE_SYM(int,pthread_mutex_destroy,(pthread_mutex_t *));
- DECLARE_SYM(int,pthread_mutex_init,(pthread_mutex_t *, const pthread_mutexattr_t *));
- DECLARE_SYM(int,pthread_mutex_lock,(pthread_mutex_t *));
- DECLARE_SYM(int,pthread_mutex_trylock,(pthread_mutex_t *));
- DECLARE_SYM(int,pthread_mutex_unlock,(pthread_mutex_t *));
-#endif
- LibCSymTable();
-
- static void* getHandle();
- static LibCSymTable& instance();
-};
-
-#endif /*LIBCSYMTABLE_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/MocksBase.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/MocksBase.cc b/src/c/tests/MocksBase.cc
deleted file mode 100644
index 60b2c75..0000000
--- a/src/c/tests/MocksBase.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * 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 <cstdlib>
-#include <new>
-
-#include "MocksBase.h"
-#include "LibCSymTable.h"
-
-// *****************************************************************************
-// Mock base
-void* Mock::operator new(std::size_t s){
- void* p=malloc(s);
- if(!p)
- throw std::bad_alloc();
- return p;
-}
-
-void Mock::operator delete(void* p){
- LIBC_SYMBOLS.free(p);
-}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/MocksBase.h
----------------------------------------------------------------------
diff --git a/src/c/tests/MocksBase.h b/src/c/tests/MocksBase.h
deleted file mode 100644
index 5b54251..0000000
--- a/src/c/tests/MocksBase.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * 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 MOCKSBASE_H_
-#define MOCKSBASE_H_
-
-#include <cstddef>
-
-// *****************************************************************************
-// Mock base
-
-class Mock
-{
-public:
- virtual ~Mock(){}
-
- static void* operator new(std::size_t s);
- static void operator delete(void* p);
-};
-
-#endif /*MOCKSBASE_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/PthreadMocks.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/PthreadMocks.cc b/src/c/tests/PthreadMocks.cc
deleted file mode 100644
index 490cebf..0000000
--- a/src/c/tests/PthreadMocks.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * 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 "PthreadMocks.h"
-
-MockPthreadsBase* MockPthreadsBase::mock_=0;
-
-#undef USING_DUMA
-
-#ifndef USING_DUMA
-int pthread_cond_broadcast (pthread_cond_t *c){
- if(!MockPthreadsBase::mock_)
- return LIBC_SYMBOLS.pthread_cond_broadcast(c);
- return MockPthreadsBase::mock_->pthread_cond_broadcast(c);
-}
-int pthread_cond_destroy (pthread_cond_t *c){
- if(!MockPthreadsBase::mock_)
- return LIBC_SYMBOLS.pthread_cond_destroy(c);
- return MockPthreadsBase::mock_->pthread_cond_destroy(c);
-}
-int pthread_cond_init (pthread_cond_t *c, const pthread_condattr_t *a){
- if(!MockPthreadsBase::mock_)
- return LIBC_SYMBOLS.pthread_cond_init(c,a);
- return MockPthreadsBase::mock_->pthread_cond_init(c,a);
-}
-int pthread_cond_signal (pthread_cond_t *c){
- if(!MockPthreadsBase::mock_)
- return LIBC_SYMBOLS.pthread_cond_signal(c);
- return MockPthreadsBase::mock_->pthread_cond_signal(c);
-}
-int pthread_cond_timedwait (pthread_cond_t *c,
- pthread_mutex_t *m, const struct timespec *t){
- if(!MockPthreadsBase::mock_)
- return LIBC_SYMBOLS.pthread_cond_timedwait(c,m,t);
- return MockPthreadsBase::mock_->pthread_cond_timedwait(c,m,t);
-}
-int pthread_cond_wait (pthread_cond_t *c, pthread_mutex_t *m){
- if(!MockPthreadsBase::mock_)
- return LIBC_SYMBOLS.pthread_cond_wait(c,m);
- return MockPthreadsBase::mock_->pthread_cond_wait(c,m);
-}
-int pthread_create (pthread_t *t, const pthread_attr_t *a,
- void *(*f)(void *), void *d){
- if(!MockPthreadsBase::mock_)
- return LIBC_SYMBOLS.pthread_create(t,a,f,d);
- return MockPthreadsBase::mock_->pthread_create(t,a,f,d);
-}
-int pthread_detach(pthread_t t){
- if(!MockPthreadsBase::mock_)
- return LIBC_SYMBOLS.pthread_detach(t);
- return MockPthreadsBase::mock_->pthread_detach(t);
-}
-int pthread_join (pthread_t t, void **r){
- if(!MockPthreadsBase::mock_)
- return LIBC_SYMBOLS.pthread_join(t,r);
- return MockPthreadsBase::mock_->pthread_join(t,r);
-}
-int pthread_mutex_destroy (pthread_mutex_t *m){
- if(!MockPthreadsBase::mock_)
- return LIBC_SYMBOLS.pthread_mutex_destroy(m);
- return MockPthreadsBase::mock_->pthread_mutex_destroy(m);
-}
-int pthread_mutex_init (pthread_mutex_t *m, const pthread_mutexattr_t *a){
- if(!MockPthreadsBase::mock_)
- return LIBC_SYMBOLS.pthread_mutex_init(m,a);
- return MockPthreadsBase::mock_->pthread_mutex_init(m,a);
-}
-
-DECLARE_WRAPPER(int,pthread_mutex_lock,(pthread_mutex_t *m)){
- if(!MockPthreadsBase::mock_)
- return CALL_REAL(pthread_mutex_lock,(m));
- return MockPthreadsBase::mock_->pthread_mutex_lock(m);
-}
-
-int pthread_mutex_trylock (pthread_mutex_t *m){
- if(!MockPthreadsBase::mock_)
- return LIBC_SYMBOLS.pthread_mutex_trylock(m);
- return MockPthreadsBase::mock_->pthread_mutex_trylock(m);
-}
-
-DECLARE_WRAPPER(int,pthread_mutex_unlock,(pthread_mutex_t *m)){
- if(!MockPthreadsBase::mock_)
- return CALL_REAL(pthread_mutex_unlock,(m));
- return MockPthreadsBase::mock_->pthread_mutex_unlock(m);
-}
-#endif
-
-CheckedPthread::ThreadMap CheckedPthread::tmap_;
-CheckedPthread::MutexMap CheckedPthread::mmap_;
-CheckedPthread::CVMap CheckedPthread::cvmap_;
-Mutex CheckedPthread::mx;
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/PthreadMocks.h
----------------------------------------------------------------------
diff --git a/src/c/tests/PthreadMocks.h b/src/c/tests/PthreadMocks.h
deleted file mode 100644
index 8db8815..0000000
--- a/src/c/tests/PthreadMocks.h
+++ /dev/null
@@ -1,449 +0,0 @@
-/**
- * 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 PTHREADMOCKS_H_
-#define PTHREADMOCKS_H_
-
-#include <pthread.h>
-#include <string.h>
-#include <errno.h>
-
-#include "src/zk_adaptor.h"
-
-#include "Util.h"
-#include "MocksBase.h"
-#include "LibCSymTable.h"
-#include "ThreadingUtil.h"
-
-// an ABC for pthreads
-class MockPthreadsBase: public Mock
-{
-public:
- MockPthreadsBase(){mock_=this;}
- virtual ~MockPthreadsBase(){mock_=0;}
-
- virtual int pthread_create(pthread_t * t, const pthread_attr_t *a,
- void *(*f)(void *), void *d) =0;
- virtual int pthread_join(pthread_t t, void ** r) =0;
- virtual int pthread_detach(pthread_t t) =0;
- virtual int pthread_cond_broadcast(pthread_cond_t *c) =0;
- virtual int pthread_cond_destroy(pthread_cond_t *c) =0;
- virtual int pthread_cond_init(pthread_cond_t *c, const pthread_condattr_t *a) =0;
- virtual int pthread_cond_signal(pthread_cond_t *c) =0;
- virtual int pthread_cond_timedwait(pthread_cond_t *c,
- pthread_mutex_t *m, const struct timespec *t) =0;
- virtual int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m) =0;
- virtual int pthread_mutex_destroy(pthread_mutex_t *m) =0;
- virtual int pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a) =0;
- virtual int pthread_mutex_lock(pthread_mutex_t *m) =0;
- virtual int pthread_mutex_trylock(pthread_mutex_t *m) =0;
- virtual int pthread_mutex_unlock(pthread_mutex_t *m) =0;
-
- static MockPthreadsBase* mock_;
-};
-
-// all pthread functions simply return an error code
-// and increment their invocation counter. No actual threads are spawned.
-class MockPthreadsNull: public MockPthreadsBase
-{
-public:
- MockPthreadsNull():
- pthread_createReturns(0),pthread_createCounter(0),
- pthread_joinReturns(0),pthread_joinCounter(0),pthread_joinResultReturn(0),
- pthread_detachReturns(0),pthread_detachCounter(0),
- pthread_cond_broadcastReturns(0),pthread_cond_broadcastCounter(0),
- pthread_cond_destroyReturns(0),pthread_cond_destroyCounter(0),
- pthread_cond_initReturns(0),pthread_cond_initCounter(0),
- pthread_cond_signalReturns(0),pthread_cond_signalCounter(0),
- pthread_cond_timedwaitReturns(0),pthread_cond_timedwaitCounter(0),
- pthread_cond_waitReturns(0),pthread_cond_waitCounter(0),
- pthread_mutex_destroyReturns(0),pthread_mutex_destroyCounter(0),
- pthread_mutex_initReturns(0),pthread_mutex_initCounter(0),
- pthread_mutex_lockReturns(0),pthread_mutex_lockCounter(0),
- pthread_mutex_trylockReturns(0),pthread_mutex_trylockCounter(0),
- pthread_mutex_unlockReturns(0),pthread_mutex_unlockCounter(0)
- {
- memset(threads,0,sizeof(threads));
- }
-
- short threads[512];
-
- int pthread_createReturns;
- int pthread_createCounter;
- virtual int pthread_create(pthread_t * t, const pthread_attr_t *a,
- void *(*f)(void *), void *d){
- char* p=(char*)&threads[pthread_createCounter++];
- p[0]='i'; // mark as created
- *t=(pthread_t)p;
- return pthread_createReturns;
- }
- int pthread_joinReturns;
- int pthread_joinCounter;
- void* pthread_joinResultReturn;
- virtual int pthread_join(pthread_t t, void ** r){
- pthread_joinCounter++;
- if(r!=0)
- *r=pthread_joinResultReturn;
- char* p=(char*)t;
- p[0]='x';p[1]+=1;
- return pthread_joinReturns;
- }
- int pthread_detachReturns;
- int pthread_detachCounter;
- virtual int pthread_detach(pthread_t t){
- pthread_detachCounter++;
- char* p=(char*)t;
- p[0]='x';p[1]+=1;
- return pthread_detachReturns;
- }
-
- template<class T>
- static bool isInitialized(const T& t){
- return ((char*)t)[0]=='i';
- }
- template<class T>
- static bool isDestroyed(const T& t){
- return ((char*)t)[0]=='x';
- }
- template<class T>
- static int getDestroyCounter(const T& t){
- return ((char*)t)[1];
- }
- template<class T>
- static int getInvalidAccessCounter(const T& t){
- return ((char*)t)[2];
- }
- int pthread_cond_broadcastReturns;
- int pthread_cond_broadcastCounter;
- virtual int pthread_cond_broadcast(pthread_cond_t *c){
- pthread_cond_broadcastCounter++;
- if(isDestroyed(c))((char*)c)[2]++;
- return pthread_cond_broadcastReturns;
- }
- int pthread_cond_destroyReturns;
- int pthread_cond_destroyCounter;
- virtual int pthread_cond_destroy(pthread_cond_t *c){
- pthread_cond_destroyCounter++;
- char* p=(char*)c;
- p[0]='x';p[1]+=1;
- return pthread_cond_destroyReturns;
- }
- int pthread_cond_initReturns;
- int pthread_cond_initCounter;
- virtual int pthread_cond_init(pthread_cond_t *c, const pthread_condattr_t *a){
- pthread_cond_initCounter++;
- char* p=(char*)c;
- p[0]='i'; // mark as created
- p[1]=0; // destruction counter
- p[2]=0; // access after destruction counter
- return pthread_cond_initReturns;
- }
- int pthread_cond_signalReturns;
- int pthread_cond_signalCounter;
- virtual int pthread_cond_signal(pthread_cond_t *c){
- pthread_cond_signalCounter++;
- if(isDestroyed(c))((char*)c)[2]++;
- return pthread_cond_signalReturns;
- }
- int pthread_cond_timedwaitReturns;
- int pthread_cond_timedwaitCounter;
- virtual int pthread_cond_timedwait(pthread_cond_t *c,
- pthread_mutex_t *m, const struct timespec *t){
- pthread_cond_timedwaitCounter++;
- if(isDestroyed(c))((char*)c)[2]++;
- return pthread_cond_timedwaitReturns;
- }
- int pthread_cond_waitReturns;
- int pthread_cond_waitCounter;
- virtual int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m){
- pthread_cond_waitCounter++;
- if(isDestroyed(c))((char*)c)[2]++;
- return pthread_cond_waitReturns;
- }
- int pthread_mutex_destroyReturns;
- int pthread_mutex_destroyCounter;
- virtual int pthread_mutex_destroy(pthread_mutex_t *m){
- pthread_mutex_destroyCounter++;
- char* p=(char*)m;
- p[0]='x';p[1]+=1;
- return pthread_mutex_destroyReturns;
- }
- int pthread_mutex_initReturns;
- int pthread_mutex_initCounter;
- virtual int pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a){
- pthread_mutex_initCounter++;
- char* p=(char*)m;
- p[0]='i'; // mark as created
- p[1]=0; // destruction counter
- p[2]=0; // access after destruction counter
- return pthread_mutex_initReturns;
- }
- int pthread_mutex_lockReturns;
- int pthread_mutex_lockCounter;
- virtual int pthread_mutex_lock(pthread_mutex_t *m){
- pthread_mutex_lockCounter++;
- if(isDestroyed(m))((char*)m)[2]++;
- return pthread_mutex_lockReturns;
- }
- int pthread_mutex_trylockReturns;
- int pthread_mutex_trylockCounter;
- virtual int pthread_mutex_trylock(pthread_mutex_t *m){
- pthread_mutex_trylockCounter++;
- if(isDestroyed(m))((char*)m)[2]++;
- return pthread_mutex_trylockReturns;
- }
- int pthread_mutex_unlockReturns;
- int pthread_mutex_unlockCounter;
- virtual int pthread_mutex_unlock(pthread_mutex_t *m){
- pthread_mutex_unlockCounter++;
- if(isDestroyed(m))((char*)m)[2]++;
- return pthread_mutex_unlockReturns;
- }
-};
-
-// simulates the way zookeeper threads make use of api_prolog/epilog and
-//
-class MockPthreadZKNull: public MockPthreadsNull
-{
- typedef std::map<pthread_t,zhandle_t*> Map;
- Map map_;
-public:
- virtual int pthread_create(pthread_t * t, const pthread_attr_t *a,
- void *(*f)(void *), void *d){
- int ret=MockPthreadsNull::pthread_create(t,a,f,d);
- zhandle_t* zh=(zhandle_t*)d;
- adaptor_threads* ad=(adaptor_threads*)zh->adaptor_priv;
- api_prolog(zh);
- ad->threadsToWait--;
- putValue(map_,*t,zh);
- return ret;
- }
- virtual int pthread_join(pthread_t t, void ** r){
- zhandle_t* zh=0;
- if(getValue(map_,t,zh))
- api_epilog(zh,0);
- return MockPthreadsNull::pthread_join(t,r);
- }
-};
-
-struct ThreadInfo{
- typedef enum {RUNNING,TERMINATED} ThreadState;
-
- ThreadInfo():
- destructionCounter_(0),invalidAccessCounter_(0),state_(RUNNING)
- {
- }
-
- ThreadInfo& incDestroyed() {
- destructionCounter_++;
- return *this;
- }
- ThreadInfo& incInvalidAccess(){
- invalidAccessCounter_++;
- return *this;
- }
- ThreadInfo& setTerminated(){
- state_=TERMINATED;
- return *this;
- }
- int destructionCounter_;
- int invalidAccessCounter_;
- ThreadState state_;
-};
-
-class CheckedPthread: public MockPthreadsBase
-{
- // first => destruction counter
- // second => invalid access counter
- //typedef std::pair<int,int> Entry;
- typedef ThreadInfo Entry;
- typedef std::map<pthread_t,Entry> ThreadMap;
- static ThreadMap tmap_;
- static ThreadMap& getMap(const TypeOp<pthread_t>::BareT&){return tmap_;}
- typedef std::map<pthread_mutex_t*,Entry> MutexMap;
- static MutexMap mmap_;
- static MutexMap& getMap(const TypeOp<pthread_mutex_t>::BareT&){return mmap_;}
- typedef std::map<pthread_cond_t*,Entry> CVMap;
- static CVMap cvmap_;
- static CVMap& getMap(const TypeOp<pthread_cond_t>::BareT&){return cvmap_;}
-
- static Mutex mx;
-
- template<class T>
- static void markDestroyed(T& t){
- typedef typename TypeOp<T>::BareT Type;
- Entry e;
- synchronized(mx);
- if(getValue(getMap(Type()),t,e)){
- putValue(getMap(Type()),t,Entry(e).incDestroyed());
- }else{
- putValue(getMap(Type()),t,Entry().incDestroyed());
- }
- }
- template<class T>
- static void markCreated(T& t){
- typedef typename TypeOp<T>::BareT Type;
- Entry e;
- synchronized(mx);
- if(!getValue(getMap(Type()),t,e))
- putValue(getMap(Type()),t,Entry());
- }
- template<class T>
- static void checkAccessed(T& t){
- typedef typename TypeOp<T>::BareT Type;
- Entry e;
- synchronized(mx);
- if(getValue(getMap(Type()),t,e) && e.destructionCounter_>0)
- putValue(getMap(Type()),t,Entry(e).incInvalidAccess());
- }
- static void setTerminated(pthread_t t){
- Entry e;
- synchronized(mx);
- if(getValue(tmap_,t,e))
- putValue(tmap_,t,Entry(e).setTerminated());
- }
-public:
- bool verbose;
- CheckedPthread():verbose(false){
- tmap_.clear();
- mmap_.clear();
- cvmap_.clear();
- mx.release();
- }
- template <class T>
- static bool isInitialized(const T& t){
- typedef typename TypeOp<T>::BareT Type;
- Entry e;
- synchronized(mx);
- return getValue(getMap(Type()),t,e) && e.destructionCounter_==0;
- }
- template <class T>
- static bool isDestroyed(const T& t){
- typedef typename TypeOp<T>::BareT Type;
- Entry e;
- synchronized(mx);
- return getValue(getMap(Type()),t,e) && e.destructionCounter_>0;
- }
- static bool isTerminated(pthread_t t){
- Entry e;
- synchronized(mx);
- return getValue(tmap_,t,e) && e.state_==ThreadInfo::TERMINATED;
- }
- template <class T>
- static int getDestroyCounter(const T& t){
- typedef typename TypeOp<T>::BareT Type;
- Entry e;
- synchronized(mx);
- return getValue(getMap(Type()),t,e)?e.destructionCounter_:-1;
- }
- template<class T>
- static int getInvalidAccessCounter(const T& t){
- typedef typename TypeOp<T>::BareT Type;
- Entry e;
- synchronized(mx);
- return getValue(getMap(Type()),t,e)?e.invalidAccessCounter_:-1;
- }
-
- struct ThreadContext{
- typedef void *(*ThreadFunc)(void *);
-
- ThreadContext(ThreadFunc func,void* param):func_(func),param_(param){}
- ThreadFunc func_;
- void* param_;
- };
- static void* threadFuncWrapper(void* v){
- ThreadContext* ctx=(ThreadContext*)v;
- pthread_t t=pthread_self();
- markCreated(t);
- void* res=ctx->func_(ctx->param_);
- setTerminated(pthread_self());
- delete ctx;
- return res;
- }
- virtual int pthread_create(pthread_t * t, const pthread_attr_t *a,
- void *(*f)(void *), void *d)
- {
- int ret=LIBC_SYMBOLS.pthread_create(t,a,threadFuncWrapper,
- new ThreadContext(f,d));
- if(verbose)
- TEST_TRACE(("thread created %p",*t));
- return ret;
- }
- virtual int pthread_join(pthread_t t, void ** r){
- if(verbose) TEST_TRACE(("thread joined %p",t));
- int ret=LIBC_SYMBOLS.pthread_join(t,r);
- if(ret==0)
- markDestroyed(t);
- return ret;
- }
- virtual int pthread_detach(pthread_t t){
- if(verbose) TEST_TRACE(("thread detached %p",t));
- int ret=LIBC_SYMBOLS.pthread_detach(t);
- if(ret==0)
- markDestroyed(t);
- return ret;
- }
- virtual int pthread_cond_broadcast(pthread_cond_t *c){
- checkAccessed(c);
- return LIBC_SYMBOLS.pthread_cond_broadcast(c);
- }
- virtual int pthread_cond_destroy(pthread_cond_t *c){
- markDestroyed(c);
- return LIBC_SYMBOLS.pthread_cond_destroy(c);
- }
- virtual int pthread_cond_init(pthread_cond_t *c, const pthread_condattr_t *a){
- markCreated(c);
- return LIBC_SYMBOLS.pthread_cond_init(c,a);
- }
- virtual int pthread_cond_signal(pthread_cond_t *c){
- checkAccessed(c);
- return LIBC_SYMBOLS.pthread_cond_signal(c);
- }
- virtual int pthread_cond_timedwait(pthread_cond_t *c,
- pthread_mutex_t *m, const struct timespec *t){
- checkAccessed(c);
- return LIBC_SYMBOLS.pthread_cond_timedwait(c,m,t);
- }
- virtual int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m){
- checkAccessed(c);
- return LIBC_SYMBOLS.pthread_cond_wait(c,m);
- }
- virtual int pthread_mutex_destroy(pthread_mutex_t *m){
- markDestroyed(m);
- return LIBC_SYMBOLS.pthread_mutex_destroy(m);
- }
- virtual int pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a){
- markCreated(m);
- return LIBC_SYMBOLS.pthread_mutex_init(m,a);
- }
- virtual int pthread_mutex_lock(pthread_mutex_t *m){
- checkAccessed(m);
- return LIBC_SYMBOLS.pthread_mutex_lock(m);
- }
- virtual int pthread_mutex_trylock(pthread_mutex_t *m){
- checkAccessed(m);
- return LIBC_SYMBOLS.pthread_mutex_trylock(m);
- }
- virtual int pthread_mutex_unlock(pthread_mutex_t *m){
- checkAccessed(m);
- return LIBC_SYMBOLS.pthread_mutex_unlock(m);
- }
-};
-
-#endif /*PTHREADMOCKS_H_*/
-
[09/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/c-doc.Doxyfile
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/c-doc.Doxyfile b/zookeeper-client/zookeeper-client-c/c-doc.Doxyfile
new file mode 100644
index 0000000..e9029cb
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/c-doc.Doxyfile
@@ -0,0 +1,1252 @@
+# Doxyfile 1.4.7
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = $(PROJECT)-$(VERSION)
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = $(DOCDIR)
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST = YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = include/zookeeper.h
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = $(GENERATE_HTML)
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = $(GENERATE_HTMLHELP)
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE = ../$(PROJECT).chm
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION = $(HHC_PATH)
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = $(GENERATE_CHI)
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = $(GENERATE_LATEX)
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = $(PAPER_SIZE)
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = $(GENERATE_PDF)
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = $(GENERATE_RTF)
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = $(GENERATE_MAN)
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = $(GENERATE_XML)
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE = $(DOCDIR)/$(PROJECT).tag
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = $(HAVE_DOT)
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH = $(DOT_PATH)
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that a graph may be further truncated if the graph's
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/cmake_config.h.in
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/cmake_config.h.in b/zookeeper-client/zookeeper-client-c/cmake_config.h.in
new file mode 100644
index 0000000..55efd8a
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/cmake_config.h.in
@@ -0,0 +1,154 @@
+/**
+ * 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 CONFIG_H_
+#define CONFIG_H_
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#cmakedefine HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#cmakedefine HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#cmakedefine HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the file `generated/zookeeper.jute.c'. */
+#cmakedefine HAVE_GENERATED_ZOOKEEPER_JUTE_C 1
+
+/* Define to 1 if you have the file `generated/zookeeper.jute.h'. */
+#cmakedefine HAVE_GENERATED_ZOOKEEPER_JUTE_H 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#cmakedefine HAVE_GETCWD 1
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#cmakedefine HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the `gethostname' function. */
+#cmakedefine HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have the `getlogin' function. */
+#cmakedefine HAVE_GETLOGIN 1
+
+/* Define to 1 if you have the `getpwuid_r' function. */
+#cmakedefine HAVE_GETPWUID_R 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#cmakedefine HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the `getuid' function. */
+#cmakedefine HAVE_GETUID 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#cmakedefine HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `rt' library (-lrt). */
+#cmakedefine HAVE_LIBRT 1
+
+/* Define to 1 if you have the `memmove' function. */
+#cmakedefine HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#cmakedefine HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#cmakedefine HAVE_MEMSET 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#cmakedefine HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#cmakedefine HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the `poll' function. */
+#cmakedefine HAVE_POLL 1
+
+/* Define to 1 if you have the `socket' function. */
+#cmakedefine HAVE_SOCKET 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#cmakedefine HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#cmakedefine HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strchr' function. */
+#cmakedefine HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strdup' function. */
+#cmakedefine HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#cmakedefine HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#cmakedefine HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#cmakedefine HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtol' function. */
+#cmakedefine HAVE_STRTOL 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#cmakedefine HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#cmakedefine HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#cmakedefine HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#cmakedefine HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/utsname.h> header file. */
+#cmakedefine HAVE_SYS_UTSNAME_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#cmakedefine HAVE_UNISTD_H 1
+
+/* Define to 1 if IPv6 support is available. */
+#cmakedefine ZOO_IPV6_ENABLED 1
+
+/* poll() second argument type */
+#define POLL_NFDS_TYPE nfds_t
+
+/* Name of package */
+#define PACKAGE "${PROJECT_NAME}"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "${email}"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "${description}"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "${description} ${PROJECT_VERSION}"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "${PROJECT_NAME}"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "${PROJECT_VERSION}"
+
+/* Version number of package */
+#define VERSION "${PROJECT_VERSION}"
+
+#endif
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/configure.ac
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/configure.ac b/zookeeper-client/zookeeper-client-c/configure.ac
new file mode 100644
index 0000000..51dcfcd
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/configure.ac
@@ -0,0 +1,165 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.59)
+
+AC_INIT([zookeeper C client],3.4.13,[user@zookeeper.apache.org],[zookeeper])
+AC_CONFIG_SRCDIR([src/zookeeper.c])
+
+# Save initial CFLAGS and CXXFLAGS values before AC_PROG_CC and AC_PROG_CXX
+init_cflags="$CFLAGS"
+init_cxxflags="$CXXFLAGS"
+
+# initialize Doxygen support
+DX_HTML_FEATURE(ON)
+DX_CHM_FEATURE(OFF)
+DX_CHI_FEATURE(OFF)
+DX_MAN_FEATURE(OFF)
+DX_RTF_FEATURE(OFF)
+DX_XML_FEATURE(OFF)
+DX_PDF_FEATURE(OFF)
+DX_PS_FEATURE(OFF)
+DX_INIT_DOXYGEN([zookeeper],[c-doc.Doxyfile],[docs])
+
+# initialize automake
+AM_INIT_AUTOMAKE([-Wall foreign])
+AC_CONFIG_HEADER([config.h])
+
+# Checks for programs.
+AC_ARG_WITH(cppunit,
+ [ --without-cppunit do not use CPPUNIT])
+
+if test "$with_cppunit" = "no" ; then
+ CPPUNIT_PATH="No_CPPUNIT"
+ CPPUNIT_INCLUDE=
+ CPPUNIT_LIBS=
+else
+ AM_PATH_CPPUNIT(1.10.2)
+fi
+
+if test "$CALLER" = "ANT" ; then
+CPPUNIT_CFLAGS="$CPPUNIT_CFLAGS -DZKSERVER_CMD=\"\\\"${base_dir}/zookeeper-client/zookeeper-client-c/tests/zkServer.sh\\\"\""
+else
+CPPUNIT_CFLAGS="$CPPUNIT_CFLAGS -DZKSERVER_CMD=\"\\\"./tests/zkServer.sh\\\"\""
+AC_CHECK_FILES([$srcdir/generated/zookeeper.jute.c $srcdir/generated/zookeeper.jute.h],[],
+ [AC_MSG_ERROR([jute files are missing! Please run "ant compile_jute" while in the zookeeper top level directory.])
+])
+fi
+AC_SUBST(CPPUNIT_CFLAGS)
+
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_CXX
+AC_PROG_INSTALL
+AC_PROG_LN_S
+
+# AC_DISABLE_SHARED
+AC_PROG_LIBTOOL
+
+#enable -D_GNU_SOURCE since the return code value of getaddrinfo
+#ifdefed with __USE_GNU
+#features.h header undef's __USE_GNU and defines it only if _GNU_SOURCE is defined
+#hence this define for gcc
+AC_ARG_ENABLE([debug],
+ [AS_HELP_STRING([--enable-debug],[enable debug build [default=no]])],
+ [],[enable_debug=no])
+
+if test "x$enable_debug" = xyes; then
+ if test "x$init_cflags" = x; then
+ CFLAGS=""
+ fi
+ CFLAGS="$CFLAGS -g -O0 -D_GNU_SOURCE"
+else
+ if test "x$init_cflags" = x; then
+ CFLAGS="-g -O2 -D_GNU_SOURCE"
+ fi
+fi
+
+if test "x$enable_debug" = xyes; then
+ if test "x$init_cxxflags" = x; then
+ CXXFLAGS=""
+ fi
+ CXXFLAGS="$CXXFLAGS -g -O0"
+else
+ if test "x$init_cxxflags" = x; then
+ CXXFLAGS="-g -O2"
+ fi
+fi
+
+# Check whether to enable gcov (coverage test)
+AC_ARG_ENABLE(gcov, [AS_HELP_STRING([--enable-gcov],[enable coverage test])])
+AC_MSG_CHECKING([whether to enable gcov])
+AS_IF([test "x${enable_gcov}" = "xyes"],AC_MSG_RESULT([yes]),AC_MSG_RESULT([no]))
+AM_CONDITIONAL([ENABLEGCOV],[test "x${enable_gcov}" = "xyes"])
+
+AC_ARG_WITH([syncapi],
+ [AS_HELP_STRING([--with-syncapi],[build with support for SyncAPI [default=yes]])],
+ [],[with_syncapi=yes])
+
+# Checks for libraries.
+AC_CHECK_LIB([pthread], [pthread_mutex_lock],[have_pthread=yes],[have_pthread=no])
+
+if test "x$with_syncapi" != xno && test "x$have_pthread" = xno; then
+ AC_MSG_WARN([cannot build SyncAPI -- pthread not found])
+ with_syncapi=no
+fi
+if test "x$with_syncapi" != xno; then
+ AC_MSG_NOTICE([building with SyncAPI support])
+else
+ AC_MSG_NOTICE([building without SyncAPI support])
+fi
+
+AM_CONDITIONAL([WANT_SYNCAPI],[test "x$with_syncapi" != xno])
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h sys/utsname.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_INLINE
+AC_HEADER_TIME
+AC_CHECK_TYPE([nfds_t],
+ [AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[poll() second argument type])],
+ [AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[poll() second argument type])],
+ [#include <poll.h>])
+
+AC_MSG_CHECKING([whether to enable ipv6])
+
+AC_TRY_RUN([ /* is AF_INET6 available? */
+#include <sys/types.h>
+#include <sys/socket.h>
+main()
+{
+ if (socket(AF_INET6, SOCK_STREAM, 0) < 0)
+ exit(1);
+ else
+ exit(0);
+}
+], AC_MSG_RESULT(yes)
+ ipv6=yes,
+ AC_MSG_RESULT(no)
+ ipv6=no,
+ AC_MSG_RESULT(no)
+ ipv6=no)
+
+if test x"$ipv6" = xyes; then
+ USEIPV6="-DZOO_IPV6_ENABLED"
+ AC_SUBST(USEIPV6)
+fi
+
+# Checks for library functions.
+AC_CHECK_FUNCS([getcwd gethostbyname gethostname getlogin getpwuid_r gettimeofday getuid memmove memset poll socket strchr strdup strerror strtol])
+
+AC_CONFIG_FILES([Makefile])
+AC_CANONICAL_HOST
+AM_CONDITIONAL([SOLARIS],[
+ case "$host_os" in
+ *solaris*)
+ true
+ ;;
+ *)
+ false
+ ;;
+ esac ])
+AC_OUTPUT
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/include/proto.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/include/proto.h b/zookeeper-client/zookeeper-client-c/include/proto.h
new file mode 100644
index 0000000..bce408e
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/include/proto.h
@@ -0,0 +1,47 @@
+/**
+ * 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 PROTO_H_
+#define PROTO_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZOO_NOTIFY_OP 0
+#define ZOO_CREATE_OP 1
+#define ZOO_DELETE_OP 2
+#define ZOO_EXISTS_OP 3
+#define ZOO_GETDATA_OP 4
+#define ZOO_SETDATA_OP 5
+#define ZOO_GETACL_OP 6
+#define ZOO_SETACL_OP 7
+#define ZOO_GETCHILDREN_OP 8
+#define ZOO_SYNC_OP 9
+#define ZOO_PING_OP 11
+#define ZOO_GETCHILDREN2_OP 12
+#define ZOO_CHECK_OP 13
+#define ZOO_MULTI_OP 14
+#define ZOO_CLOSE_OP -11
+#define ZOO_SETAUTH_OP 100
+#define ZOO_SETWATCHES_OP 101
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*PROTO_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/include/recordio.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/include/recordio.h b/zookeeper-client/zookeeper-client-c/include/recordio.h
new file mode 100644
index 0000000..eed5f99
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/include/recordio.h
@@ -0,0 +1,83 @@
+/**
+ * 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 __RECORDIO_H__
+#define __RECORDIO_H__
+
+#include <sys/types.h>
+#include <stdint.h> /* for int64_t */
+#ifdef WIN32
+#include "winconfig.h"
+#define STRUCT_INITIALIZER(l,r) r
+#else
+#define STRUCT_INITIALIZER(l,r) .l = r
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct buffer {
+ int32_t len;
+ char *buff;
+};
+
+void deallocate_String(char **s);
+void deallocate_Buffer(struct buffer *b);
+void deallocate_vector(void *d);
+struct iarchive {
+ int (*start_record)(struct iarchive *ia, const char *tag);
+ int (*end_record)(struct iarchive *ia, const char *tag);
+ int (*start_vector)(struct iarchive *ia, const char *tag, int32_t *count);
+ int (*end_vector)(struct iarchive *ia, const char *tag);
+ int (*deserialize_Bool)(struct iarchive *ia, const char *name, int32_t *);
+ int (*deserialize_Int)(struct iarchive *ia, const char *name, int32_t *);
+ int (*deserialize_Long)(struct iarchive *ia, const char *name, int64_t *);
+ int (*deserialize_Buffer)(struct iarchive *ia, const char *name,
+ struct buffer *);
+ int (*deserialize_String)(struct iarchive *ia, const char *name, char **);
+ void *priv;
+};
+struct oarchive {
+ int (*start_record)(struct oarchive *oa, const char *tag);
+ int (*end_record)(struct oarchive *oa, const char *tag);
+ int (*start_vector)(struct oarchive *oa, const char *tag, const int32_t *count);
+ int (*end_vector)(struct oarchive *oa, const char *tag);
+ int (*serialize_Bool)(struct oarchive *oa, const char *name, const int32_t *);
+ int (*serialize_Int)(struct oarchive *oa, const char *name, const int32_t *);
+ int (*serialize_Long)(struct oarchive *oa, const char *name,
+ const int64_t *);
+ int (*serialize_Buffer)(struct oarchive *oa, const char *name,
+ const struct buffer *);
+ int (*serialize_String)(struct oarchive *oa, const char *name, char **);
+ void *priv;
+};
+
+struct oarchive *create_buffer_oarchive(void);
+void close_buffer_oarchive(struct oarchive **oa, int free_buffer);
+struct iarchive *create_buffer_iarchive(char *buffer, int len);
+void close_buffer_iarchive(struct iarchive **ia);
+char *get_buffer(struct oarchive *);
+int get_buffer_len(struct oarchive *);
+
+int64_t zoo_htonll(int64_t v);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/include/winconfig.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/include/winconfig.h b/zookeeper-client/zookeeper-client-c/include/winconfig.h
new file mode 100644
index 0000000..c273a93
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/include/winconfig.h
@@ -0,0 +1,15 @@
+#ifndef WINCONFIG_H_
+#define WINCONFIG_H_
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#define inline __inline
+#endif
+
+#define __attribute__(x)
+#define __func__ __FUNCTION__
+
+#define ACL ZKACL /* Conflict with windows API */
+
+#endif
[16/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/src/recordio.c
----------------------------------------------------------------------
diff --git a/src/c/src/recordio.c b/src/c/src/recordio.c
deleted file mode 100644
index 0fcf48e..0000000
--- a/src/c/src/recordio.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/**
- * 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 <recordio.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#ifndef WIN32
-#include <netinet/in.h>
-#else
-#include <winsock2.h> /* for _htonl and _ntohl */
-#endif
-
-void deallocate_String(char **s)
-{
- if (*s)
- free(*s);
- *s = 0;
-}
-
-void deallocate_Buffer(struct buffer *b)
-{
- if (b->buff)
- free(b->buff);
- b->buff = 0;
-}
-
-struct buff_struct {
- int32_t len;
- int32_t off;
- char *buffer;
-};
-
-static int resize_buffer(struct buff_struct *s, int newlen)
-{
- char *buffer= NULL;
- while (s->len < newlen) {
- s->len *= 2;
- }
- buffer = (char*)realloc(s->buffer, s->len);
- if (!buffer) {
- s->buffer = 0;
- return -ENOMEM;
- }
- s->buffer = buffer;
- return 0;
-}
-
-int oa_start_record(struct oarchive *oa, const char *tag)
-{
- return 0;
-}
-int oa_end_record(struct oarchive *oa, const char *tag)
-{
- return 0;
-}
-int oa_serialize_int(struct oarchive *oa, const char *tag, const int32_t *d)
-{
- struct buff_struct *priv = oa->priv;
- int32_t i = htonl(*d);
- if ((priv->len - priv->off) < sizeof(i)) {
- int rc = resize_buffer(priv, priv->len + sizeof(i));
- if (rc < 0) return rc;
- }
- memcpy(priv->buffer+priv->off, &i, sizeof(i));
- priv->off+=sizeof(i);
- return 0;
-}
-int64_t zoo_htonll(int64_t v)
-{
- int i = 0;
- char *s = (char *)&v;
- if (htonl(1) == 1) {
- return v;
- }
- for (i = 0; i < 4; i++) {
- int tmp = s[i];
- s[i] = s[8-i-1];
- s[8-i-1] = tmp;
- }
-
- return v;
-}
-
-int oa_serialize_long(struct oarchive *oa, const char *tag, const int64_t *d)
-{
- const int64_t i = zoo_htonll(*d);
- struct buff_struct *priv = oa->priv;
- if ((priv->len - priv->off) < sizeof(i)) {
- int rc = resize_buffer(priv, priv->len + sizeof(i));
- if (rc < 0) return rc;
- }
- memcpy(priv->buffer+priv->off, &i, sizeof(i));
- priv->off+=sizeof(i);
- return 0;
-}
-int oa_start_vector(struct oarchive *oa, const char *tag, const int32_t *count)
-{
- return oa_serialize_int(oa, tag, count);
-}
-int oa_end_vector(struct oarchive *oa, const char *tag)
-{
- return 0;
-}
-int oa_serialize_bool(struct oarchive *oa, const char *name, const int32_t *i)
-{
- //return oa_serialize_int(oa, name, i);
- struct buff_struct *priv = oa->priv;
- if ((priv->len - priv->off) < 1) {
- int rc = resize_buffer(priv, priv->len + 1);
- if (rc < 0)
- return rc;
- }
- priv->buffer[priv->off] = (*i == 0 ? '\0' : '\1');
- priv->off++;
- return 0;
-}
-static const int32_t negone = -1;
-int oa_serialize_buffer(struct oarchive *oa, const char *name,
- const struct buffer *b)
-{
- struct buff_struct *priv = oa->priv;
- int rc;
- if (!b) {
- return oa_serialize_int(oa, "len", &negone);
- }
- rc = oa_serialize_int(oa, "len", &b->len);
- if (rc < 0)
- return rc;
- // this means a buffer of NUll
- // with size of -1. This is
- // waht we use in java serialization for NULL
- if (b->len == -1) {
- return rc;
- }
- if ((priv->len - priv->off) < b->len) {
- rc = resize_buffer(priv, priv->len + b->len);
- if (rc < 0)
- return rc;
- }
- memcpy(priv->buffer+priv->off, b->buff, b->len);
- priv->off += b->len;
- return 0;
-}
-int oa_serialize_string(struct oarchive *oa, const char *name, char **s)
-{
- struct buff_struct *priv = oa->priv;
- int32_t len;
- int rc;
- if (!*s) {
- oa_serialize_int(oa, "len", &negone);
- return 0;
- }
- len = strlen(*s);
- rc = oa_serialize_int(oa, "len", &len);
- if (rc < 0)
- return rc;
- if ((priv->len - priv->off) < len) {
- rc = resize_buffer(priv, priv->len + len);
- if (rc < 0)
- return rc;
- }
- memcpy(priv->buffer+priv->off, *s, len);
- priv->off += len;
- return 0;
-}
-int ia_start_record(struct iarchive *ia, const char *tag)
-{
- return 0;
-}
-int ia_end_record(struct iarchive *ia, const char *tag)
-{
- return 0;
-}
-int ia_deserialize_int(struct iarchive *ia, const char *tag, int32_t *count)
-{
- struct buff_struct *priv = ia->priv;
- if ((priv->len - priv->off) < sizeof(*count)) {
- return -E2BIG;
- }
- memcpy(count, priv->buffer+priv->off, sizeof(*count));
- priv->off+=sizeof(*count);
- *count = ntohl(*count);
- return 0;
-}
-
-int ia_deserialize_long(struct iarchive *ia, const char *tag, int64_t *count)
-{
- struct buff_struct *priv = ia->priv;
- int64_t v = 0;
- if ((priv->len - priv->off) < sizeof(*count)) {
- return -E2BIG;
- }
- memcpy(count, priv->buffer+priv->off, sizeof(*count));
- priv->off+=sizeof(*count);
- v = zoo_htonll(*count); // htonll and ntohll do the same
- *count = v;
- return 0;
-}
-int ia_start_vector(struct iarchive *ia, const char *tag, int32_t *count)
-{
- return ia_deserialize_int(ia, tag, count);
-}
-int ia_end_vector(struct iarchive *ia, const char *tag)
-{
- return 0;
-}
-int ia_deserialize_bool(struct iarchive *ia, const char *name, int32_t *v)
-{
- struct buff_struct *priv = ia->priv;
- //fprintf(stderr, "Deserializing bool %d\n", priv->off);
- //return ia_deserialize_int(ia, name, v);
- if ((priv->len - priv->off) < 1) {
- return -E2BIG;
- }
- *v = priv->buffer[priv->off];
- priv->off+=1;
- //fprintf(stderr, "Deserializing bool end %d\n", priv->off);
- return 0;
-}
-int ia_deserialize_buffer(struct iarchive *ia, const char *name,
- struct buffer *b)
-{
- struct buff_struct *priv = ia->priv;
- int rc = ia_deserialize_int(ia, "len", &b->len);
- if (rc < 0)
- return rc;
- if ((priv->len - priv->off) < b->len) {
- return -E2BIG;
- }
- // set the buffer to null
- if (b->len == -1) {
- b->buff = NULL;
- return rc;
- }
- b->buff = malloc(b->len);
- if (!b->buff) {
- return -ENOMEM;
- }
- memcpy(b->buff, priv->buffer+priv->off, b->len);
- priv->off += b->len;
- return 0;
-}
-int ia_deserialize_string(struct iarchive *ia, const char *name, char **s)
-{
- struct buff_struct *priv = ia->priv;
- int32_t len;
- int rc = ia_deserialize_int(ia, "len", &len);
- if (rc < 0)
- return rc;
- if ((priv->len - priv->off) < len) {
- return -E2BIG;
- }
- if (len < 0) {
- return -EINVAL;
- }
- *s = malloc(len+1);
- if (!*s) {
- return -ENOMEM;
- }
- memcpy(*s, priv->buffer+priv->off, len);
- (*s)[len] = '\0';
- priv->off += len;
- return 0;
-}
-
-static struct iarchive ia_default = { STRUCT_INITIALIZER (start_record ,ia_start_record),
- STRUCT_INITIALIZER (end_record ,ia_end_record), STRUCT_INITIALIZER (start_vector , ia_start_vector),
- STRUCT_INITIALIZER (end_vector ,ia_end_vector), STRUCT_INITIALIZER (deserialize_Bool , ia_deserialize_bool),
- STRUCT_INITIALIZER (deserialize_Int ,ia_deserialize_int),
- STRUCT_INITIALIZER (deserialize_Long , ia_deserialize_long) ,
- STRUCT_INITIALIZER (deserialize_Buffer, ia_deserialize_buffer),
- STRUCT_INITIALIZER (deserialize_String, ia_deserialize_string) };
-
-static struct oarchive oa_default = { STRUCT_INITIALIZER (start_record , oa_start_record),
- STRUCT_INITIALIZER (end_record , oa_end_record), STRUCT_INITIALIZER (start_vector , oa_start_vector),
- STRUCT_INITIALIZER (end_vector , oa_end_vector), STRUCT_INITIALIZER (serialize_Bool , oa_serialize_bool),
- STRUCT_INITIALIZER (serialize_Int , oa_serialize_int),
- STRUCT_INITIALIZER (serialize_Long , oa_serialize_long) ,
- STRUCT_INITIALIZER (serialize_Buffer , oa_serialize_buffer),
- STRUCT_INITIALIZER (serialize_String , oa_serialize_string) };
-
-struct iarchive *create_buffer_iarchive(char *buffer, int len)
-{
- struct iarchive *ia;
- struct buff_struct *buff;
- ia = malloc(sizeof(*ia));
- if (!ia) return 0;
- buff = malloc(sizeof(struct buff_struct));
- if (!buff) {
- free(ia);
- return 0;
- }
- *ia = ia_default;
- buff->off = 0;
- buff->buffer = buffer;
- buff->len = len;
- ia->priv = buff;
- return ia;
-}
-
-struct oarchive *create_buffer_oarchive()
-{
- struct oarchive *oa;
- struct buff_struct *buff;
- oa = malloc(sizeof(*oa));
- if (!oa) return 0;
- buff = malloc(sizeof(struct buff_struct));
- if (!buff) {
- free(oa);
- return 0;
- }
- *oa = oa_default;
- buff->off = 0;
- buff->buffer = malloc(128);
- buff->len = 128;
- oa->priv = buff;
- return oa;
-}
-
-void close_buffer_iarchive(struct iarchive **ia)
-{
- free((*ia)->priv);
- free(*ia);
- *ia = 0;
-}
-
-void close_buffer_oarchive(struct oarchive **oa, int free_buffer)
-{
- if (free_buffer) {
- struct buff_struct *buff = (struct buff_struct *)(*oa)->priv;
- if (buff->buffer) {
- free(buff->buffer);
- }
- }
- free((*oa)->priv);
- free(*oa);
- *oa = 0;
-}
-
-char *get_buffer(struct oarchive *oa)
-{
- struct buff_struct *buff = oa->priv;
- return buff->buffer;
-}
-int get_buffer_len(struct oarchive *oa)
-{
- struct buff_struct *buff = oa->priv;
- return buff->off;
-}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/src/st_adaptor.c
----------------------------------------------------------------------
diff --git a/src/c/src/st_adaptor.c b/src/c/src/st_adaptor.c
deleted file mode 100644
index 23573b3..0000000
--- a/src/c/src/st_adaptor.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * 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 DLL_EXPORT
-# define USE_STATIC_LIB
-#endif
-
-#include "zk_adaptor.h"
-#include <stdlib.h>
-#include <time.h>
-
-int zoo_lock_auth(zhandle_t *zh)
-{
- return 0;
-}
-int zoo_unlock_auth(zhandle_t *zh)
-{
- return 0;
-}
-int lock_buffer_list(buffer_head_t *l)
-{
- return 0;
-}
-int unlock_buffer_list(buffer_head_t *l)
-{
- return 0;
-}
-int lock_completion_list(completion_head_t *l)
-{
- return 0;
-}
-int unlock_completion_list(completion_head_t *l)
-{
- return 0;
-}
-struct sync_completion *alloc_sync_completion(void)
-{
- return (struct sync_completion*)calloc(1, sizeof(struct sync_completion));
-}
-int wait_sync_completion(struct sync_completion *sc)
-{
- return 0;
-}
-
-void free_sync_completion(struct sync_completion *sc)
-{
- free(sc);
-}
-
-void notify_sync_completion(struct sync_completion *sc)
-{
-}
-
-int process_async(int outstanding_sync)
-{
- return outstanding_sync == 0;
-}
-
-int adaptor_init(zhandle_t *zh)
-{
- return 0;
-}
-
-void adaptor_finish(zhandle_t *zh){}
-
-void adaptor_destroy(zhandle_t *zh){}
-
-int flush_send_queue(zhandle_t *, int);
-
-int adaptor_send_queue(zhandle_t *zh, int timeout)
-{
- return flush_send_queue(zh, timeout);
-}
-
-int32_t inc_ref_counter(zhandle_t* zh,int i)
-{
- zh->ref_counter+=(i<0?-1:(i>0?1:0));
- return zh->ref_counter;
-}
-
-int32_t get_xid()
-{
- static int32_t xid = -1;
- if (xid == -1) {
- xid = time(0);
- }
- return xid++;
-}
-
-int enter_critical(zhandle_t* zh)
-{
- return 0;
-}
-
-int leave_critical(zhandle_t* zh)
-{
- return 0;
-}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/src/winport.c
----------------------------------------------------------------------
diff --git a/src/c/src/winport.c b/src/c/src/winport.c
deleted file mode 100644
index 3592ea1..0000000
--- a/src/c/src/winport.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/**
- * 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.
- */
-
-#ifdef WIN32
-#include "winport.h"
-#include <stdlib.h>
-#include <stdint.h> /* for int64_t */
-#include <winsock2.h> /* must always be included before ws2tcpip.h */
-#include <ws2tcpip.h> /* for SOCKET */
-
-int pthread_mutex_lock(pthread_mutex_t* _mutex ){
- int rc = WaitForSingleObject( *_mutex, // handle to mutex
- INFINITE); // no time-out interval
- return ((rc == WAIT_OBJECT_0) ? 0: rc);
-}
-
-int pthread_mutex_unlock( pthread_mutex_t* _mutex ){
- int rc = ReleaseMutex(*_mutex);
- return ((rc != 0)? 0: GetLastError());
-}
-
-int pthread_mutex_init(pthread_mutex_t* _mutex, void* ignoredAttr){
- //use CreateMutex as we are using the HANDLES in pthread_cond
- *_mutex = CreateMutex(
- NULL, // default security attributes
- FALSE, // initially not owned
- NULL); // unnamed mutex
- return ((*_mutex == NULL) ? GetLastError() : 0);
-}
-
-int pthread_mutex_destroy(pthread_mutex_t* _mutex)
-{
- int rc = CloseHandle(*_mutex);
- return ((rc != 0)? 0: GetLastError());
-}
-
-int pthread_create(pthread_t *thread, const pthread_attr_t *attr, unsigned (__stdcall* start_routine)(void* a), void *arg)
-{
- int _intThreadId;
- (*thread).thread_handle = (HANDLE)_beginthreadex( NULL, 0, start_routine , arg, 0, (unsigned int*)&_intThreadId );
- (*thread).thread_id = _intThreadId;
- return (((*thread).thread_handle == 0 ) ? errno : 0 );
-}
-
-
-int pthread_equal(pthread_t t1, pthread_t t2){
-//Is there a better way to do this? GetThreadId(handle) is only supported Windows 2003 n above.
- return ((t1.thread_id == t2.thread_id) ? 1:0);
-}
-
-pthread_t pthread_self(){
- pthread_t thread_self;
- thread_self.thread_handle = GetCurrentThread();
- thread_self.thread_id = GetCurrentThreadId();
- return thread_self;
-}
-
-int pthread_join(pthread_t _thread, void** ignore)
-{
- int rc = WaitForSingleObject( _thread.thread_handle, INFINITE );
- return ((rc == WAIT_OBJECT_0) ? 0: rc);
-}
-
-int pthread_detach(pthread_t _thread)
-{
- int rc = CloseHandle(_thread.thread_handle) ;
- return (rc != 0) ? 0: GetLastError();
-}
-
-void pthread_mutexattr_init(pthread_mutexattr_t* ignore){}
-void pthread_mutexattr_settype(pthread_mutexattr_t* ingore_attr, int ignore){}
-void pthread_mutexattr_destroy(pthread_mutexattr_t* ignore_attr){}
-
-int
-pthread_cond_init (pthread_cond_t *cv,
- const pthread_condattr_t * ignore)
-{
- cv->waiters_count_ = 0;
- cv->was_broadcast_ = 0;
- cv->sema_ = CreateSemaphore (NULL, // no security
- 0, // initially 0
- 0x7fffffff, // max count
- NULL); // unnamed
- if (cv->sema_ == NULL )
- return GetLastError();
- InitializeCriticalSection (&cv->waiters_count_lock_);
- cv->waiters_done_ = CreateEvent (NULL, // no security
- FALSE, // auto-reset
- FALSE, // non-signaled initially
- NULL); // unnamed
- return (cv->waiters_done_ == NULL) ? GetLastError() : 0;
-
-}
-
-
-int pthread_cond_destroy(pthread_cond_t *cond)
-{
- CloseHandle( cond->sema_);
- DeleteCriticalSection(&cond->waiters_count_lock_);
- return (CloseHandle( cond->waiters_done_ ) == 0)? GetLastError(): 0 ;
-}
-
-
-int
-pthread_cond_signal (pthread_cond_t *cv)
-{
- int have_waiters;
- EnterCriticalSection (& (cv->waiters_count_lock_));
- have_waiters = cv->waiters_count_ > 0;
- LeaveCriticalSection (&cv->waiters_count_lock_);
-
- // If there aren't any waiters, then this is a no-op.
- if (have_waiters){
- return (ReleaseSemaphore (cv->sema_, 1, 0) == 0 ) ? GetLastError() : 0 ;
- }else
- return 0;
-}
-
-
-int
-pthread_cond_broadcast (pthread_cond_t *cv)
-{
- // This is needed to ensure that <waiters_count_> and <was_broadcast_> are
- // consistent relative to each other.
- int have_waiters = 0;
- EnterCriticalSection (&cv->waiters_count_lock_);
-
- if (cv->waiters_count_ > 0) {
- // We are broadcasting, even if there is just one waiter...
- // Record that we are broadcasting, which helps optimize
- // <pthread_cond_wait> for the non-broadcast case.
- cv->was_broadcast_ = 1;
- have_waiters = 1;
- }
-
- if (have_waiters) {
- // Wake up all the waiters atomically.
- ReleaseSemaphore (cv->sema_, cv->waiters_count_, 0);
-
- LeaveCriticalSection (&cv->waiters_count_lock_);
-
- // Wait for all the awakened threads to acquire the counting
- // semaphore.
- WaitForSingleObject (cv->waiters_done_, INFINITE);
- // This assignment is okay, even without the <waiters_count_lock_> held
- // because no other waiter threads can wake up to access it.
- cv->was_broadcast_ = 0;
- }
- else
- LeaveCriticalSection (&cv->waiters_count_lock_);
-}
-
-
-int
-pthread_cond_wait (pthread_cond_t *cv,
- pthread_mutex_t *external_mutex)
-{
- int last_waiter;
- // Avoid race conditions.
- EnterCriticalSection (&cv->waiters_count_lock_);
- cv->waiters_count_++;
- LeaveCriticalSection (&cv->waiters_count_lock_);
-
- // This call atomically releases the mutex and waits on the
- // semaphore until <pthread_cond_signal> or <pthread_cond_broadcast>
- // are called by another thread.
- SignalObjectAndWait (*external_mutex, cv->sema_, INFINITE, FALSE);
-
- // Reacquire lock to avoid race conditions.
- EnterCriticalSection (&cv->waiters_count_lock_);
-
- // We're no longer waiting...
- cv->waiters_count_--;
-
- // Check to see if we're the last waiter after <pthread_cond_broadcast>.
- last_waiter = cv->was_broadcast_ && cv->waiters_count_ == 0;
-
- LeaveCriticalSection (&cv->waiters_count_lock_);
-
- // If we're the last waiter thread during this particular broadcast
- // then let all the other threads proceed.
- if (last_waiter)
- // This call atomically signals the <waiters_done_> event and waits until
- // it can acquire the <external_mutex>. This is required to ensure fairness.
- SignalObjectAndWait (cv->waiters_done_, *external_mutex, INFINITE, FALSE);
- else
- // Always regain the external mutex since that's the guarantee we
- // give to our callers.
- WaitForSingleObject (*external_mutex, INFINITE);
-}
-
-int pthread_key_create(pthread_key_t *key, void (*destructor)(void *) )
-{
- int result = 0;
- pthread_key_t* newkey;
-
- if ((newkey = (pthread_key_t*) calloc (1, sizeof (pthread_key_t))) == NULL)
- {
- result = ENOMEM;
- }
- else if ((newkey->key = TlsAlloc ()) == TLS_OUT_OF_INDEXES)
- {
- result = EAGAIN;
- free (newkey);
- newkey = NULL;
- }
- else if (destructor != NULL)
- {
- //--we have to store the function pointer for destructor, so that we can call it
- //--to free up the user allocated storage--
- newkey->destructor = destructor;
- }
- key = newkey;
- return (result);
-}
-
-int pthread_key_delete(pthread_key_t key)
-{
- int rc = 0;
- LPVOID lpvData = TlsGetValue(key.key);
- rc = TlsFree (key.key);
- rc = (rc != 0 ) ? 0 : GetLastError();
- if (key.destructor != NULL && lpvData != 0){
- key.destructor(lpvData); //we take control of calling destructor, instead of calling it on thread exit.
- }
- free (&key);
- return (rc);
-}
-
-void *pthread_getspecific(pthread_key_t key)
-{
- LPVOID lpvData = TlsGetValue(key.key);
- if ((lpvData == 0) && (GetLastError() != ERROR_SUCCESS))
- return NULL;
- else
- return lpvData;
-}
-
-int pthread_setspecific(pthread_key_t key, const void *value)
-{
- int rc = TlsSetValue (key.key, value);
- return ((rc != 0 ) ? 0 : GetLastError());
-}
-
-int gettimeofday(struct timeval *tp, void *tzp) {
- int64_t now = 0;
- if (tzp != 0) { errno = EINVAL; return -1; }
- GetSystemTimeAsFileTime( (LPFILETIME)&now );
- tp->tv_sec = (long)(now / 10000000 - 11644473600LL);
- tp->tv_usec = (now / 10) % 1000000;
- return 0;
-}
-
-int close(SOCKET fd) {
- return closesocket(fd);
-}
-
-int Win32WSAStartup()
-{
- WORD wVersionRq;
- WSADATA wsaData;
- int err;
-
- wVersionRq = MAKEWORD(2,0);
- err = WSAStartup(wVersionRq, &wsaData);
- if (err != 0)
- return 1;
-
- // confirm the version information
- if ((LOBYTE(wsaData.wVersion) != 2) ||
- (HIBYTE(wsaData.wVersion) != 0))
- {
- Win32WSACleanup();
- return 1;
- }
- return 0;
-}
-
-void Win32WSACleanup()
-{
- WSACleanup();
-}
-
-#endif //WIN32
-
-
-
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/src/winport.h
----------------------------------------------------------------------
diff --git a/src/c/src/winport.h b/src/c/src/winport.h
deleted file mode 100644
index da6028c..0000000
--- a/src/c/src/winport.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * This header file is to port pthread lib , sockets and other utility methods on windows.
- * Specifically the threads function, mutexes, keys, and socket initialization.
- */
-
-#ifndef WINPORT_H_
-#define WINPORT_H_
-
-#ifdef WIN32
-#include "winconfig.h"
-
-#define _WINSOCK_DEPRECATED_NO_WARNINGS
-#include <winsock2.h> /* must always be included before ws2tcpip.h */
-#include <ws2tcpip.h> /* for struct sock_addr used in zookeeper.h */
-
-/* POSIX names are deprecated, use ISO conformant names instead. */
-#define strdup _strdup
-#define getcwd _getcwd
-#define getpid _getpid
-
-/* Windows "secure" versions of POSIX reentrant functions */
-#define strtok_r strtok_s
-#define localtime_r(a,b) localtime_s(b,a)
-
-/* After this version of MSVC, snprintf became a defined function,
- and so cannot be redefined, nor can #ifndef be used to guard it. */
-#if ((defined(_MSC_VER) && _MSC_VER < 1900) || !defined(_MSC_VER))
-#define snprintf _snprintf
-#endif
-
-
-#include <errno.h>
-#include <process.h>
-#include <stdint.h> /* for int64_t */
-#include <stdlib.h>
-#include <malloc.h>
-
-
-typedef int ssize_t;
-typedef HANDLE pthread_mutex_t;
-
-struct pthread_t_
-{
- HANDLE thread_handle;
- DWORD thread_id;
-};
-
-typedef struct pthread_t_ pthread_t;
-typedef int pthread_mutexattr_t;
-typedef int pthread_condattr_t;
-typedef int pthread_attr_t;
-#define PTHREAD_MUTEX_RECURSIVE 0
-
-int pthread_mutex_lock(pthread_mutex_t* _mutex );
-int pthread_mutex_unlock( pthread_mutex_t* _mutex );
-int pthread_mutex_init(pthread_mutex_t* _mutex, void* ignoredAttr);
-int pthread_mutex_destroy(pthread_mutex_t* _mutex);
-int pthread_create(pthread_t *thread, const pthread_attr_t *attr, unsigned (__stdcall* start_routine)(void* a), void *arg);
-int pthread_equal(pthread_t t1, pthread_t t2);
-pthread_t pthread_self();
-int pthread_join(pthread_t _thread, void** ignore);
-int pthread_detach(pthread_t _thread);
-
-void pthread_mutexattr_init(pthread_mutexattr_t* ignore);
-void pthread_mutexattr_settype(pthread_mutexattr_t* ingore_attr, int ignore);
-void pthread_mutexattr_destroy(pthread_mutexattr_t* ignore_attr);
-
-
-// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
-
-typedef struct
-{
- int waiters_count_;
- // Number of waiting threads.
-
- CRITICAL_SECTION waiters_count_lock_;
- // Serialize access to <waiters_count_>.
-
- HANDLE sema_;
- // Semaphore used to queue up threads waiting for the condition to
- // become signaled.
-
- HANDLE waiters_done_;
- // An auto-reset event used by the broadcast/signal thread to wait
- // for all the waiting thread(s) to wake up and be released from the
- // semaphore.
-
- size_t was_broadcast_;
- // Keeps track of whether we were broadcasting or signaling. This
- // allows us to optimize the code if we're just signaling.
-}pthread_cond_t;
-
-int pthread_cond_init (pthread_cond_t *cv,const pthread_condattr_t * ignore);
-int pthread_cond_destroy(pthread_cond_t *cond);
-int pthread_cond_signal (pthread_cond_t *cv);
-int pthread_cond_broadcast (pthread_cond_t *cv);
-int pthread_cond_wait (pthread_cond_t *cv, pthread_mutex_t *external_mutex);
-
-
-struct pthread_key_t_
-{
- DWORD key;
- void (*destructor) (void *);
-};
-
-typedef struct pthread_key_t_ pthread_key_t;
-int pthread_key_create(pthread_key_t *key, void (*destructor)(void *) );
-int pthread_key_delete(pthread_key_t key);
-void *pthread_getspecific(pthread_key_t key);
-int pthread_setspecific(pthread_key_t key, const void *value);
-
-int gettimeofday(struct timeval *tp, void *tzp);
-int close(SOCKET fd);
-int Win32WSAStartup();
-void Win32WSACleanup();
-#endif //WIN32
-
-
-
-#endif //WINPORT_H_
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/src/zk_adaptor.h
----------------------------------------------------------------------
diff --git a/src/c/src/zk_adaptor.h b/src/c/src/zk_adaptor.h
deleted file mode 100644
index b990779..0000000
--- a/src/c/src/zk_adaptor.h
+++ /dev/null
@@ -1,276 +0,0 @@
-/**
- * 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_ADAPTOR_H_
-#define ZK_ADAPTOR_H_
-#include <zookeeper.jute.h>
-#ifdef THREADED
-#ifndef WIN32
-#include <pthread.h>
-#else
-#include "winport.h"
-#endif
-#endif
-#include "zookeeper.h"
-#include "zk_hashtable.h"
-
-/* predefined xid's values recognized as special by the server */
-#define WATCHER_EVENT_XID -1
-#define PING_XID -2
-#define AUTH_XID -4
-#define SET_WATCHES_XID -8
-
-/* zookeeper state constants */
-#define EXPIRED_SESSION_STATE_DEF -112
-#define AUTH_FAILED_STATE_DEF -113
-#define CONNECTING_STATE_DEF 1
-#define ASSOCIATING_STATE_DEF 2
-#define CONNECTED_STATE_DEF 3
-#define NOTCONNECTED_STATE_DEF 999
-
-/* zookeeper event type constants */
-#define CREATED_EVENT_DEF 1
-#define DELETED_EVENT_DEF 2
-#define CHANGED_EVENT_DEF 3
-#define CHILD_EVENT_DEF 4
-#define SESSION_EVENT_DEF -1
-#define NOTWATCHING_EVENT_DEF -2
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct _buffer_list;
-struct _completion_list;
-
-typedef struct _buffer_head {
- struct _buffer_list *volatile head;
- struct _buffer_list *last;
-#ifdef THREADED
- pthread_mutex_t lock;
-#endif
-} buffer_head_t;
-
-typedef struct _completion_head {
- struct _completion_list *volatile head;
- struct _completion_list *last;
-#ifdef THREADED
- pthread_cond_t cond;
- pthread_mutex_t lock;
-#endif
-} completion_head_t;
-
-int lock_buffer_list(buffer_head_t *l);
-int unlock_buffer_list(buffer_head_t *l);
-int lock_completion_list(completion_head_t *l);
-int unlock_completion_list(completion_head_t *l);
-
-struct sync_completion {
- int rc;
- union {
- struct {
- char *str;
- int str_len;
- } str;
- struct Stat stat;
- struct {
- char *buffer;
- int buff_len;
- struct Stat stat;
- } data;
- struct {
- struct ACL_vector acl;
- struct Stat stat;
- } acl;
- struct String_vector strs2;
- struct {
- struct String_vector strs2;
- struct Stat stat2;
- } strs_stat;
- } u;
- int complete;
-#ifdef THREADED
- pthread_cond_t cond;
- pthread_mutex_t lock;
-#endif
-};
-
-typedef struct _auth_info {
- int state; /* 0=>inactive, >0 => active */
- char* scheme;
- struct buffer auth;
- void_completion_t completion;
- const char* data;
- struct _auth_info *next;
-} auth_info;
-
-/**
- * This structure represents a packet being read or written.
- */
-typedef struct _buffer_list {
- char *buffer;
- int len; /* This represents the length of sizeof(header) + length of buffer */
- int curr_offset; /* This is the offset into the header followed by offset into the buffer */
- struct _buffer_list *next;
-} buffer_list_t;
-
-/* the size of connect request */
-#define HANDSHAKE_REQ_SIZE 44
-/* connect request */
-struct connect_req {
- int32_t protocolVersion;
- int64_t lastZxidSeen;
- int32_t timeOut;
- int64_t sessionId;
- int32_t passwd_len;
- char passwd[16];
-};
-
-/* the connect response */
-struct prime_struct {
- int32_t len;
- int32_t protocolVersion;
- int32_t timeOut;
- int64_t sessionId;
- int32_t passwd_len;
- char passwd[16];
-};
-
-#ifdef THREADED
-/* this is used by mt_adaptor internally for thread management */
-struct adaptor_threads {
- pthread_t io;
- pthread_t completion;
- int threadsToWait; // barrier
- pthread_cond_t cond; // barrier's conditional
- pthread_mutex_t lock; // ... and a lock
- pthread_mutex_t zh_lock; // critical section lock
-#ifdef WIN32
- SOCKET self_pipe[2];
-#else
- int self_pipe[2];
-#endif
-};
-#endif
-
-/** the auth list for adding auth */
-typedef struct _auth_list_head {
- auth_info *auth;
-#ifdef THREADED
- pthread_mutex_t lock;
-#endif
-} auth_list_head_t;
-
-/**
- * This structure represents the connection to zookeeper.
- */
-
-struct _zhandle {
-#ifdef WIN32
- SOCKET fd; /* the descriptor used to talk to zookeeper */
-#else
- int fd; /* the descriptor used to talk to zookeeper */
-#endif
- char *hostname; /* the hostname of zookeeper */
- struct sockaddr_storage *addrs; /* the addresses that correspond to the hostname */
- int addrs_count; /* The number of addresses in the addrs array */
- watcher_fn watcher; /* the registered watcher */
- struct timeval last_recv; /* The time that the last message was received */
- struct timeval last_send; /* The time that the last message was sent */
- struct timeval last_ping; /* The time that the last PING was sent */
- struct timeval next_deadline; /* The time of the next deadline */
- int recv_timeout; /* The maximum amount of time that can go by without
- receiving anything from the zookeeper server */
- buffer_list_t *input_buffer; /* the current buffer being read in */
- buffer_head_t to_process; /* The buffers that have been read and are ready to be processed. */
- buffer_head_t to_send; /* The packets queued to send */
- completion_head_t sent_requests; /* The outstanding requests */
- completion_head_t completions_to_process; /* completions that are ready to run */
- int connect_index; /* The index of the address to connect to */
- clientid_t client_id;
- long long last_zxid;
- int outstanding_sync; /* Number of outstanding synchronous requests */
- struct _buffer_list primer_buffer; /* The buffer used for the handshake at the start of a connection */
- struct prime_struct primer_storage; /* the connect response */
- char primer_storage_buffer[40]; /* the true size of primer_storage */
- volatile int state;
- void *context;
- auth_list_head_t auth_h; /* authentication data list */
- /* zookeeper_close is not reentrant because it de-allocates the zhandler.
- * This guard variable is used to defer the destruction of zhandle till
- * right before top-level API call returns to the caller */
- int32_t ref_counter;
- volatile int close_requested;
- void *adaptor_priv;
- /* Used for debugging only: non-zero value indicates the time when the zookeeper_process
- * call returned while there was at least one unprocessed server response
- * available in the socket recv buffer */
- struct timeval socket_readable;
-
- zk_hashtable* active_node_watchers;
- zk_hashtable* active_exist_watchers;
- zk_hashtable* active_child_watchers;
- /** used for chroot path at the client side **/
- char *chroot;
-};
-
-
-int adaptor_init(zhandle_t *zh);
-void adaptor_finish(zhandle_t *zh);
-void adaptor_destroy(zhandle_t *zh);
-struct sync_completion *alloc_sync_completion(void);
-int wait_sync_completion(struct sync_completion *sc);
-void free_sync_completion(struct sync_completion *sc);
-void notify_sync_completion(struct sync_completion *sc);
-int adaptor_send_queue(zhandle_t *zh, int timeout);
-int process_async(int outstanding_sync);
-void process_completions(zhandle_t *zh);
-int flush_send_queue(zhandle_t*zh, int timeout);
-char* sub_string(zhandle_t *zh, const char* server_path);
-void free_duplicate_path(const char* free_path, const char* path);
-int zoo_lock_auth(zhandle_t *zh);
-int zoo_unlock_auth(zhandle_t *zh);
-
-// critical section guards
-int enter_critical(zhandle_t* zh);
-int leave_critical(zhandle_t* zh);
-// zhandle object reference counting
-void api_prolog(zhandle_t* zh);
-int api_epilog(zhandle_t *zh, int rc);
-int32_t get_xid();
-// returns the new value of the ref counter
-int32_t inc_ref_counter(zhandle_t* zh,int i);
-
-#ifdef THREADED
-// atomic post-increment
-int32_t fetch_and_add(volatile int32_t* operand, int incr);
-// in mt mode process session event asynchronously by the completion thread
-#define PROCESS_SESSION_EVENT(zh,newstate) queue_session_event(zh,newstate)
-#else
-// in single-threaded mode process session event immediately
-//#define PROCESS_SESSION_EVENT(zh,newstate) deliverWatchers(zh,ZOO_SESSION_EVENT,newstate,0)
-#define PROCESS_SESSION_EVENT(zh,newstate) queue_session_event(zh,newstate)
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*ZK_ADAPTOR_H_*/
-
-
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/src/zk_hashtable.c
----------------------------------------------------------------------
diff --git a/src/c/src/zk_hashtable.c b/src/c/src/zk_hashtable.c
deleted file mode 100644
index 0efc5aa..0000000
--- a/src/c/src/zk_hashtable.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "zk_hashtable.h"
-#include "zk_adaptor.h"
-#include "hashtable/hashtable.h"
-#include "hashtable/hashtable_itr.h"
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-typedef struct _watcher_object {
- watcher_fn watcher;
- void* context;
- struct _watcher_object* next;
-} watcher_object_t;
-
-
-struct _zk_hashtable {
- struct hashtable* ht;
-};
-
-struct watcher_object_list {
- watcher_object_t* head;
-};
-
-/* the following functions are for testing only */
-typedef struct hashtable hashtable_impl;
-
-hashtable_impl* getImpl(zk_hashtable* ht){
- return ht->ht;
-}
-
-watcher_object_t* getFirstWatcher(zk_hashtable* ht,const char* path)
-{
- watcher_object_list_t* wl=hashtable_search(ht->ht,(void*)path);
- if(wl!=0)
- return wl->head;
- return 0;
-}
-/* end of testing functions */
-
-watcher_object_t* clone_watcher_object(watcher_object_t* wo)
-{
- watcher_object_t* res=calloc(1,sizeof(watcher_object_t));
- assert(res);
- res->watcher=wo->watcher;
- res->context=wo->context;
- return res;
-}
-
-static unsigned int string_hash_djb2(void *str)
-{
- unsigned int hash = 5381;
- int c;
- const char* cstr = (const char*)str;
- while ((c = *cstr++))
- hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
-
- return hash;
-}
-
-static int string_equal(void *key1,void *key2)
-{
- return strcmp((const char*)key1,(const char*)key2)==0;
-}
-
-static watcher_object_t* create_watcher_object(watcher_fn watcher,void* ctx)
-{
- watcher_object_t* wo=calloc(1,sizeof(watcher_object_t));
- assert(wo);
- wo->watcher=watcher;
- wo->context=ctx;
- return wo;
-}
-
-static watcher_object_list_t* create_watcher_object_list(watcher_object_t* head)
-{
- watcher_object_list_t* wl=calloc(1,sizeof(watcher_object_list_t));
- assert(wl);
- wl->head=head;
- return wl;
-}
-
-static void destroy_watcher_object_list(watcher_object_list_t* list)
-{
- watcher_object_t* e = NULL;
-
- if(list==0)
- return;
- e=list->head;
- while(e!=0){
- watcher_object_t* this=e;
- e=e->next;
- free(this);
- }
- free(list);
-}
-
-zk_hashtable* create_zk_hashtable()
-{
- struct _zk_hashtable *ht=calloc(1,sizeof(struct _zk_hashtable));
- assert(ht);
- ht->ht=create_hashtable(32,string_hash_djb2,string_equal);
- return ht;
-}
-
-static void do_clean_hashtable(zk_hashtable* ht)
-{
- struct hashtable_itr *it;
- int hasMore;
- if(hashtable_count(ht->ht)==0)
- return;
- it=hashtable_iterator(ht->ht);
- do {
- watcher_object_list_t* w=hashtable_iterator_value(it);
- destroy_watcher_object_list(w);
- hasMore=hashtable_iterator_remove(it);
- } while(hasMore);
- free(it);
-}
-
-void destroy_zk_hashtable(zk_hashtable* ht)
-{
- if(ht!=0){
- do_clean_hashtable(ht);
- hashtable_destroy(ht->ht,0);
- free(ht);
- }
-}
-
-// searches for a watcher object instance in a watcher object list;
-// two watcher objects are equal if their watcher function and context pointers
-// are equal
-static watcher_object_t* search_watcher(watcher_object_list_t** wl,watcher_object_t* wo)
-{
- watcher_object_t* wobj=(*wl)->head;
- while(wobj!=0){
- if(wobj->watcher==wo->watcher && wobj->context==wo->context)
- return wobj;
- wobj=wobj->next;
- }
- return 0;
-}
-
-static int add_to_list(watcher_object_list_t **wl, watcher_object_t *wo,
- int clone)
-{
- if (search_watcher(wl, wo)==0) {
- watcher_object_t* cloned=wo;
- if (clone) {
- cloned = clone_watcher_object(wo);
- assert(cloned);
- }
- cloned->next = (*wl)->head;
- (*wl)->head = cloned;
- return 1;
- } else if (!clone) {
- // If it's here and we aren't supposed to clone, we must destroy
- free(wo);
- }
- return 0;
-}
-
-static int do_insert_watcher_object(zk_hashtable *ht, const char *path, watcher_object_t* wo)
-{
- int res=1;
- watcher_object_list_t* wl;
-
- wl=hashtable_search(ht->ht,(void*)path);
- if(wl==0){
- int res;
- /* inserting a new path element */
- res=hashtable_insert(ht->ht,strdup(path),create_watcher_object_list(wo));
- assert(res);
- }else{
- /*
- * Path already exists; check if the watcher already exists.
- * Don't clone the watcher since it's allocated on the heap --- avoids
- * a memory leak and saves a clone operation (calloc + copy).
- */
- res = add_to_list(&wl, wo, 0);
- }
- return res;
-}
-
-
-char **collect_keys(zk_hashtable *ht, int *count)
-{
- char **list;
- struct hashtable_itr *it;
- int i;
-
- *count = hashtable_count(ht->ht);
- list = calloc(*count, sizeof(char*));
- it=hashtable_iterator(ht->ht);
- for(i = 0; i < *count; i++) {
- list[i] = strdup(hashtable_iterator_key(it));
- hashtable_iterator_advance(it);
- }
- free(it);
- return list;
-}
-
-static int insert_watcher_object(zk_hashtable *ht, const char *path,
- watcher_object_t* wo)
-{
- int res;
- res=do_insert_watcher_object(ht,path,wo);
- return res;
-}
-
-static void copy_watchers(watcher_object_list_t *from, watcher_object_list_t *to, int clone)
-{
- watcher_object_t* wo=from->head;
- while(wo){
- watcher_object_t *next = wo->next;
- add_to_list(&to, wo, clone);
- wo=next;
- }
-}
-
-static void copy_table(zk_hashtable *from, watcher_object_list_t *to) {
- struct hashtable_itr *it;
- int hasMore;
- if(hashtable_count(from->ht)==0)
- return;
- it=hashtable_iterator(from->ht);
- do {
- watcher_object_list_t *w = hashtable_iterator_value(it);
- copy_watchers(w, to, 1);
- hasMore=hashtable_iterator_advance(it);
- } while(hasMore);
- free(it);
-}
-
-static void collect_session_watchers(zhandle_t *zh,
- watcher_object_list_t **list)
-{
- copy_table(zh->active_node_watchers, *list);
- copy_table(zh->active_exist_watchers, *list);
- copy_table(zh->active_child_watchers, *list);
-}
-
-static void add_for_event(zk_hashtable *ht, char *path, watcher_object_list_t **list)
-{
- watcher_object_list_t* wl;
- wl = (watcher_object_list_t*)hashtable_remove(ht->ht, path);
- if (wl) {
- copy_watchers(wl, *list, 0);
- // Since we move, not clone the watch_objects, we just need to free the
- // head pointer
- free(wl);
- }
-}
-
-static void do_foreach_watcher(watcher_object_t* wo,zhandle_t* zh,
- const char* path,int type,int state)
-{
- // session event's don't have paths
- const char *client_path =
- (type != ZOO_SESSION_EVENT ? sub_string(zh, path) : path);
- while(wo!=0){
- wo->watcher(zh,type,state,client_path,wo->context);
- wo=wo->next;
- }
- free_duplicate_path(client_path, path);
-}
-
-watcher_object_list_t *collectWatchers(zhandle_t *zh,int type, char *path)
-{
- struct watcher_object_list *list = create_watcher_object_list(0);
-
- if(type==ZOO_SESSION_EVENT){
- watcher_object_t defWatcher;
- defWatcher.watcher=zh->watcher;
- defWatcher.context=zh->context;
- add_to_list(&list, &defWatcher, 1);
- collect_session_watchers(zh, &list);
- return list;
- }
- switch(type){
- case CREATED_EVENT_DEF:
- case CHANGED_EVENT_DEF:
- // look up the watchers for the path and move them to a delivery list
- add_for_event(zh->active_node_watchers,path,&list);
- add_for_event(zh->active_exist_watchers,path,&list);
- break;
- case CHILD_EVENT_DEF:
- // look up the watchers for the path and move them to a delivery list
- add_for_event(zh->active_child_watchers,path,&list);
- break;
- case DELETED_EVENT_DEF:
- // look up the watchers for the path and move them to a delivery list
- add_for_event(zh->active_node_watchers,path,&list);
- add_for_event(zh->active_exist_watchers,path,&list);
- add_for_event(zh->active_child_watchers,path,&list);
- break;
- }
- return list;
-}
-
-void deliverWatchers(zhandle_t *zh, int type,int state, char *path, watcher_object_list_t **list)
-{
- if (!list || !(*list)) return;
- do_foreach_watcher((*list)->head, zh, path, type, state);
- destroy_watcher_object_list(*list);
- *list = 0;
-}
-
-void activateWatcher(zhandle_t *zh, watcher_registration_t* reg, int rc)
-{
- if(reg){
- /* in multithreaded lib, this code is executed
- * by the IO thread */
- zk_hashtable *ht = reg->checker(zh, rc);
- if(ht){
- insert_watcher_object(ht,reg->path,
- create_watcher_object(reg->watcher, reg->context));
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/src/zk_hashtable.h
----------------------------------------------------------------------
diff --git a/src/c/src/zk_hashtable.h b/src/c/src/zk_hashtable.h
deleted file mode 100644
index 31109c1..0000000
--- a/src/c/src/zk_hashtable.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ZK_HASHTABLE_H_
-#define ZK_HASHTABLE_H_
-
-#include <zookeeper.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
- typedef struct watcher_object_list watcher_object_list_t;
-typedef struct _zk_hashtable zk_hashtable;
-
-/**
- * The function must return a non-zero value if the watcher object can be activated
- * as a result of the server response. Normally, a watch can only be activated
- * if the server returns a success code (ZOK). However in the case when zoo_exists()
- * returns a ZNONODE code the watcher should be activated nevertheless.
- */
-typedef zk_hashtable *(*result_checker_fn)(zhandle_t *, int rc);
-
-/**
- * A watcher object gets temporarily stored with the completion entry until
- * the server response comes back at which moment the watcher object is moved
- * to the active watchers map.
- */
-typedef struct _watcher_registration {
- watcher_fn watcher;
- void* context;
- result_checker_fn checker;
- const char* path;
-} watcher_registration_t;
-
-zk_hashtable* create_zk_hashtable();
-void destroy_zk_hashtable(zk_hashtable* ht);
-
-char **collect_keys(zk_hashtable *ht, int *count);
-
-/**
- * check if the completion has a watcher object associated
- * with it. If it does, move the watcher object to the map of
- * active watchers (only if the checker allows to do so)
- */
- void activateWatcher(zhandle_t *zh, watcher_registration_t* reg, int rc);
- watcher_object_list_t *collectWatchers(zhandle_t *zh,int type, char *path);
- void deliverWatchers(zhandle_t *zh, int type, int state, char *path, struct watcher_object_list **list);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*ZK_HASHTABLE_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/src/zk_log.c
----------------------------------------------------------------------
diff --git a/src/c/src/zk_log.c b/src/c/src/zk_log.c
deleted file mode 100644
index 6b4fdfa..0000000
--- a/src/c/src/zk_log.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/**
- * 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.
- */
-
-#if !defined(DLL_EXPORT) && !defined(USE_STATIC_LIB)
-# define USE_STATIC_LIB
-#endif
-
-#include "zookeeper_log.h"
-#ifndef WIN32
-#include <unistd.h>
-#else
-typedef DWORD pid_t;
-#include <process.h> /* for getpid */
-#endif
-
-#include <stdarg.h>
-#include <time.h>
-
-#define TIME_NOW_BUF_SIZE 1024
-#define FORMAT_LOG_BUF_SIZE 4096
-
-#ifdef THREADED
-#ifndef WIN32
-#include <pthread.h>
-#else
-#include "winport.h"
-#endif
-
-static pthread_key_t time_now_buffer;
-static pthread_key_t format_log_msg_buffer;
-
-void freeBuffer(void* p){
- if(p) free(p);
-}
-
-__attribute__((constructor)) void prepareTSDKeys() {
- pthread_key_create (&time_now_buffer, freeBuffer);
- pthread_key_create (&format_log_msg_buffer, freeBuffer);
-}
-
-char* getTSData(pthread_key_t key,int size){
- char* p=pthread_getspecific(key);
- if(p==0){
- int res;
- p=calloc(1,size);
- res=pthread_setspecific(key,p);
- if(res!=0){
- fprintf(stderr,"Failed to set TSD key: %d",res);
- }
- }
- return p;
-}
-
-char* get_time_buffer(){
- return getTSData(time_now_buffer,TIME_NOW_BUF_SIZE);
-}
-
-char* get_format_log_buffer(){
- return getTSData(format_log_msg_buffer,FORMAT_LOG_BUF_SIZE);
-}
-#else
-char* get_time_buffer(){
- static char buf[TIME_NOW_BUF_SIZE];
- return buf;
-}
-
-char* get_format_log_buffer(){
- static char buf[FORMAT_LOG_BUF_SIZE];
- return buf;
-}
-
-#endif
-
-ZooLogLevel logLevel=ZOO_LOG_LEVEL_INFO;
-
-static FILE* logStream=0;
-FILE* getLogStream(){
- if(logStream==0)
- logStream=stderr;
- return logStream;
-}
-
-void zoo_set_log_stream(FILE* stream){
- logStream=stream;
-}
-
-static const char* time_now(char* now_str){
- struct timeval tv;
- struct tm lt;
- time_t now = 0;
- size_t len = 0;
-
- gettimeofday(&tv,0);
-
- now = tv.tv_sec;
- localtime_r(&now, <);
-
- // clone the format used by log4j ISO8601DateFormat
- // specifically: "yyyy-MM-dd HH:mm:ss,SSS"
-
- len = strftime(now_str, TIME_NOW_BUF_SIZE,
- "%Y-%m-%d %H:%M:%S",
- <);
-
- len += snprintf(now_str + len,
- TIME_NOW_BUF_SIZE - len,
- ",%03d",
- (int)(tv.tv_usec/1000));
-
- return now_str;
-}
-
-void log_message(ZooLogLevel curLevel,int line,const char* funcName,
- const char* message)
-{
- static const char* dbgLevelStr[]={"ZOO_INVALID","ZOO_ERROR","ZOO_WARN",
- "ZOO_INFO","ZOO_DEBUG"};
- static pid_t pid=0;
-#ifdef WIN32
- char timebuf [TIME_NOW_BUF_SIZE];
-#endif
- if(pid==0)pid=getpid();
-#ifndef THREADED
- // pid_t is long on Solaris
- fprintf(LOGSTREAM, "%s:%ld:%s@%s@%d: %s\n", time_now(get_time_buffer()),(long)pid,
- dbgLevelStr[curLevel],funcName,line,message);
-#else
-#ifdef WIN32
- fprintf(LOGSTREAM, "%s:%d(0x%lx):%s@%s@%d: %s\n", time_now(timebuf),pid,
- (unsigned long int)(pthread_self().thread_id),
- dbgLevelStr[curLevel],funcName,line,message);
-#else
- fprintf(LOGSTREAM, "%s:%ld(0x%lx):%s@%s@%d: %s\n", time_now(get_time_buffer()),(long)pid,
- (unsigned long int)pthread_self(),
- dbgLevelStr[curLevel],funcName,line,message);
-#endif
-#endif
- fflush(LOGSTREAM);
-}
-
-const char* format_log_message(const char* format,...)
-{
- va_list va;
- char* buf=get_format_log_buffer();
- if(!buf)
- return "format_log_message: Unable to allocate memory buffer";
-
- va_start(va,format);
- vsnprintf(buf, FORMAT_LOG_BUF_SIZE-1,format,va);
- va_end(va);
- return buf;
-}
-
-void zoo_set_debug_level(ZooLogLevel level)
-{
- if(level==0){
- // disable logging (unit tests do this)
- logLevel=(ZooLogLevel)0;
- return;
- }
- if(level<ZOO_LOG_LEVEL_ERROR)level=ZOO_LOG_LEVEL_ERROR;
- if(level>ZOO_LOG_LEVEL_DEBUG)level=ZOO_LOG_LEVEL_DEBUG;
- logLevel=level;
-}
-
[08/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/include/zookeeper.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/include/zookeeper.h b/zookeeper-client/zookeeper-client-c/include/zookeeper.h
new file mode 100644
index 0000000..aee865b
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/include/zookeeper.h
@@ -0,0 +1,1589 @@
+/**
+ * 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_H_
+#define ZOOKEEPER_H_
+
+#include <stdlib.h>
+
+/* we must not include config.h as a public header */
+#ifndef WIN32
+#include <sys/socket.h>
+#include <sys/time.h>
+#endif
+
+#ifdef WIN32
+#include <winsock2.h> /* must always be included before ws2tcpip.h */
+#include <ws2tcpip.h> /* for struct sock_addr and socklen_t */
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "proto.h"
+#include "zookeeper_version.h"
+#include "recordio.h"
+#include "zookeeper.jute.h"
+
+/**
+ * \file zookeeper.h
+ * \brief ZooKeeper functions and definitions.
+ *
+ * ZooKeeper is a network service that may be backed by a cluster of
+ * synchronized servers. The data in the service is represented as a tree
+ * of data nodes. Each node has data, children, an ACL, and status information.
+ * The data for a node is read and write in its entirety.
+ *
+ * ZooKeeper clients can leave watches when they queries the data or children
+ * of a node. If a watch is left, that client will be notified of the change.
+ * The notification is a one time trigger. Subsequent chances to the node will
+ * not trigger a notification unless the client issues a query with the watch
+ * flag set. If the client is ever disconnected from the service, the watches do
+ * not need to be reset. The client automatically resets the watches.
+ *
+ * When a node is created, it may be flagged as an ephemeral node. Ephemeral
+ * nodes are automatically removed when a client session is closed or when
+ * a session times out due to inactivity (the ZooKeeper runtime fills in
+ * periods of inactivity with pings). Ephemeral nodes cannot have children.
+ *
+ * ZooKeeper clients are identified by a server assigned session id. For
+ * security reasons The server
+ * also generates a corresponding password for a session. A client may save its
+ * id and corresponding password to persistent storage in order to use the
+ * session across program invocation boundaries.
+ */
+
+/* Support for building on various platforms */
+
+// on cygwin we should take care of exporting/importing symbols properly
+#ifdef DLL_EXPORT
+# define ZOOAPI __declspec(dllexport)
+#else
+# if (defined(__CYGWIN__) || defined(WIN32)) && !defined(USE_STATIC_LIB)
+# define ZOOAPI __declspec(dllimport)
+# else
+# define ZOOAPI
+# endif
+#endif
+
+/** zookeeper return constants **/
+
+enum ZOO_ERRORS {
+ ZOK = 0, /*!< Everything is OK */
+
+ /** System and server-side errors.
+ * This is never thrown by the server, it shouldn't be used other than
+ * to indicate a range. Specifically error codes greater than this
+ * value, but lesser than {@link #ZAPIERROR}, are system errors. */
+ ZSYSTEMERROR = -1,
+ ZRUNTIMEINCONSISTENCY = -2, /*!< A runtime inconsistency was found */
+ ZDATAINCONSISTENCY = -3, /*!< A data inconsistency was found */
+ ZCONNECTIONLOSS = -4, /*!< Connection to the server has been lost */
+ ZMARSHALLINGERROR = -5, /*!< Error while marshalling or unmarshalling data */
+ ZUNIMPLEMENTED = -6, /*!< Operation is unimplemented */
+ ZOPERATIONTIMEOUT = -7, /*!< Operation timeout */
+ ZBADARGUMENTS = -8, /*!< Invalid arguments */
+ ZINVALIDSTATE = -9, /*!< Invliad zhandle state */
+
+ /** API errors.
+ * This is never thrown by the server, it shouldn't be used other than
+ * to indicate a range. Specifically error codes greater than this
+ * value are API errors (while values less than this indicate a
+ * {@link #ZSYSTEMERROR}).
+ */
+ ZAPIERROR = -100,
+ ZNONODE = -101, /*!< Node does not exist */
+ ZNOAUTH = -102, /*!< Not authenticated */
+ ZBADVERSION = -103, /*!< Version conflict */
+ ZNOCHILDRENFOREPHEMERALS = -108, /*!< Ephemeral nodes may not have children */
+ ZNODEEXISTS = -110, /*!< The node already exists */
+ ZNOTEMPTY = -111, /*!< The node has children */
+ ZSESSIONEXPIRED = -112, /*!< The session has been expired by the server */
+ ZINVALIDCALLBACK = -113, /*!< Invalid callback specified */
+ ZINVALIDACL = -114, /*!< Invalid ACL specified */
+ ZAUTHFAILED = -115, /*!< Client authentication failed */
+ ZCLOSING = -116, /*!< ZooKeeper is closing */
+ ZNOTHING = -117, /*!< (not error) no server responses to process */
+ ZSESSIONMOVED = -118 /*!<session moved to another server, so operation is ignored */
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* @name Debug levels
+*/
+typedef enum {ZOO_LOG_LEVEL_ERROR=1,ZOO_LOG_LEVEL_WARN=2,ZOO_LOG_LEVEL_INFO=3,ZOO_LOG_LEVEL_DEBUG=4} ZooLogLevel;
+
+/**
+ * @name ACL Consts
+ */
+extern ZOOAPI const int ZOO_PERM_READ;
+extern ZOOAPI const int ZOO_PERM_WRITE;
+extern ZOOAPI const int ZOO_PERM_CREATE;
+extern ZOOAPI const int ZOO_PERM_DELETE;
+extern ZOOAPI const int ZOO_PERM_ADMIN;
+extern ZOOAPI const int ZOO_PERM_ALL;
+
+/** This Id represents anyone. */
+extern ZOOAPI struct Id ZOO_ANYONE_ID_UNSAFE;
+/** This Id is only usable to set ACLs. It will get substituted with the
+ * Id's the client authenticated with.
+ */
+extern ZOOAPI struct Id ZOO_AUTH_IDS;
+
+/** This is a completely open ACL*/
+extern ZOOAPI struct ACL_vector ZOO_OPEN_ACL_UNSAFE;
+/** This ACL gives the world the ability to read. */
+extern ZOOAPI struct ACL_vector ZOO_READ_ACL_UNSAFE;
+/** This ACL gives the creators authentication id's all permissions. */
+extern ZOOAPI struct ACL_vector ZOO_CREATOR_ALL_ACL;
+
+/**
+ * @name Interest Consts
+ * These constants are used to express interest in an event and to
+ * indicate to zookeeper which events have occurred. They can
+ * be ORed together to express multiple interests. These flags are
+ * used in the interest and event parameters of
+ * \ref zookeeper_interest and \ref zookeeper_process.
+ */
+// @{
+extern ZOOAPI const int ZOOKEEPER_WRITE;
+extern ZOOAPI const int ZOOKEEPER_READ;
+// @}
+
+/**
+ * @name Create Flags
+ *
+ * These flags are used by zoo_create to affect node create. They may
+ * be ORed together to combine effects.
+ */
+// @{
+extern ZOOAPI const int ZOO_EPHEMERAL;
+extern ZOOAPI const int ZOO_SEQUENCE;
+// @}
+
+/**
+ * @name State Consts
+ * These constants represent the states of a zookeeper connection. They are
+ * possible parameters of the watcher callback.
+ */
+// @{
+extern ZOOAPI const int ZOO_EXPIRED_SESSION_STATE;
+extern ZOOAPI const int ZOO_AUTH_FAILED_STATE;
+extern ZOOAPI const int ZOO_CONNECTING_STATE;
+extern ZOOAPI const int ZOO_ASSOCIATING_STATE;
+extern ZOOAPI const int ZOO_CONNECTED_STATE;
+// @}
+
+/**
+ * @name Watch Types
+ * These constants indicate the event that caused the watch event. They are
+ * possible values of the first parameter of the watcher callback.
+ */
+// @{
+/**
+ * \brief a node has been created.
+ *
+ * This is only generated by watches on non-existent nodes. These watches
+ * are set using \ref zoo_exists.
+ */
+extern ZOOAPI const int ZOO_CREATED_EVENT;
+/**
+ * \brief a node has been deleted.
+ *
+ * This is only generated by watches on nodes. These watches
+ * are set using \ref zoo_exists and \ref zoo_get.
+ */
+extern ZOOAPI const int ZOO_DELETED_EVENT;
+/**
+ * \brief a node has changed.
+ *
+ * This is only generated by watches on nodes. These watches
+ * are set using \ref zoo_exists and \ref zoo_get.
+ */
+extern ZOOAPI const int ZOO_CHANGED_EVENT;
+/**
+ * \brief a change as occurred in the list of children.
+ *
+ * This is only generated by watches on the child list of a node. These watches
+ * are set using \ref zoo_get_children or \ref zoo_get_children2.
+ */
+extern ZOOAPI const int ZOO_CHILD_EVENT;
+/**
+ * \brief a session has been lost.
+ *
+ * This is generated when a client loses contact or reconnects with a server.
+ */
+extern ZOOAPI const int ZOO_SESSION_EVENT;
+
+/**
+ * \brief a watch has been removed.
+ *
+ * This is generated when the server for some reason, probably a resource
+ * constraint, will no longer watch a node for a client.
+ */
+extern ZOOAPI const int ZOO_NOTWATCHING_EVENT;
+// @}
+
+/**
+ * \brief ZooKeeper handle.
+ *
+ * This is the handle that represents a connection to the ZooKeeper service.
+ * It is needed to invoke any ZooKeeper function. A handle is obtained using
+ * \ref zookeeper_init.
+ */
+typedef struct _zhandle zhandle_t;
+
+/**
+ * \brief client id structure.
+ *
+ * This structure holds the id and password for the session. This structure
+ * should be treated as opaque. It is received from the server when a session
+ * is established and needs to be sent back as-is when reconnecting a session.
+ */
+typedef struct {
+ int64_t client_id;
+ char passwd[16];
+} clientid_t;
+
+/**
+ * \brief zoo_op structure.
+ *
+ * This structure holds all the arguments necessary for one op as part
+ * of a containing multi_op via \ref zoo_multi or \ref zoo_amulti.
+ * This structure should be treated as opaque and initialized via
+ * \ref zoo_create_op_init, \ref zoo_delete_op_init, \ref zoo_set_op_init
+ * and \ref zoo_check_op_init.
+ */
+typedef struct zoo_op {
+ int type;
+ union {
+ // CREATE
+ struct {
+ const char *path;
+ const char *data;
+ int datalen;
+ char *buf;
+ int buflen;
+ const struct ACL_vector *acl;
+ int flags;
+ } create_op;
+
+ // DELETE
+ struct {
+ const char *path;
+ int version;
+ } delete_op;
+
+ // SET
+ struct {
+ const char *path;
+ const char *data;
+ int datalen;
+ int version;
+ struct Stat *stat;
+ } set_op;
+
+ // CHECK
+ struct {
+ const char *path;
+ int version;
+ } check_op;
+ };
+} zoo_op_t;
+
+/**
+ * \brief zoo_create_op_init.
+ *
+ * This function initializes a zoo_op_t with the arguments for a ZOO_CREATE_OP.
+ *
+ * \param op A pointer to the zoo_op_t to be initialized.
+ * \param path The name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param value The data to be stored in the node.
+ * \param valuelen The number of bytes in data. To set the data to be NULL use
+ * value as NULL and valuelen as -1.
+ * \param acl The initial ACL of the node. The ACL must not be null or empty.
+ * \param flags this parameter can be set to 0 for normal create or an OR
+ * of the Create Flags
+ * \param path_buffer Buffer which will be filled with the path of the
+ * new node (this might be different than the supplied path
+ * because of the ZOO_SEQUENCE flag). The path string will always be
+ * null-terminated. This parameter may be NULL if path_buffer_len = 0.
+ * \param path_buffer_len Size of path buffer; if the path of the new
+ * node (including space for the null terminator) exceeds the buffer size,
+ * the path string will be truncated to fit. The actual path of the
+ * new node in the server will not be affected by the truncation.
+ * The path string will always be null-terminated.
+ */
+void zoo_create_op_init(zoo_op_t *op, const char *path, const char *value,
+ int valuelen, const struct ACL_vector *acl, int flags,
+ char *path_buffer, int path_buffer_len);
+
+/**
+ * \brief zoo_delete_op_init.
+ *
+ * This function initializes a zoo_op_t with the arguments for a ZOO_DELETE_OP.
+ *
+ * \param op A pointer to the zoo_op_t to be initialized.
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param version the expected version of the node. The function will fail if the
+ * actual version of the node does not match the expected version.
+ * If -1 is used the version check will not take place.
+ */
+void zoo_delete_op_init(zoo_op_t *op, const char *path, int version);
+
+/**
+ * \brief zoo_set_op_init.
+ *
+ * This function initializes an zoo_op_t with the arguments for a ZOO_SETDATA_OP.
+ *
+ * \param op A pointer to the zoo_op_t to be initialized.
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param buffer the buffer holding data to be written to the node.
+ * \param buflen the number of bytes from buffer to write. To set NULL as data
+ * use buffer as NULL and buflen as -1.
+ * \param version the expected version of the node. The function will fail if
+ * the actual version of the node does not match the expected version. If -1 is
+ * used the version check will not take place.
+ */
+void zoo_set_op_init(zoo_op_t *op, const char *path, const char *buffer,
+ int buflen, int version, struct Stat *stat);
+
+/**
+ * \brief zoo_check_op_init.
+ *
+ * This function initializes an zoo_op_t with the arguments for a ZOO_CHECK_OP.
+ *
+ * \param op A pointer to the zoo_op_t to be initialized.
+ * \param path The name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param version the expected version of the node. The function will fail if the
+ * actual version of the node does not match the expected version.
+ */
+void zoo_check_op_init(zoo_op_t *op, const char *path, int version);
+
+/**
+ * \brief zoo_op_result structure.
+ *
+ * This structure holds the result for an op submitted as part of a multi_op
+ * via \ref zoo_multi or \ref zoo_amulti.
+ */
+typedef struct zoo_op_result {
+ int err;
+ char *value;
+ int valuelen;
+ struct Stat *stat;
+} zoo_op_result_t;
+
+/**
+ * \brief signature of a watch function.
+ *
+ * There are two ways to receive watch notifications: legacy and watcher object.
+ * <p>
+ * The legacy style, an application wishing to receive events from ZooKeeper must
+ * first implement a function with this signature and pass a pointer to the function
+ * to \ref zookeeper_init. Next, the application sets a watch by calling one of
+ * the getter API that accept the watch integer flag (for example, \ref zoo_aexists,
+ * \ref zoo_get, etc).
+ * <p>
+ * The watcher object style uses an instance of a "watcher object" which in
+ * the C world is represented by a pair: a pointer to a function implementing this
+ * signature and a pointer to watcher context -- handback user-specific data.
+ * When a watch is triggered this function will be called along with
+ * the watcher context. An application wishing to use this style must use
+ * the getter API functions with the "w" prefix in their names (for example, \ref
+ * zoo_awexists, \ref zoo_wget, etc).
+ *
+ * \param zh zookeeper handle
+ * \param type event type. This is one of the *_EVENT constants.
+ * \param state connection state. The state value will be one of the *_STATE constants.
+ * \param path znode path for which the watcher is triggered. NULL if the event
+ * type is ZOO_SESSION_EVENT
+ * \param watcherCtx watcher context.
+ */
+typedef void (*watcher_fn)(zhandle_t *zh, int type,
+ int state, const char *path,void *watcherCtx);
+
+/**
+ * \brief create a handle to used communicate with zookeeper.
+ *
+ * This method creates a new handle and a zookeeper session that corresponds
+ * to that handle. Session establishment is asynchronous, meaning that the
+ * session should not be considered established until (and unless) an
+ * event of state ZOO_CONNECTED_STATE is received.
+ * \param host comma separated host:port pairs, each corresponding to a zk
+ * server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002"
+ * \param fn the global watcher callback function. When notifications are
+ * triggered this function will be invoked.
+ * \param clientid the id of a previously established session that this
+ * client will be reconnecting to. Pass 0 if not reconnecting to a previous
+ * session. Clients can access the session id of an established, valid,
+ * connection by calling \ref zoo_client_id. If the session corresponding to
+ * the specified clientid has expired, or if the clientid is invalid for
+ * any reason, the returned zhandle_t will be invalid -- the zhandle_t
+ * state will indicate the reason for failure (typically
+ * ZOO_EXPIRED_SESSION_STATE).
+ * \param context the handback object that will be associated with this instance
+ * of zhandle_t. Application can access it (for example, in the watcher
+ * callback) using \ref zoo_get_context. The object is not used by zookeeper
+ * internally and can be null.
+ * \param flags reserved for future use. Should be set to zero.
+ * \return a pointer to the opaque zhandle structure. If it fails to create
+ * a new zhandle the function returns NULL and the errno variable
+ * indicates the reason.
+ */
+ZOOAPI zhandle_t *zookeeper_init(const char *host, watcher_fn fn,
+ int recv_timeout, const clientid_t *clientid, void *context, int flags);
+
+/**
+ * \brief close the zookeeper handle and free up any resources.
+ *
+ * After this call, the client session will no longer be valid. The function
+ * will flush any outstanding send requests before return. As a result it may
+ * block.
+ *
+ * This method should only be called only once on a zookeeper handle. Calling
+ * twice will cause undefined (and probably undesirable behavior). Calling any other
+ * zookeeper method after calling close is undefined behaviour and should be avoided.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \return a result code. Regardless of the error code returned, the zhandle
+ * will be destroyed and all resources freed.
+ *
+ * ZOK - success
+ * ZBADARGUMENTS - invalid input parameters
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ * ZOPERATIONTIMEOUT - failed to flush the buffers within the specified timeout.
+ * ZCONNECTIONLOSS - a network error occurred while attempting to send request to server
+ * ZSYSTEMERROR -- a system (OS) error occurred; it's worth checking errno to get details
+ */
+ZOOAPI int zookeeper_close(zhandle_t *zh);
+
+/**
+ * \brief return the client session id, only valid if the connections
+ * is currently connected (ie. last watcher state is ZOO_CONNECTED_STATE)
+ */
+ZOOAPI const clientid_t *zoo_client_id(zhandle_t *zh);
+
+/**
+ * \brief return the timeout for this session, only valid if the connections
+ * is currently connected (ie. last watcher state is ZOO_CONNECTED_STATE). This
+ * value may change after a server re-connect.
+ */
+ZOOAPI int zoo_recv_timeout(zhandle_t *zh);
+
+/**
+ * \brief return the context for this handle.
+ */
+ZOOAPI const void *zoo_get_context(zhandle_t *zh);
+
+/**
+ * \brief set the context for this handle.
+ */
+ZOOAPI void zoo_set_context(zhandle_t *zh, void *context);
+
+/**
+ * \brief set a watcher function
+ * \return previous watcher function
+ */
+ZOOAPI watcher_fn zoo_set_watcher(zhandle_t *zh,watcher_fn newFn);
+
+/**
+ * \brief returns the socket address for the current connection
+ * \return socket address of the connected host or NULL on failure, only valid if the
+ * connection is current connected
+ */
+ZOOAPI struct sockaddr* zookeeper_get_connected_host(zhandle_t *zh,
+ struct sockaddr *addr, socklen_t *addr_len);
+
+#ifndef THREADED
+/**
+ * \brief Returns the events that zookeeper is interested in.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param fd is the file descriptor of interest
+ * \param interest is an or of the ZOOKEEPER_WRITE and ZOOKEEPER_READ flags to
+ * indicate the I/O of interest on fd.
+ * \param tv a timeout value to be used with select/poll system call
+ * \return a result code.
+ * ZOK - success
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZCONNECTIONLOSS - a network error occurred while attempting to establish
+ * a connection to the server
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ * ZOPERATIONTIMEOUT - hasn't received anything from the server for 2/3 of the
+ * timeout value specified in zookeeper_init()
+ * ZSYSTEMERROR -- a system (OS) error occurred; it's worth checking errno to get details
+ */
+#ifdef WIN32
+ZOOAPI int zookeeper_interest(zhandle_t *zh, SOCKET *fd, int *interest,
+ struct timeval *tv);
+#else
+ZOOAPI int zookeeper_interest(zhandle_t *zh, int *fd, int *interest,
+ struct timeval *tv);
+#endif
+
+/**
+ * \brief Notifies zookeeper that an event of interest has happened.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param events will be an OR of the ZOOKEEPER_WRITE and ZOOKEEPER_READ flags.
+ * \return a result code.
+ * ZOK - success
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZCONNECTIONLOSS - a network error occurred while attempting to send request to server
+ * ZSESSIONEXPIRED - connection attempt failed -- the session's expired
+ * ZAUTHFAILED - authentication request failed, e.i. invalid credentials
+ * ZRUNTIMEINCONSISTENCY - a server response came out of order
+ * ZSYSTEMERROR -- a system (OS) error occurred; it's worth checking errno to get details
+ * ZNOTHING -- not an error; simply indicates that there no more data from the server
+ * to be processed (when called with ZOOKEEPER_READ flag).
+ */
+ZOOAPI int zookeeper_process(zhandle_t *zh, int events);
+#endif
+
+/**
+ * \brief signature of a completion function for a call that returns void.
+ *
+ * This method will be invoked at the end of a asynchronous call and also as
+ * a result of connection loss or timeout.
+ * \param rc the error code of the call. Connection loss/timeout triggers
+ * the completion with one of the following error codes:
+ * ZCONNECTIONLOSS -- lost connection to the server
+ * ZOPERATIONTIMEOUT -- connection timed out
+ * Data related events trigger the completion with error codes listed the
+ * Exceptions section of the documentation of the function that initiated the
+ * call. (Zero indicates call was successful.)
+ * \param data the pointer that was passed by the caller when the function
+ * that this completion corresponds to was invoked. The programmer
+ * is responsible for any memory freeing associated with the data
+ * pointer.
+ */
+typedef void (*void_completion_t)(int rc, const void *data);
+
+/**
+ * \brief signature of a completion function that returns a Stat structure.
+ *
+ * This method will be invoked at the end of a asynchronous call and also as
+ * a result of connection loss or timeout.
+ * \param rc the error code of the call. Connection loss/timeout triggers
+ * the completion with one of the following error codes:
+ * ZCONNECTIONLOSS -- lost connection to the server
+ * ZOPERATIONTIMEOUT -- connection timed out
+ * Data related events trigger the completion with error codes listed the
+ * Exceptions section of the documentation of the function that initiated the
+ * call. (Zero indicates call was successful.)
+ * \param stat a pointer to the stat information for the node involved in
+ * this function. If a non zero error code is returned, the content of
+ * stat is undefined. The programmer is NOT responsible for freeing stat.
+ * \param data the pointer that was passed by the caller when the function
+ * that this completion corresponds to was invoked. The programmer
+ * is responsible for any memory freeing associated with the data
+ * pointer.
+ */
+typedef void (*stat_completion_t)(int rc, const struct Stat *stat,
+ const void *data);
+
+/**
+ * \brief signature of a completion function that returns data.
+ *
+ * This method will be invoked at the end of a asynchronous call and also as
+ * a result of connection loss or timeout.
+ * \param rc the error code of the call. Connection loss/timeout triggers
+ * the completion with one of the following error codes:
+ * ZCONNECTIONLOSS -- lost connection to the server
+ * ZOPERATIONTIMEOUT -- connection timed out
+ * Data related events trigger the completion with error codes listed the
+ * Exceptions section of the documentation of the function that initiated the
+ * call. (Zero indicates call was successful.)
+ * \param value the value of the information returned by the asynchronous call.
+ * If a non zero error code is returned, the content of value is undefined.
+ * The programmer is NOT responsible for freeing value.
+ * \param value_len the number of bytes in value.
+ * \param stat a pointer to the stat information for the node involved in
+ * this function. If a non zero error code is returned, the content of
+ * stat is undefined. The programmer is NOT responsible for freeing stat.
+ * \param data the pointer that was passed by the caller when the function
+ * that this completion corresponds to was invoked. The programmer
+ * is responsible for any memory freeing associated with the data
+ * pointer.
+ */
+typedef void (*data_completion_t)(int rc, const char *value, int value_len,
+ const struct Stat *stat, const void *data);
+
+/**
+ * \brief signature of a completion function that returns a list of strings.
+ *
+ * This method will be invoked at the end of a asynchronous call and also as
+ * a result of connection loss or timeout.
+ * \param rc the error code of the call. Connection loss/timeout triggers
+ * the completion with one of the following error codes:
+ * ZCONNECTIONLOSS -- lost connection to the server
+ * ZOPERATIONTIMEOUT -- connection timed out
+ * Data related events trigger the completion with error codes listed the
+ * Exceptions section of the documentation of the function that initiated the
+ * call. (Zero indicates call was successful.)
+ * \param strings a pointer to the structure containng the list of strings of the
+ * names of the children of a node. If a non zero error code is returned,
+ * the content of strings is undefined. The programmer is NOT responsible
+ * for freeing strings.
+ * \param data the pointer that was passed by the caller when the function
+ * that this completion corresponds to was invoked. The programmer
+ * is responsible for any memory freeing associated with the data
+ * pointer.
+ */
+typedef void (*strings_completion_t)(int rc,
+ const struct String_vector *strings, const void *data);
+
+/**
+ * \brief signature of a completion function that returns a list of strings and stat.
+ * .
+ *
+ * This method will be invoked at the end of a asynchronous call and also as
+ * a result of connection loss or timeout.
+ * \param rc the error code of the call. Connection loss/timeout triggers
+ * the completion with one of the following error codes:
+ * ZCONNECTIONLOSS -- lost connection to the server
+ * ZOPERATIONTIMEOUT -- connection timed out
+ * Data related events trigger the completion with error codes listed the
+ * Exceptions section of the documentation of the function that initiated the
+ * call. (Zero indicates call was successful.)
+ * \param strings a pointer to the structure containng the list of strings of the
+ * names of the children of a node. If a non zero error code is returned,
+ * the content of strings is undefined. The programmer is NOT responsible
+ * for freeing strings.
+ * \param stat a pointer to the stat information for the node involved in
+ * this function. If a non zero error code is returned, the content of
+ * stat is undefined. The programmer is NOT responsible for freeing stat.
+ * \param data the pointer that was passed by the caller when the function
+ * that this completion corresponds to was invoked. The programmer
+ * is responsible for any memory freeing associated with the data
+ * pointer.
+ */
+typedef void (*strings_stat_completion_t)(int rc,
+ const struct String_vector *strings, const struct Stat *stat,
+ const void *data);
+
+/**
+ * \brief signature of a completion function that returns a list of strings.
+ *
+ * This method will be invoked at the end of a asynchronous call and also as
+ * a result of connection loss or timeout.
+ * \param rc the error code of the call. Connection loss/timeout triggers
+ * the completion with one of the following error codes:
+ * ZCONNECTIONLOSS -- lost connection to the server
+ * ZOPERATIONTIMEOUT -- connection timed out
+ * Data related events trigger the completion with error codes listed the
+ * Exceptions section of the documentation of the function that initiated the
+ * call. (Zero indicates call was successful.)
+ * \param value the value of the string returned.
+ * \param data the pointer that was passed by the caller when the function
+ * that this completion corresponds to was invoked. The programmer
+ * is responsible for any memory freeing associated with the data
+ * pointer.
+ */
+typedef void
+ (*string_completion_t)(int rc, const char *value, const void *data);
+
+/**
+ * \brief signature of a completion function that returns an ACL.
+ *
+ * This method will be invoked at the end of a asynchronous call and also as
+ * a result of connection loss or timeout.
+ * \param rc the error code of the call. Connection loss/timeout triggers
+ * the completion with one of the following error codes:
+ * ZCONNECTIONLOSS -- lost connection to the server
+ * ZOPERATIONTIMEOUT -- connection timed out
+ * Data related events trigger the completion with error codes listed the
+ * Exceptions section of the documentation of the function that initiated the
+ * call. (Zero indicates call was successful.)
+ * \param acl a pointer to the structure containng the ACL of a node. If a non
+ * zero error code is returned, the content of strings is undefined. The
+ * programmer is NOT responsible for freeing acl.
+ * \param stat a pointer to the stat information for the node involved in
+ * this function. If a non zero error code is returned, the content of
+ * stat is undefined. The programmer is NOT responsible for freeing stat.
+ * \param data the pointer that was passed by the caller when the function
+ * that this completion corresponds to was invoked. The programmer
+ * is responsible for any memory freeing associated with the data
+ * pointer.
+ */
+typedef void (*acl_completion_t)(int rc, struct ACL_vector *acl,
+ struct Stat *stat, const void *data);
+
+/**
+ * \brief get the state of the zookeeper connection.
+ *
+ * The return value will be one of the \ref State Consts.
+ */
+ZOOAPI int zoo_state(zhandle_t *zh);
+
+/**
+ * \brief create a node.
+ *
+ * This method will create a node in ZooKeeper. A node can only be created if
+ * it does not already exists. The Create Flags affect the creation of nodes.
+ * If ZOO_EPHEMERAL flag is set, the node will automatically get removed if the
+ * client session goes away. If the ZOO_SEQUENCE flag is set, a unique
+ * monotonically increasing sequence number is appended to the path name. The
+ * sequence number is always fixed length of 10 digits, 0 padded.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path The name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param value The data to be stored in the node.
+ * \param valuelen The number of bytes in data.
+ * \param acl The initial ACL of the node. The ACL must not be null or empty.
+ * \param flags this parameter can be set to 0 for normal create or an OR
+ * of the Create Flags
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed successfully
+ * ZNONODE the parent node does not exist.
+ * ZNODEEXISTS the node already exists
+ * ZNOAUTH the client does not have permission.
+ * ZNOCHILDRENFOREPHEMERALS cannot create children of ephemeral nodes.
+ * \param data The data that will be passed to the completion routine when the
+ * function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_acreate(zhandle_t *zh, const char *path, const char *value,
+ int valuelen, const struct ACL_vector *acl, int flags,
+ string_completion_t completion, const void *data);
+
+/**
+ * \brief delete a node in zookeeper.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param version the expected version of the node. The function will fail if the
+ * actual version of the node does not match the expected version.
+ * If -1 is used the version check will not take place.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADVERSION expected version does not match actual version.
+ * ZNOTEMPTY children are present; node cannot be deleted.
+ * \param data the data that will be passed to the completion routine when
+ * the function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_adelete(zhandle_t *zh, const char *path, int version,
+ void_completion_t completion, const void *data);
+
+/**
+ * \brief checks the existence of a node in zookeeper.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watch if nonzero, a watch will be set at the server to notify the
+ * client if the node changes. The watch will be set even if the node does not
+ * exist. This allows clients to watch for nodes to appear.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * \param data the data that will be passed to the completion routine when the
+ * function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_aexists(zhandle_t *zh, const char *path, int watch,
+ stat_completion_t completion, const void *data);
+
+/**
+ * \brief checks the existence of a node in zookeeper.
+ *
+ * This function is similar to \ref zoo_axists except it allows one specify
+ * a watcher object - a function pointer and associated context. The function
+ * will be called once the watch has fired. The associated context data will be
+ * passed to the function as the watcher context parameter.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watcher if non-null a watch will set on the specified znode on the server.
+ * The watch will be set even if the node does not exist. This allows clients
+ * to watch for nodes to appear.
+ * \param watcherCtx user specific data, will be passed to the watcher callback.
+ * Unlike the global context set by \ref zookeeper_init, this watcher context
+ * is associated with the given instance of the watcher only.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * \param data the data that will be passed to the completion routine when the
+ * function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_awexists(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx,
+ stat_completion_t completion, const void *data);
+
+/**
+ * \brief gets the data associated with a node.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watch if nonzero, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * \param data the data that will be passed to the completion routine when
+ * the function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either in ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_aget(zhandle_t *zh, const char *path, int watch,
+ data_completion_t completion, const void *data);
+
+/**
+ * \brief gets the data associated with a node.
+ *
+ * This function is similar to \ref zoo_aget except it allows one specify
+ * a watcher object rather than a boolean watch flag.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watcher if non-null, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param watcherCtx user specific data, will be passed to the watcher callback.
+ * Unlike the global context set by \ref zookeeper_init, this watcher context
+ * is associated with the given instance of the watcher only.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * \param data the data that will be passed to the completion routine when
+ * the function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either in ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_awget(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx,
+ data_completion_t completion, const void *data);
+
+/**
+ * \brief sets the data associated with a node.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param buffer the buffer holding data to be written to the node.
+ * \param buflen the number of bytes from buffer to write.
+ * \param version the expected version of the node. The function will fail if
+ * the actual version of the node does not match the expected version. If -1 is
+ * used the version check will not take place. * completion: If null,
+ * the function will execute synchronously. Otherwise, the function will return
+ * immediately and invoke the completion routine when the request completes.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADVERSION expected version does not match actual version.
+ * \param data the data that will be passed to the completion routine when
+ * the function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_aset(zhandle_t *zh, const char *path, const char *buffer, int buflen,
+ int version, stat_completion_t completion, const void *data);
+
+/**
+ * \brief lists the children of a node.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watch if nonzero, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * \param data the data that will be passed to the completion routine when
+ * the function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_aget_children(zhandle_t *zh, const char *path, int watch,
+ strings_completion_t completion, const void *data);
+
+/**
+ * \brief lists the children of a node.
+ *
+ * This function is similar to \ref zoo_aget_children except it allows one specify
+ * a watcher object rather than a boolean watch flag.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watcher if non-null, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param watcherCtx user specific data, will be passed to the watcher callback.
+ * Unlike the global context set by \ref zookeeper_init, this watcher context
+ * is associated with the given instance of the watcher only.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * \param data the data that will be passed to the completion routine when
+ * the function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_awget_children(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx,
+ strings_completion_t completion, const void *data);
+
+/**
+ * \brief lists the children of a node, and get the parent stat.
+ *
+ * This function is new in version 3.3.0
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watch if nonzero, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * \param data the data that will be passed to the completion routine when
+ * the function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_aget_children2(zhandle_t *zh, const char *path, int watch,
+ strings_stat_completion_t completion, const void *data);
+
+/**
+ * \brief lists the children of a node, and get the parent stat.
+ *
+ * This function is similar to \ref zoo_aget_children2 except it allows one specify
+ * a watcher object rather than a boolean watch flag.
+ *
+ * This function is new in version 3.3.0
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watcher if non-null, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param watcherCtx user specific data, will be passed to the watcher callback.
+ * Unlike the global context set by \ref zookeeper_init, this watcher context
+ * is associated with the given instance of the watcher only.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * \param data the data that will be passed to the completion routine when
+ * the function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_awget_children2(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx,
+ strings_stat_completion_t completion, const void *data);
+
+/**
+ * \brief Flush leader channel.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * \param data the data that will be passed to the completion routine when
+ * the function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+
+ZOOAPI int zoo_async(zhandle_t *zh, const char *path,
+ string_completion_t completion, const void *data);
+
+
+/**
+ * \brief gets the acl associated with a node.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * \param data the data that will be passed to the completion routine when
+ * the function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_aget_acl(zhandle_t *zh, const char *path, acl_completion_t completion,
+ const void *data);
+
+/**
+ * \brief sets the acl associated with a node.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param buffer the buffer holding the acls to be written to the node.
+ * \param buflen the number of bytes from buffer to write.
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with one of the following codes passed in as the rc argument:
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZINVALIDACL invalid ACL specified
+ * ZBADVERSION expected version does not match actual version.
+ * \param data the data that will be passed to the completion routine when
+ * the function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_aset_acl(zhandle_t *zh, const char *path, int version,
+ struct ACL_vector *acl, void_completion_t, const void *data);
+
+/**
+ * \brief atomically commits multiple zookeeper operations.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param count the number of operations
+ * \param ops an array of operations to commit
+ * \param results an array to hold the results of the operations
+ * \param completion the routine to invoke when the request completes. The completion
+ * will be triggered with any of the error codes that can that can be returned by the
+ * ops supported by a multi op (see \ref zoo_acreate, \ref zoo_adelete, \ref zoo_aset).
+ * \param data the data that will be passed to the completion routine when
+ * the function completes.
+ * \return the return code for the function call. This can be any of the
+ * values that can be returned by the ops supported by a multi op (see
+ * \ref zoo_acreate, \ref zoo_adelete, \ref zoo_aset).
+ */
+ZOOAPI int zoo_amulti(zhandle_t *zh, int count, const zoo_op_t *ops,
+ zoo_op_result_t *results, void_completion_t, const void *data);
+
+/**
+ * \brief return an error string.
+ *
+ * \param return code
+ * \return string corresponding to the return code
+ */
+ZOOAPI const char* zerror(int c);
+
+/**
+ * \brief specify application credentials.
+ *
+ * The application calls this function to specify its credentials for purposes
+ * of authentication. The server will use the security provider specified by
+ * the scheme parameter to authenticate the client connection. If the
+ * authentication request has failed:
+ * - the server connection is dropped
+ * - the watcher is called with the ZOO_AUTH_FAILED_STATE value as the state
+ * parameter.
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param scheme the id of authentication scheme. Natively supported:
+ * "digest" password-based authentication
+ * \param cert application credentials. The actual value depends on the scheme.
+ * \param certLen the length of the data parameter
+ * \param completion the routine to invoke when the request completes. One of
+ * the following result codes may be passed into the completion callback:
+ * ZOK operation completed successfully
+ * ZAUTHFAILED authentication failed
+ * \param data the data that will be passed to the completion routine when the
+ * function completes.
+ * \return ZOK on success or one of the following errcodes on failure:
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ * ZSYSTEMERROR - a system error occurred
+ */
+ZOOAPI int zoo_add_auth(zhandle_t *zh,const char* scheme,const char* cert,
+ int certLen, void_completion_t completion, const void *data);
+
+/**
+ * \brief checks if the current zookeeper connection state can't be recovered.
+ *
+ * The application must close the zhandle and try to reconnect.
+ *
+ * \param zh the zookeeper handle (see \ref zookeeper_init)
+ * \return ZINVALIDSTATE if connection is unrecoverable
+ */
+ZOOAPI int is_unrecoverable(zhandle_t *zh);
+
+/**
+ * \brief sets the debugging level for the library
+ */
+ZOOAPI void zoo_set_debug_level(ZooLogLevel logLevel);
+
+/**
+ * \brief sets the stream to be used by the library for logging
+ *
+ * The zookeeper library uses stderr as its default log stream. Application
+ * must make sure the stream is writable. Passing in NULL resets the stream
+ * to its default value (stderr).
+ */
+ZOOAPI void zoo_set_log_stream(FILE* logStream);
+
+/**
+ * \brief enable/disable quorum endpoint order randomization
+ *
+ * Note: typically this method should NOT be used outside of testing.
+ *
+ * If passed a non-zero value, will make the client connect to quorum peers
+ * in the order as specified in the zookeeper_init() call.
+ * A zero value causes zookeeper_init() to permute the peer endpoints
+ * which is good for more even client connection distribution among the
+ * quorum peers.
+ */
+ZOOAPI void zoo_deterministic_conn_order(int yesOrNo);
+
+/**
+ * \brief create a node synchronously.
+ *
+ * This method will create a node in ZooKeeper. A node can only be created if
+ * it does not already exists. The Create Flags affect the creation of nodes.
+ * If ZOO_EPHEMERAL flag is set, the node will automatically get removed if the
+ * client session goes away. If the ZOO_SEQUENCE flag is set, a unique
+ * monotonically increasing sequence number is appended to the path name.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path The name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param value The data to be stored in the node.
+ * \param valuelen The number of bytes in data. To set the data to be NULL use
+ * value as NULL and valuelen as -1.
+ * \param acl The initial ACL of the node. The ACL must not be null or empty.
+ * \param flags this parameter can be set to 0 for normal create or an OR
+ * of the Create Flags
+ * \param path_buffer Buffer which will be filled with the path of the
+ * new node (this might be different than the supplied path
+ * because of the ZOO_SEQUENCE flag). The path string will always be
+ * null-terminated. This parameter may be NULL if path_buffer_len = 0.
+ * \param path_buffer_len Size of path buffer; if the path of the new
+ * node (including space for the null terminator) exceeds the buffer size,
+ * the path string will be truncated to fit. The actual path of the
+ * new node in the server will not be affected by the truncation.
+ * The path string will always be null-terminated.
+ * \return one of the following codes are returned:
+ * ZOK operation completed successfully
+ * ZNONODE the parent node does not exist.
+ * ZNODEEXISTS the node already exists
+ * ZNOAUTH the client does not have permission.
+ * ZNOCHILDRENFOREPHEMERALS cannot create children of ephemeral nodes.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_create(zhandle_t *zh, const char *path, const char *value,
+ int valuelen, const struct ACL_vector *acl, int flags,
+ char *path_buffer, int path_buffer_len);
+
+/**
+ * \brief delete a node in zookeeper synchronously.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param version the expected version of the node. The function will fail if the
+ * actual version of the node does not match the expected version.
+ * If -1 is used the version check will not take place.
+ * \return one of the following values is returned.
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADVERSION expected version does not match actual version.
+ * ZNOTEMPTY children are present; node cannot be deleted.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_delete(zhandle_t *zh, const char *path, int version);
+
+
+/**
+ * \brief checks the existence of a node in zookeeper synchronously.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watch if nonzero, a watch will be set at the server to notify the
+ * client if the node changes. The watch will be set even if the node does not
+ * exist. This allows clients to watch for nodes to appear.
+ * \param the return stat value of the node.
+ * \return return code of the function call.
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_exists(zhandle_t *zh, const char *path, int watch, struct Stat *stat);
+
+/**
+ * \brief checks the existence of a node in zookeeper synchronously.
+ *
+ * This function is similar to \ref zoo_exists except it allows one specify
+ * a watcher object rather than a boolean watch flag.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watcher if non-null a watch will set on the specified znode on the server.
+ * The watch will be set even if the node does not exist. This allows clients
+ * to watch for nodes to appear.
+ * \param watcherCtx user specific data, will be passed to the watcher callback.
+ * Unlike the global context set by \ref zookeeper_init, this watcher context
+ * is associated with the given instance of the watcher only.
+ * \param the return stat value of the node.
+ * \return return code of the function call.
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_wexists(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx, struct Stat *stat);
+
+/**
+ * \brief gets the data associated with a node synchronously.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watch if nonzero, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param buffer the buffer holding the node data returned by the server
+ * \param buffer_len is the size of the buffer pointed to by the buffer parameter.
+ * It'll be set to the actual data length upon return. If the data is NULL, length is -1.
+ * \param stat if not NULL, will hold the value of stat for the path on return.
+ * \return return value of the function call.
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either in ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_get(zhandle_t *zh, const char *path, int watch, char *buffer,
+ int* buffer_len, struct Stat *stat);
+
+/**
+ * \brief gets the data associated with a node synchronously.
+ *
+ * This function is similar to \ref zoo_get except it allows one specify
+ * a watcher object rather than a boolean watch flag.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watcher if non-null, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param watcherCtx user specific data, will be passed to the watcher callback.
+ * Unlike the global context set by \ref zookeeper_init, this watcher context
+ * is associated with the given instance of the watcher only.
+ * \param buffer the buffer holding the node data returned by the server
+ * \param buffer_len is the size of the buffer pointed to by the buffer parameter.
+ * It'll be set to the actual data length upon return. If the data is NULL, length is -1.
+ * \param stat if not NULL, will hold the value of stat for the path on return.
+ * \return return value of the function call.
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either in ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_wget(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx,
+ char *buffer, int* buffer_len, struct Stat *stat);
+
+/**
+ * \brief sets the data associated with a node. See zoo_set2 function if
+ * you require access to the stat information associated with the znode.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param buffer the buffer holding data to be written to the node.
+ * \param buflen the number of bytes from buffer to write. To set NULL as data
+ * use buffer as NULL and buflen as -1.
+ * \param version the expected version of the node. The function will fail if
+ * the actual version of the node does not match the expected version. If -1 is
+ * used the version check will not take place.
+ * \return the return code for the function call.
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADVERSION expected version does not match actual version.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_set(zhandle_t *zh, const char *path, const char *buffer,
+ int buflen, int version);
+
+/**
+ * \brief sets the data associated with a node. This function is the same
+ * as zoo_set except that it also provides access to stat information
+ * associated with the znode.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param buffer the buffer holding data to be written to the node.
+ * \param buflen the number of bytes from buffer to write. To set NULL as data
+ * use buffer as NULL and buflen as -1.
+ * \param version the expected version of the node. The function will fail if
+ * the actual version of the node does not match the expected version. If -1 is
+ * used the version check will not take place.
+ * \param stat if not NULL, will hold the value of stat for the path on return.
+ * \return the return code for the function call.
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADVERSION expected version does not match actual version.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_set2(zhandle_t *zh, const char *path, const char *buffer,
+ int buflen, int version, struct Stat *stat);
+
+/**
+ * \brief lists the children of a node synchronously.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watch if nonzero, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param strings return value of children paths.
+ * \return the return code of the function.
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_get_children(zhandle_t *zh, const char *path, int watch,
+ struct String_vector *strings);
+
+/**
+ * \brief lists the children of a node synchronously.
+ *
+ * This function is similar to \ref zoo_get_children except it allows one specify
+ * a watcher object rather than a boolean watch flag.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watcher if non-null, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param watcherCtx user specific data, will be passed to the watcher callback.
+ * Unlike the global context set by \ref zookeeper_init, this watcher context
+ * is associated with the given instance of the watcher only.
+ * \param strings return value of children paths.
+ * \return the return code of the function.
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_wget_children(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx,
+ struct String_vector *strings);
+
+/**
+ * \brief lists the children of a node and get its stat synchronously.
+ *
+ * This function is new in version 3.3.0
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watch if nonzero, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param strings return value of children paths.
+ * \param stat return value of node stat.
+ * \return the return code of the function.
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_get_children2(zhandle_t *zh, const char *path, int watch,
+ struct String_vector *strings, struct Stat *stat);
+
+/**
+ * \brief lists the children of a node and get its stat synchronously.
+ *
+ * This function is similar to \ref zoo_get_children except it allows one specify
+ * a watcher object rather than a boolean watch flag.
+ *
+ * This function is new in version 3.3.0
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param watcher if non-null, a watch will be set at the server to notify
+ * the client if the node changes.
+ * \param watcherCtx user specific data, will be passed to the watcher callback.
+ * Unlike the global context set by \ref zookeeper_init, this watcher context
+ * is associated with the given instance of the watcher only.
+ * \param strings return value of children paths.
+ * \param stat return value of node stat.
+ * \return the return code of the function.
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_wget_children2(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx,
+ struct String_vector *strings, struct Stat *stat);
+
+/**
+ * \brief gets the acl associated with a node synchronously.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param acl the return value of acls on the path.
+ * \param stat returns the stat of the path specified.
+ * \return the return code for the function call.
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_get_acl(zhandle_t *zh, const char *path, struct ACL_vector *acl,
+ struct Stat *stat);
+
+/**
+ * \brief sets the acl associated with a node synchronously.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param path the name of the node. Expressed as a file name with slashes
+ * separating ancestors of the node.
+ * \param version the expected version of the path.
+ * \param acl the acl to be set on the path.
+ * \return the return code for the function call.
+ * ZOK operation completed successfully
+ * ZNONODE the node does not exist.
+ * ZNOAUTH the client does not have permission.
+ * ZINVALIDACL invalid ACL specified
+ * ZBADVERSION expected version does not match actual version.
+ * ZBADARGUMENTS - invalid input parameters
+ * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE
+ * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory
+ */
+ZOOAPI int zoo_set_acl(zhandle_t *zh, const char *path, int version,
+ const struct ACL_vector *acl);
+
+/**
+ * \brief atomically commits multiple zookeeper operations synchronously.
+ *
+ * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init
+ * \param count the number of operations
+ * \param ops an array of operations to commit
+ * \param results an array to hold the results of the operations
+ * \return the return code for the function call. This can be any of the
+ * values that can be returned by the ops supported by a multi op (see
+ * \ref zoo_acreate, \ref zoo_adelete, \ref zoo_aset).
+ */
+ZOOAPI int zoo_multi(zhandle_t *zh, int count, const zoo_op_t *ops, zoo_op_result_t *results);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*ZOOKEEPER_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/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..e5917cb
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/include/zookeeper_log.h
@@ -0,0 +1,51 @@
+/**
+ * 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 LOGSTREAM getLogStream()
+
+#define LOG_ERROR(x) if(logLevel>=ZOO_LOG_LEVEL_ERROR) \
+ log_message(ZOO_LOG_LEVEL_ERROR,__LINE__,__func__,format_log_message x)
+#define LOG_WARN(x) if(logLevel>=ZOO_LOG_LEVEL_WARN) \
+ log_message(ZOO_LOG_LEVEL_WARN,__LINE__,__func__,format_log_message x)
+#define LOG_INFO(x) if(logLevel>=ZOO_LOG_LEVEL_INFO) \
+ log_message(ZOO_LOG_LEVEL_INFO,__LINE__,__func__,format_log_message x)
+#define LOG_DEBUG(x) if(logLevel==ZOO_LOG_LEVEL_DEBUG) \
+ log_message(ZOO_LOG_LEVEL_DEBUG,__LINE__,__func__,format_log_message x)
+
+ZOOAPI void log_message(ZooLogLevel curLevel, int line,const char* funcName,
+ const char* message);
+
+ZOOAPI const char* format_log_message(const char* format,...);
+
+FILE* getLogStream();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*ZK_LOG_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/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..518f7e6
--- /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 4
+#define ZOO_PATCH_VERSION 12
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZOOKEEPER_VERSION_H_ */
[03/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/TestClient.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/TestClient.cc b/zookeeper-client/zookeeper-client-c/tests/TestClient.cc
new file mode 100644
index 0000000..154fbed
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/TestClient.cc
@@ -0,0 +1,1135 @@
+/**
+ * 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 <cppunit/extensions/HelperMacros.h>
+#include "CppAssertHelper.h"
+
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/select.h>
+
+#include "CollectionUtil.h"
+#include "ThreadingUtil.h"
+
+using namespace Util;
+
+#include "Vector.h"
+using namespace std;
+
+#include <cstring>
+#include <list>
+
+#include <zookeeper.h>
+#include <errno.h>
+#include <recordio.h>
+#include "Util.h"
+
+struct buff_struct_2 {
+ int32_t len;
+ int32_t off;
+ char *buffer;
+};
+
+static int Stat_eq(struct Stat* a, struct Stat* b)
+{
+ if (a->czxid != b->czxid) return 0;
+ if (a->mzxid != b->mzxid) return 0;
+ if (a->ctime != b->ctime) return 0;
+ if (a->mtime != b->mtime) return 0;
+ if (a->version != b->version) return 0;
+ if (a->cversion != b->cversion) return 0;
+ if (a->aversion != b->aversion) return 0;
+ if (a->ephemeralOwner != b->ephemeralOwner) return 0;
+ if (a->dataLength != b->dataLength) return 0;
+ if (a->numChildren != b->numChildren) return 0;
+ if (a->pzxid != b->pzxid) return 0;
+ return 1;
+}
+#ifdef THREADED
+ static void yield(zhandle_t *zh, int i)
+ {
+ sleep(i);
+ }
+#else
+ static void yield(zhandle_t *zh, int seconds)
+ {
+ int fd;
+ int interest;
+ int events;
+ struct timeval tv;
+ int rc;
+ time_t expires = time(0) + seconds;
+ time_t timeLeft = seconds;
+ fd_set rfds, wfds, efds;
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ FD_ZERO(&efds);
+
+ while(timeLeft >= 0) {
+ 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);
+ if (tv.tv_sec > timeLeft) {
+ tv.tv_sec = timeLeft;
+ }
+ rc = select(fd+1, &rfds, &wfds, &efds, &tv);
+ timeLeft = expires - time(0);
+ events = 0;
+ if (FD_ISSET(fd, &rfds)) {
+ events |= ZOOKEEPER_READ;
+ }
+ if (FD_ISSET(fd, &wfds)) {
+ events |= ZOOKEEPER_WRITE;
+ }
+ zookeeper_process(zh, events);
+ }
+ }
+#endif
+
+typedef struct evt {
+ string path;
+ int type;
+} evt_t;
+
+typedef struct watchCtx {
+private:
+ list<evt_t> events;
+ watchCtx(const watchCtx&);
+ watchCtx& operator=(const watchCtx&);
+public:
+ bool connected;
+ zhandle_t *zh;
+ Mutex mutex;
+
+ watchCtx() {
+ connected = false;
+ zh = 0;
+ }
+ ~watchCtx() {
+ if (zh) {
+ zookeeper_close(zh);
+ zh = 0;
+ }
+ }
+
+ evt_t getEvent() {
+ evt_t evt;
+ mutex.acquire();
+ CPPUNIT_ASSERT( events.size() > 0);
+ evt = events.front();
+ events.pop_front();
+ mutex.release();
+ return evt;
+ }
+
+ int countEvents() {
+ int count;
+ mutex.acquire();
+ count = events.size();
+ mutex.release();
+ return count;
+ }
+
+ void putEvent(evt_t evt) {
+ mutex.acquire();
+ events.push_back(evt);
+ mutex.release();
+ }
+
+ bool waitForConnected(zhandle_t *zh) {
+ time_t expires = time(0) + 10;
+ while(!connected && time(0) < expires) {
+ yield(zh, 1);
+ }
+ return connected;
+ }
+ bool waitForDisconnected(zhandle_t *zh) {
+ time_t expires = time(0) + 15;
+ while(connected && time(0) < expires) {
+ yield(zh, 1);
+ }
+ return !connected;
+ }
+} watchctx_t;
+
+class Zookeeper_simpleSystem : public CPPUNIT_NS::TestFixture
+{
+ CPPUNIT_TEST_SUITE(Zookeeper_simpleSystem);
+ CPPUNIT_TEST(testAsyncWatcherAutoReset);
+ CPPUNIT_TEST(testDeserializeString);
+ CPPUNIT_TEST(testFirstServerDown);
+#ifdef THREADED
+ CPPUNIT_TEST(testNullData);
+#ifdef ZOO_IPV6_ENABLED
+ CPPUNIT_TEST(testIPV6);
+#endif
+ CPPUNIT_TEST(testPath);
+ CPPUNIT_TEST(testPathValidation);
+ CPPUNIT_TEST(testPing);
+ CPPUNIT_TEST(testAcl);
+ CPPUNIT_TEST(testChroot);
+ CPPUNIT_TEST(testAuth);
+ CPPUNIT_TEST(testHangingClient);
+ CPPUNIT_TEST(testWatcherAutoResetWithGlobal);
+ CPPUNIT_TEST(testWatcherAutoResetWithLocal);
+ CPPUNIT_TEST(testGetChildren2);
+#endif
+ CPPUNIT_TEST_SUITE_END();
+
+ static void watcher(zhandle_t *, int type, int state, const char *path,void*v){
+ watchctx_t *ctx = (watchctx_t*)v;
+
+ if (state == ZOO_CONNECTED_STATE) {
+ ctx->connected = true;
+ } else {
+ ctx->connected = false;
+ }
+ if (type != ZOO_SESSION_EVENT) {
+ evt_t evt;
+ evt.path = path;
+ evt.type = type;
+ ctx->putEvent(evt);
+ }
+ }
+
+ static const char hostPorts[];
+
+ const char *getHostPorts() {
+ return hostPorts;
+ }
+
+ zhandle_t *createClient(watchctx_t *ctx) {
+ return createClient(hostPorts, ctx);
+ }
+
+ zhandle_t *createClient(const char *hp, watchctx_t *ctx) {
+ zhandle_t *zk = zookeeper_init(hp, watcher, 10000, 0, ctx, 0);
+ ctx->zh = zk;
+ sleep(1);
+ return zk;
+ }
+
+ zhandle_t *createchClient(watchctx_t *ctx, const char* chroot) {
+ zhandle_t *zk = zookeeper_init(chroot, watcher, 10000, 0, ctx, 0);
+ ctx->zh = zk;
+ sleep(1);
+ return zk;
+ }
+
+ FILE *logfile;
+public:
+
+ Zookeeper_simpleSystem() {
+ logfile = openlogfile("Zookeeper_simpleSystem");
+ }
+
+ ~Zookeeper_simpleSystem() {
+ if (logfile) {
+ fflush(logfile);
+ fclose(logfile);
+ logfile = 0;
+ }
+ }
+
+ void setUp()
+ {
+ zoo_set_log_stream(logfile);
+ }
+
+
+ void startServer() {
+ char cmd[1024];
+ sprintf(cmd, "%s start %s", ZKSERVER_CMD, getHostPorts());
+ CPPUNIT_ASSERT(system(cmd) == 0);
+ }
+
+ void stopServer() {
+ char cmd[1024];
+ sprintf(cmd, "%s stop %s", ZKSERVER_CMD, getHostPorts());
+ CPPUNIT_ASSERT(system(cmd) == 0);
+ }
+
+ void tearDown()
+ {
+ }
+
+ /** have a callback in the default watcher **/
+ static void default_zoo_watcher(zhandle_t *zzh, int type, int state, const char *path, void *context){
+ int zrc = 0;
+ struct String_vector str_vec = {0, NULL};
+ zrc = zoo_wget_children(zzh, "/mytest", default_zoo_watcher, NULL, &str_vec);
+ }
+
+ /** ZOOKEEPER-1057 This checks that the client connects to the second server when the first is not reachable **/
+ void testFirstServerDown() {
+ watchctx_t ctx;
+
+ zoo_deterministic_conn_order(true);
+
+ zhandle_t* zk = createClient("127.0.0.1:22182,127.0.0.1:22181", &ctx);
+ CPPUNIT_ASSERT(zk != 0);
+ CPPUNIT_ASSERT(ctx.waitForConnected(zk));
+ }
+
+ /** this checks for a deadlock in calling zookeeper_close and calls from a default watcher that might get triggered just when zookeeper_close() is in progress **/
+ void testHangingClient() {
+ int zrc = 0;
+ char buff[10] = "testall";
+ char path[512];
+ watchctx_t *ctx;
+ struct String_vector str_vec = {0, NULL};
+ zhandle_t *zh = zookeeper_init(hostPorts, NULL, 10000, 0, ctx, 0);
+ sleep(1);
+ zrc = zoo_create(zh, "/mytest", buff, 10, &ZOO_OPEN_ACL_UNSAFE, 0, path, 512);
+ zrc = zoo_wget_children(zh, "/mytest", default_zoo_watcher, NULL, &str_vec);
+ zrc = zoo_create(zh, "/mytest/test1", buff, 10, &ZOO_OPEN_ACL_UNSAFE, 0, path, 512);
+ zrc = zoo_wget_children(zh, "/mytest", default_zoo_watcher, NULL, &str_vec);
+ zrc = zoo_delete(zh, "/mytest/test1", -1);
+ zookeeper_close(zh);
+ }
+
+
+ void testPing()
+ {
+ watchctx_t ctxIdle;
+ watchctx_t ctxWC;
+ zhandle_t *zkIdle = createClient(&ctxIdle);
+ zhandle_t *zkWatchCreator = createClient(&ctxWC);
+
+ CPPUNIT_ASSERT(zkIdle);
+ CPPUNIT_ASSERT(zkWatchCreator);
+
+ char path[80];
+ sprintf(path, "/testping");
+ int rc = zoo_create(zkWatchCreator, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ for(int i = 0; i < 30; i++) {
+ sprintf(path, "/testping/%i", i);
+ rc = zoo_create(zkWatchCreator, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ }
+
+ for(int i = 0; i < 30; i++) {
+ sprintf(path, "/testping/%i", i);
+ struct Stat stat;
+ rc = zoo_exists(zkIdle, path, 1, &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ }
+
+ for(int i = 0; i < 30; i++) {
+ sprintf(path, "/testping/%i", i);
+ usleep(500000);
+ rc = zoo_delete(zkWatchCreator, path, -1);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ }
+ struct Stat stat;
+ CPPUNIT_ASSERT_EQUAL((int)ZNONODE, zoo_exists(zkIdle, "/testping/0", 0, &stat));
+ }
+
+ bool waitForEvent(zhandle_t *zh, watchctx_t *ctx, int seconds) {
+ time_t expires = time(0) + seconds;
+ while(ctx->countEvents() == 0 && time(0) < expires) {
+ yield(zh, 1);
+ }
+ return ctx->countEvents() > 0;
+ }
+
+#define COUNT 100
+
+ static zhandle_t *async_zk;
+ static volatile int count;
+ static const char* hp_chroot;
+
+ static void statCompletion(int rc, const struct Stat *stat, const void *data) {
+ int tmp = (int) (long) data;
+ CPPUNIT_ASSERT_EQUAL(tmp, rc);
+ }
+
+ static void stringCompletion(int rc, const char *value, const void *data) {
+ char *path = (char*)data;
+
+ if (rc == ZCONNECTIONLOSS && path) {
+ // Try again
+ rc = zoo_acreate(async_zk, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, stringCompletion, 0);
+ } else if (rc != ZOK) {
+ // fprintf(stderr, "rc = %d with path = %s\n", rc, (path ? path : "null"));
+ }
+ if (path) {
+ free(path);
+ }
+ }
+
+ static void create_completion_fn(int rc, const char* value, const void *data) {
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ count++;
+ }
+
+ static void waitForCreateCompletion(int seconds) {
+ time_t expires = time(0) + seconds;
+ while(count == 0 && time(0) < expires) {
+ sleep(1);
+ }
+ count--;
+ }
+
+ static void watcher_chroot_fn(zhandle_t *zh, int type,
+ int state, const char *path,void *watcherCtx) {
+ // check for path
+ char *client_path = (char *) watcherCtx;
+ CPPUNIT_ASSERT(strcmp(client_path, path) == 0);
+ count ++;
+ }
+
+ static void waitForChrootWatch(int seconds) {
+ time_t expires = time(0) + seconds;
+ while (count == 0 && time(0) < expires) {
+ sleep(1);
+ }
+ count--;
+ }
+
+ static void waitForVoidCompletion(int seconds) {
+ time_t expires = time(0) + seconds;
+ while(count == 0 && time(0) < expires) {
+ sleep(1);
+ }
+ count--;
+ }
+
+ static void voidCompletion(int rc, const void *data) {
+ int tmp = (int) (long) data;
+ CPPUNIT_ASSERT_EQUAL(tmp, rc);
+ count++;
+ }
+
+ static void verifyCreateFails(const char *path, zhandle_t *zk) {
+ CPPUNIT_ASSERT_EQUAL((int)ZBADARGUMENTS, zoo_create(zk,
+ path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0));
+ }
+
+ static void verifyCreateOk(const char *path, zhandle_t *zk) {
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_create(zk,
+ path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0));
+ }
+
+ static void verifyCreateFailsSeq(const char *path, zhandle_t *zk) {
+ CPPUNIT_ASSERT_EQUAL((int)ZBADARGUMENTS, zoo_create(zk,
+ path, "", 0, &ZOO_OPEN_ACL_UNSAFE, ZOO_SEQUENCE, 0, 0));
+ }
+
+ static void verifyCreateOkSeq(const char *path, zhandle_t *zk) {
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_create(zk,
+ path, "", 0, &ZOO_OPEN_ACL_UNSAFE, ZOO_SEQUENCE, 0, 0));
+ }
+
+
+ /**
+ returns false if the vectors dont match
+ **/
+ bool compareAcl(struct ACL_vector acl1, struct ACL_vector acl2) {
+ if (acl1.count != acl2.count) {
+ return false;
+ }
+ struct ACL *aclval1 = acl1.data;
+ struct ACL *aclval2 = acl2.data;
+ if (aclval1->perms != aclval2->perms) {
+ return false;
+ }
+ struct Id id1 = aclval1->id;
+ struct Id id2 = aclval2->id;
+ if (strcmp(id1.scheme, id2.scheme) != 0) {
+ return false;
+ }
+ if (strcmp(id1.id, id2.id) != 0) {
+ return false;
+ }
+ return true;
+ }
+
+ void testDeserializeString() {
+ char *val_str;
+ int rc = 0;
+ int val = -1;
+ struct iarchive *ia;
+ struct buff_struct_2 *b;
+ struct oarchive *oa = create_buffer_oarchive();
+ oa->serialize_Int(oa, "int", &val);
+ b = (struct buff_struct_2 *) oa->priv;
+ ia = create_buffer_iarchive(b->buffer, b->len);
+ rc = ia->deserialize_String(ia, "string", &val_str);
+ CPPUNIT_ASSERT_EQUAL(-EINVAL, rc);
+ }
+
+ void testAcl() {
+ int rc;
+ struct ACL_vector aclvec;
+ struct Stat stat;
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+ rc = zoo_create(zk, "/acl", "", 0,
+ &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ rc = zoo_get_acl(zk, "/acl", &aclvec, &stat );
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ bool cmp = compareAcl(ZOO_OPEN_ACL_UNSAFE, aclvec);
+ CPPUNIT_ASSERT_EQUAL(true, cmp);
+ rc = zoo_set_acl(zk, "/acl", -1, &ZOO_READ_ACL_UNSAFE);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ rc = zoo_get_acl(zk, "/acl", &aclvec, &stat);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ cmp = compareAcl(ZOO_READ_ACL_UNSAFE, aclvec);
+ CPPUNIT_ASSERT_EQUAL(true, cmp);
+ }
+
+
+ void testAuth() {
+ int rc;
+ count = 0;
+ watchctx_t ctx1, ctx2, ctx3, ctx4, ctx5;
+ zhandle_t *zk = createClient(&ctx1);
+ struct ACL_vector nodeAcl;
+ struct ACL acl_val;
+ rc = zoo_add_auth(0, "", 0, 0, voidCompletion, (void*)-1);
+ CPPUNIT_ASSERT_EQUAL((int) ZBADARGUMENTS, rc);
+
+ rc = zoo_add_auth(zk, 0, 0, 0, voidCompletion, (void*)-1);
+ CPPUNIT_ASSERT_EQUAL((int) ZBADARGUMENTS, rc);
+
+ // auth as pat, create /tauth1, close session
+ rc = zoo_add_auth(zk, "digest", "pat:passwd", 10, voidCompletion,
+ (void*)ZOK);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ waitForVoidCompletion(3);
+ CPPUNIT_ASSERT(count == 0);
+
+ rc = zoo_create(zk, "/tauth1", "", 0, &ZOO_CREATOR_ALL_ACL, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ {
+ //create a new client
+ zk = createClient(&ctx4);
+ rc = zoo_add_auth(zk, "digest", "", 0, voidCompletion, (void*)ZOK);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ waitForVoidCompletion(3);
+ CPPUNIT_ASSERT(count == 0);
+
+ rc = zoo_add_auth(zk, "digest", "", 0, voidCompletion, (void*)ZOK);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ waitForVoidCompletion(3);
+ CPPUNIT_ASSERT(count == 0);
+ }
+
+ //create a new client
+ zk = createClient(&ctx2);
+
+ rc = zoo_add_auth(zk, "digest", "pat:passwd2", 11, voidCompletion,
+ (void*)ZOK);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ waitForVoidCompletion(3);
+ CPPUNIT_ASSERT(count == 0);
+
+ char buf[1024];
+ int blen = sizeof(buf);
+ struct Stat stat;
+ rc = zoo_get(zk, "/tauth1", 0, buf, &blen, &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZNOAUTH, rc);
+ // add auth pat w/correct pass verify success
+ rc = zoo_add_auth(zk, "digest", "pat:passwd", 10, voidCompletion,
+ (void*)ZOK);
+
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ rc = zoo_get(zk, "/tauth1", 0, buf, &blen, &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ waitForVoidCompletion(3);
+ CPPUNIT_ASSERT(count == 0);
+ //create a new client
+ zk = createClient(&ctx3);
+ rc = zoo_add_auth(zk, "digest", "pat:passwd", 10, voidCompletion, (void*) ZOK);
+ waitForVoidCompletion(3);
+ CPPUNIT_ASSERT(count == 0);
+ rc = zoo_add_auth(zk, "ip", "none", 4, voidCompletion, (void*)ZOK);
+ //make the server forget the auths
+ waitForVoidCompletion(3);
+ CPPUNIT_ASSERT(count == 0);
+
+ stopServer();
+ CPPUNIT_ASSERT(ctx3.waitForDisconnected(zk));
+ startServer();
+ CPPUNIT_ASSERT(ctx3.waitForConnected(zk));
+ // now try getting the data
+ rc = zoo_get(zk, "/tauth1", 0, buf, &blen, &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ // also check for get
+ rc = zoo_get_acl(zk, "/", &nodeAcl, &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ // check if the acl has all the perms
+ CPPUNIT_ASSERT_EQUAL((int)1, (int)nodeAcl.count);
+ acl_val = *(nodeAcl.data);
+ CPPUNIT_ASSERT_EQUAL((int) acl_val.perms, ZOO_PERM_ALL);
+ // verify on root node
+ rc = zoo_set_acl(zk, "/", -1, &ZOO_CREATOR_ALL_ACL);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+
+ rc = zoo_set_acl(zk, "/", -1, &ZOO_OPEN_ACL_UNSAFE);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+
+ //[ZOOKEEPER-1108], test that auth info is sent to server, if client is not
+ //connected to server when zoo_add_auth was called.
+ zhandle_t *zk_auth = zookeeper_init(hostPorts, NULL, 10000, 0, NULL, 0);
+ rc = zoo_add_auth(zk_auth, "digest", "pat:passwd", 10, voidCompletion, (void*)ZOK);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ sleep(2);
+ CPPUNIT_ASSERT(count == 1);
+ count = 0;
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, zookeeper_close(zk_auth));
+
+ // [ZOOKEEPER-800] zoo_add_auth should return ZINVALIDSTATE if
+ // the connection is closed.
+ zhandle_t *zk2 = zookeeper_init(hostPorts, NULL, 10000, 0, NULL, 0);
+ sleep(1);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, zookeeper_close(zk2));
+ CPPUNIT_ASSERT_EQUAL(0, zoo_state(zk2)); // 0 ==> ZOO_CLOSED_STATE
+ rc = zoo_add_auth(zk2, "digest", "pat:passwd", 10, voidCompletion, (void*)ZOK);
+ CPPUNIT_ASSERT_EQUAL((int) ZINVALIDSTATE, rc);
+
+ struct sockaddr addr;
+ socklen_t addr_len = sizeof(addr);
+ zk = createClient(&ctx5);
+ stopServer();
+ CPPUNIT_ASSERT(ctx5.waitForDisconnected(zk));
+ CPPUNIT_ASSERT(zookeeper_get_connected_host(zk, &addr, &addr_len) == NULL);
+ addr_len = sizeof(addr);
+ startServer();
+ CPPUNIT_ASSERT(ctx5.waitForConnected(zk));
+ CPPUNIT_ASSERT(zookeeper_get_connected_host(zk, &addr, &addr_len) != NULL);
+ }
+
+ void testGetChildren2() {
+ int rc;
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+
+ rc = zoo_create(zk, "/parent", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ rc = zoo_create(zk, "/parent/child_a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ rc = zoo_create(zk, "/parent/child_b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ rc = zoo_create(zk, "/parent/child_c", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ rc = zoo_create(zk, "/parent/child_d", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ struct String_vector strings;
+ struct Stat stat_a, stat_b;
+
+ rc = zoo_get_children2(zk, "/parent", 0, &strings, &stat_a);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ rc = zoo_exists(zk, "/parent", 0, &stat_b);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ CPPUNIT_ASSERT(Stat_eq(&stat_a, &stat_b));
+ CPPUNIT_ASSERT(stat_a.numChildren == 4);
+ }
+
+ void testIPV6() {
+ watchctx_t ctx;
+ zhandle_t *zk = createClient("::1:22181", &ctx);
+ CPPUNIT_ASSERT(zk);
+ int rc = 0;
+ rc = zoo_create(zk, "/ipv6", NULL, -1,
+ &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ }
+
+ void testNullData() {
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+ CPPUNIT_ASSERT(zk);
+ int rc = 0;
+ rc = zoo_create(zk, "/mahadev", NULL, -1,
+ &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ char buffer[512];
+ struct Stat stat;
+ int len = 512;
+ rc = zoo_wget(zk, "/mahadev", NULL, NULL, buffer, &len, &stat);
+ CPPUNIT_ASSERT_EQUAL( -1, len);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ rc = zoo_set(zk, "/mahadev", NULL, -1, -1);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ rc = zoo_wget(zk, "/mahadev", NULL, NULL, buffer, &len, &stat);
+ CPPUNIT_ASSERT_EQUAL( -1, len);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ }
+
+ void testPath() {
+ watchctx_t ctx;
+ char pathbuf[20];
+ zhandle_t *zk = createClient(&ctx);
+ CPPUNIT_ASSERT(zk);
+ int rc = 0;
+
+ memset(pathbuf, 'X', 20);
+ rc = zoo_create(zk, "/testpathpath0", "", 0,
+ &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 0);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ CPPUNIT_ASSERT_EQUAL('X', pathbuf[0]);
+
+ rc = zoo_create(zk, "/testpathpath1", "", 0,
+ &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 1);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ CPPUNIT_ASSERT(strlen(pathbuf) == 0);
+
+ rc = zoo_create(zk, "/testpathpath2", "", 0,
+ &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 2);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ CPPUNIT_ASSERT(strcmp(pathbuf, "/") == 0);
+
+ rc = zoo_create(zk, "/testpathpath3", "", 0,
+ &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 3);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ CPPUNIT_ASSERT(strcmp(pathbuf, "/t") == 0);
+
+ rc = zoo_create(zk, "/testpathpath7", "", 0,
+ &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 15);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ CPPUNIT_ASSERT(strcmp(pathbuf, "/testpathpath7") == 0);
+
+ rc = zoo_create(zk, "/testpathpath8", "", 0,
+ &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 16);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ CPPUNIT_ASSERT(strcmp(pathbuf, "/testpathpath8") == 0);
+ }
+
+ void testPathValidation() {
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+ CPPUNIT_ASSERT(zk);
+
+ verifyCreateFails(0, zk);
+ verifyCreateFails("", zk);
+ verifyCreateFails("//", zk);
+ verifyCreateFails("///", zk);
+ verifyCreateFails("////", zk);
+ verifyCreateFails("/.", zk);
+ verifyCreateFails("/..", zk);
+ verifyCreateFails("/./", zk);
+ verifyCreateFails("/../", zk);
+ verifyCreateFails("/foo/./", zk);
+ verifyCreateFails("/foo/../", zk);
+ verifyCreateFails("/foo/.", zk);
+ verifyCreateFails("/foo/..", zk);
+ verifyCreateFails("/./.", zk);
+ verifyCreateFails("/../..", zk);
+ verifyCreateFails("/foo/bar/", zk);
+ verifyCreateFails("/foo//bar", zk);
+ verifyCreateFails("/foo/bar//", zk);
+
+ verifyCreateFails("foo", zk);
+ verifyCreateFails("a", zk);
+
+ // verify that trailing fails, except for seq which adds suffix
+ verifyCreateOk("/createseq", zk);
+ verifyCreateFails("/createseq/", zk);
+ verifyCreateOkSeq("/createseq/", zk);
+ verifyCreateOkSeq("/createseq/.", zk);
+ verifyCreateOkSeq("/createseq/..", zk);
+ verifyCreateFailsSeq("/createseq//", zk);
+ verifyCreateFailsSeq("/createseq/./", zk);
+ verifyCreateFailsSeq("/createseq/../", zk);
+
+ verifyCreateOk("/.foo", zk);
+ verifyCreateOk("/.f.", zk);
+ verifyCreateOk("/..f", zk);
+ verifyCreateOk("/..f..", zk);
+ verifyCreateOk("/f.c", zk);
+ verifyCreateOk("/f", zk);
+ verifyCreateOk("/f/.f", zk);
+ verifyCreateOk("/f/f.", zk);
+ verifyCreateOk("/f/..f", zk);
+ verifyCreateOk("/f/f..", zk);
+ verifyCreateOk("/f/.f/f", zk);
+ verifyCreateOk("/f/f./f", zk);
+ }
+
+ void testChroot() {
+ // the c client async callbacks do
+ // not callback with the path, so
+ // we dont need to test taht for now
+ // we should fix that though soon!
+ watchctx_t ctx, ctx_ch;
+ zhandle_t *zk, *zk_ch;
+ char buf[60];
+ int rc, len;
+ struct Stat stat;
+ const char* data = "garbage";
+ const char* retStr = "/chroot";
+ const char* root= "/";
+ zk_ch = createchClient(&ctx_ch, "127.0.0.1:22181/testch1/mahadev");
+ CPPUNIT_ASSERT(zk_ch != NULL);
+ zk = createClient(&ctx);
+ // first test with a NULL zk handle, make sure client library does not
+ // dereference a null pointer, but instead returns ZBADARGUMENTS
+ rc = zoo_create(NULL, "/testch1", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int) ZBADARGUMENTS, rc);
+ rc = zoo_create(zk, "/testch1", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ rc = zoo_create(zk, "/testch1/mahadev", data, 7, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ // try an exists with /
+ len = 60;
+ rc = zoo_get(zk_ch, "/", 0, buf, &len, &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ //check if the data is the same
+ CPPUNIT_ASSERT(strncmp(buf, data, 7) == 0);
+ //check for watches
+ rc = zoo_wexists(zk_ch, "/chroot", watcher_chroot_fn, (void *) retStr, &stat);
+ //now check if we can do create/delete/get/sets/acls/getChildren and others
+ //check create
+ rc = zoo_create(zk_ch, "/chroot", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0,0);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ waitForChrootWatch(3);
+ CPPUNIT_ASSERT(count == 0);
+ rc = zoo_create(zk_ch, "/chroot/child", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ rc = zoo_exists(zk, "/testch1/mahadev/chroot/child", 0, &stat);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+
+ rc = zoo_delete(zk_ch, "/chroot/child", -1);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ rc = zoo_exists(zk, "/testch1/mahadev/chroot/child", 0, &stat);
+ CPPUNIT_ASSERT_EQUAL((int) ZNONODE, rc);
+ rc = zoo_wget(zk_ch, "/chroot", watcher_chroot_fn, (char*) retStr,
+ buf, &len, &stat);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ rc = zoo_set(zk_ch, "/chroot",buf, 3, -1);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ waitForChrootWatch(3);
+ CPPUNIT_ASSERT(count == 0);
+ // check for getchildren
+ struct String_vector children;
+ rc = zoo_get_children(zk_ch, "/", 0, &children);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ CPPUNIT_ASSERT_EQUAL((int)1, (int)children.count);
+ //check if te child if chroot
+ CPPUNIT_ASSERT(strcmp((retStr+1), children.data[0]) == 0);
+ // check for get/set acl
+ struct ACL_vector acl;
+ rc = zoo_get_acl(zk_ch, "/", &acl, &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ CPPUNIT_ASSERT_EQUAL((int)1, (int)acl.count);
+ CPPUNIT_ASSERT_EQUAL((int)ZOO_PERM_ALL, (int)acl.data->perms);
+ // set acl
+ rc = zoo_set_acl(zk_ch, "/chroot", -1, &ZOO_READ_ACL_UNSAFE);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ // see if you add children
+ rc = zoo_create(zk_ch, "/chroot/child1", "",0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZNOAUTH, rc);
+ //add wget children test
+ rc = zoo_wget_children(zk_ch, "/", watcher_chroot_fn, (char*) root, &children);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ //now create a node
+ rc = zoo_create(zk_ch, "/child2", "",0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ waitForChrootWatch(3);
+ CPPUNIT_ASSERT(count == 0);
+ //check for one async call just to make sure
+ rc = zoo_acreate(zk_ch, "/child3", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0,
+ create_completion_fn, 0);
+ waitForCreateCompletion(3);
+ CPPUNIT_ASSERT(count == 0);
+
+ //ZOOKEEPER-1027 correctly return path_buffer without prefixed chroot
+ const char* path = "/zookeeper1027";
+ char path_buffer[1024];
+ int path_buffer_len=sizeof(path_buffer);
+ rc = zoo_create(zk_ch, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, path_buffer, path_buffer_len);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ CPPUNIT_ASSERT_EQUAL(string(path), string(path_buffer));
+ }
+
+ void testAsyncWatcherAutoReset()
+ {
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+ watchctx_t lctx[COUNT];
+ int i;
+ char path[80];
+ int rc;
+ evt_t evt;
+
+ async_zk = zk;
+ for(i = 0; i < COUNT; i++) {
+ sprintf(path, "/awar%d", i);
+ rc = zoo_awexists(zk, path, watcher, &lctx[i], statCompletion, (void*)ZNONODE);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ }
+
+ yield(zk, 0);
+
+ for(i = 0; i < COUNT/2; i++) {
+ sprintf(path, "/awar%d", i);
+ rc = zoo_acreate(zk, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, stringCompletion, strdup(path));
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ }
+
+ yield(zk, 3);
+ for(i = 0; i < COUNT/2; i++) {
+ sprintf(path, "/awar%d", i);
+ CPPUNIT_ASSERT_MESSAGE(path, waitForEvent(zk, &lctx[i], 5));
+ evt = lctx[i].getEvent();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path.c_str(), ZOO_CREATED_EVENT, evt.type);
+ CPPUNIT_ASSERT_EQUAL(string(path), evt.path);
+ }
+
+ for(i = COUNT/2 + 1; i < COUNT*10; i++) {
+ sprintf(path, "/awar%d", i);
+ rc = zoo_acreate(zk, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, stringCompletion, strdup(path));
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ }
+
+ yield(zk, 1);
+ stopServer();
+ CPPUNIT_ASSERT(ctx.waitForDisconnected(zk));
+ startServer();
+ CPPUNIT_ASSERT(ctx.waitForConnected(zk));
+ yield(zk, 3);
+ for(i = COUNT/2+1; i < COUNT; i++) {
+ sprintf(path, "/awar%d", i);
+ CPPUNIT_ASSERT_MESSAGE(path, waitForEvent(zk, &lctx[i], 5));
+ evt = lctx[i].getEvent();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CREATED_EVENT, evt.type);
+ CPPUNIT_ASSERT_EQUAL(string(path), evt.path);
+ }
+ }
+
+ void testWatcherAutoReset(zhandle_t *zk, watchctx_t *ctxGlobal,
+ watchctx_t *ctxLocal)
+ {
+ bool isGlobal = (ctxGlobal == ctxLocal);
+ int rc;
+ struct Stat stat;
+ char buf[1024];
+ int blen;
+ struct String_vector strings;
+ const char *testName;
+
+ rc = zoo_create(zk, "/watchtest", "", 0,
+ &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ rc = zoo_create(zk, "/watchtest/child", "", 0,
+ &ZOO_OPEN_ACL_UNSAFE, ZOO_EPHEMERAL, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ if (isGlobal) {
+ testName = "GlobalTest";
+ rc = zoo_get_children(zk, "/watchtest", 1, &strings);
+ deallocate_String_vector(&strings);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ blen = sizeof(buf);
+ rc = zoo_get(zk, "/watchtest/child", 1, buf, &blen, &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ rc = zoo_exists(zk, "/watchtest/child2", 1, &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
+ } else {
+ testName = "LocalTest";
+ rc = zoo_wget_children(zk, "/watchtest", watcher, ctxLocal,
+ &strings);
+ deallocate_String_vector(&strings);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ blen = sizeof(buf);
+ rc = zoo_wget(zk, "/watchtest/child", watcher, ctxLocal,
+ buf, &blen, &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ rc = zoo_wexists(zk, "/watchtest/child2", watcher, ctxLocal,
+ &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
+ }
+
+ CPPUNIT_ASSERT(ctxLocal->countEvents() == 0);
+
+ stopServer();
+ CPPUNIT_ASSERT_MESSAGE(testName, ctxGlobal->waitForDisconnected(zk));
+ startServer();
+ CPPUNIT_ASSERT_MESSAGE(testName, ctxLocal->waitForConnected(zk));
+
+ CPPUNIT_ASSERT(ctxLocal->countEvents() == 0);
+
+ rc = zoo_set(zk, "/watchtest/child", "1", 1, -1);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ struct Stat stat1, stat2;
+ rc = zoo_set2(zk, "/watchtest/child", "1", 1, -1, &stat1);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ CPPUNIT_ASSERT(stat1.version >= 0);
+ rc = zoo_set2(zk, "/watchtest/child", "1", 1, stat1.version, &stat2);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ rc = zoo_set(zk, "/watchtest/child", "1", 1, stat2.version);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ rc = zoo_create(zk, "/watchtest/child2", "", 0,
+ &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
+
+ evt_t evt = ctxLocal->getEvent();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CHANGED_EVENT, evt.type);
+ CPPUNIT_ASSERT_EQUAL(string("/watchtest/child"), evt.path);
+
+ CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
+ // The create will trigget the get children and the
+ // exists watches
+ evt = ctxLocal->getEvent();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CREATED_EVENT, evt.type);
+ CPPUNIT_ASSERT_EQUAL(string("/watchtest/child2"), evt.path);
+ CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
+ evt = ctxLocal->getEvent();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CHILD_EVENT, evt.type);
+ CPPUNIT_ASSERT_EQUAL(string("/watchtest"), evt.path);
+
+ // Make sure Pings are giving us problems
+ sleep(5);
+
+ CPPUNIT_ASSERT(ctxLocal->countEvents() == 0);
+
+ stopServer();
+ CPPUNIT_ASSERT_MESSAGE(testName, ctxGlobal->waitForDisconnected(zk));
+ startServer();
+ CPPUNIT_ASSERT_MESSAGE(testName, ctxGlobal->waitForConnected(zk));
+
+ if (isGlobal) {
+ testName = "GlobalTest";
+ rc = zoo_get_children(zk, "/watchtest", 1, &strings);
+ deallocate_String_vector(&strings);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ blen = sizeof(buf);
+ rc = zoo_get(zk, "/watchtest/child", 1, buf, &blen, &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ rc = zoo_exists(zk, "/watchtest/child2", 1, &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ } else {
+ testName = "LocalTest";
+ rc = zoo_wget_children(zk, "/watchtest", watcher, ctxLocal,
+ &strings);
+ deallocate_String_vector(&strings);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ blen = sizeof(buf);
+ rc = zoo_wget(zk, "/watchtest/child", watcher, ctxLocal,
+ buf, &blen, &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ rc = zoo_wexists(zk, "/watchtest/child2", watcher, ctxLocal,
+ &stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ }
+
+ zoo_delete(zk, "/watchtest/child2", -1);
+
+ CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
+
+ evt = ctxLocal->getEvent();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_DELETED_EVENT, evt.type);
+ CPPUNIT_ASSERT_EQUAL(string("/watchtest/child2"), evt.path);
+
+ CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
+ evt = ctxLocal->getEvent();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CHILD_EVENT, evt.type);
+ CPPUNIT_ASSERT_EQUAL(string("/watchtest"), evt.path);
+
+ stopServer();
+ CPPUNIT_ASSERT_MESSAGE(testName, ctxGlobal->waitForDisconnected(zk));
+ startServer();
+ CPPUNIT_ASSERT_MESSAGE(testName, ctxLocal->waitForConnected(zk));
+
+ zoo_delete(zk, "/watchtest/child", -1);
+ zoo_delete(zk, "/watchtest", -1);
+
+ CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
+
+ evt = ctxLocal->getEvent();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_DELETED_EVENT, evt.type);
+ CPPUNIT_ASSERT_EQUAL(string("/watchtest/child"), evt.path);
+
+ // Make sure nothing is straggling
+ sleep(1);
+ CPPUNIT_ASSERT(ctxLocal->countEvents() == 0);
+ }
+
+ void testWatcherAutoResetWithGlobal()
+ {
+ {
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+ int rc = zoo_create(zk, "/testarwg", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ rc = zoo_create(zk, "/testarwg/arwg", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ }
+
+ {
+ watchctx_t ctx;
+ zhandle_t *zk = createchClient(&ctx, "127.0.0.1:22181/testarwg/arwg");
+
+ testWatcherAutoReset(zk, &ctx, &ctx);
+ }
+ }
+
+ void testWatcherAutoResetWithLocal()
+ {
+ {
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+ int rc = zoo_create(zk, "/testarwl", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ rc = zoo_create(zk, "/testarwl/arwl", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ }
+
+ {
+ watchctx_t ctx;
+ watchctx_t lctx;
+ zhandle_t *zk = createchClient(&ctx, "127.0.0.1:22181/testarwl/arwl");
+ testWatcherAutoReset(zk, &ctx, &lctx);
+ }
+ }
+};
+
+volatile int Zookeeper_simpleSystem::count;
+zhandle_t *Zookeeper_simpleSystem::async_zk;
+const char Zookeeper_simpleSystem::hostPorts[] = "127.0.0.1:22181";
+CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_simpleSystem);
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/TestClientRetry.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/TestClientRetry.cc b/zookeeper-client/zookeeper-client-c/tests/TestClientRetry.cc
new file mode 100644
index 0000000..41d5179
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/TestClientRetry.cc
@@ -0,0 +1,273 @@
+/**
+ * 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 <cppunit/extensions/HelperMacros.h>
+#include "CppAssertHelper.h"
+
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/select.h>
+
+#include "CollectionUtil.h"
+#include "ThreadingUtil.h"
+
+using namespace Util;
+
+#include "Vector.h"
+using namespace std;
+
+#include <cstring>
+#include <list>
+
+#include <zookeeper.h>
+
+#include "Util.h"
+
+#ifdef THREADED
+ static void yield(zhandle_t *zh, int i)
+ {
+ sleep(i);
+ }
+#else
+ static void yield(zhandle_t *zh, int seconds)
+ {
+ int fd;
+ int interest;
+ int events;
+ struct timeval tv;
+ int rc;
+ time_t expires = time(0) + seconds;
+ time_t timeLeft = seconds;
+ fd_set rfds, wfds, efds;
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ FD_ZERO(&efds);
+
+ while(timeLeft >= 0) {
+ 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);
+ if (tv.tv_sec > timeLeft) {
+ tv.tv_sec = timeLeft;
+ }
+ rc = select(fd+1, &rfds, &wfds, &efds, &tv);
+ timeLeft = expires - time(0);
+ events = 0;
+ if (FD_ISSET(fd, &rfds)) {
+ events |= ZOOKEEPER_READ;
+ }
+ if (FD_ISSET(fd, &wfds)) {
+ events |= ZOOKEEPER_WRITE;
+ }
+ zookeeper_process(zh, events);
+ }
+ }
+#endif
+
+typedef struct evt {
+ string path;
+ int type;
+} evt_t;
+
+typedef struct watchCtx {
+private:
+ list<evt_t> events;
+public:
+ bool connected;
+ zhandle_t *zh;
+ Mutex mutex;
+
+ watchCtx() {
+ connected = false;
+ zh = 0;
+ }
+ ~watchCtx() {
+ if (zh) {
+ zookeeper_close(zh);
+ zh = 0;
+ }
+ }
+
+ evt_t getEvent() {
+ evt_t evt;
+ mutex.acquire();
+ CPPUNIT_ASSERT( events.size() > 0);
+ evt = events.front();
+ events.pop_front();
+ mutex.release();
+ return evt;
+ }
+
+ int countEvents() {
+ int count;
+ mutex.acquire();
+ count = events.size();
+ mutex.release();
+ return count;
+ }
+
+ void putEvent(evt_t evt) {
+ mutex.acquire();
+ events.push_back(evt);
+ mutex.release();
+ }
+
+ bool waitForConnected(zhandle_t *zh) {
+ time_t expires = time(0) + 10;
+ while(!connected && time(0) < expires) {
+ yield(zh, 1);
+ }
+ return connected;
+ }
+ bool waitForDisconnected(zhandle_t *zh) {
+ time_t expires = time(0) + 15;
+ while(connected && time(0) < expires) {
+ yield(zh, 1);
+ }
+ return !connected;
+ }
+} watchctx_t;
+
+class Zookeeper_clientretry : public CPPUNIT_NS::TestFixture
+{
+ CPPUNIT_TEST_SUITE(Zookeeper_clientretry);
+#ifdef THREADED
+ CPPUNIT_TEST(testRetry);
+#endif
+ CPPUNIT_TEST_SUITE_END();
+
+ static void watcher(zhandle_t *, int type, int state, const char *path,void*v){
+ watchctx_t *ctx = (watchctx_t*)v;
+
+ if (state == ZOO_CONNECTED_STATE) {
+ ctx->connected = true;
+ } else {
+ ctx->connected = false;
+ }
+ if (type != ZOO_SESSION_EVENT) {
+ evt_t evt;
+ evt.path = path;
+ evt.type = type;
+ ctx->putEvent(evt);
+ }
+ }
+
+ static const char hostPorts[];
+
+ const char *getHostPorts() {
+ return hostPorts;
+ }
+
+ zhandle_t *createClient(watchctx_t *ctx) {
+ zhandle_t *zk = zookeeper_init(hostPorts, watcher, 10000, 0,
+ ctx, 0);
+ ctx->zh = zk;
+ sleep(1);
+ return zk;
+ }
+
+ FILE *logfile;
+public:
+
+ Zookeeper_clientretry() {
+ logfile = openlogfile("Zookeeper_clientretry");
+ }
+
+ ~Zookeeper_clientretry() {
+ if (logfile) {
+ fflush(logfile);
+ fclose(logfile);
+ logfile = 0;
+ }
+ }
+
+ void setUp()
+ {
+ zoo_set_log_stream(logfile);
+
+ char cmd[1024];
+ sprintf(cmd, "%s stop %s", ZKSERVER_CMD, getHostPorts());
+ CPPUNIT_ASSERT(system(cmd) == 0);
+
+ /* we are testing that if max cnxns is exceeded the server does the right thing */
+ sprintf(cmd, "export ZKMAXCNXNS=1;%s startClean %s", ZKSERVER_CMD, getHostPorts());
+ CPPUNIT_ASSERT(system(cmd) == 0);
+
+ struct sigaction act;
+ act.sa_handler = SIG_IGN;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ CPPUNIT_ASSERT(sigaction(SIGPIPE, &act, NULL) == 0);
+ }
+
+ void tearDown()
+ {
+ char cmd[1024];
+ sprintf(cmd, "%s stop %s", ZKSERVER_CMD, getHostPorts());
+ CPPUNIT_ASSERT(system(cmd) == 0);
+
+ /* restart the server in "normal" mode */
+ sprintf(cmd, "%s startClean %s", ZKSERVER_CMD, getHostPorts());
+ CPPUNIT_ASSERT(system(cmd) == 0);
+
+ struct sigaction act;
+ act.sa_handler = SIG_IGN;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ CPPUNIT_ASSERT(sigaction(SIGPIPE, &act, NULL) == 0);
+ }
+
+ bool waitForEvent(zhandle_t *zh, watchctx_t *ctx, int seconds) {
+ time_t expires = time(0) + seconds;
+ while(ctx->countEvents() == 0 && time(0) < expires) {
+ yield(zh, 1);
+ }
+ return ctx->countEvents() > 0;
+ }
+
+ static zhandle_t *async_zk;
+
+ void testRetry()
+ {
+ watchctx_t ctx1, ctx2;
+ zhandle_t *zk1 = createClient(&ctx1);
+ CPPUNIT_ASSERT_EQUAL(true, ctx1.waitForConnected(zk1));
+ zhandle_t *zk2 = createClient(&ctx2);
+ zookeeper_close(zk1);
+ CPPUNIT_ASSERT_EQUAL(true, ctx2.waitForConnected(zk2));
+ ctx1.zh = 0;
+ }
+};
+
+zhandle_t *Zookeeper_clientretry::async_zk;
+const char Zookeeper_clientretry::hostPorts[] = "127.0.0.1:22181";
+CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_clientretry);
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/TestDriver.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/TestDriver.cc b/zookeeper-client/zookeeper-client-c/tests/TestDriver.cc
new file mode 100644
index 0000000..d60db69
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/TestDriver.cc
@@ -0,0 +1,173 @@
+/**
+ * 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 <string>
+#include <cppunit/TestRunner.h>
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/TextTestProgressListener.h>
+#include <cppunit/BriefTestProgressListener.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdexcept>
+#include <unistd.h>
+#include <sys/select.h>
+#include <cppunit/Exception.h>
+#include <cppunit/TestFailure.h>
+#include <cppunit/XmlOutputter.h>
+#include <cppunit/TestAssert.h>
+#include <fstream>
+#include <time.h>
+
+#include "Util.h"
+#include "zookeeper_log.h"
+
+using namespace std;
+
+CPPUNIT_NS_BEGIN
+
+class EclipseOutputter: public CompilerOutputter
+{
+public:
+ EclipseOutputter(TestResultCollector *result,ostream &stream):
+ CompilerOutputter(result,stream,"%p:%l: "),stream_(stream)
+ {
+ }
+ virtual void printFailedTestName( TestFailure *failure ){}
+ virtual void printFailureMessage( TestFailure *failure )
+ {
+ stream_<<": ";
+ Message msg = failure->thrownException()->message();
+ stream_<< msg.shortDescription();
+
+ string text;
+ for(int i=0; i<msg.detailCount();i++){
+ text+=msg.detailAt(i);
+ if(i+1!=msg.detailCount())
+ text+=", ";
+ }
+ if(text.length()!=0)
+ stream_ <<" ["<<text<<"]";
+ stream_<<"\n";
+ }
+ ostream& stream_;
+};
+
+CPPUNIT_NS_END
+
+class TimingListener : public CPPUNIT_NS::BriefTestProgressListener {
+ public:
+ void startTest( CPPUNIT_NS::Test *test )
+ {
+ gettimeofday(&_start_time, NULL);
+
+ CPPUNIT_NS::BriefTestProgressListener::startTest(test);
+ }
+
+ void endTest( CPPUNIT_NS::Test *test )
+ {
+ struct timeval end;
+ gettimeofday(&end, NULL);
+
+ long seconds = end.tv_sec - _start_time.tv_sec;
+ long useconds = end.tv_usec - _start_time.tv_usec;
+
+ long mtime = seconds * 1000 + useconds/1000.0;
+ CPPUNIT_NS::stdCOut() << " : elapsed " << mtime;
+ CPPUNIT_NS::BriefTestProgressListener::endTest(test);
+ }
+
+ private:
+ struct timeval _start_time;
+};
+
+class ZKServer {
+public:
+ ZKServer() {
+ char cmd[1024];
+ sprintf(cmd, "%s startClean %s", ZKSERVER_CMD, "127.0.0.1:22181");
+ CPPUNIT_ASSERT(system(cmd) == 0);
+
+ struct sigaction act;
+ act.sa_handler = SIG_IGN;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ CPPUNIT_ASSERT(sigaction(SIGPIPE, &act, NULL) == 0);
+ }
+ virtual ~ZKServer(){
+ char cmd[1024];
+ sprintf(cmd, "%s stop %s", ZKSERVER_CMD, "127.0.0.1:22181");
+ CPPUNIT_ASSERT(system(cmd) == 0);
+ }
+};
+
+int main( int argc, char* argv[] ) {
+ // if command line contains "-ide" then this is the post build check
+ // => the output must be in the compiler error format.
+ //bool selfTest = (argc > 1) && (std::string("-ide") == argv[1]);
+ globalTestConfig.addConfigFromCmdLine(argc,argv);
+
+ ZKServer zkserver;
+
+ // Create the event manager and test controller
+ CPPUNIT_NS::TestResult controller;
+ // Add a listener that colllects test result
+ CPPUNIT_NS::TestResultCollector result;
+ controller.addListener( &result );
+
+ // A listener that print dots as tests run.
+ // CPPUNIT_NS::TextTestProgressListener progress;
+ // CPPUNIT_NS::BriefTestProgressListener progress;
+
+ // brief + elapsed time
+ TimingListener progress;
+ controller.addListener( &progress );
+
+ CPPUNIT_NS::TestRunner runner;
+ runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );
+
+ try {
+ CPPUNIT_NS::stdCOut() << endl << "Running " << endl;
+
+ zoo_set_debug_level(ZOO_LOG_LEVEL_INFO);
+ //zoo_set_debug_level(ZOO_LOG_LEVEL_DEBUG);
+
+ runner.run( controller, globalTestConfig.getTestName());
+
+ // Print test in a compiler compatible format.
+ CPPUNIT_NS::EclipseOutputter outputter( &result,cout);
+ outputter.write();
+
+ // Uncomment this for XML output
+#ifdef ENABLE_XML_OUTPUT
+ std::ofstream file( "tests.xml" );
+ CPPUNIT_NS::XmlOutputter xml( &result, file );
+ xml.setStyleSheet( "report.xsl" );
+ xml.write();
+ file.close();
+#endif
+ } catch ( std::invalid_argument &e ) {
+ // Test path not resolved
+ cout<<"\nERROR: "<<e.what()<<endl;
+ return 0;
+ }
+
+ return result.wasSuccessful() ? 0 : 1;
+ }
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/TestMulti.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/TestMulti.cc b/zookeeper-client/zookeeper-client-c/tests/TestMulti.cc
new file mode 100644
index 0000000..a54e047
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/TestMulti.cc
@@ -0,0 +1,703 @@
+/**
+ * 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 <cppunit/extensions/HelperMacros.h>
+#include "CppAssertHelper.h"
+
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/select.h>
+
+#include "CollectionUtil.h"
+#include "ThreadingUtil.h"
+
+using namespace Util;
+
+#include "Vector.h"
+using namespace std;
+
+#include <cstring>
+#include <list>
+
+#include <zookeeper.h>
+#include <errno.h>
+#include <recordio.h>
+#include "Util.h"
+
+#ifdef THREADED
+ static void yield(zhandle_t *zh, int i)
+ {
+ sleep(i);
+ }
+#else
+ static void yield(zhandle_t *zh, int seconds)
+ {
+ int fd;
+ int interest;
+ int events;
+ struct timeval tv;
+ int rc;
+ time_t expires = time(0) + seconds;
+ time_t timeLeft = seconds;
+ fd_set rfds, wfds, efds;
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ FD_ZERO(&efds);
+
+ while(timeLeft >= 0) {
+ 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);
+ if (tv.tv_sec > timeLeft) {
+ tv.tv_sec = timeLeft;
+ }
+ rc = select(fd+1, &rfds, &wfds, &efds, &tv);
+ timeLeft = expires - time(0);
+ events = 0;
+ if (FD_ISSET(fd, &rfds)) {
+ events |= ZOOKEEPER_READ;
+ }
+ if (FD_ISSET(fd, &wfds)) {
+ events |= ZOOKEEPER_WRITE;
+ }
+ zookeeper_process(zh, events);
+ }
+ }
+#endif
+
+typedef struct evt {
+ string path;
+ int type;
+} evt_t;
+
+typedef struct watchCtx {
+private:
+ list<evt_t> events;
+ watchCtx(const watchCtx&);
+ watchCtx& operator=(const watchCtx&);
+public:
+ bool connected;
+ zhandle_t *zh;
+ Mutex mutex;
+
+ watchCtx() {
+ connected = false;
+ zh = 0;
+ }
+ ~watchCtx() {
+ if (zh) {
+ zookeeper_close(zh);
+ zh = 0;
+ }
+ }
+
+ evt_t getEvent() {
+ evt_t evt;
+ mutex.acquire();
+ CPPUNIT_ASSERT( events.size() > 0);
+ evt = events.front();
+ events.pop_front();
+ mutex.release();
+ return evt;
+ }
+
+ int countEvents() {
+ int count;
+ mutex.acquire();
+ count = events.size();
+ mutex.release();
+ return count;
+ }
+
+ void putEvent(evt_t evt) {
+ mutex.acquire();
+ events.push_back(evt);
+ mutex.release();
+ }
+
+ bool waitForConnected(zhandle_t *zh) {
+ time_t expires = time(0) + 10;
+ while(!connected && time(0) < expires) {
+ yield(zh, 1);
+ }
+ return connected;
+ }
+ bool waitForDisconnected(zhandle_t *zh) {
+ time_t expires = time(0) + 15;
+ while(connected && time(0) < expires) {
+ yield(zh, 1);
+ }
+ return !connected;
+ }
+} watchctx_t;
+
+class Zookeeper_multi : public CPPUNIT_NS::TestFixture
+{
+ CPPUNIT_TEST_SUITE(Zookeeper_multi);
+//FIXME: None of these tests pass in single-threaded mode. It seems to be a
+//flaw in the test suite setup.
+#ifdef THREADED
+ CPPUNIT_TEST(testCreate);
+ CPPUNIT_TEST(testCreateDelete);
+ CPPUNIT_TEST(testInvalidVersion);
+ CPPUNIT_TEST(testNestedCreate);
+ CPPUNIT_TEST(testSetData);
+ CPPUNIT_TEST(testUpdateConflict);
+ CPPUNIT_TEST(testDeleteUpdateConflict);
+ CPPUNIT_TEST(testAsyncMulti);
+ CPPUNIT_TEST(testMultiFail);
+ CPPUNIT_TEST(testCheck);
+ CPPUNIT_TEST(testWatch);
+ CPPUNIT_TEST(testSequentialNodeCreateInAsyncMulti);
+#endif
+ CPPUNIT_TEST_SUITE_END();
+
+ static void watcher(zhandle_t *, int type, int state, const char *path,void*v){
+ watchctx_t *ctx = (watchctx_t*)v;
+
+ if (state == ZOO_CONNECTED_STATE) {
+ ctx->connected = true;
+ } else {
+ ctx->connected = false;
+ }
+ if (type != ZOO_SESSION_EVENT) {
+ evt_t evt;
+ evt.path = path;
+ evt.type = type;
+ ctx->putEvent(evt);
+ }
+ }
+
+ static const char hostPorts[];
+
+ const char *getHostPorts() {
+ return hostPorts;
+ }
+
+ zhandle_t *createClient(watchctx_t *ctx) {
+ return createClient(hostPorts, ctx);
+ }
+
+ zhandle_t *createClient(const char *hp, watchctx_t *ctx) {
+ zhandle_t *zk = zookeeper_init(hp, watcher, 10000, 0, ctx, 0);
+ ctx->zh = zk;
+ CPPUNIT_ASSERT_EQUAL(true, ctx->waitForConnected(zk));
+ return zk;
+ }
+
+ FILE *logfile;
+public:
+
+ Zookeeper_multi() {
+ logfile = openlogfile("Zookeeper_multi");
+ }
+
+ ~Zookeeper_multi() {
+ if (logfile) {
+ fflush(logfile);
+ fclose(logfile);
+ logfile = 0;
+ }
+ }
+
+ void setUp()
+ {
+ zoo_set_log_stream(logfile);
+ }
+
+ void tearDown()
+ {
+ }
+
+ static volatile int count;
+
+ static void multi_completion_fn(int rc, const void *data) {
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+ count++;
+ }
+
+ static void multi_completion_fn_no_assert(int rc, const void *data) {
+ count++;
+ }
+
+ static void waitForMultiCompletion(int seconds) {
+ time_t expires = time(0) + seconds;
+ while(count == 0 && time(0) < expires) {
+ sleep(1);
+ }
+ count--;
+ }
+
+ static void resetCounter() {
+ count = 0;
+ }
+
+ /**
+ * Test basic multi-op create functionality
+ */
+ void testCreate() {
+ int rc;
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+
+ int sz = 512;
+ char p1[sz];
+ char p2[sz];
+ char p3[sz];
+ p1[0] = p2[0] = p3[0] = '\0';
+
+ int nops = 3 ;
+ zoo_op_t ops[nops];
+ zoo_op_result_t results[nops];
+
+ zoo_create_op_init(&ops[0], "/multi1", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
+ zoo_create_op_init(&ops[1], "/multi1/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p2, sz);
+ zoo_create_op_init(&ops[2], "/multi1/b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p3, sz);
+
+ rc = zoo_multi(zk, nops, ops, results);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ CPPUNIT_ASSERT(strcmp(p1, "/multi1") == 0);
+ CPPUNIT_ASSERT(strcmp(p2, "/multi1/a") == 0);
+ CPPUNIT_ASSERT(strcmp(p3, "/multi1/b") == 0);
+
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[2].err);
+ }
+
+ /**
+ * Test create followed by delete
+ */
+ void testCreateDelete() {
+ int rc;
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+ int sz = 512;
+ char p1[sz];
+ p1[0] = '\0';
+ int nops = 2 ;
+ zoo_op_t ops[nops];
+ zoo_op_result_t results[nops];
+
+ zoo_create_op_init(&ops[0], "/multi2", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
+ zoo_delete_op_init(&ops[1], "/multi2", 0);
+
+ rc = zoo_multi(zk, nops, ops, results);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ // '/multi2' should have been deleted
+ rc = zoo_exists(zk, "/multi2", 0, NULL);
+ CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
+ }
+
+ /**
+ * Test invalid versions
+ */
+ void testInvalidVersion() {
+ int rc;
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+ int nops = 4;
+ zoo_op_t ops[nops];
+ zoo_op_result_t results[nops];
+
+ zoo_create_op_init(&ops[0], "/multi3", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
+ zoo_delete_op_init(&ops[1], "/multi3", 1);
+ zoo_create_op_init(&ops[2], "/multi3", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
+ zoo_create_op_init(&ops[3], "/multi3/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
+
+ rc = zoo_multi(zk, nops, ops, results);
+ CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, rc);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, results[1].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZRUNTIMEINCONSISTENCY, results[2].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZRUNTIMEINCONSISTENCY, results[3].err);
+ }
+
+ /**
+ * Test nested creates that rely on state in earlier op in multi
+ */
+ void testNestedCreate() {
+ int rc;
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+ int sz = 512;
+ char p1[sz];
+ p1[0] = '\0';
+ int nops = 6;
+ zoo_op_t ops[nops];
+ zoo_op_result_t results[nops];
+
+ /* Create */
+ zoo_create_op_init(&ops[0], "/multi4", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
+ zoo_create_op_init(&ops[1], "/multi4/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
+ zoo_create_op_init(&ops[2], "/multi4/a/1", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
+
+ /* Delete */
+ zoo_delete_op_init(&ops[3], "/multi4/a/1", 0);
+ zoo_delete_op_init(&ops[4], "/multi4/a", 0);
+ zoo_delete_op_init(&ops[5], "/multi4", 0);
+
+ rc = zoo_multi(zk, nops, ops, results);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ // Verify tree deleted
+ rc = zoo_exists(zk, "/multi4/a/1", 0, NULL);
+ CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
+
+ rc = zoo_exists(zk, "/multi4/a", 0, NULL);
+ CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
+
+ rc = zoo_exists(zk, "/multi4", 0, NULL);
+ CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
+ }
+
+ /**
+ * Test setdata functionality
+ */
+ void testSetData() {
+ int rc;
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+ int sz = 512;
+ struct Stat s1;
+
+ char buf[sz];
+ int blen = sz ;
+
+ char p1[sz], p2[sz];
+
+ int nops = 2;
+ zoo_op_t ops[nops];
+ zoo_op_result_t results[nops];
+
+ zoo_create_op_init(&ops[0], "/multi5", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
+ zoo_create_op_init(&ops[1], "/multi5/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p2, sz);
+
+ rc = zoo_multi(zk, nops, ops, results);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ yield(zk, 5);
+
+ zoo_op_t setdata_ops[nops];
+ zoo_op_result_t setdata_results[nops];
+
+ zoo_set_op_init(&setdata_ops[0], "/multi5", "1", 1, 0, &s1);
+ zoo_set_op_init(&setdata_ops[1], "/multi5/a", "2", 1, 0, &s1);
+
+ rc = zoo_multi(zk, nops, setdata_ops, setdata_results);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1].err);
+
+ memset(buf, '\0', blen);
+ rc = zoo_get(zk, "/multi5", 0, buf, &blen, &s1);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ CPPUNIT_ASSERT_EQUAL(1, blen);
+ CPPUNIT_ASSERT(strcmp("1", buf) == 0);
+
+ memset(buf, '\0', blen);
+ rc = zoo_get(zk, "/multi5/a", 0, buf, &blen, &s1);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ CPPUNIT_ASSERT_EQUAL(1, blen);
+ CPPUNIT_ASSERT(strcmp("2", buf) == 0);
+ }
+
+ /**
+ * Test update conflicts
+ */
+ void testUpdateConflict() {
+ int rc;
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+ int sz = 512;
+ char buf[sz];
+ int blen = sz;
+ char p1[sz];
+ p1[0] = '\0';
+ struct Stat s1;
+ int nops = 3;
+ zoo_op_t ops[nops];
+ zoo_op_result_t results[nops];
+
+ zoo_create_op_init(&ops[0], "/multi6", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
+ zoo_set_op_init(&ops[1], "/multi6", "X", 1, 0, &s1);
+ zoo_set_op_init(&ops[2], "/multi6", "Y", 1, 0, &s1);
+
+ rc = zoo_multi(zk, nops, ops, results);
+ CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, rc);
+
+ //Updating version solves conflict -- order matters
+ ops[2].set_op.version = 1;
+ rc = zoo_multi(zk, nops, ops, results);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ memset(buf, 0, sz);
+ rc = zoo_get(zk, "/multi6", 0, buf, &blen, &s1);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ CPPUNIT_ASSERT_EQUAL(blen, 1);
+ CPPUNIT_ASSERT(strncmp(buf, "Y", 1) == 0);
+ }
+
+ /**
+ * Test delete-update conflicts
+ */
+ void testDeleteUpdateConflict() {
+ int rc;
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+ int sz = 512;
+ char buf[sz];
+ int blen;
+ char p1[sz];
+ p1[0] = '\0';
+ struct Stat stat;
+ int nops = 3;
+ zoo_op_t ops[nops];
+ zoo_op_result_t results[nops];
+
+ zoo_create_op_init(&ops[0], "/multi7", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
+ zoo_delete_op_init(&ops[1], "/multi7", 0);
+ zoo_set_op_init(&ops[2], "/multi7", "Y", 1, 0, &stat);
+
+ rc = zoo_multi(zk, nops, ops, results);
+ CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
+
+ // '/multi' should never have been created as entire op should fail
+ rc = zoo_exists(zk, "/multi7", 0, NULL);
+ CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
+ }
+
+ void testAsyncMulti() {
+ int rc;
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+
+ int sz = 512;
+ char p1[sz], p2[sz], p3[sz];
+ p1[0] = '\0';
+ p2[0] = '\0';
+ p3[0] = '\0';
+
+ int nops = 3;
+ zoo_op_t ops[nops];
+ zoo_op_result_t results[nops];
+
+ zoo_create_op_init(&ops[0], "/multi8", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
+ zoo_create_op_init(&ops[1], "/multi8/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p2, sz);
+ zoo_create_op_init(&ops[2], "/multi8/b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p3, sz);
+
+ rc = zoo_amulti(zk, nops, ops, results, multi_completion_fn, 0);
+ waitForMultiCompletion(10);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ CPPUNIT_ASSERT(strcmp(p1, "/multi8") == 0);
+ CPPUNIT_ASSERT(strcmp(p2, "/multi8/a") == 0);
+ CPPUNIT_ASSERT(strcmp(p3, "/multi8/b") == 0);
+
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[2].err);
+ }
+
+ void testMultiFail() {
+ int rc;
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+
+ int sz = 512;
+ char p1[sz], p2[sz], p3[sz];
+
+ p1[0] = '\0';
+ p2[0] = '\0';
+ p3[0] = '\0';
+
+ int nops = 3;
+ zoo_op_t ops[nops];
+ zoo_op_result_t results[nops];
+
+ zoo_create_op_init(&ops[0], "/multi9", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
+ zoo_create_op_init(&ops[1], "/multi9", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p2, sz);
+ zoo_create_op_init(&ops[2], "/multi9/b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p3, sz);
+
+ rc = zoo_multi(zk, nops, ops, results);
+ CPPUNIT_ASSERT_EQUAL((int)ZNODEEXISTS, rc);
+ }
+
+ /**
+ * Test basic multi-op check functionality
+ */
+ void testCheck() {
+ int rc;
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+ int sz = 512;
+ char p1[sz];
+ p1[0] = '\0';
+ struct Stat s1;
+
+ rc = zoo_create(zk, "/multi0", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ // Conditionally create /multi0/a' only if '/multi0' at version 0
+ int nops = 2;
+ zoo_op_t ops[nops];
+ zoo_op_result_t results[nops];
+
+ zoo_check_op_init(&ops[0], "/multi0", 0);
+ zoo_create_op_init(&ops[1], "/multi0/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
+
+ rc = zoo_multi(zk, nops, ops, results);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1].err);
+
+ // '/multi0/a' should have been created as it passed version check
+ rc = zoo_exists(zk, "/multi0/a", 0, NULL);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ // Only create '/multi0/b' if '/multi0' at version 10 (which it's not)
+ zoo_op_t ops2[nops];
+ zoo_check_op_init(&ops2[0], "/multi0", 10);
+ zoo_create_op_init(&ops2[1], "/multi0/b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
+
+ rc = zoo_multi(zk, nops, ops2, results);
+ CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, rc);
+
+ CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, results[0].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZRUNTIMEINCONSISTENCY, results[1].err);
+
+ // '/multi0/b' should NOT have been created
+ rc = zoo_exists(zk, "/multi0/b", 0, NULL);
+ CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
+ }
+
+ /**
+ * Do a multi op inside a watch callback context.
+ */
+ static void doMultiInWatch(zhandle_t *zk, int type, int state, const char *path, void *ctx) {
+ int rc;
+ int sz = 512;
+ char p1[sz];
+ p1[0] = '\0';
+ struct Stat s1;
+
+ int nops = 1;
+ zoo_op_t ops[nops];
+ zoo_op_result_t results[nops];
+
+ zoo_set_op_init(&ops[0], "/multiwatch", "1", 1, -1, NULL);
+
+ rc = zoo_multi(zk, nops, ops, results);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
+
+ memset(p1, '\0', sz);
+ rc = zoo_get(zk, "/multiwatch", 0, p1, &sz, &s1);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ CPPUNIT_ASSERT_EQUAL(1, sz);
+ CPPUNIT_ASSERT(strcmp("1", p1) == 0);
+ count++;
+ }
+
+ /**
+ * Test multi-op called from a watch
+ */
+ void testWatch() {
+ int rc;
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+ int sz = 512;
+ char p1[sz];
+ p1[0] = '\0';
+
+ rc = zoo_create(zk, "/multiwatch", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+
+ // create a watch on node '/multiwatch'
+ rc = zoo_wget(zk, "/multiwatch", doMultiInWatch, &ctx, p1, &sz, NULL);
+
+ // setdata on node '/multiwatch' this should trip the watch
+ rc = zoo_set(zk, "/multiwatch", NULL, -1, -1);
+ CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
+
+ // wait for multi completion in doMultiInWatch
+ waitForMultiCompletion(5);
+ }
+
+ /**
+ * ZOOKEEPER-1624: PendingChanges of create sequential node request didn't
+ * get rollbacked correctly when multi-op failed. This caused
+ * create sequential node request in subsequent multi-op to failed because
+ * sequential node name generation is incorrect.
+ *
+ * The check is to make sure that each request in multi-op failed with
+ * the correct reason.
+ */
+ void testSequentialNodeCreateInAsyncMulti() {
+ int rc;
+ watchctx_t ctx;
+ zhandle_t *zk = createClient(&ctx);
+
+ int iteration = 4;
+ int nops = 2;
+
+ zoo_op_result_t results[iteration][nops];
+ zoo_op_t ops[nops];
+ zoo_create_op_init(&ops[0], "/node-", "", 0, &ZOO_OPEN_ACL_UNSAFE, ZOO_SEQUENCE, NULL, 0);
+ zoo_create_op_init(&ops[1], "/dup", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
+ for (int i = 0; i < iteration ; ++i) {
+ rc = zoo_amulti(zk, nops, ops, results[i], multi_completion_fn_no_assert, 0);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
+ }
+
+ waitForMultiCompletion(10);
+
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0][0].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1][0].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[2][0].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[3][0].err);
+
+ CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0][1].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZNODEEXISTS, results[1][1].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZNODEEXISTS, results[2][1].err);
+ CPPUNIT_ASSERT_EQUAL((int)ZNODEEXISTS, results[3][1].err);
+
+ resetCounter();
+ }
+};
+
+volatile int Zookeeper_multi::count;
+const char Zookeeper_multi::hostPorts[] = "127.0.0.1:22181";
+CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_multi);
[11/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/TestZookeeperInit.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/TestZookeeperInit.cc b/src/c/tests/TestZookeeperInit.cc
deleted file mode 100644
index eadf41d..0000000
--- a/src/c/tests/TestZookeeperInit.cc
+++ /dev/null
@@ -1,301 +0,0 @@
-/**
- * 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 <cppunit/extensions/HelperMacros.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <errno.h>
-
-#include "Util.h"
-#include "LibCMocks.h"
-#include "ZKMocks.h"
-
-#ifdef THREADED
-#include "PthreadMocks.h"
-#else
-class MockPthreadsNull;
-#endif
-
-using namespace std;
-
-class Zookeeper_init : public CPPUNIT_NS::TestFixture
-{
- CPPUNIT_TEST_SUITE(Zookeeper_init);
- CPPUNIT_TEST(testBasic);
- CPPUNIT_TEST(testAddressResolution);
- CPPUNIT_TEST(testMultipleAddressResolution);
- CPPUNIT_TEST(testNullAddressString);
- CPPUNIT_TEST(testEmptyAddressString);
- CPPUNIT_TEST(testOneSpaceAddressString);
- CPPUNIT_TEST(testTwoSpacesAddressString);
- CPPUNIT_TEST(testInvalidAddressString1);
- CPPUNIT_TEST(testInvalidAddressString2);
- CPPUNIT_TEST(testNonexistentHost);
- CPPUNIT_TEST(testOutOfMemory_init);
- CPPUNIT_TEST(testOutOfMemory_getaddrs1);
-#if !defined(__CYGWIN__) // not valid for cygwin
- CPPUNIT_TEST(testOutOfMemory_getaddrs2);
-#endif
- CPPUNIT_TEST(testPermuteAddrsList);
- CPPUNIT_TEST_SUITE_END();
- zhandle_t *zh;
- MockPthreadsNull* pthreadMock;
- static void watcher(zhandle_t *, int , int , const char *,void*){}
- FILE *logfile;
-public:
- Zookeeper_init():zh(0),pthreadMock(0){
- logfile = openlogfile("Zookeeper_init");
- }
-
- ~Zookeeper_init() {
- if (logfile) {
- fflush(logfile);
- fclose(logfile);
- logfile = 0;
- }
- }
-
- void setUp()
- {
- zoo_set_log_stream(logfile);
-
- zoo_deterministic_conn_order(0);
-#ifdef THREADED
- // disable threading
- pthreadMock=new MockPthreadZKNull;
-#endif
- zh=0;
- }
-
- void tearDown()
- {
- zookeeper_close(zh);
-#ifdef THREADED
- delete pthreadMock;
-#endif
- }
-
- void testBasic()
- {
- const string EXPECTED_HOST("127.0.0.1:2121");
- const int EXPECTED_ADDRS_COUNT =1;
- const int EXPECTED_RECV_TIMEOUT=10000;
- clientid_t cid;
- memset(&cid,0xFE,sizeof(cid));
-
- zh=zookeeper_init(EXPECTED_HOST.c_str(),watcher,EXPECTED_RECV_TIMEOUT,
- &cid,(void*)1,0);
-
- CPPUNIT_ASSERT(zh!=0);
- CPPUNIT_ASSERT(zh->fd == -1);
- CPPUNIT_ASSERT(zh->hostname!=0);
- CPPUNIT_ASSERT_EQUAL(EXPECTED_ADDRS_COUNT,zh->addrs_count);
- CPPUNIT_ASSERT_EQUAL(EXPECTED_HOST,string(zh->hostname));
- CPPUNIT_ASSERT(zh->state == NOTCONNECTED_STATE_DEF);
- CPPUNIT_ASSERT(zh->context == (void*)1);
- CPPUNIT_ASSERT_EQUAL(EXPECTED_RECV_TIMEOUT,zh->recv_timeout);
- CPPUNIT_ASSERT(zh->watcher == watcher);
- CPPUNIT_ASSERT(zh->connect_index==0);
- CPPUNIT_ASSERT(zh->primer_buffer.buffer==zh->primer_storage_buffer);
- CPPUNIT_ASSERT(zh->primer_buffer.curr_offset ==0);
- CPPUNIT_ASSERT(zh->primer_buffer.len == sizeof(zh->primer_storage_buffer));
- CPPUNIT_ASSERT(zh->primer_buffer.next == 0);
- CPPUNIT_ASSERT(zh->last_zxid ==0);
- CPPUNIT_ASSERT(memcmp(&zh->client_id,&cid,sizeof(cid))==0);
-
-#ifdef THREADED
- // thread specific checks
- adaptor_threads* adaptor=(adaptor_threads*)zh->adaptor_priv;
- CPPUNIT_ASSERT(adaptor!=0);
- CPPUNIT_ASSERT(pthreadMock->pthread_createCounter==2);
- CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(adaptor->io));
- CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(adaptor->completion));
- CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(&zh->to_process.lock));
- CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(&zh->to_send.lock));
- CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(&zh->sent_requests.lock));
- CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(&zh->completions_to_process.lock));
- CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(&zh->sent_requests.cond));
- CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(&zh->completions_to_process.cond));
-#endif
- }
- void testAddressResolution()
- {
- const char EXPECTED_IPS[][4]={{127,0,0,1}};
- const int EXPECTED_ADDRS_COUNT =COUNTOF(EXPECTED_IPS);
-
- zoo_deterministic_conn_order(1);
- zh=zookeeper_init("127.0.0.1:2121",0,10000,0,0,0);
-
- CPPUNIT_ASSERT(zh!=0);
- CPPUNIT_ASSERT_EQUAL(EXPECTED_ADDRS_COUNT,zh->addrs_count);
- for(int i=0;i<zh->addrs_count;i++){
- sockaddr_in* addr=(struct sockaddr_in*)&zh->addrs[i];
- CPPUNIT_ASSERT(memcmp(EXPECTED_IPS[i],&addr->sin_addr,sizeof(addr->sin_addr))==0);
- CPPUNIT_ASSERT_EQUAL(2121,(int)ntohs(addr->sin_port));
- }
- }
- void testMultipleAddressResolution()
- {
- const string EXPECTED_HOST("127.0.0.1:2121,127.0.0.2:3434");
- const char EXPECTED_IPS[][4]={{127,0,0,1},{127,0,0,2}};
- const int EXPECTED_ADDRS_COUNT =COUNTOF(EXPECTED_IPS);
-
- zoo_deterministic_conn_order(1);
- zh=zookeeper_init(EXPECTED_HOST.c_str(),0,1000,0,0,0);
-
- CPPUNIT_ASSERT(zh!=0);
- CPPUNIT_ASSERT_EQUAL(EXPECTED_ADDRS_COUNT,zh->addrs_count);
-
- for(int i=0;i<zh->addrs_count;i++){
- sockaddr_in* addr=(struct sockaddr_in*)&zh->addrs[i];
- CPPUNIT_ASSERT(memcmp(EXPECTED_IPS[i],&addr->sin_addr,sizeof(addr->sin_addr))==0);
- if(i<1)
- CPPUNIT_ASSERT_EQUAL(2121,(int)ntohs(addr->sin_port));
- else
- CPPUNIT_ASSERT_EQUAL(3434,(int)ntohs(addr->sin_port));
- }
- }
- void testMultipleAddressWithSpace()
- {
- const string EXPECTED_HOST("127.0.0.1:2121, 127.0.0.2:3434");
- const char EXPECTED_IPS[][4]={{127,0,0,1},{127,0,0,2}};
- const int EXPECTED_ADDRS_COUNT =COUNTOF(EXPECTED_IPS);
-
- zoo_deterministic_conn_order(1);
- zh=zookeeper_init(EXPECTED_HOST.c_str(),0,1000,0,0,0);
-
- CPPUNIT_ASSERT(zh!=0);
- CPPUNIT_ASSERT_EQUAL(EXPECTED_ADDRS_COUNT,zh->addrs_count);
-
- for(int i=0;i<zh->addrs_count;i++){
- sockaddr_in* addr=(struct sockaddr_in*)&zh->addrs[i];
- CPPUNIT_ASSERT(memcmp(EXPECTED_IPS[i],&addr->sin_addr,sizeof(addr->sin_addr))==0);
- if(i<1)
- CPPUNIT_ASSERT_EQUAL(2121,(int)ntohs(addr->sin_port));
- else
- CPPUNIT_ASSERT_EQUAL(3434,(int)ntohs(addr->sin_port));
- }
- }
- void testNullAddressString()
- {
- zh=zookeeper_init(NULL,0,0,0,0,0);
- CPPUNIT_ASSERT(zh==0);
- CPPUNIT_ASSERT_EQUAL(EINVAL,errno);
- }
- void testEmptyAddressString()
- {
- const string INVALID_HOST("");
- zh=zookeeper_init(INVALID_HOST.c_str(),0,0,0,0,0);
- CPPUNIT_ASSERT(zh==0);
- CPPUNIT_ASSERT_EQUAL(EINVAL,errno);
- }
- void testOneSpaceAddressString()
- {
- const string INVALID_HOST(" ");
- zh=zookeeper_init(INVALID_HOST.c_str(),0,0,0,0,0);
- CPPUNIT_ASSERT(zh==0);
- CPPUNIT_ASSERT_EQUAL(EINVAL,errno);
- }
- void testTwoSpacesAddressString()
- {
- const string INVALID_HOST(" ");
- zh=zookeeper_init(INVALID_HOST.c_str(),0,0,0,0,0);
- CPPUNIT_ASSERT(zh==0);
- CPPUNIT_ASSERT_EQUAL(EINVAL,errno);
- }
- void testInvalidAddressString1()
- {
- const string INVALID_HOST("host1");
- zh=zookeeper_init(INVALID_HOST.c_str(),0,0,0,0,0);
- CPPUNIT_ASSERT(zh==0);
- CPPUNIT_ASSERT_EQUAL(EINVAL,errno);
- }
- void testInvalidAddressString2()
- {
- const string INVALID_HOST("host1:1111+host:123");
- zh=zookeeper_init(INVALID_HOST.c_str(),0,0,0,0,0);
- CPPUNIT_ASSERT(zh==0);
- CPPUNIT_ASSERT((ENOENT|EINVAL) & errno);
- }
- void testNonexistentHost()
- {
- const string EXPECTED_HOST("host1.blabadibla.bla.:1111");
-
- zh=zookeeper_init(EXPECTED_HOST.c_str(),0,0,0,0,0);
-
- CPPUNIT_ASSERT(zh==0);
- //With the switch to thread safe getaddrinfo, we don't get
- //these global variables
- //CPPUNIT_ASSERT_EQUAL(EINVAL,errno);
- //CPPUNIT_ASSERT_EQUAL(HOST_NOT_FOUND,h_errno);
- }
- void testOutOfMemory_init()
- {
- Mock_calloc mock;
- mock.callsBeforeFailure=0; // fail first calloc in init()
-
- zh=zookeeper_init("ahost:123",watcher,10000,0,0,0);
-
- CPPUNIT_ASSERT(zh==0);
- CPPUNIT_ASSERT_EQUAL(ENOMEM,errno);
- }
- void testOutOfMemory_getaddrs1()
- {
- Mock_realloc reallocMock;
- reallocMock.callsBeforeFailure=0; // fail on first call to realloc
-
- zh=zookeeper_init("127.0.0.1:123",0,0,0,0,0);
-
- CPPUNIT_ASSERT(zh==0);
- CPPUNIT_ASSERT_EQUAL(ENOMEM,errno);
- }
- void testOutOfMemory_getaddrs2()
- {
- Mock_realloc reallocMock;
- reallocMock.callsBeforeFailure=1; // fail on the second call to realloc
-
- zh=zookeeper_init("127.0.0.1:123,127.0.0.2:123,127.0.0.3:123,127.0.0.4:123,127.0.0.5:123,127.0.0.6:123,127.0.0.7:123,127.0.0.8:123,127.0.0.9:123,127.0.0.10:123,127.0.0.11:123,127.0.0.12:123,127.0.0.13:123,127.0.0.14:123,127.0.0.15:123,127.0.0.16:123,127.0.0.17:123",0,0,0,0,0);
-
- CPPUNIT_ASSERT(zh==0);
- CPPUNIT_ASSERT_EQUAL(ENOMEM,errno);
- }
- void testPermuteAddrsList()
- {
- const char EXPECTED[][5]={"\0\0\0\0","\1\1\1\1","\2\2\2\2","\3\3\3\3"};
- const int EXPECTED_ADDR_COUNT=COUNTOF(EXPECTED);
-
- const int RAND_SEQ[]={0,1,1,-1};
- const int RAND_SIZE=COUNTOF(RAND_SEQ);
- Mock_random randomMock;
- randomMock.randomReturns.assign(RAND_SEQ,RAND_SEQ+RAND_SIZE-1);
- zh=zookeeper_init("0.0.0.0:123,1.1.1.1:123,2.2.2.2:123,3.3.3.3:123",0,1000,0,0,0);
-
- CPPUNIT_ASSERT(zh!=0);
- CPPUNIT_ASSERT_EQUAL(EXPECTED_ADDR_COUNT,zh->addrs_count);
- const string EXPECTED_SEQ("3210");
- char ACTUAL_SEQ[EXPECTED_ADDR_COUNT+1]; ACTUAL_SEQ[EXPECTED_ADDR_COUNT]=0;
- for(int i=0;i<zh->addrs_count;i++){
- sockaddr_in* addr=(struct sockaddr_in*)&zh->addrs[i];
- // match the first byte of the EXPECTED and of the actual address
- ACTUAL_SEQ[i]=((char*)&addr->sin_addr)[0]+'0';
- }
- CPPUNIT_ASSERT_EQUAL(EXPECTED_SEQ,string(ACTUAL_SEQ));
- }
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_init);
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/ThreadingUtil.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/ThreadingUtil.cc b/src/c/tests/ThreadingUtil.cc
deleted file mode 100644
index 3b5170a..0000000
--- a/src/c/tests/ThreadingUtil.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * 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 <sys/types.h>
-#include "ThreadingUtil.h"
-#include "LibCSymTable.h"
-
-#ifdef THREADED
-
-// ****************************************************************************
-// Mutex wrapper
-struct Mutex::Impl{
- Impl(){
- LIBC_SYMBOLS.pthread_mutex_init(&mut_, 0);
- }
- ~Impl(){
- LIBC_SYMBOLS.pthread_mutex_destroy(&mut_);
- }
- pthread_mutex_t mut_;
-};
-
-Mutex::Mutex():impl_(new Impl) {}
-Mutex::~Mutex() { delete impl_;}
-void Mutex::acquire() {
- LIBC_SYMBOLS.pthread_mutex_lock(&impl_->mut_);
-}
-void Mutex::release() {
- LIBC_SYMBOLS.pthread_mutex_unlock(&impl_->mut_);
-}
-
-// ****************************************************************************
-// Atomics
-int32_t atomic_post_incr(volatile int32_t* operand, int32_t incr)
-{
-#if defined(__GNUC__)
- return __sync_fetch_and_add(operand,incr);
-#else
- int32_t result;
- __asm__ __volatile__(
- "lock xaddl %0,%1\n"
- : "=r"(result), "=m"(*operand)
- : "0"(incr)
- : "memory");
- return result;
-#endif
-}
-int32_t atomic_fetch_store(volatile int32_t *ptr, int32_t value)
-{
-#if defined(__GNUC__)
- return __sync_lock_test_and_set(ptr,value);
-#else
- int32_t result;
- __asm__ __volatile__("lock xchgl %0,%1\n"
- : "=r"(result), "=m"(*ptr)
- : "0"(value)
- : "memory");
- return result;
-#endif
-}
-#else
-int32_t atomic_post_incr(volatile int32_t* operand, int32_t incr){
- int32_t v=*operand;
- *operand+=incr;
- return v;
-}
-int32_t atomic_fetch_store(volatile int32_t *ptr, int32_t value)
-{
- int32_t result=*ptr;
- *ptr=value;
- return result;
-}
-#endif // THREADED
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/ThreadingUtil.h
----------------------------------------------------------------------
diff --git a/src/c/tests/ThreadingUtil.h b/src/c/tests/ThreadingUtil.h
deleted file mode 100644
index 9165412..0000000
--- a/src/c/tests/ThreadingUtil.h
+++ /dev/null
@@ -1,261 +0,0 @@
-/**
- * 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 THREADINGUTIL_H_
-#define THREADINGUTIL_H_
-
-#include <vector>
-
-#ifdef THREADED
-#include "pthread.h"
-#endif
-
-// *****************************************************************************
-// Threading primitives
-
-// atomic post-increment; returns the previous value of the operand
-int32_t atomic_post_incr(volatile int32_t* operand, int32_t incr);
-// atomic fetch&store; returns the previous value of the operand
-int32_t atomic_fetch_store(volatile int32_t *operand, int32_t value);
-
-// a partial implementation of an atomic integer type
-class AtomicInt{
-public:
- explicit AtomicInt(int32_t init=0):v_(init){}
- AtomicInt(const AtomicInt& other):v_(other){}
- // assigment
- AtomicInt& operator=(const AtomicInt& lhs){
- atomic_fetch_store(&v_,lhs);
- return *this;
- }
- AtomicInt& operator=(int32_t i){
- atomic_fetch_store(&v_,i);
- return *this;
- }
- // pre-increment
- AtomicInt& operator++() {
- atomic_post_incr(&v_,1);
- return *this;
- }
- // pre-decrement
- AtomicInt& operator--() {
- atomic_post_incr(&v_,-1);
- return *this;
- }
- // post-increment
- AtomicInt operator++(int){
- return AtomicInt(atomic_post_incr(&v_,1));
- }
- // post-decrement
- AtomicInt operator--(int){
- return AtomicInt(atomic_post_incr(&v_,-1));
- }
-
- operator int() const{
- return atomic_post_incr(&v_,0);
- }
- int get() const{
- return atomic_post_incr(&v_,0);
- }
-private:
- mutable int32_t v_;
-};
-
-#ifdef THREADED
-// ****************************************************************************
-#define VALIDATE_JOBS(jm) jm.validateJobs(__FILE__,__LINE__)
-#define VALIDATE_JOB(j) j.validate(__FILE__,__LINE__)
-
-class Mutex{
-public:
- Mutex();
- ~Mutex();
- void acquire();
- void release();
-private:
- Mutex(const Mutex&);
- Mutex& operator=(const Mutex&);
- struct Impl;
- Impl* impl_;
-};
-
-class MTLock{
-public:
- MTLock(Mutex& m):m_(m){m.acquire();}
- ~MTLock(){m_.release();}
- Mutex& m_;
-};
-
-#define synchronized(m) MTLock __lock(m)
-
-// ****************************************************************************
-class Latch {
-public:
- virtual ~Latch() {}
- virtual void await() const =0;
- virtual void signalAndWait() =0;
- virtual void signal() =0;
-};
-
-class CountDownLatch: public Latch {
-public:
- CountDownLatch(int count):count_(count) {
- pthread_cond_init(&cond_,0);
- pthread_mutex_init(&mut_,0);
- }
- virtual ~CountDownLatch() {
- pthread_mutex_lock(&mut_);
- if(count_!=0) {
- count_=0;
- pthread_cond_broadcast(&cond_);
- }
- pthread_mutex_unlock(&mut_);
-
- pthread_cond_destroy(&cond_);
- pthread_mutex_destroy(&mut_);
- }
-
- virtual void await() const {
- pthread_mutex_lock(&mut_);
- awaitImpl();
- pthread_mutex_unlock(&mut_);
- }
- virtual void signalAndWait() {
- pthread_mutex_lock(&mut_);
- signalImpl();
- awaitImpl();
- pthread_mutex_unlock(&mut_);
- }
- virtual void signal() {
- pthread_mutex_lock(&mut_);
- signalImpl();
- pthread_mutex_unlock(&mut_);
- }
-private:
- void awaitImpl() const{
- while(count_!=0)
- pthread_cond_wait(&cond_,&mut_);
- }
- void signalImpl() {
- if(count_>0) {
- count_--;
- pthread_cond_broadcast(&cond_);
- }
- }
- int count_;
- mutable pthread_mutex_t mut_;
- mutable pthread_cond_t cond_;
-};
-
-class TestJob {
-public:
- typedef long JobId;
- TestJob():hasRun_(false),startLatch_(0),endLatch_(0) {}
- virtual ~TestJob() {
- join();
- }
- virtual TestJob* clone() const =0;
-
- virtual void run() =0;
- virtual void validate(const char* file, int line) const =0;
-
- virtual void start(Latch* startLatch=0,Latch* endLatch=0) {
- startLatch_=startLatch;endLatch_=endLatch;
- hasRun_=true;
- pthread_create(&thread_, 0, thread, this);
- }
- virtual JobId getJobId() const {
- return (JobId)thread_;
- }
- virtual void join() {
- if(!hasRun_)
- return;
- if(!pthread_equal(thread_,pthread_self()))
- pthread_join(thread_,0);
- else
- pthread_detach(thread_);
- }
-private:
- void awaitStart() {
- if(startLatch_==0) return;
- startLatch_->signalAndWait();
- }
- void signalFinished() {
- if(endLatch_==0) return;
- endLatch_->signal();
- }
- static void* thread(void* p) {
- TestJob* j=(TestJob*)p;
- j->awaitStart(); // wait for the start command
- j->run();
- j->signalFinished();
- return 0;
- }
- bool hasRun_;
- Latch* startLatch_;
- Latch* endLatch_;
- pthread_t thread_;
-};
-
-class TestJobManager {
- typedef std::vector<TestJob*> JobList;
-public:
- TestJobManager(const TestJob& tj,int threadCount=1):
- startLatch_(threadCount),endLatch_(threadCount)
- {
- for(int i=0;i<threadCount;++i)
- jobs_.push_back(tj.clone());
- }
- virtual ~TestJobManager(){
- for(unsigned i=0;i<jobs_.size();++i)
- delete jobs_[i];
- }
-
- virtual void startAllJobs() {
- for(unsigned i=0;i<jobs_.size();++i)
- jobs_[i]->start(&startLatch_,&endLatch_);
- }
- virtual void startJobsImmediately() {
- for(unsigned i=0;i<jobs_.size();++i)
- jobs_[i]->start(0,&endLatch_);
- }
- virtual void wait() const {
- endLatch_.await();
- }
- virtual void validateJobs(const char* file, int line) const{
- for(unsigned i=0;i<jobs_.size();++i)
- jobs_[i]->validate(file,line);
- }
-private:
- JobList jobs_;
- CountDownLatch startLatch_;
- CountDownLatch endLatch_;
-};
-
-#else // THREADED
-// single THREADED
-class Mutex{
-public:
- void acquire(){}
- void release(){}
-};
-#define synchronized(m)
-
-#endif // THREADED
-
-#endif /*THREADINGUTIL_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/Util.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/Util.cc b/src/c/tests/Util.cc
deleted file mode 100644
index 2b9da84..0000000
--- a/src/c/tests/Util.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * 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 "Util.h"
-#include "string.h"
-
-const std::string EMPTY_STRING;
-
-TestConfig globalTestConfig;
-
-void millisleep(int ms){
- timespec ts;
- ts.tv_sec=ms/1000;
- ts.tv_nsec=(ms%1000)*1000000; // to nanoseconds
- nanosleep(&ts,0);
-}
-
-FILE *openlogfile(const char* testname) {
- char name[1024];
- strcpy(name, "TEST-");
- strncpy(name + 5, testname, sizeof(name) - 5);
-#ifdef THREADED
- strcpy(name + strlen(name), "-mt.txt");
-#else
- strcpy(name + strlen(name), "-st.txt");
-#endif
-
- FILE *logfile = fopen(name, "a");
-
- if (logfile == 0) {
- fprintf(stderr, "Can't open log file %s!\n", name);
- return 0;
- }
-
- return logfile;
-}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/Util.h
----------------------------------------------------------------------
diff --git a/src/c/tests/Util.h b/src/c/tests/Util.h
deleted file mode 100644
index 01e21ce..0000000
--- a/src/c/tests/Util.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * 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 UTIL_H_
-#define UTIL_H_
-
-#include <map>
-#include <vector>
-#include <string>
-
-#include "zookeeper_log.h"
-
-// number of elements in array
-#define COUNTOF(array) sizeof(array)/sizeof(array[0])
-
-#define DECLARE_WRAPPER(ret,sym,sig) \
- extern "C" ret __real_##sym sig; \
- extern "C" ret __wrap_##sym sig
-
-#define CALL_REAL(sym,params) \
- __real_##sym params
-
-// must include "src/zookeeper_log.h" to be able to use this macro
-#define TEST_TRACE(x) \
- log_message(ZOO_LOG_LEVEL_DEBUG,__LINE__,__func__,format_log_message x)
-
-extern const std::string EMPTY_STRING;
-
-// *****************************************************************************
-// A bit of wizardry to get to the bare type from a reference or a pointer
-// to the type
-template <class T>
-struct TypeOp {
- typedef T BareT;
- typedef T ArgT;
-};
-
-// partial specialization for reference types
-template <class T>
-struct TypeOp<T&>{
- typedef T& ArgT;
- typedef typename TypeOp<T>::BareT BareT;
-};
-
-// partial specialization for pointers
-template <class T>
-struct TypeOp<T*>{
- typedef T* ArgT;
- typedef typename TypeOp<T>::BareT BareT;
-};
-
-// *****************************************************************************
-// Container utilities
-
-template <class K, class V>
-void putValue(std::map<K,V>& map,const K& k, const V& v){
- typedef std::map<K,V> Map;
- typename Map::const_iterator it=map.find(k);
- if(it==map.end())
- map.insert(typename Map::value_type(k,v));
- else
- map[k]=v;
-}
-
-template <class K, class V>
-bool getValue(const std::map<K,V>& map,const K& k,V& v){
- typedef std::map<K,V> Map;
- typename Map::const_iterator it=map.find(k);
- if(it==map.end())
- return false;
- v=it->second;
- return true;
-}
-
-// *****************************************************************************
-// misc utils
-
-// millisecond sleep
-void millisleep(int ms);
-FILE *openlogfile(const char* name);
-// evaluate given predicate until it returns true or the timeout
-// (in millis) has expired
-template<class Predicate>
-int ensureCondition(const Predicate& p,int timeout){
- int elapsed=0;
- while(!p() && elapsed<timeout){
- millisleep(2);
- elapsed+=2;
- }
- return elapsed;
-};
-
-// *****************************************************************************
-// test global configuration data
-class TestConfig{
- typedef std::vector<std::string> CmdLineOptList;
-public:
- typedef CmdLineOptList::const_iterator const_iterator;
- TestConfig(){}
- ~TestConfig(){}
- void addConfigFromCmdLine(int argc, char* argv[]){
- if(argc>=2)
- testName_=argv[1];
- for(int i=2; i<argc;++i)
- cmdOpts_.push_back(argv[i]);
- }
- const_iterator getExtraOptBegin() const {return cmdOpts_.begin();}
- const_iterator getExtraOptEnd() const {return cmdOpts_.end();}
- size_t getExtraOptCount() const {
- return cmdOpts_.size();
- }
- const std::string& getTestName() const {
- return testName_=="all"?EMPTY_STRING:testName_;
- }
-private:
- CmdLineOptList cmdOpts_;
- std::string testName_;
-};
-
-extern TestConfig globalTestConfig;
-
-#endif /*UTIL_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/Vector.h
----------------------------------------------------------------------
diff --git a/src/c/tests/Vector.h b/src/c/tests/Vector.h
deleted file mode 100644
index d75fe07..0000000
--- a/src/c/tests/Vector.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * 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 _VECTOR_UTIL_H
-#define _VECTOR_UTIL_H
-
-#include <vector>
-
-// function to conveniently stream vectors
-template <class U>
-std::ostream& operator<<(std::ostream& os,const std::vector<U>& c){
- typedef std::vector<U> V;
- os<<"[";
- if(c.size()>0){
- for(typename V::const_iterator it=c.begin();it!=c.end();++it)
- os<<*it<<",";
- os.seekp(-1,std::ios::cur);
- }
- os<<"]";
- return os;
-}
-
-#endif // _VECTOR_UTIL_H
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/ZKMocks.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/ZKMocks.cc b/src/c/tests/ZKMocks.cc
deleted file mode 100644
index 69bea16..0000000
--- a/src/c/tests/ZKMocks.cc
+++ /dev/null
@@ -1,519 +0,0 @@
-/**
- * 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 <arpa/inet.h> // for htonl
-#include <memory>
-
-#include <zookeeper.h>
-#include <proto.h>
-
-#ifdef THREADED
-#include "PthreadMocks.h"
-#endif
-#include "ZKMocks.h"
-
-using namespace std;
-
-TestClientId testClientId;
-const char* TestClientId::PASSWD="1234567890123456";
-
-HandshakeRequest* HandshakeRequest::parse(const std::string& buf){
- auto_ptr<HandshakeRequest> req(new HandshakeRequest);
-
- memcpy(&req->protocolVersion,buf.data(), sizeof(req->protocolVersion));
- req->protocolVersion = htonl(req->protocolVersion);
-
- int offset=sizeof(req->protocolVersion);
-
- memcpy(&req->lastZxidSeen,buf.data()+offset,sizeof(req->lastZxidSeen));
- req->lastZxidSeen = zoo_htonll(req->lastZxidSeen);
- offset+=sizeof(req->lastZxidSeen);
-
- memcpy(&req->timeOut,buf.data()+offset,sizeof(req->timeOut));
- req->timeOut = htonl(req->timeOut);
- offset+=sizeof(req->timeOut);
-
- memcpy(&req->sessionId,buf.data()+offset,sizeof(req->sessionId));
- req->sessionId = zoo_htonll(req->sessionId);
- offset+=sizeof(req->sessionId);
-
- memcpy(&req->passwd_len,buf.data()+offset,sizeof(req->passwd_len));
- req->passwd_len = htonl(req->passwd_len);
- offset+=sizeof(req->passwd_len);
-
- memcpy(req->passwd,buf.data()+offset,sizeof(req->passwd));
- if(testClientId.client_id==req->sessionId &&
- !memcmp(testClientId.passwd,req->passwd,sizeof(req->passwd)))
- return req.release();
- // the request didn't match -- may not be a handshake request after all
- return 0;
-}
-
-// *****************************************************************************
-// watcher action implementation
-void activeWatcher(zhandle_t *zh, int type, int state, const char *path,void* ctx){
- if(zh==0 || ctx==0) return;
- WatcherAction* action=(WatcherAction*)ctx;
-
- if(type==ZOO_SESSION_EVENT){
- if(state==ZOO_EXPIRED_SESSION_STATE)
- action->onSessionExpired(zh);
- else if(state==ZOO_CONNECTING_STATE)
- action->onConnectionLost(zh);
- else if(state==ZOO_CONNECTED_STATE)
- action->onConnectionEstablished(zh);
- }else if(type==ZOO_CHANGED_EVENT)
- action->onNodeValueChanged(zh,path);
- else if(type==ZOO_DELETED_EVENT)
- action->onNodeDeleted(zh,path);
- else if(type==ZOO_CHILD_EVENT)
- action->onChildChanged(zh,path);
- // TODO: implement for the rest of the event types
- // ...
- action->setWatcherTriggered();
-}
-SyncedBoolCondition WatcherAction::isWatcherTriggered() const{
- return SyncedBoolCondition(triggered_,mx_);
-}
-
-// *****************************************************************************
-// a set of async completion signatures
-void asyncCompletion(int rc, ACL_vector *acl,Stat *stat, const void *data){
- assert("Completion data is NULL"&&data);
- static_cast<AsyncCompletion*>((void*)data)->aclCompl(rc,acl,stat);
-}
-void asyncCompletion(int rc, const char *value, int len, const Stat *stat,
- const void *data){
- assert("Completion data is NULL"&&data);
- static_cast<AsyncCompletion*>((void*)data)->dataCompl(rc,value,len,stat);
-}
-void asyncCompletion(int rc, const Stat *stat, const void *data){
- assert("Completion data is NULL"&&data);
- static_cast<AsyncCompletion*>((void*)data)->statCompl(rc,stat);
-}
-void asyncCompletion(int rc, const char *value, const void *data){
- assert("Completion data is NULL"&&data);
- static_cast<AsyncCompletion*>((void*)data)->stringCompl(rc,value);
-}
-void asyncCompletion(int rc,const String_vector *strings, const void *data){
- assert("Completion data is NULL"&&data);
- static_cast<AsyncCompletion*>((void*)data)->stringsCompl(rc,strings);
-}
-void asyncCompletion(int rc, const void *data){
- assert("Completion data is NULL"&&data);
- static_cast<AsyncCompletion*>((void*)data)->voidCompl(rc);
-}
-
-// *****************************************************************************
-// a predicate implementation
-bool IOThreadStopped::operator()() const{
-#ifdef THREADED
- adaptor_threads* adaptor=(adaptor_threads*)zh_->adaptor_priv;
- return CheckedPthread::isTerminated(adaptor->io);
-#else
- assert("IOThreadStopped predicate is only for use with THREADED client"&& false);
- return false;
-#endif
-}
-
-//******************************************************************************
-//
-DECLARE_WRAPPER(int,flush_send_queue,(zhandle_t*zh, int timeout))
-{
- if(!Mock_flush_send_queue::mock_)
- return CALL_REAL(flush_send_queue,(zh,timeout));
- return Mock_flush_send_queue::mock_->call(zh,timeout);
-}
-
-Mock_flush_send_queue* Mock_flush_send_queue::mock_=0;
-
-//******************************************************************************
-//
-DECLARE_WRAPPER(int32_t,get_xid,())
-{
- if(!Mock_get_xid::mock_)
- return CALL_REAL(get_xid,());
- return Mock_get_xid::mock_->call();
-}
-
-Mock_get_xid* Mock_get_xid::mock_=0;
-
-//******************************************************************************
-// activateWatcher mock
-
-DECLARE_WRAPPER(void,activateWatcher,(zhandle_t *zh, watcher_registration_t* reg, int rc))
-{
- if(!Mock_activateWatcher::mock_){
- CALL_REAL(activateWatcher,(zh, reg,rc));
- }else{
- Mock_activateWatcher::mock_->call(zh, reg,rc);
- }
-}
-Mock_activateWatcher* Mock_activateWatcher::mock_=0;
-
-class ActivateWatcherWrapper: public Mock_activateWatcher{
-public:
- ActivateWatcherWrapper():ctx_(0),activated_(false){}
-
- virtual void call(zhandle_t *zh, watcher_registration_t* reg, int rc){
- CALL_REAL(activateWatcher,(zh, reg,rc));
- synchronized(mx_);
- if(reg->context==ctx_){
- activated_=true;
- ctx_=0;
- }
- }
-
- void setContext(void* ctx){
- synchronized(mx_);
- ctx_=ctx;
- activated_=false;
- }
-
- SyncedBoolCondition isActivated() const{
- return SyncedBoolCondition(activated_,mx_);
- }
- mutable Mutex mx_;
- void* ctx_;
- bool activated_;
-};
-
-WatcherActivationTracker::WatcherActivationTracker():
- wrapper_(new ActivateWatcherWrapper)
-{
-}
-
-WatcherActivationTracker::~WatcherActivationTracker(){
- delete wrapper_;
-}
-
-void WatcherActivationTracker::track(void* ctx){
- wrapper_->setContext(ctx);
-}
-
-SyncedBoolCondition WatcherActivationTracker::isWatcherActivated() const{
- return wrapper_->isActivated();
-}
-
-//******************************************************************************
-//
-DECLARE_WRAPPER(void,deliverWatchers,(zhandle_t* zh,int type,int state, const char* path, watcher_object_list_t **list))
-{
- if(!Mock_deliverWatchers::mock_){
- CALL_REAL(deliverWatchers,(zh,type,state,path, list));
- }else{
- Mock_deliverWatchers::mock_->call(zh,type,state,path, list);
- }
-}
-
-Mock_deliverWatchers* Mock_deliverWatchers::mock_=0;
-
-struct RefCounterValue{
- RefCounterValue(zhandle_t* const& zh,int32_t expectedCounter,Mutex& mx):
- zh_(zh),expectedCounter_(expectedCounter),mx_(mx){}
- bool operator()() const{
- {
- synchronized(mx_);
- if(zh_==0)
- return false;
- }
- return inc_ref_counter(zh_,0)==expectedCounter_;
- }
- zhandle_t* const& zh_;
- int32_t expectedCounter_;
- Mutex& mx_;
-};
-
-
-class DeliverWatchersWrapper: public Mock_deliverWatchers{
-public:
- DeliverWatchersWrapper(int type,int state,bool terminate):
- type_(type),state_(state),
- allDelivered_(false),terminate_(terminate),zh_(0),deliveryCounter_(0){}
- virtual void call(zhandle_t* zh,int type,int state, const char* path, watcher_object_list **list){
- {
- synchronized(mx_);
- zh_=zh;
- allDelivered_=false;
- }
- CALL_REAL(deliverWatchers,(zh,type,state,path, list));
- if(type_==type && state_==state){
- if(terminate_){
- // prevent zhandle_t from being prematurely distroyed;
- // this will also ensure that zookeeper_close() cleanups the thread
- // resources by calling finish_adaptor()
- inc_ref_counter(zh,1);
- terminateZookeeperThreads(zh);
- }
- synchronized(mx_);
- allDelivered_=true;
- deliveryCounter_++;
- }
- }
- SyncedBoolCondition isDelivered() const{
- if(terminate_){
- int i=ensureCondition(RefCounterValue(zh_,1,mx_),1000);
- assert(i<1000);
- }
- return SyncedBoolCondition(allDelivered_,mx_);
- }
- void resetDeliveryCounter(){
- synchronized(mx_);
- deliveryCounter_=0;
- }
- SyncedIntegerEqual deliveryCounterEquals(int expected) const{
- if(terminate_){
- int i=ensureCondition(RefCounterValue(zh_,1,mx_),1000);
- assert(i<1000);
- }
- return SyncedIntegerEqual(deliveryCounter_,expected,mx_);
- }
- int type_;
- int state_;
- mutable Mutex mx_;
- bool allDelivered_;
- bool terminate_;
- zhandle_t* zh_;
- int deliveryCounter_;
-};
-
-WatcherDeliveryTracker::WatcherDeliveryTracker(
- int type,int state,bool terminateCompletionThread):
- deliveryWrapper_(new DeliverWatchersWrapper(
- type,state,terminateCompletionThread)){
-}
-
-WatcherDeliveryTracker::~WatcherDeliveryTracker(){
- delete deliveryWrapper_;
-}
-
-SyncedBoolCondition WatcherDeliveryTracker::isWatcherProcessingCompleted() const{
- return deliveryWrapper_->isDelivered();
-}
-
-void WatcherDeliveryTracker::resetDeliveryCounter(){
- deliveryWrapper_->resetDeliveryCounter();
-}
-
-SyncedIntegerEqual WatcherDeliveryTracker::deliveryCounterEquals(int expected) const{
- return deliveryWrapper_->deliveryCounterEquals(expected);
-}
-
-//******************************************************************************
-//
-string HandshakeResponse::toString() const {
- string buf;
- int32_t tmp=htonl(protocolVersion);
- buf.append((char*)&tmp,sizeof(tmp));
- tmp=htonl(timeOut);
- buf.append((char*)&tmp,sizeof(tmp));
- int64_t tmp64=zoo_htonll(sessionId);
- buf.append((char*)&tmp64,sizeof(sessionId));
- tmp=htonl(passwd_len);
- buf.append((char*)&tmp,sizeof(tmp));
- buf.append(passwd,sizeof(passwd));
- // finally set the buffer length
- tmp=htonl(buf.size()+sizeof(tmp));
- buf.insert(0,(char*)&tmp, sizeof(tmp));
- return buf;
-}
-
-string ZooGetResponse::toString() const{
- oarchive* oa=create_buffer_oarchive();
-
- ReplyHeader h = {xid_,1,ZOK};
- serialize_ReplyHeader(oa, "hdr", &h);
-
- GetDataResponse resp;
- char buf[1024];
- assert("GetDataResponse is too long"&&data_.size()<=sizeof(buf));
- resp.data.len=data_.size();
- resp.data.buff=buf;
- data_.copy(resp.data.buff, data_.size());
- resp.stat=stat_;
- serialize_GetDataResponse(oa, "reply", &resp);
- int32_t len=htonl(get_buffer_len(oa));
- string res((char*)&len,sizeof(len));
- res.append(get_buffer(oa),get_buffer_len(oa));
-
- close_buffer_oarchive(&oa,1);
- return res;
-}
-
-string ZooStatResponse::toString() const{
- oarchive* oa=create_buffer_oarchive();
-
- ReplyHeader h = {xid_,1,rc_};
- serialize_ReplyHeader(oa, "hdr", &h);
-
- SetDataResponse resp;
- resp.stat=stat_;
- serialize_SetDataResponse(oa, "reply", &resp);
- int32_t len=htonl(get_buffer_len(oa));
- string res((char*)&len,sizeof(len));
- res.append(get_buffer(oa),get_buffer_len(oa));
-
- close_buffer_oarchive(&oa,1);
- return res;
-}
-
-string ZooGetChildrenResponse::toString() const{
- oarchive* oa=create_buffer_oarchive();
-
- ReplyHeader h = {xid_,1,rc_};
- serialize_ReplyHeader(oa, "hdr", &h);
-
- GetChildrenResponse resp;
- // populate the string vector
- allocate_String_vector(&resp.children,strings_.size());
- for(int i=0;i<(int)strings_.size();++i)
- resp.children.data[i]=strdup(strings_[i].c_str());
- serialize_GetChildrenResponse(oa, "reply", &resp);
- deallocate_GetChildrenResponse(&resp);
-
- int32_t len=htonl(get_buffer_len(oa));
- string res((char*)&len,sizeof(len));
- res.append(get_buffer(oa),get_buffer_len(oa));
-
- close_buffer_oarchive(&oa,1);
- return res;
-}
-
-string ZNodeEvent::toString() const{
- oarchive* oa=create_buffer_oarchive();
- struct WatcherEvent evt = {type_,0,(char*)path_.c_str()};
- struct ReplyHeader h = {WATCHER_EVENT_XID,0,ZOK };
-
- serialize_ReplyHeader(oa, "hdr", &h);
- serialize_WatcherEvent(oa, "event", &evt);
-
- int32_t len=htonl(get_buffer_len(oa));
- string res((char*)&len,sizeof(len));
- res.append(get_buffer(oa),get_buffer_len(oa));
-
- close_buffer_oarchive(&oa,1);
- return res;
-}
-
-string PingResponse::toString() const{
- oarchive* oa=create_buffer_oarchive();
-
- ReplyHeader h = {PING_XID,1,ZOK};
- serialize_ReplyHeader(oa, "hdr", &h);
-
- int32_t len=htonl(get_buffer_len(oa));
- string res((char*)&len,sizeof(len));
- res.append(get_buffer(oa),get_buffer_len(oa));
-
- close_buffer_oarchive(&oa,1);
- return res;
-}
-
-//******************************************************************************
-// Zookeeper server simulator
-//
-bool ZookeeperServer::hasMoreRecv() const{
- return recvHasMore.get()!=0 || connectionLost;
-}
-
-ssize_t ZookeeperServer::callRecv(int s,void *buf,size_t len,int flags){
- if(connectionLost){
- recvReturnBuffer.erase();
- return 0;
- }
- // done transmitting the current buffer?
- if(recvReturnBuffer.size()==0){
- synchronized(recvQMx);
- if(recvQueue.empty()){
- recvErrno=EAGAIN;
- return Mock_socket::callRecv(s,buf,len,flags);
- }
- --recvHasMore;
- Element& el=recvQueue.front();
- if(el.first!=0){
- recvReturnBuffer=el.first->toString();
- delete el.first;
- }
- recvErrno=el.second;
- recvQueue.pop_front();
- }
- return Mock_socket::callRecv(s,buf,len,flags);
-}
-
-void ZookeeperServer::onMessageReceived(const RequestHeader& rh, iarchive* ia){
- // no-op by default
-}
-
-void ZookeeperServer::notifyBufferSent(const std::string& buffer){
- if(HandshakeRequest::isValid(buffer)){
- // could be a connect request
- auto_ptr<HandshakeRequest> req(HandshakeRequest::parse(buffer));
- if(req.get()!=0){
- // handle the handshake
- int64_t sessId=sessionExpired?req->sessionId+1:req->sessionId;
- sessionExpired=false;
- addRecvResponse(new HandshakeResponse(sessId));
- return;
- }
- // not a connect request -- fall thru
- }
- // parse the buffer to extract the request type and its xid
- iarchive *ia=create_buffer_iarchive((char*)buffer.data(), buffer.size());
- RequestHeader rh;
- deserialize_RequestHeader(ia,"hdr",&rh);
- // notify the "server" a client request has arrived
- if (rh.xid == -8) {
- Element e = Element(new ZooStatResponse,0);
- e.first->setXID(-8);
- addRecvResponse(e);
- close_buffer_iarchive(&ia);
- return;
- } else {
- onMessageReceived(rh,ia);
- }
- close_buffer_iarchive(&ia);
- if(rh.type==ZOO_CLOSE_OP){
- ++closeSent;
- return; // no reply for close requests
- }
- // get the next response from the response queue and append it to the receive list
- Element e;
- {
- synchronized(respQMx);
- if(respQueue.empty())
- return;
- e=respQueue.front();
- respQueue.pop_front();
- }
- e.first->setXID(rh.xid);
- addRecvResponse(e);
-}
-
-void forceConnected(zhandle_t* zh){
- // simulate connected state
- zh->state=ZOO_CONNECTED_STATE;
- zh->fd=ZookeeperServer::FD;
- zh->input_buffer=0;
- gettimeofday(&zh->last_recv,0);
- gettimeofday(&zh->last_send,0);
-}
-
-void terminateZookeeperThreads(zhandle_t* zh){
- // this will cause the zookeeper threads to terminate
- zh->close_requested=1;
-}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/ZKMocks.h
----------------------------------------------------------------------
diff --git a/src/c/tests/ZKMocks.h b/src/c/tests/ZKMocks.h
deleted file mode 100644
index fbcfc4f..0000000
--- a/src/c/tests/ZKMocks.h
+++ /dev/null
@@ -1,509 +0,0 @@
-/**
- * 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 ZKMOCKS_H_
-#define ZKMOCKS_H_
-
-#include <zookeeper.h>
-#include "src/zk_adaptor.h"
-
-#include "Util.h"
-#include "LibCMocks.h"
-#include "MocksBase.h"
-
-// *****************************************************************************
-// sets internal zhandle_t members to certain values to simulate the client
-// connected state. This function should only be used with the single-threaded
-// Async API tests!
-void forceConnected(zhandle_t* zh);
-
-/**
- * Gracefully terminates zookeeper I/O and completion threads.
- */
-void terminateZookeeperThreads(zhandle_t* zh);
-
-// *****************************************************************************
-// Abstract watcher action
-struct SyncedBoolCondition;
-
-class WatcherAction{
-public:
- WatcherAction():triggered_(false){}
- virtual ~WatcherAction(){}
-
- virtual void onSessionExpired(zhandle_t*){}
- virtual void onConnectionEstablished(zhandle_t*){}
- virtual void onConnectionLost(zhandle_t*){}
- virtual void onNodeValueChanged(zhandle_t*,const char* path){}
- virtual void onNodeDeleted(zhandle_t*,const char* path){}
- virtual void onChildChanged(zhandle_t*,const char* path){}
-
- SyncedBoolCondition isWatcherTriggered() const;
- void setWatcherTriggered(){
- synchronized(mx_);
- triggered_=true;
- }
-
-protected:
- mutable Mutex mx_;
- bool triggered_;
-};
-// zh->context is a pointer to a WatcherAction instance
-// based on the event type and state, the watcher calls a specific watcher
-// action method
-void activeWatcher(zhandle_t *zh, int type, int state, const char *path,void* ctx);
-
-// *****************************************************************************
-// a set of async completion signatures
-class AsyncCompletion{
-public:
- virtual ~AsyncCompletion(){}
- virtual void aclCompl(int rc, ACL_vector *acl,Stat *stat){}
- virtual void dataCompl(int rc, const char *value, int len, const Stat *stat){}
- virtual void statCompl(int rc, const Stat *stat){}
- virtual void stringCompl(int rc, const char *value){}
- virtual void stringsCompl(int rc,const String_vector *strings){}
- virtual void voidCompl(int rc){}
-};
-void asyncCompletion(int rc, ACL_vector *acl,Stat *stat, const void *data);
-void asyncCompletion(int rc, const char *value, int len, const Stat *stat,
- const void *data);
-void asyncCompletion(int rc, const Stat *stat, const void *data);
-void asyncCompletion(int rc, const char *value, const void *data);
-void asyncCompletion(int rc,const String_vector *strings, const void *data);
-void asyncCompletion(int rc, const void *data);
-
-// *****************************************************************************
-// some common predicates to use with ensureCondition():
-// checks if the connection is established
-struct ClientConnected{
- ClientConnected(zhandle_t* zh):zh_(zh){}
- bool operator()() const{
- return zoo_state(zh_)==ZOO_CONNECTED_STATE;
- }
- zhandle_t* zh_;
-};
-// check in the session expired
-struct SessionExpired{
- SessionExpired(zhandle_t* zh):zh_(zh){}
- bool operator()() const{
- return zoo_state(zh_)==ZOO_EXPIRED_SESSION_STATE;
- }
- zhandle_t* zh_;
-};
-// checks if the IO thread has stopped; CheckedPthread must be active
-struct IOThreadStopped{
- IOThreadStopped(zhandle_t* zh):zh_(zh){}
- bool operator()() const;
- zhandle_t* zh_;
-};
-
-// a synchronized boolean condition
-struct SyncedBoolCondition{
- SyncedBoolCondition(const bool& cond,Mutex& mx):cond_(cond),mx_(mx){}
- bool operator()() const{
- synchronized(mx_);
- return cond_;
- }
- const bool& cond_;
- Mutex& mx_;
-};
-
-// a synchronized integer comparison
-struct SyncedIntegerEqual{
- SyncedIntegerEqual(const int& cond,int expected,Mutex& mx):
- cond_(cond),expected_(expected),mx_(mx){}
- bool operator()() const{
- synchronized(mx_);
- return cond_==expected_;
- }
- const int& cond_;
- const int expected_;
- Mutex& mx_;
-};
-
-// *****************************************************************************
-// make sure to call zookeeper_close() even in presence of exceptions
-struct CloseFinally{
- CloseFinally(zhandle_t** zh):zh_(zh){}
- ~CloseFinally(){
- execute();
- }
- int execute(){
- if(zh_==0)return ZOK;
- zhandle_t* lzh=*zh_;
- *zh_=0;
- disarm();
- return zookeeper_close(lzh);
- }
- void disarm(){zh_=0;}
- zhandle_t ** zh_;
-};
-
-struct TestClientId: clientid_t{
- static const int SESSION_ID=123456789;
- static const char* PASSWD;
- TestClientId(){
- client_id=SESSION_ID;
- memcpy(passwd,PASSWD,sizeof(passwd));
- }
-};
-
-// *****************************************************************************
-// special client id recongnized by the ZK server simulator
-extern TestClientId testClientId;
-#define TEST_CLIENT_ID &testClientId
-
-// *****************************************************************************
-//
-struct HandshakeRequest: public connect_req
-{
- static HandshakeRequest* parse(const std::string& buf);
- static bool isValid(const std::string& buf){
- // this is just quick and dirty check before we go and parse the request
- return buf.size()==HANDSHAKE_REQ_SIZE;
- }
-};
-
-// *****************************************************************************
-// flush_send_queue
-class Mock_flush_send_queue: public Mock
-{
-public:
- Mock_flush_send_queue():counter(0),callReturns(ZOK){mock_=this;}
- ~Mock_flush_send_queue(){mock_=0;}
-
- int counter;
- int callReturns;
- virtual int call(zhandle_t* zh, int timeout){
- counter++;
- return callReturns;
- }
-
- static Mock_flush_send_queue* mock_;
-};
-
-// *****************************************************************************
-// get_xid
-class Mock_get_xid: public Mock
-{
-public:
- static const int32_t XID=123456;
- Mock_get_xid(int retValue=XID):callReturns(retValue){mock_=this;}
- ~Mock_get_xid(){mock_=0;}
-
- int callReturns;
- virtual int call(){
- return callReturns;
- }
-
- static Mock_get_xid* mock_;
-};
-
-// *****************************************************************************
-// activateWatcher
-class Mock_activateWatcher: public Mock{
-public:
- Mock_activateWatcher(){mock_=this;}
- virtual ~Mock_activateWatcher(){mock_=0;}
-
- virtual void call(zhandle_t *zh, watcher_registration_t* reg, int rc){}
- static Mock_activateWatcher* mock_;
-};
-
-class ActivateWatcherWrapper;
-class WatcherActivationTracker{
-public:
- WatcherActivationTracker();
- ~WatcherActivationTracker();
-
- void track(void* ctx);
- SyncedBoolCondition isWatcherActivated() const;
-private:
- ActivateWatcherWrapper* wrapper_;
-};
-
-// *****************************************************************************
-// deliverWatchers
-class Mock_deliverWatchers: public Mock{
-public:
- Mock_deliverWatchers(){mock_=this;}
- virtual ~Mock_deliverWatchers(){mock_=0;}
-
- virtual void call(zhandle_t* zh,int type,int state, const char* path, watcher_object_list **){}
- static Mock_deliverWatchers* mock_;
-};
-
-class DeliverWatchersWrapper;
-class WatcherDeliveryTracker{
-public:
- // filters deliveries by state and type
- WatcherDeliveryTracker(int type,int state,bool terminateCompletionThread=true);
- ~WatcherDeliveryTracker();
-
- // if the thread termination requested (see the ctor params)
- // this function will wait for the I/O and completion threads to
- // terminate before returning a SyncBoolCondition instance
- SyncedBoolCondition isWatcherProcessingCompleted() const;
- void resetDeliveryCounter();
- SyncedIntegerEqual deliveryCounterEquals(int expected) const;
-private:
- DeliverWatchersWrapper* deliveryWrapper_;
-};
-
-// *****************************************************************************
-// a zookeeper Stat wrapper
-struct NodeStat: public Stat
-{
- NodeStat(){
- czxid=0;
- mzxid=0;
- ctime=0;
- mtime=0;
- version=1;
- cversion=0;
- aversion=0;
- ephemeralOwner=0;
- }
- NodeStat(const Stat& other){
- memcpy(this,&other,sizeof(*this));
- }
-};
-
-// *****************************************************************************
-// Abstract server Response
-class Response
-{
-public:
- virtual ~Response(){}
-
- virtual void setXID(int32_t xid){}
- // this method is used by the ZookeeperServer class to serialize
- // the instance of Response
- virtual std::string toString() const =0;
-};
-
-// *****************************************************************************
-// Handshake response
-class HandshakeResponse: public Response
-{
-public:
- HandshakeResponse(int64_t sessId=1)
- :protocolVersion(1),timeOut(10000),sessionId(sessId),passwd_len(sizeof(passwd))
- {
- memcpy(passwd,"1234567890123456",sizeof(passwd));
- }
- int32_t protocolVersion;
- int32_t timeOut;
- int64_t sessionId;
- int32_t passwd_len;
- char passwd[16];
- virtual std::string toString() const ;
-};
-
-// zoo_get() response
-class ZooGetResponse: public Response
-{
-public:
- ZooGetResponse(const char* data, int len,int32_t xid=0,int rc=ZOK,const Stat& stat=NodeStat())
- :xid_(xid),data_(data,len),rc_(rc),stat_(stat)
- {
- }
- virtual std::string toString() const;
- virtual void setXID(int32_t xid) {xid_=xid;}
-
-private:
- int32_t xid_;
- std::string data_;
- int rc_;
- Stat stat_;
-};
-
-// zoo_exists(), zoo_set() response
-class ZooStatResponse: public Response
-{
-public:
- ZooStatResponse(int32_t xid=0,int rc=ZOK,const Stat& stat=NodeStat())
- :xid_(xid),rc_(rc),stat_(stat)
- {
- }
- virtual std::string toString() const;
- virtual void setXID(int32_t xid) {xid_=xid;}
-
-private:
- int32_t xid_;
- int rc_;
- Stat stat_;
-};
-
-// zoo_get_children()
-class ZooGetChildrenResponse: public Response
-{
-public:
- typedef std::vector<std::string> StringVector;
- ZooGetChildrenResponse(const StringVector& v,int rc=ZOK):
- xid_(0),strings_(v),rc_(rc)
- {
- }
-
- virtual std::string toString() const;
- virtual void setXID(int32_t xid) {xid_=xid;}
-
- int32_t xid_;
- StringVector strings_;
- int rc_;
-};
-
-// PING response
-class PingResponse: public Response
-{
-public:
- virtual std::string toString() const;
-};
-
-// watcher znode event
-class ZNodeEvent: public Response
-{
-public:
- ZNodeEvent(int type,const char* path):type_(type),path_(path){}
-
- virtual std::string toString() const;
-
-private:
- int type_;
- std::string path_;
-};
-
-// ****************************************************************************
-// Zookeeper server simulator
-
-class ZookeeperServer: public Mock_socket
-{
-public:
- ZookeeperServer():
- serverDownSkipCount_(-1),sessionExpired(false),connectionLost(false)
- {
- connectReturns=-1;
- connectErrno=EWOULDBLOCK;
- }
- virtual ~ZookeeperServer(){
- clearRecvQueue();
- clearRespQueue();
- }
- virtual int callClose(int fd){
- if(fd!=FD)
- return LIBC_SYMBOLS.close(fd);
- clearRecvQueue();
- clearRespQueue();
- return Mock_socket::callClose(fd);
- }
- // connection handling
- // what to do when the handshake request comes in?
- int serverDownSkipCount_;
- // this will cause getsockopt(zh->fd,SOL_SOCKET,SO_ERROR,&error,&len) return
- // a failure after skipCount dropped to zero, thus simulating a server down
- // condition
- // passing skipCount==-1 will make every connect attempt succeed
- void setServerDown(int skipCount=0){
- serverDownSkipCount_=skipCount;
- optvalSO_ERROR=0;
- }
- virtual void setSO_ERROR(void *optval,socklen_t len){
- if(serverDownSkipCount_!=-1){
- if(serverDownSkipCount_==0)
- optvalSO_ERROR=ECONNREFUSED;
- else
- serverDownSkipCount_--;
- }
- Mock_socket::setSO_ERROR(optval,len);
- }
-
- // this is a trigger that gets reset back to false
- // a connect request will return a non-matching session id thus causing
- // the client throw SESSION_EXPIRED
- volatile bool sessionExpired;
- void returnSessionExpired(){ sessionExpired=true; }
-
- // this is a one shot trigger that gets reset back to false
- // next recv call will return 0 length, thus simulating a connecton loss
- volatile bool connectionLost;
- void setConnectionLost() {connectionLost=true;}
-
- // recv
- // this queue is used for server responses: client's recv() system call
- // returns next available message from this queue
- typedef std::pair<Response*,int> Element;
- typedef std::deque<Element> ResponseList;
- ResponseList recvQueue;
- mutable Mutex recvQMx;
- AtomicInt recvHasMore;
- ZookeeperServer& addRecvResponse(Response* resp, int errnum=0){
- synchronized(recvQMx);
- recvQueue.push_back(Element(resp,errnum));
- ++recvHasMore;
- return *this;
- }
- ZookeeperServer& addRecvResponse(int errnum){
- synchronized(recvQMx);
- recvQueue.push_back(Element(0,errnum));
- ++recvHasMore;
- return *this;
- }
- ZookeeperServer& addRecvResponse(const Element& e){
- synchronized(recvQMx);
- recvQueue.push_back(e);
- ++recvHasMore;
- return *this;
- }
- void clearRecvQueue(){
- synchronized(recvQMx);
- recvHasMore=0;
- for(unsigned i=0; i<recvQueue.size();i++)
- delete recvQueue[i].first;
- recvQueue.clear();
- }
-
- virtual ssize_t callRecv(int s,void *buf,size_t len,int flags);
- virtual bool hasMoreRecv() const;
-
- // the operation response queue holds zookeeper operation responses till the
- // operation request has been sent to the server. After that, the operation
- // response gets moved on to the recv queue (see above) ready to be read by
- // the next recv() system call
- // send operation doesn't try to match request to the response
- ResponseList respQueue;
- mutable Mutex respQMx;
- ZookeeperServer& addOperationResponse(Response* resp, int errnum=0){
- synchronized(respQMx);
- respQueue.push_back(Element(resp,errnum));
- return *this;
- }
- void clearRespQueue(){
- synchronized(respQMx);
- for(unsigned i=0; i<respQueue.size();i++)
- delete respQueue[i].first;
- respQueue.clear();
- }
- AtomicInt closeSent;
- virtual void notifyBufferSent(const std::string& buffer);
- // simulates an arrival of a client request
- // a callback to be implemented by subclasses (no-op by default)
- virtual void onMessageReceived(const RequestHeader& rh, iarchive* ia);
-};
-
-#endif /*ZKMOCKS_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/wrappers-mt.opt
----------------------------------------------------------------------
diff --git a/src/c/tests/wrappers-mt.opt b/src/c/tests/wrappers-mt.opt
deleted file mode 100644
index 01046fb..0000000
--- a/src/c/tests/wrappers-mt.opt
+++ /dev/null
@@ -1,3 +0,0 @@
--Wl,--wrap -Wl,pthread_mutex_lock
--Wl,--wrap -Wl,pthread_mutex_trylock
--Wl,--wrap -Wl,pthread_mutex_unlock
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/wrappers.opt
----------------------------------------------------------------------
diff --git a/src/c/tests/wrappers.opt b/src/c/tests/wrappers.opt
deleted file mode 100644
index bce192f..0000000
--- a/src/c/tests/wrappers.opt
+++ /dev/null
@@ -1,7 +0,0 @@
--Wl,--wrap -Wl,calloc
--Wl,--wrap -Wl,free
--Wl,--wrap -Wl,flush_send_queue
--Wl,--wrap -Wl,get_xid
--Wl,--wrap -Wl,deliverWatchers
--Wl,--wrap -Wl,activateWatcher
--Wl,--wrap -Wl,realloc
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/zkServer.sh
----------------------------------------------------------------------
diff --git a/src/c/tests/zkServer.sh b/src/c/tests/zkServer.sh
deleted file mode 100755
index 4872fba..0000000
--- a/src/c/tests/zkServer.sh
+++ /dev/null
@@ -1,161 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-# This is the port where zookeeper server runs on.
-ZOOPORT=22181
-
-if [ "x$1" == "x" ]
-then
- echo "USAGE: $0 startClean|start|stop hostPorts"
- exit 2
-fi
-
-case "`uname`" in
- CYGWIN*) cygwin=true ;;
- *) cygwin=false ;;
-esac
-
-if [ "x$1" == "xstartClean" ]
-then
- if [ "x${base_dir}" == "x" ]
- then
- rm -rf /tmp/zkdata
- else
- rm -rf "${base_dir}/build/tmp"
- fi
-fi
-
-if $cygwin
-then
- # cygwin has a "kill" in the shell itself, gets confused
- KILL=/bin/kill
-else
- KILL=kill
-fi
-
-# Make sure nothing is left over from before
-if [ -r "/tmp/zk.pid" ]
-then
-pid=`cat /tmp/zk.pid`
-$KILL -9 $pid
-rm -f /tmp/zk.pid
-fi
-
-if [ -r "${base_dir}/build/tmp/zk.pid" ]
-then
-pid=`cat "${base_dir}/build/tmp/zk.pid"`
-$KILL -9 $pid
-rm -f "${base_dir}/build/tmp/zk.pid"
-fi
-
-# [ZOOKEEPER-820] If lsof command is present, look for a process listening
-# on ZOOPORT and kill it.
-which lsof &> /dev/null
-if [ $? -eq 0 ]
-then
- pid=`lsof -i :$ZOOPORT | grep LISTEN | awk '{print $2}'`
- if [ -n "$pid" ]
- then
- $KILL -9 $pid
- fi
-fi
-
-if [ "x${base_dir}" == "x" ]
-then
-zk_base="../../"
-else
-zk_base="${base_dir}"
-fi
-
-CLASSPATH="$CLASSPATH:${zk_base}/build/classes"
-CLASSPATH="$CLASSPATH:${zk_base}/conf"
-
-for i in "${zk_base}"/build/lib/*.jar
-do
- CLASSPATH="$CLASSPATH:$i"
-done
-
-for i in "${zk_base}"/src/java/lib/*.jar
-do
- CLASSPATH="$CLASSPATH:$i"
-done
-
-CLASSPATH="$CLASSPATH:${CLOVER_HOME}/lib/clover.jar"
-
-if $cygwin
-then
- CLASSPATH=`cygpath -wp "$CLASSPATH"`
-fi
-
-case $1 in
-start|startClean)
- if [ "x${base_dir}" == "x" ]
- then
- mkdir -p /tmp/zkdata
- java -cp "$CLASSPATH" org.apache.zookeeper.server.ZooKeeperServerMain $ZOOPORT /tmp/zkdata 3000 $ZKMAXCNXNS &> /tmp/zk.log &
- pid=$!
- echo -n $! > /tmp/zk.pid
- else
- mkdir -p "${base_dir}/build/tmp/zkdata"
- java -cp "$CLASSPATH" org.apache.zookeeper.server.ZooKeeperServerMain $ZOOPORT "${base_dir}/build/tmp/zkdata" 3000 $ZKMAXCNXNS &> "${base_dir}/build/tmp/zk.log" &
- pid=$!
- echo -n $pid > "${base_dir}/build/tmp/zk.pid"
- fi
-
- # wait max 120 seconds for server to be ready to server clients
- # this handles testing on slow hosts
- success=false
- for i in {1..120}
- do
- if ps -p $pid > /dev/null
- then
- java -cp "$CLASSPATH" org.apache.zookeeper.ZooKeeperMain -server localhost:$ZOOPORT ls / > /dev/null 2>&1
- if [ $? -ne 0 ]
- then
- # server not up yet - wait
- sleep 1
- else
- # server is up and serving client connections
- success=true
- break
- fi
- else
- # server died - exit now
- echo -n " ZooKeeper server process failed"
- break
- fi
- done
-
- if $success
- then
- ## in case for debug, but generally don't use as it messes up the
- ## console test output
- echo -n " ZooKeeper server started"
- else
- echo -n " ZooKeeper server NOT started"
- fi
-
- ;;
-stop)
- # Already killed above
- ;;
-*)
- echo "Unknown command " + $1
- exit 2
-esac
-
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/CMakeLists.txt b/zookeeper-client/zookeeper-client-c/CMakeLists.txt
new file mode 100644
index 0000000..e7dfbeb
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/CMakeLists.txt
@@ -0,0 +1,237 @@
+# 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.
+
+cmake_minimum_required(VERSION 3.6)
+
+project(zookeeper VERSION 3.4.13)
+set(email user@zookeeper.apache.org)
+set(description "zookeeper C client")
+
+# general options
+include_directories(include tests generated ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
+if(UNIX)
+ add_compile_options(-Wall -fPIC)
+elseif(WIN32)
+ add_compile_options(/W3)
+endif()
+add_definitions(-DUSE_STATIC_LIB)
+
+# TODO: Enable /WX and /W4 on Windows. Currently there are ~1000 warnings.
+# TODO: Add Solaris support.
+# TODO: Add a shared library option.
+# TODO: Specify symbols to export.
+# TODO: Generate doxygen documentation.
+
+# Sync API option
+option(WANT_SYNCAPI "Enables Sync API support" ON)
+if(WANT_SYNCAPI)
+ add_definitions(-DTHREADED)
+ if(WIN32)
+ # Note that the generator expression ensures that `/MTd` is used when Debug
+ # configurations are built.
+ add_compile_options(/MT$<$<CONFIG:Debug>:d>)
+ endif()
+endif()
+
+# CppUnit option
+if(WIN32 OR APPLE)
+ # The tests do not yet compile on Windows or macOS,
+ # so we set this to off by default.
+ #
+ # Note that CMake does not have expressions except in conditionals,
+ # so we're left with this if/else/endif pattern.
+ set(DEFAULT_WANT_CPPUNIT OFF)
+else()
+ set(DEFAULT_WANT_CPPUNIT ON)
+endif()
+option(WANT_CPPUNIT "Enables CppUnit and tests" ${DEFAULT_WANT_CPPUNIT})
+
+# The function `to_have(in out)` converts a header name like `arpa/inet.h`
+# into an Autotools style preprocessor definition `HAVE_ARPA_INET_H`.
+# This is then set or unset in `configure_file()` step.
+#
+# Note that CMake functions do not have return values; instead an "out"
+# variable must be passed, and explicitly set with parent scope.
+function(to_have in out)
+ string(TOUPPER ${in} str)
+ string(REGEX REPLACE "/|\\." "_" str ${str})
+ set(${out} "HAVE_${str}" PARENT_SCOPE)
+endfunction()
+
+# include file checks
+foreach(f generated/zookeeper.jute.h generated/zookeeper.jute.c)
+ if(EXISTS "${CMAKE_SOURCE_DIR}/${f}")
+ to_have(${f} name)
+ set(${name} 1)
+ else()
+ message(FATAL_ERROR
+ "jute files are missing!\n"
+ "Please run 'ant compile_jute' while in the ZooKeeper top level directory.")
+ endif()
+endforeach()
+
+# header checks
+include(CheckIncludeFile)
+set(check_headers
+ arpa/inet.h
+ dlfcn.h
+ fcntl.h
+ inttypes.h
+ memory.h
+ netdb.h
+ netinet/in.h
+ stdint.h
+ stdlib.h
+ string.h
+ strings.h
+ sys/socket.h
+ sys/stat.h
+ sys/time.h
+ sys/types.h
+ unistd.h
+ sys/utsname.h)
+
+foreach(f ${check_headers})
+ to_have(${f} name)
+ check_include_file(${f} ${name})
+endforeach()
+
+# function checks
+include(CheckFunctionExists)
+set(check_functions
+ getcwd
+ gethostbyname
+ gethostname
+ getlogin
+ getpwuid_r
+ gettimeofday
+ getuid
+ memmove
+ memset
+ poll
+ socket
+ strchr
+ strdup
+ strerror
+ strtol)
+
+foreach(fn ${check_functions})
+ to_have(${fn} name)
+ check_function_exists(${fn} ${name})
+endforeach()
+
+# library checks
+set(check_libraries rt m pthread)
+foreach(lib ${check_libraries})
+ to_have("lib${lib}" name)
+ find_library(${name} ${lib})
+endforeach()
+
+# IPv6 check
+include(CheckStructHasMember)
+check_struct_has_member("struct sockaddr_in6" sin6_addr "netinet/in.h" ZOO_IPV6_ENABLED)
+
+# configure
+configure_file(cmake_config.h.in ${CMAKE_SOURCE_DIR}/include/config.h)
+
+# hashtable library
+set(hashtable_sources src/hashtable/hashtable_itr.c src/hashtable/hashtable.c)
+add_library(hashtable STATIC ${hashtable_sources})
+target_link_libraries(hashtable PUBLIC $<$<PLATFORM_ID:Linux>:m>)
+
+# zookeeper library
+set(zookeeper_sources
+ src/zookeeper.c
+ src/recordio.c
+ generated/zookeeper.jute.c
+ src/zk_log.c
+ src/zk_hashtable.c)
+
+if(WANT_SYNCAPI)
+ list(APPEND zookeeper_sources src/mt_adaptor.c)
+else()
+ list(APPEND zookeeper_sources src/st_adaptor.c)
+endif()
+
+if(WIN32)
+ list(APPEND zookeeper_sources src/winport.c)
+endif()
+
+add_library(zookeeper STATIC ${zookeeper_sources})
+target_link_libraries(zookeeper PUBLIC
+ hashtable
+ $<$<PLATFORM_ID:Linux>:rt> # clock_gettime
+ $<$<PLATFORM_ID:Windows>:ws2_32>) # Winsock 2.0
+
+if(WANT_SYNCAPI AND NOT WIN32)
+ find_package(Threads REQUIRED)
+ target_link_libraries(zookeeper PUBLIC Threads::Threads)
+endif()
+
+# cli executable
+add_executable(cli src/cli.c)
+target_link_libraries(cli zookeeper)
+
+# load_gen executable
+if(WANT_SYNCAPI AND NOT WIN32)
+ add_executable(load_gen src/load_gen.c)
+ target_link_libraries(load_gen zookeeper)
+endif()
+
+# tests
+set(test_sources
+ tests/TestDriver.cc
+ tests/LibCMocks.cc
+ tests/LibCSymTable.cc
+ tests/MocksBase.cc
+ tests/ZKMocks.cc
+ tests/Util.cc
+ tests/ThreadingUtil.cc
+ tests/TestZookeeperInit.cc
+ tests/TestZookeeperClose.cc
+ tests/TestClientRetry.cc
+ tests/TestOperations.cc
+ tests/TestMulti.cc
+ tests/TestWatchers.cc
+ tests/TestClient.cc)
+
+if(WANT_SYNCAPI)
+ list(APPEND test_sources tests/PthreadMocks.cc)
+endif()
+
+if(WANT_CPPUNIT)
+ add_executable(zktest ${test_sources})
+ target_compile_definitions(zktest
+ PRIVATE -DZKSERVER_CMD="${CMAKE_SOURCE_DIR}/tests/zkServer.sh")
+ # TODO: Use `find_library()` for `cppunit`.
+ target_link_libraries(zktest zookeeper cppunit dl)
+
+ # This reads the link flags from the file `tests/wrappers.opt` into
+ # the variable `symbol_wrappers` for use in `target_link_libraries`.
+ # It is a holdover from the original build system.
+ file(STRINGS tests/wrappers.opt symbol_wrappers)
+ if(WANT_SYNCAPI)
+ file(STRINGS tests/wrappers-mt.opt symbol_wrappers_mt)
+ endif()
+
+ target_link_libraries(zktest ${symbol_wrappers} ${symbol_wrappers_mt})
+
+ enable_testing()
+ add_test(NAME zktest_runner COMMAND zktest)
+ set_property(TEST zktest_runner PROPERTY ENVIRONMENT
+ "ZKROOT=${CMAKE_SOURCE_DIR}/../.."
+ "CLASSPATH=$CLASSPATH:$CLOVER_HOME/lib/clover.jar")
+endif()
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/ChangeLog
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/ChangeLog b/zookeeper-client/zookeeper-client-c/ChangeLog
new file mode 100644
index 0000000..c85a6c0
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/ChangeLog
@@ -0,0 +1,116 @@
+Release 2.1.1
+2008-04-30 Andrew Kornev <ak...@users.sourceforge.net>
+
+ * changed the distributino package name to "c-client-src"
+
+Release 2.1.0
+2008-04-30 Andrew Kornev <ak...@users.sourceforge.net>
+
+ * added the client latency diagnostics; the client prints a warning when the
+ reponse latency exceeds 20ms
+
+ * modified logging format to report the znode path for which the zookeeper
+ operation is called
+
+ * fixed a minor bug where error messages were missing for some of the newer
+ zookeeper error codes (ZCLOSING and ZNOTHING).
+
+ * improved logging by adding the XID to the message to make it easy to match
+ requests to responses
+
+ * fixed the bug causing sporadic session termination and timeouts
+
+ * added a new return code to zookeeper_process() -- ZNOTHING --
+ that indicates that the socket has no more data to read
+
+ * more unit tests added
+
+Release 1.1.3
+2008-02-07 Andrew Kornev <ak...@users.sourceforge.net>
+
+ * get_xid() is not thread-safe (xid initialization race condition
+ in the multi-threaded mode).
+
+ * the I/O thread doesn�t automatically terminate on AUTH_FAILURE and
+ SESSION_EXPIRED events.
+
+ * all session events should be processed on the completion thread.
+
+ * PING operation doesn�t atomically enqueue the completion and
+ send buffers like other operations do.
+
+ * corrected zookeeper_init() doxygen docs.
+
+ * new unit tests added.
+
+
+Release 1.1.2
+2008-01-24 Andrew Kornev <ak...@users.sourceforge.net>
+
+ * fixed a race condition caused by the code in zookeeper_process()
+ and free_completions() setting sc->complete to 1 without proper
+ synchronization;
+
+ * fixed zoo_get() not updating buffer_len value with the actual
+ buffer length on return; added missing enter_critical/leave_critical
+ calls to the async ZK operations.
+
+ * Replaced select() with poll() to fix the problem with the FD_SET
+ macro causing stack corruption for FDs higher than 1024
+
+ * Added zoo_set_log_stream() to the public API. The function allows
+ applications to specify a different log file.
+
+ * Removed unused declarations from zookeeper.h (ACL related)
+
+ * changed zoo_get() signature to take a pointer to buffer length.
+ The function sets the parameter to the actual data length upon return.
+
+ * the watcher callback now takes the zhandle as its first parameter. This
+ is to avoid a race condition in the multi-threaded client when a watcher
+ is called before zookeeper_init() has returned.
+
+ * fixed zookeeper_close() resource leaks and race conditions,
+ fixed the race condition causing xid mismatch.
+
+ * added support for cppunit, added new targets: "check" and "run-check"
+ to build and run unit tests.
+
+ * Changed the signature of zookeeper_init(): it now takes a context pointer
+ as a parameter. This is to avoid a race condition in the multi-threaded client.
+
+ * Using a self-pipe rather than SIGUSR1 to wake up select() in the I/O thread
+
+ * Added the doxygen target to the autoconf scripts
+
+ * Pulled out the logging functionality from zookeeper.c to zk_log.c/.h.
+ Fixed a minor issue with PING responses being unnecessarily put on
+ the completion queue rather than simply dropped. Make use of DLL_EXPORT
+ symbol for building shared lib on cygwin.
+
+ * Implemented new Zookeeper operation sync() to flush the leader channel
+ to ensure that all updates have reached the followers.
+
+ * Synchronous methods not being handled properly on disconnect
+
+ * breed: fixed an incorrect parameter passed to zookeeper API by
+ the Sync API wrapper functions
+
+ * breed: the set and delete commands now support both Sync and Async API.
+ Prefix the command name with an 'a' to call the Async API: aset, adelete
+
+ * Make sure mutexes and condition variables are properly initialized
+ and destroyed
+
+ * Fixed zookeeper_close() causing core dumps with mt_adaptor
+
+
+Release 1.0.0
+2007-11-27 Andrew Kornev <ak...@users.sourceforge.net>
+
+ * configure.ac and Makefile.am added support for GNU autotools
+
+ * recordio.c/.h updated jute IO routines to use bit-explicit integer types
+ (int32_t vs. int, and int64_t vs. long long)
+
+ * README rough draft
\ No newline at end of file
[07/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/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..ef32a10
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/cli.c
@@ -0,0 +1,697 @@
+/**
+ * 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_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_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, " 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, " 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 (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++;
+ if (async) {
+ rc = zoo_aset(zh, line, ptr, strlen(ptr), -1, my_stat_completion,
+ strdup(line));
+ } else {
+ struct Stat stat;
+ rc = zoo_set2(zh, line, ptr, strlen(ptr), -1, &stat);
+ }
+ 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 ")) {
+ int flags = 0;
+ line += 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));
+// }
+ 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;
+ }
+ if (async) {
+ rc = zoo_adelete(zh, line, -1, my_void_completion, strdup(line));
+ } else {
+ rc = zoo_delete(zh, line, -1);
+ }
+ 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;
+ FILE *fh;
+
+ if (argc < 2) {
+ fprintf(stderr,
+ "USAGE %s zookeeper_host_list [clientid_file|cmd:(ls|ls2|create|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);
+ }
+ }
+ }
+#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, 0, 0);
+ 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 (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/5694559d/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/5694559d/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..763357e
--- /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,hash(h,k));
+ pE = &(h->table[index]);
+ e = *pE;
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+ {
+ *pE = e->next;
+ h->entrycount--;
+ v = e->v;
+ freekey(e->k);
+ free(e);
+ return v;
+ }
+ pE = &(e->next);
+ e = e->next;
+ }
+ return NULL;
+}
+
+/*****************************************************************************/
+/* destroy */
+void
+hashtable_destroy(struct hashtable *h, int free_values)
+{
+ unsigned int i;
+ struct entry *e, *f;
+ struct entry **table = h->table;
+ if (free_values)
+ {
+ for (i = 0; i < h->tablelength; i++)
+ {
+ e = table[i];
+ while (NULL != e)
+ { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
+ }
+ }
+ else
+ {
+ for (i = 0; i < h->tablelength; i++)
+ {
+ e = table[i];
+ while (NULL != e)
+ { f = e; e = e->next; freekey(f->k); free(f); }
+ }
+ }
+ free(h->table);
+ free(h);
+}
+
+/*
+ * Copyright (c) 2002, Christopher Clark
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/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/5694559d/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/5694559d/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/5694559d/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/5694559d/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..546d5d1
--- /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){
+ 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(("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(("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(("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(("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(("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(("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(("Deleting %s",root));
+ rc=zoo_delete(zh,root,-1);
+ if(rc!=ZOK){
+ LOG_ERROR(("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(("Checking server connection..."));
+ ensureConnected();
+ if(cleaning==1){
+ int rc = 0;
+ deletedCounter=0;
+ rc=recursiveDelete(argv[2]);
+ if(rc==ZOK){
+ LOG_INFO(("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(("Creating children for path %s",argv[2]));
+ doCreateNodes(argv[2],nodeCount);
+ waitCounter();
+
+ LOG_INFO(("Starting the write cycle for path %s",argv[2]));
+ doWrites(argv[2],nodeCount);
+ waitCounter();
+ LOG_INFO(("Starting the read cycle for path %s",argv[2]));
+ doReads(argv[2],nodeCount);
+ waitCounter();
+
+ LOG_INFO(("Starting the delete cycle for path %s",argv[2]));
+ doDeletes(argv[2],nodeCount);
+ waitCounter();
+ }
+ zookeeper_close(zh);
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/src/mt_adaptor.c
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/mt_adaptor.c b/zookeeper-client/zookeeper-client-c/src/mt_adaptor.c
new file mode 100644
index 0000000..52d86d5
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/mt_adaptor.c
@@ -0,0 +1,519 @@
+/**
+ * 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 THREADED
+#define THREADED
+#endif
+
+#if !defined(DLL_EXPORT) && !defined(USE_STATIC_LIB)
+# define USE_STATIC_LIB
+#endif
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "zk_adaptor.h"
+#include "zookeeper_log.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <errno.h>
+
+#ifndef WIN32
+#include <signal.h>
+#include <poll.h>
+#include <unistd.h>
+#include <sys/time.h>
+#endif
+
+int zoo_lock_auth(zhandle_t *zh)
+{
+ return pthread_mutex_lock(&zh->auth_h.lock);
+}
+int zoo_unlock_auth(zhandle_t *zh)
+{
+ return pthread_mutex_unlock(&zh->auth_h.lock);
+}
+int lock_buffer_list(buffer_head_t *l)
+{
+ return pthread_mutex_lock(&l->lock);
+}
+int unlock_buffer_list(buffer_head_t *l)
+{
+ return pthread_mutex_unlock(&l->lock);
+}
+int lock_completion_list(completion_head_t *l)
+{
+ return pthread_mutex_lock(&l->lock);
+}
+int unlock_completion_list(completion_head_t *l)
+{
+ pthread_cond_broadcast(&l->cond);
+ return pthread_mutex_unlock(&l->lock);
+}
+struct sync_completion *alloc_sync_completion(void)
+{
+ struct sync_completion *sc = (struct sync_completion*)calloc(1, sizeof(struct sync_completion));
+ if (sc) {
+ pthread_cond_init(&sc->cond, 0);
+ pthread_mutex_init(&sc->lock, 0);
+ }
+ return sc;
+}
+int wait_sync_completion(struct sync_completion *sc)
+{
+ pthread_mutex_lock(&sc->lock);
+ while (!sc->complete) {
+ pthread_cond_wait(&sc->cond, &sc->lock);
+ }
+ pthread_mutex_unlock(&sc->lock);
+ return 0;
+}
+
+void free_sync_completion(struct sync_completion *sc)
+{
+ if (sc) {
+ pthread_mutex_destroy(&sc->lock);
+ pthread_cond_destroy(&sc->cond);
+ free(sc);
+ }
+}
+
+void notify_sync_completion(struct sync_completion *sc)
+{
+ pthread_mutex_lock(&sc->lock);
+ sc->complete = 1;
+ pthread_cond_broadcast(&sc->cond);
+ pthread_mutex_unlock(&sc->lock);
+}
+
+int process_async(int outstanding_sync)
+{
+ return 0;
+}
+
+#ifdef WIN32
+unsigned __stdcall do_io( void * );
+unsigned __stdcall do_completion( void * );
+
+int handle_error(SOCKET sock, char* message)
+{
+ LOG_ERROR(("%s. %d",message, WSAGetLastError()));
+ closesocket (sock);
+ return -1;
+}
+
+//--create socket pair for interupting selects.
+int create_socket_pair(SOCKET fds[2])
+{
+ struct sockaddr_in inaddr;
+ struct sockaddr addr;
+ int yes=1;
+ int len=0;
+
+ SOCKET lst=socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
+ if (lst == INVALID_SOCKET ){
+ LOG_ERROR(("Error creating socket. %d",WSAGetLastError()));
+ return -1;
+ }
+ memset(&inaddr, 0, sizeof(inaddr));
+ memset(&addr, 0, sizeof(addr));
+ inaddr.sin_family = AF_INET;
+ inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ inaddr.sin_port = 0; //--system assigns the port
+
+ if ( setsockopt(lst,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes)) == SOCKET_ERROR ) {
+ return handle_error(lst,"Error trying to set socket option.");
+ }
+ if (bind(lst,(struct sockaddr *)&inaddr,sizeof(inaddr)) == SOCKET_ERROR){
+ return handle_error(lst,"Error trying to bind socket.");
+ }
+ if (listen(lst,1) == SOCKET_ERROR){
+ return handle_error(lst,"Error trying to listen on socket.");
+ }
+ len=sizeof(inaddr);
+ getsockname(lst, &addr,&len);
+ fds[0]=socket(AF_INET, SOCK_STREAM,0);
+ if (connect(fds[0],&addr,len) == SOCKET_ERROR){
+ return handle_error(lst, "Error while connecting to socket.");
+ }
+ if ((fds[1]=accept(lst,0,0)) == INVALID_SOCKET){
+ closesocket(fds[0]);
+ return handle_error(lst, "Error while accepting socket connection.");
+ }
+ closesocket(lst);
+ return 0;
+}
+#else
+void *do_io(void *);
+void *do_completion(void *);
+#endif
+
+
+int wakeup_io_thread(zhandle_t *zh);
+
+#ifdef WIN32
+static int set_nonblock(SOCKET fd){
+ ULONG nonblocking_flag = 1;
+ if (ioctlsocket(fd, FIONBIO, &nonblocking_flag) == 0)
+ return 1;
+ else
+ return -1;
+}
+#else
+static int set_nonblock(int fd){
+ long l = fcntl(fd, F_GETFL);
+ if(l & O_NONBLOCK) return 0;
+ return fcntl(fd, F_SETFL, l | O_NONBLOCK);
+}
+#endif
+
+void wait_for_others(zhandle_t* zh)
+{
+ struct adaptor_threads* adaptor=zh->adaptor_priv;
+ pthread_mutex_lock(&adaptor->lock);
+ while(adaptor->threadsToWait>0)
+ pthread_cond_wait(&adaptor->cond,&adaptor->lock);
+ pthread_mutex_unlock(&adaptor->lock);
+}
+
+void notify_thread_ready(zhandle_t* zh)
+{
+ struct adaptor_threads* adaptor=zh->adaptor_priv;
+ pthread_mutex_lock(&adaptor->lock);
+ adaptor->threadsToWait--;
+ pthread_cond_broadcast(&adaptor->cond);
+ while(adaptor->threadsToWait>0)
+ pthread_cond_wait(&adaptor->cond,&adaptor->lock);
+ pthread_mutex_unlock(&adaptor->lock);
+}
+
+
+void start_threads(zhandle_t* zh)
+{
+ int rc = 0;
+ struct adaptor_threads* adaptor=zh->adaptor_priv;
+ pthread_cond_init(&adaptor->cond,0);
+ pthread_mutex_init(&adaptor->lock,0);
+ adaptor->threadsToWait=2; // wait for 2 threads before opening the barrier
+
+ // use api_prolog() to make sure zhandle doesn't get destroyed
+ // while initialization is in progress
+ api_prolog(zh);
+ LOG_DEBUG(("starting threads..."));
+ rc=pthread_create(&adaptor->io, 0, do_io, zh);
+ assert("pthread_create() failed for the IO thread"&&!rc);
+ rc=pthread_create(&adaptor->completion, 0, do_completion, zh);
+ assert("pthread_create() failed for the completion thread"&&!rc);
+ wait_for_others(zh);
+ api_epilog(zh, 0);
+}
+
+int adaptor_init(zhandle_t *zh)
+{
+ pthread_mutexattr_t recursive_mx_attr;
+ struct adaptor_threads *adaptor_threads = calloc(1, sizeof(*adaptor_threads));
+ if (!adaptor_threads) {
+ LOG_ERROR(("Out of memory"));
+ return -1;
+ }
+
+ /* We use a pipe for interrupting select() in unix/sol and socketpair in windows. */
+#ifdef WIN32
+ if (create_socket_pair(adaptor_threads->self_pipe) == -1){
+ LOG_ERROR(("Can't make a socket."));
+#else
+ if(pipe(adaptor_threads->self_pipe)==-1) {
+ LOG_ERROR(("Can't make a pipe %d",errno));
+#endif
+ free(adaptor_threads);
+ return -1;
+ }
+ set_nonblock(adaptor_threads->self_pipe[1]);
+ set_nonblock(adaptor_threads->self_pipe[0]);
+
+ pthread_mutex_init(&zh->auth_h.lock,0);
+
+ zh->adaptor_priv = adaptor_threads;
+ pthread_mutex_init(&zh->to_process.lock,0);
+ pthread_mutex_init(&adaptor_threads->zh_lock,0);
+ // to_send must be recursive mutex
+ pthread_mutexattr_init(&recursive_mx_attr);
+ pthread_mutexattr_settype(&recursive_mx_attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&zh->to_send.lock,&recursive_mx_attr);
+ pthread_mutexattr_destroy(&recursive_mx_attr);
+
+ pthread_mutex_init(&zh->sent_requests.lock,0);
+ pthread_cond_init(&zh->sent_requests.cond,0);
+ pthread_mutex_init(&zh->completions_to_process.lock,0);
+ pthread_cond_init(&zh->completions_to_process.cond,0);
+ start_threads(zh);
+ return 0;
+}
+
+void adaptor_finish(zhandle_t *zh)
+{
+ struct adaptor_threads *adaptor_threads;
+ // make sure zh doesn't get destroyed until after we're done here
+ api_prolog(zh);
+ adaptor_threads = zh->adaptor_priv;
+ if(adaptor_threads==0) {
+ api_epilog(zh,0);
+ return;
+ }
+
+ if(!pthread_equal(adaptor_threads->io,pthread_self())){
+ wakeup_io_thread(zh);
+ pthread_join(adaptor_threads->io, 0);
+ }else
+ pthread_detach(adaptor_threads->io);
+
+ if(!pthread_equal(adaptor_threads->completion,pthread_self())){
+ pthread_mutex_lock(&zh->completions_to_process.lock);
+ pthread_cond_broadcast(&zh->completions_to_process.cond);
+ pthread_mutex_unlock(&zh->completions_to_process.lock);
+ pthread_join(adaptor_threads->completion, 0);
+ }else
+ pthread_detach(adaptor_threads->completion);
+
+ api_epilog(zh,0);
+}
+
+void adaptor_destroy(zhandle_t *zh)
+{
+ struct adaptor_threads *adaptor = zh->adaptor_priv;
+ if(adaptor==0) return;
+
+ pthread_cond_destroy(&adaptor->cond);
+ pthread_mutex_destroy(&adaptor->lock);
+ pthread_mutex_destroy(&zh->to_process.lock);
+ pthread_mutex_destroy(&zh->to_send.lock);
+ pthread_mutex_destroy(&zh->sent_requests.lock);
+ pthread_cond_destroy(&zh->sent_requests.cond);
+ pthread_mutex_destroy(&zh->completions_to_process.lock);
+ pthread_cond_destroy(&zh->completions_to_process.cond);
+ pthread_mutex_destroy(&adaptor->zh_lock);
+
+ pthread_mutex_destroy(&zh->auth_h.lock);
+
+ close(adaptor->self_pipe[0]);
+ close(adaptor->self_pipe[1]);
+ free(adaptor);
+ zh->adaptor_priv=0;
+}
+
+int wakeup_io_thread(zhandle_t *zh)
+{
+ struct adaptor_threads *adaptor_threads = zh->adaptor_priv;
+ char c=0;
+#ifndef WIN32
+ return write(adaptor_threads->self_pipe[1],&c,1)==1? ZOK: ZSYSTEMERROR;
+#else
+ return send(adaptor_threads->self_pipe[1], &c, 1, 0)==1? ZOK: ZSYSTEMERROR;
+#endif
+}
+
+int adaptor_send_queue(zhandle_t *zh, int timeout)
+{
+ if(!zh->close_requested)
+ return wakeup_io_thread(zh);
+ // don't rely on the IO thread to send the messages if the app has
+ // requested to close
+ return flush_send_queue(zh, timeout);
+}
+
+/* These two are declared here because we will run the event loop
+ * and not the client */
+#ifdef WIN32
+int zookeeper_interest(zhandle_t *zh, SOCKET *fd, int *interest,
+ struct timeval *tv);
+#else
+int zookeeper_interest(zhandle_t *zh, int *fd, int *interest,
+ struct timeval *tv);
+#endif
+int zookeeper_process(zhandle_t *zh, int events);
+
+#ifdef WIN32
+unsigned __stdcall do_io( void * v)
+#else
+void *do_io(void *v)
+#endif
+{
+ zhandle_t *zh = (zhandle_t*)v;
+#ifndef WIN32
+ struct pollfd fds[2];
+ struct adaptor_threads *adaptor_threads = zh->adaptor_priv;
+
+ api_prolog(zh);
+ notify_thread_ready(zh);
+ LOG_DEBUG(("started IO thread"));
+ fds[0].fd=adaptor_threads->self_pipe[0];
+ fds[0].events=POLLIN;
+ while(!zh->close_requested) {
+ struct timeval tv;
+ int fd;
+ int interest;
+ int timeout;
+ int maxfd=1;
+
+ zookeeper_interest(zh, &fd, &interest, &tv);
+ if (fd != -1) {
+ fds[1].fd=fd;
+ fds[1].events=(interest&ZOOKEEPER_READ)?POLLIN:0;
+ fds[1].events|=(interest&ZOOKEEPER_WRITE)?POLLOUT:0;
+ maxfd=2;
+ }
+ timeout=tv.tv_sec * 1000 + (tv.tv_usec/1000);
+
+ poll(fds,maxfd,timeout);
+ if (fd != -1) {
+ interest=(fds[1].revents&POLLIN)?ZOOKEEPER_READ:0;
+ interest|=((fds[1].revents&POLLOUT)||(fds[1].revents&POLLHUP))?ZOOKEEPER_WRITE:0;
+ }
+ if(fds[0].revents&POLLIN){
+ // flush the pipe
+ char b[128];
+ while(read(adaptor_threads->self_pipe[0],b,sizeof(b))==sizeof(b)){}
+ }
+#else
+ fd_set rfds, wfds, efds;
+ struct adaptor_threads *adaptor_threads = zh->adaptor_priv;
+ api_prolog(zh);
+ notify_thread_ready(zh);
+ LOG_DEBUG(("started IO thread"));
+ FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds);
+ while(!zh->close_requested) {
+ struct timeval tv;
+ SOCKET fd;
+ SOCKET maxfd=adaptor_threads->self_pipe[0];
+ int interest;
+ 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);
+ }
+ }
+ FD_SET( adaptor_threads->self_pipe[0] ,&rfds );
+ rc = select((int)maxfd, &rfds, &wfds, &efds, &tv);
+ if (fd != -1)
+ {
+ interest = (FD_ISSET(fd, &rfds))? ZOOKEEPER_READ:0;
+ interest|= (FD_ISSET(fd, &wfds))? ZOOKEEPER_WRITE:0;
+ }
+
+ if (FD_ISSET(adaptor_threads->self_pipe[0], &rfds)){
+ // flush the pipe/socket
+ char b[128];
+ while(recv(adaptor_threads->self_pipe[0],b,sizeof(b), 0)==sizeof(b)){}
+ }
+#endif
+ // dispatch zookeeper events
+ zookeeper_process(zh, interest);
+ // check the current state of the zhandle and terminate
+ // if it is_unrecoverable()
+ if(is_unrecoverable(zh))
+ break;
+ }
+ api_epilog(zh, 0);
+ LOG_DEBUG(("IO thread terminated"));
+ return 0;
+}
+
+#ifdef WIN32
+unsigned __stdcall do_completion( void * v)
+#else
+void *do_completion(void *v)
+#endif
+{
+ zhandle_t *zh = v;
+ api_prolog(zh);
+ notify_thread_ready(zh);
+ LOG_DEBUG(("started completion thread"));
+ while(!zh->close_requested) {
+ pthread_mutex_lock(&zh->completions_to_process.lock);
+ while(!zh->completions_to_process.head && !zh->close_requested) {
+ pthread_cond_wait(&zh->completions_to_process.cond, &zh->completions_to_process.lock);
+ }
+ pthread_mutex_unlock(&zh->completions_to_process.lock);
+ process_completions(zh);
+ }
+ api_epilog(zh, 0);
+ LOG_DEBUG(("completion thread terminated"));
+ return 0;
+}
+
+int32_t inc_ref_counter(zhandle_t* zh,int i)
+{
+ int incr=(i<0?-1:(i>0?1:0));
+ // fetch_and_add implements atomic post-increment
+ int v=fetch_and_add(&zh->ref_counter,incr);
+ // inc_ref_counter wants pre-increment
+ v+=incr; // simulate pre-increment
+ return v;
+}
+
+int32_t fetch_and_add(volatile int32_t* operand, int incr)
+{
+#ifndef WIN32
+ return __sync_fetch_and_add(operand, incr);
+#else
+ return InterlockedExchangeAdd(operand, incr);
+#endif
+}
+
+// make sure the static xid is initialized before any threads started
+__attribute__((constructor)) int32_t get_xid()
+{
+ static int32_t xid = -1;
+ if (xid == -1) {
+ xid = time(0);
+ }
+ return fetch_and_add(&xid,1);
+}
+
+int enter_critical(zhandle_t* zh)
+{
+ struct adaptor_threads *adaptor = zh->adaptor_priv;
+ if (adaptor) {
+ return pthread_mutex_lock(&adaptor->zh_lock);
+ } else {
+ return 0;
+ }
+}
+
+int leave_critical(zhandle_t* zh)
+{
+ struct adaptor_threads *adaptor = zh->adaptor_priv;
+ if (adaptor) {
+ return pthread_mutex_unlock(&adaptor->zh_lock);
+ } else {
+ return 0;
+ }
+}
[15/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/src/zookeeper.c
----------------------------------------------------------------------
diff --git a/src/c/src/zookeeper.c b/src/c/src/zookeeper.c
deleted file mode 100644
index c087864..0000000
--- a/src/c/src/zookeeper.c
+++ /dev/null
@@ -1,3767 +0,0 @@
-/**
- * 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.
- */
-
-#if !defined(DLL_EXPORT) && !defined(USE_STATIC_LIB)
-# define USE_STATIC_LIB
-#endif
-
-#if defined(__CYGWIN__)
-#define USE_IPV6
-#endif
-
-#include "config.h"
-#include <zookeeper.h>
-#include <zookeeper.jute.h>
-#include <proto.h>
-#include "zk_adaptor.h"
-#include "zookeeper_log.h"
-#include "zk_hashtable.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <stdarg.h>
-#include <limits.h>
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#ifdef HAVE_POLL
-#include <poll.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#endif
-
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h> // needed for _POSIX_MONOTONIC_CLOCK
-#endif
-
-#ifdef HAVE_SYS_UTSNAME_H
-#include <sys/utsname.h>
-#endif
-
-#ifdef HAVE_GETPWUID_R
-#include <pwd.h>
-#endif
-
-#ifdef WIN32
-#define random rand /* replace POSIX random with Windows rand */
-#include <process.h> /* for getpid */
-#include <direct.h> /* for getcwd */
-#define EAI_ADDRFAMILY WSAEINVAL /* is this still needed? */
-#define EHOSTDOWN EPIPE
-#define ESTALE ENODEV
-#endif
-
-#define IF_DEBUG(x) if(logLevel==ZOO_LOG_LEVEL_DEBUG) {x;}
-
-const int ZOOKEEPER_WRITE = 1 << 0;
-const int ZOOKEEPER_READ = 1 << 1;
-
-const int ZOO_EPHEMERAL = 1 << 0;
-const int ZOO_SEQUENCE = 1 << 1;
-
-const int ZOO_EXPIRED_SESSION_STATE = EXPIRED_SESSION_STATE_DEF;
-const int ZOO_AUTH_FAILED_STATE = AUTH_FAILED_STATE_DEF;
-const int ZOO_CONNECTING_STATE = CONNECTING_STATE_DEF;
-const int ZOO_ASSOCIATING_STATE = ASSOCIATING_STATE_DEF;
-const int ZOO_CONNECTED_STATE = CONNECTED_STATE_DEF;
-static __attribute__ ((unused)) const char* state2String(int state){
- switch(state){
- case 0:
- return "ZOO_CLOSED_STATE";
- case CONNECTING_STATE_DEF:
- return "ZOO_CONNECTING_STATE";
- case ASSOCIATING_STATE_DEF:
- return "ZOO_ASSOCIATING_STATE";
- case CONNECTED_STATE_DEF:
- return "ZOO_CONNECTED_STATE";
- case EXPIRED_SESSION_STATE_DEF:
- return "ZOO_EXPIRED_SESSION_STATE";
- case AUTH_FAILED_STATE_DEF:
- return "ZOO_AUTH_FAILED_STATE";
- }
- return "INVALID_STATE";
-}
-
-const int ZOO_CREATED_EVENT = CREATED_EVENT_DEF;
-const int ZOO_DELETED_EVENT = DELETED_EVENT_DEF;
-const int ZOO_CHANGED_EVENT = CHANGED_EVENT_DEF;
-const int ZOO_CHILD_EVENT = CHILD_EVENT_DEF;
-const int ZOO_SESSION_EVENT = SESSION_EVENT_DEF;
-const int ZOO_NOTWATCHING_EVENT = NOTWATCHING_EVENT_DEF;
-static __attribute__ ((unused)) const char* watcherEvent2String(int ev){
- switch(ev){
- case 0:
- return "ZOO_ERROR_EVENT";
- case CREATED_EVENT_DEF:
- return "ZOO_CREATED_EVENT";
- case DELETED_EVENT_DEF:
- return "ZOO_DELETED_EVENT";
- case CHANGED_EVENT_DEF:
- return "ZOO_CHANGED_EVENT";
- case CHILD_EVENT_DEF:
- return "ZOO_CHILD_EVENT";
- case SESSION_EVENT_DEF:
- return "ZOO_SESSION_EVENT";
- case NOTWATCHING_EVENT_DEF:
- return "ZOO_NOTWATCHING_EVENT";
- }
- return "INVALID_EVENT";
-}
-
-const int ZOO_PERM_READ = 1 << 0;
-const int ZOO_PERM_WRITE = 1 << 1;
-const int ZOO_PERM_CREATE = 1 << 2;
-const int ZOO_PERM_DELETE = 1 << 3;
-const int ZOO_PERM_ADMIN = 1 << 4;
-const int ZOO_PERM_ALL = 0x1f;
-struct Id ZOO_ANYONE_ID_UNSAFE = {"world", "anyone"};
-struct Id ZOO_AUTH_IDS = {"auth", ""};
-static struct ACL _OPEN_ACL_UNSAFE_ACL[] = {{0x1f, {"world", "anyone"}}};
-static struct ACL _READ_ACL_UNSAFE_ACL[] = {{0x01, {"world", "anyone"}}};
-static struct ACL _CREATOR_ALL_ACL_ACL[] = {{0x1f, {"auth", ""}}};
-struct ACL_vector ZOO_OPEN_ACL_UNSAFE = { 1, _OPEN_ACL_UNSAFE_ACL};
-struct ACL_vector ZOO_READ_ACL_UNSAFE = { 1, _READ_ACL_UNSAFE_ACL};
-struct ACL_vector ZOO_CREATOR_ALL_ACL = { 1, _CREATOR_ALL_ACL_ACL};
-
-#define COMPLETION_WATCH -1
-#define COMPLETION_VOID 0
-#define COMPLETION_STAT 1
-#define COMPLETION_DATA 2
-#define COMPLETION_STRINGLIST 3
-#define COMPLETION_STRINGLIST_STAT 4
-#define COMPLETION_ACLLIST 5
-#define COMPLETION_STRING 6
-#define COMPLETION_MULTI 7
-
-typedef struct _auth_completion_list {
- void_completion_t completion;
- const char *auth_data;
- struct _auth_completion_list *next;
-} auth_completion_list_t;
-
-typedef struct completion {
- int type; /* one of COMPLETION_* values above */
- union {
- void_completion_t void_result;
- stat_completion_t stat_result;
- data_completion_t data_result;
- strings_completion_t strings_result;
- strings_stat_completion_t strings_stat_result;
- acl_completion_t acl_result;
- string_completion_t string_result;
- struct watcher_object_list *watcher_result;
- };
- completion_head_t clist; /* For multi-op */
-} completion_t;
-
-typedef struct _completion_list {
- int xid;
- completion_t c;
- const void *data;
- buffer_list_t *buffer;
- struct _completion_list *next;
- watcher_registration_t* watcher;
-} completion_list_t;
-
-const char*err2string(int err);
-static int queue_session_event(zhandle_t *zh, int state);
-static const char* format_endpoint_info(const struct sockaddr_storage* ep);
-static const char* format_current_endpoint_info(zhandle_t* zh);
-
-/* deserialize forward declarations */
-static void deserialize_response(int type, int xid, int failed, int rc, completion_list_t *cptr, struct iarchive *ia);
-static int deserialize_multi(int xid, completion_list_t *cptr, struct iarchive *ia);
-
-/* completion routine forward declarations */
-static int add_completion(zhandle_t *zh, int xid, int completion_type,
- const void *dc, const void *data, int add_to_front,
- watcher_registration_t* wo, completion_head_t *clist);
-static completion_list_t* create_completion_entry(int xid, int completion_type,
- const void *dc, const void *data, watcher_registration_t* wo,
- completion_head_t *clist);
-static void destroy_completion_entry(completion_list_t* c);
-static void queue_completion_nolock(completion_head_t *list, completion_list_t *c,
- int add_to_front);
-static void queue_completion(completion_head_t *list, completion_list_t *c,
- int add_to_front);
-static int handle_socket_error_msg(zhandle_t *zh, int line, int rc,
- const char* format,...);
-static void cleanup_bufs(zhandle_t *zh,int callCompletion,int rc);
-
-static int disable_conn_permute=0; // permute enabled by default
-
-static __attribute__((unused)) void print_completion_queue(zhandle_t *zh);
-
-static void *SYNCHRONOUS_MARKER = (void*)&SYNCHRONOUS_MARKER;
-static int isValidPath(const char* path, const int flags);
-
-#ifdef _WINDOWS
-static int zookeeper_send(SOCKET s, const char* buf, int len)
-#else
-static ssize_t zookeeper_send(int s, const void* buf, size_t len)
-#endif
-{
-#ifdef __linux__
- return send(s, buf, len, MSG_NOSIGNAL);
-#else
- return send(s, buf, len, 0);
-#endif
-}
-
-const void *zoo_get_context(zhandle_t *zh)
-{
- return zh->context;
-}
-
-void zoo_set_context(zhandle_t *zh, void *context)
-{
- if (zh != NULL) {
- zh->context = context;
- }
-}
-
-int zoo_recv_timeout(zhandle_t *zh)
-{
- return zh->recv_timeout;
-}
-
-/** these functions are thread unsafe, so make sure that
- zoo_lock_auth is called before you access them **/
-static auth_info* get_last_auth(auth_list_head_t *auth_list) {
- auth_info *element;
- element = auth_list->auth;
- if (element == NULL) {
- return NULL;
- }
- while (element->next != NULL) {
- element = element->next;
- }
- return element;
-}
-
-static void free_auth_completion(auth_completion_list_t *a_list) {
- auth_completion_list_t *tmp, *ftmp;
- if (a_list == NULL) {
- return;
- }
- tmp = a_list->next;
- while (tmp != NULL) {
- ftmp = tmp;
- tmp = tmp->next;
- ftmp->completion = NULL;
- ftmp->auth_data = NULL;
- free(ftmp);
- }
- a_list->completion = NULL;
- a_list->auth_data = NULL;
- a_list->next = NULL;
- return;
-}
-
-static void add_auth_completion(auth_completion_list_t* a_list, void_completion_t* completion,
- const char *data) {
- auth_completion_list_t *element;
- auth_completion_list_t *n_element;
- element = a_list;
- if (a_list->completion == NULL) {
- //this is the first element
- a_list->completion = *completion;
- a_list->next = NULL;
- a_list->auth_data = data;
- return;
- }
- while (element->next != NULL) {
- element = element->next;
- }
- n_element = (auth_completion_list_t*) malloc(sizeof(auth_completion_list_t));
- n_element->next = NULL;
- n_element->completion = *completion;
- n_element->auth_data = data;
- element->next = n_element;
- return;
-}
-
-static void get_auth_completions(auth_list_head_t *auth_list, auth_completion_list_t *a_list) {
- auth_info *element;
- element = auth_list->auth;
- if (element == NULL) {
- return;
- }
- while (element) {
- if (element->completion) {
- add_auth_completion(a_list, &element->completion, element->data);
- }
- element->completion = NULL;
- element = element->next;
- }
- return;
-}
-
-static void add_last_auth(auth_list_head_t *auth_list, auth_info *add_el) {
- auth_info *element;
- element = auth_list->auth;
- if (element == NULL) {
- //first element in the list
- auth_list->auth = add_el;
- return;
- }
- while (element->next != NULL) {
- element = element->next;
- }
- element->next = add_el;
- return;
-}
-
-static void init_auth_info(auth_list_head_t *auth_list)
-{
- auth_list->auth = NULL;
-}
-
-static void mark_active_auth(zhandle_t *zh) {
- auth_list_head_t auth_h = zh->auth_h;
- auth_info *element;
- if (auth_h.auth == NULL) {
- return;
- }
- element = auth_h.auth;
- while (element != NULL) {
- element->state = 1;
- element = element->next;
- }
-}
-
-static void free_auth_info(auth_list_head_t *auth_list)
-{
- auth_info *auth = auth_list->auth;
- while (auth != NULL) {
- auth_info* old_auth = NULL;
- if(auth->scheme!=NULL)
- free(auth->scheme);
- deallocate_Buffer(&auth->auth);
- old_auth = auth;
- auth = auth->next;
- free(old_auth);
- }
- init_auth_info(auth_list);
-}
-
-int is_unrecoverable(zhandle_t *zh)
-{
- return (zh->state<0)? ZINVALIDSTATE: ZOK;
-}
-
-zk_hashtable *exists_result_checker(zhandle_t *zh, int rc)
-{
- if (rc == ZOK) {
- return zh->active_node_watchers;
- } else if (rc == ZNONODE) {
- return zh->active_exist_watchers;
- }
- return 0;
-}
-
-zk_hashtable *data_result_checker(zhandle_t *zh, int rc)
-{
- return rc==ZOK ? zh->active_node_watchers : 0;
-}
-
-zk_hashtable *child_result_checker(zhandle_t *zh, int rc)
-{
- return rc==ZOK ? zh->active_child_watchers : 0;
-}
-
-/**
- * Frees and closes everything associated with a handle,
- * including the handle itself.
- */
-static void destroy(zhandle_t *zh)
-{
- if (zh == NULL) {
- return;
- }
- /* call any outstanding completions with a special error code */
- cleanup_bufs(zh,1,ZCLOSING);
- if (zh->hostname != 0) {
- free(zh->hostname);
- zh->hostname = NULL;
- }
- if (zh->fd != -1) {
- close(zh->fd);
- zh->fd = -1;
- zh->state = 0;
- }
- if (zh->addrs != 0) {
- free(zh->addrs);
- zh->addrs = NULL;
- }
-
- if (zh->chroot != 0) {
- free(zh->chroot);
- zh->chroot = NULL;
- }
-
- free_auth_info(&zh->auth_h);
- destroy_zk_hashtable(zh->active_node_watchers);
- destroy_zk_hashtable(zh->active_exist_watchers);
- destroy_zk_hashtable(zh->active_child_watchers);
-}
-
-static void setup_random()
-{
-#ifndef WIN32 // TODO: better seed
- int seed;
- int fd = open("/dev/urandom", O_RDONLY);
- if (fd == -1) {
- seed = getpid();
- } else {
- int seed_len = 0;
-
- /* Enter a loop to fill in seed with random data from /dev/urandom.
- * This is done in a loop so that we can safely handle short reads
- * which can happen due to signal interruptions.
- */
- while (seed_len < sizeof(seed)) {
- /* Assert we either read something or we were interrupted due to a
- * signal (errno == EINTR) in which case we need to retry.
- */
- int rc = read(fd, &seed + seed_len, sizeof(seed) - seed_len);
- assert(rc > 0 || errno == EINTR);
- if (rc > 0) {
- seed_len += rc;
- }
- }
- close(fd);
- }
- srandom(seed);
-#endif
-}
-
-#ifndef __CYGWIN__
-/**
- * get the errno from the return code
- * of get addrinfo. Errno is not set
- * with the call to getaddrinfo, so thats
- * why we have to do this.
- */
-static int getaddrinfo_errno(int rc) {
- switch(rc) {
- case EAI_NONAME:
-// ZOOKEEPER-1323 EAI_NODATA and EAI_ADDRFAMILY are deprecated in FreeBSD.
-#if defined EAI_NODATA && EAI_NODATA != EAI_NONAME
- case EAI_NODATA:
-#endif
- return ENOENT;
- case EAI_MEMORY:
- return ENOMEM;
- default:
- return EINVAL;
- }
-}
-#endif
-
-/**
- * fill in the addrs array of the zookeeper servers in the zhandle. after filling
- * them in, we will permute them for load balancing.
- */
-int getaddrs(zhandle_t *zh)
-{
- char *hosts = strdup(zh->hostname);
- char *host;
- char *strtok_last;
- struct sockaddr_storage *addr;
- int i;
- int rc;
- int alen = 0; /* the allocated length of the addrs array */
-
- zh->addrs_count = 0;
- if (zh->addrs) {
- free(zh->addrs);
- zh->addrs = 0;
- }
- if (!hosts) {
- LOG_ERROR(("out of memory"));
- errno=ENOMEM;
- return ZSYSTEMERROR;
- }
- zh->addrs = 0;
- host=strtok_r(hosts, ",", &strtok_last);
- while(host) {
- char *port_spec = strrchr(host, ':');
- char *end_port_spec;
- int port;
- if (!port_spec) {
- LOG_ERROR(("no port in %s", host));
- errno=EINVAL;
- rc=ZBADARGUMENTS;
- goto fail;
- }
- *port_spec = '\0';
- port_spec++;
- port = strtol(port_spec, &end_port_spec, 0);
- if (!*port_spec || *end_port_spec || port == 0) {
- LOG_ERROR(("invalid port in %s", host));
- errno=EINVAL;
- rc=ZBADARGUMENTS;
- goto fail;
- }
-#if defined(__CYGWIN__)
- // sadly CYGWIN doesn't have getaddrinfo
- // but happily gethostbyname is threadsafe in windows
- {
- struct hostent *he;
- char **ptr;
- struct sockaddr_in *addr4;
-
- he = gethostbyname(host);
- if (!he) {
- LOG_ERROR(("could not resolve %s", host));
- errno=ENOENT;
- rc=ZBADARGUMENTS;
- goto fail;
- }
-
- /* Setup the address array */
- for(ptr = he->h_addr_list;*ptr != 0; ptr++) {
- if (zh->addrs_count == alen) {
- alen += 16;
- zh->addrs = realloc(zh->addrs, sizeof(*zh->addrs)*alen);
- if (zh->addrs == 0) {
- LOG_ERROR(("out of memory"));
- errno=ENOMEM;
- rc=ZSYSTEMERROR;
- goto fail;
- }
- }
- addr = &zh->addrs[zh->addrs_count];
- addr4 = (struct sockaddr_in*)addr;
- addr->ss_family = he->h_addrtype;
- if (addr->ss_family == AF_INET) {
- addr4->sin_port = htons(port);
- memset(&addr4->sin_zero, 0, sizeof(addr4->sin_zero));
- memcpy(&addr4->sin_addr, *ptr, he->h_length);
- zh->addrs_count++;
- }
-#if defined(AF_INET6)
- else if (addr->ss_family == AF_INET6) {
- struct sockaddr_in6 *addr6;
-
- addr6 = (struct sockaddr_in6*)addr;
- addr6->sin6_port = htons(port);
- addr6->sin6_scope_id = 0;
- addr6->sin6_flowinfo = 0;
- memcpy(&addr6->sin6_addr, *ptr, he->h_length);
- zh->addrs_count++;
- }
-#endif
- else {
- LOG_WARN(("skipping unknown address family %x for %s",
- addr->ss_family, zh->hostname));
- }
- }
- host = strtok_r(0, ",", &strtok_last);
- }
-#else
- {
- struct addrinfo hints, *res, *res0;
-
- memset(&hints, 0, sizeof(hints));
-#ifdef AI_ADDRCONFIG
- hints.ai_flags = AI_ADDRCONFIG;
-#else
- hints.ai_flags = 0;
-#endif
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
-
- while(isspace(*host) && host != strtok_last)
- host++;
-
- if ((rc = getaddrinfo(host, port_spec, &hints, &res0)) != 0) {
- //bug in getaddrinfo implementation when it returns
- //EAI_BADFLAGS or EAI_ADDRFAMILY with AF_UNSPEC and
- // ai_flags as AI_ADDRCONFIG
-#ifdef AI_ADDRCONFIG
- if ((hints.ai_flags == AI_ADDRCONFIG) &&
-// ZOOKEEPER-1323 EAI_NODATA and EAI_ADDRFAMILY are deprecated in FreeBSD.
-#ifdef EAI_ADDRFAMILY
- ((rc ==EAI_BADFLAGS) || (rc == EAI_ADDRFAMILY))) {
-#else
- (rc == EAI_BADFLAGS)) {
-#endif
- //reset ai_flags to null
- hints.ai_flags = 0;
- //retry getaddrinfo
- rc = getaddrinfo(host, port_spec, &hints, &res0);
- }
-#endif
- if (rc != 0) {
- errno = getaddrinfo_errno(rc);
-#ifdef WIN32
- LOG_ERROR(("Win32 message: %s\n", gai_strerror(rc)));
-#else
- LOG_ERROR(("getaddrinfo: %s\n", strerror(errno)));
-#endif
- rc=ZSYSTEMERROR;
- goto fail;
- }
- }
-
- for (res = res0; res; res = res->ai_next) {
- // Expand address list if needed
- if (zh->addrs_count == alen) {
- void *tmpaddr;
- alen += 16;
- tmpaddr = realloc(zh->addrs, sizeof(*zh->addrs)*alen);
- if (tmpaddr == 0) {
- LOG_ERROR(("out of memory"));
- errno=ENOMEM;
- rc=ZSYSTEMERROR;
- goto fail;
- }
- zh->addrs=tmpaddr;
- }
-
- // Copy addrinfo into address list
- addr = &zh->addrs[zh->addrs_count];
- switch (res->ai_family) {
- case AF_INET:
-#if defined(AF_INET6)
- case AF_INET6:
-#endif
- memcpy(addr, res->ai_addr, res->ai_addrlen);
- ++zh->addrs_count;
- break;
- default:
- LOG_WARN(("skipping unknown address family %x for %s",
- res->ai_family, zh->hostname));
- break;
- }
- }
-
- freeaddrinfo(res0);
-
- host = strtok_r(0, ",", &strtok_last);
- }
-#endif
- }
- free(hosts);
-
- if(!disable_conn_permute){
- setup_random();
- /* Permute */
- for (i = zh->addrs_count - 1; i > 0; --i) {
- long int j = random()%(i+1);
- if (i != j) {
- struct sockaddr_storage t = zh->addrs[i];
- zh->addrs[i] = zh->addrs[j];
- zh->addrs[j] = t;
- }
- }
- }
- return ZOK;
-fail:
- if (zh->addrs) {
- free(zh->addrs);
- zh->addrs=0;
- }
- if (hosts) {
- free(hosts);
- }
- return rc;
-}
-
-const clientid_t *zoo_client_id(zhandle_t *zh)
-{
- return &zh->client_id;
-}
-
-static void null_watcher_fn(zhandle_t* p1, int p2, int p3,const char* p4,void*p5){}
-
-watcher_fn zoo_set_watcher(zhandle_t *zh,watcher_fn newFn)
-{
- watcher_fn oldWatcher=zh->watcher;
- if (newFn) {
- zh->watcher = newFn;
- } else {
- zh->watcher = null_watcher_fn;
- }
- return oldWatcher;
-}
-
-struct sockaddr* zookeeper_get_connected_host(zhandle_t *zh,
- struct sockaddr *addr, socklen_t *addr_len)
-{
- if (zh->state!=ZOO_CONNECTED_STATE) {
- return NULL;
- }
- if (getpeername(zh->fd, addr, addr_len)==-1) {
- return NULL;
- }
- return addr;
-}
-
-static void log_env() {
- char buf[2048];
-#ifdef HAVE_SYS_UTSNAME_H
- struct utsname utsname;
-#endif
-
-#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID_R)
- struct passwd pw;
- struct passwd *pwp = NULL;
- uid_t uid = 0;
-#endif
-
- LOG_INFO(("Client environment:zookeeper.version=%s", PACKAGE_STRING));
-
-#ifdef HAVE_GETHOSTNAME
- gethostname(buf, sizeof(buf));
- LOG_INFO(("Client environment:host.name=%s", buf));
-#else
- LOG_INFO(("Client environment:host.name=<not implemented>"));
-#endif
-
-#ifdef HAVE_SYS_UTSNAME_H
- uname(&utsname);
- LOG_INFO(("Client environment:os.name=%s", utsname.sysname));
- LOG_INFO(("Client environment:os.arch=%s", utsname.release));
- LOG_INFO(("Client environment:os.version=%s", utsname.version));
-#else
- LOG_INFO(("Client environment:os.name=<not implemented>"));
- LOG_INFO(("Client environment:os.arch=<not implemented>"));
- LOG_INFO(("Client environment:os.version=<not implemented>"));
-#endif
-
-#ifdef HAVE_GETLOGIN
- LOG_INFO(("Client environment:user.name=%s", getlogin()));
-#else
- LOG_INFO(("Client environment:user.name=<not implemented>"));
-#endif
-
-#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID_R)
- uid = getuid();
- if (!getpwuid_r(uid, &pw, buf, sizeof(buf), &pwp)) {
- LOG_INFO(("Client environment:user.home=%s", pw.pw_dir));
- } else {
- LOG_INFO(("Client environment:user.home=<NA>"));
- }
-#else
- LOG_INFO(("Client environment:user.home=<not implemented>"));
-#endif
-
-#ifdef HAVE_GETCWD
- if (!getcwd(buf, sizeof(buf))) {
- LOG_INFO(("Client environment:user.dir=<toolong>"));
- } else {
- LOG_INFO(("Client environment:user.dir=%s", buf));
- }
-#else
- LOG_INFO(("Client environment:user.dir=<not implemented>"));
-#endif
-}
-
-/**
- * Create a zookeeper handle associated with the given host and port.
- */
-zhandle_t *zookeeper_init(const char *host, watcher_fn watcher,
- int recv_timeout, const clientid_t *clientid, void *context, int flags)
-{
- int errnosave = 0;
- zhandle_t *zh = NULL;
- char *index_chroot = NULL;
-
- log_env();
-#ifdef WIN32
- if (Win32WSAStartup()){
- LOG_ERROR(("Error initializing ws2_32.dll"));
- return 0;
- }
-#endif
- LOG_INFO(("Initiating client connection, host=%s sessionTimeout=%d watcher=%p"
- " sessionId=%#llx sessionPasswd=%s context=%p flags=%d",
- host,
- recv_timeout,
- watcher,
- (clientid == 0 ? 0 : clientid->client_id),
- ((clientid == 0) || (clientid->passwd[0] == 0) ?
- "<null>" : "<hidden>"),
- context,
- flags));
-
- zh = calloc(1, sizeof(*zh));
- if (!zh) {
- return 0;
- }
- zh->fd = -1;
- zh->state = NOTCONNECTED_STATE_DEF;
- zh->context = context;
- zh->recv_timeout = recv_timeout;
- init_auth_info(&zh->auth_h);
- if (watcher) {
- zh->watcher = watcher;
- } else {
- zh->watcher = null_watcher_fn;
- }
- if (host == 0 || *host == 0) { // what we shouldn't dup
- errno=EINVAL;
- goto abort;
- }
- //parse the host to get the chroot if
- //available
- index_chroot = strchr(host, '/');
- if (index_chroot) {
- zh->chroot = strdup(index_chroot);
- if (zh->chroot == NULL) {
- goto abort;
- }
- // if chroot is just / set it to null
- if (strlen(zh->chroot) == 1) {
- free(zh->chroot);
- zh->chroot = NULL;
- }
- // cannot use strndup so allocate and strcpy
- zh->hostname = (char *) malloc(index_chroot - host + 1);
- zh->hostname = strncpy(zh->hostname, host, (index_chroot - host));
- //strncpy does not null terminate
- *(zh->hostname + (index_chroot - host)) = '\0';
-
- } else {
- zh->chroot = NULL;
- zh->hostname = strdup(host);
- }
- if (zh->chroot && !isValidPath(zh->chroot, 0)) {
- errno = EINVAL;
- goto abort;
- }
- if (zh->hostname == 0) {
- goto abort;
- }
- if(getaddrs(zh)!=0) {
- goto abort;
- }
- zh->connect_index = 0;
- if (clientid) {
- memcpy(&zh->client_id, clientid, sizeof(zh->client_id));
- } else {
- memset(&zh->client_id, 0, sizeof(zh->client_id));
- }
- zh->primer_buffer.buffer = zh->primer_storage_buffer;
- zh->primer_buffer.curr_offset = 0;
- zh->primer_buffer.len = sizeof(zh->primer_storage_buffer);
- zh->primer_buffer.next = 0;
- zh->last_zxid = 0;
- zh->next_deadline.tv_sec=zh->next_deadline.tv_usec=0;
- zh->socket_readable.tv_sec=zh->socket_readable.tv_usec=0;
- zh->active_node_watchers=create_zk_hashtable();
- zh->active_exist_watchers=create_zk_hashtable();
- zh->active_child_watchers=create_zk_hashtable();
-
- if (adaptor_init(zh) == -1) {
- goto abort;
- }
-
- return zh;
-abort:
- errnosave=errno;
- destroy(zh);
- free(zh);
- errno=errnosave;
- return 0;
-}
-
-/**
- * deallocated the free_path only its beeen allocated
- * and not equal to path
- */
-void free_duplicate_path(const char *free_path, const char* path) {
- if (free_path != path) {
- free((void*)free_path);
- }
-}
-
-/**
- prepend the chroot path if available else return the path
-*/
-static char* prepend_string(zhandle_t *zh, const char* client_path) {
- char *ret_str;
- if (zh == NULL || zh->chroot == NULL)
- return (char *) client_path;
- // handle the chroot itself, client_path = "/"
- if (strlen(client_path) == 1) {
- return strdup(zh->chroot);
- }
- ret_str = (char *) malloc(strlen(zh->chroot) + strlen(client_path) + 1);
- strcpy(ret_str, zh->chroot);
- return strcat(ret_str, client_path);
-}
-
-/**
- strip off the chroot string from the server path
- if there is one else return the exact path
- */
-char* sub_string(zhandle_t *zh, const char* server_path) {
- char *ret_str;
- if (zh->chroot == NULL)
- return (char *) server_path;
- //ZOOKEEPER-1027
- if (strncmp(server_path, zh->chroot, strlen(zh->chroot)) != 0) {
- LOG_ERROR(("server path %s does not include chroot path %s",
- server_path, zh->chroot));
- return (char *) server_path;
- }
- if (strlen(server_path) == strlen(zh->chroot)) {
- //return "/"
- ret_str = strdup("/");
- return ret_str;
- }
- ret_str = strdup(server_path + strlen(zh->chroot));
- return ret_str;
-}
-
-static buffer_list_t *allocate_buffer(char *buff, int len)
-{
- buffer_list_t *buffer = calloc(1, sizeof(*buffer));
- if (buffer == 0)
- return 0;
-
- buffer->len = len==0?sizeof(*buffer):len;
- buffer->curr_offset = 0;
- buffer->buffer = buff;
- buffer->next = 0;
- return buffer;
-}
-
-static void free_buffer(buffer_list_t *b)
-{
- if (!b) {
- return;
- }
- if (b->buffer) {
- free(b->buffer);
- }
- free(b);
-}
-
-static buffer_list_t *dequeue_buffer(buffer_head_t *list)
-{
- buffer_list_t *b;
- lock_buffer_list(list);
- b = list->head;
- if (b) {
- list->head = b->next;
- if (!list->head) {
- assert(b == list->last);
- list->last = 0;
- }
- }
- unlock_buffer_list(list);
- return b;
-}
-
-static int remove_buffer(buffer_head_t *list)
-{
- buffer_list_t *b = dequeue_buffer(list);
- if (!b) {
- return 0;
- }
- free_buffer(b);
- return 1;
-}
-
-static void queue_buffer(buffer_head_t *list, buffer_list_t *b, int add_to_front)
-{
- b->next = 0;
- lock_buffer_list(list);
- if (list->head) {
- assert(list->last);
- // The list is not empty
- if (add_to_front) {
- b->next = list->head;
- list->head = b;
- } else {
- list->last->next = b;
- list->last = b;
- }
- }else{
- // The list is empty
- assert(!list->head);
- list->head = b;
- list->last = b;
- }
- unlock_buffer_list(list);
-}
-
-static int queue_buffer_bytes(buffer_head_t *list, char *buff, int len)
-{
- buffer_list_t *b = allocate_buffer(buff,len);
- if (!b)
- return ZSYSTEMERROR;
- queue_buffer(list, b, 0);
- return ZOK;
-}
-
-static int queue_front_buffer_bytes(buffer_head_t *list, char *buff, int len)
-{
- buffer_list_t *b = allocate_buffer(buff,len);
- if (!b)
- return ZSYSTEMERROR;
- queue_buffer(list, b, 1);
- return ZOK;
-}
-
-static __attribute__ ((unused)) int get_queue_len(buffer_head_t *list)
-{
- int i;
- buffer_list_t *ptr;
- lock_buffer_list(list);
- ptr = list->head;
- for (i=0; ptr!=0; ptr=ptr->next, i++)
- ;
- unlock_buffer_list(list);
- return i;
-}
-/* returns:
- * -1 if send failed,
- * 0 if send would block while sending the buffer (or a send was incomplete),
- * 1 if success
- */
-#ifdef WIN32
-static int send_buffer(SOCKET fd, buffer_list_t *buff)
-#else
-static int send_buffer(int fd, buffer_list_t *buff)
-#endif
-{
- int len = buff->len;
- int off = buff->curr_offset;
- int rc = -1;
-
- if (off < 4) {
- /* we need to send the length at the beginning */
- int nlen = htonl(len);
- char *b = (char*)&nlen;
- rc = zookeeper_send(fd, b + off, sizeof(nlen) - off);
- if (rc == -1) {
-#ifndef _WINDOWS
- if (errno != EAGAIN) {
-#else
- if (WSAGetLastError() != WSAEWOULDBLOCK) {
-#endif
- return -1;
- } else {
- return 0;
- }
- } else {
- buff->curr_offset += rc;
- }
- off = buff->curr_offset;
- }
- if (off >= 4) {
- /* want off to now represent the offset into the buffer */
- off -= sizeof(buff->len);
- rc = zookeeper_send(fd, buff->buffer + off, len - off);
- if (rc == -1) {
-#ifndef _WINDOWS
- if (errno != EAGAIN) {
-#else
- if (WSAGetLastError() != WSAEWOULDBLOCK) {
-#endif
- return -1;
- }
- } else {
- buff->curr_offset += rc;
- }
- }
- return buff->curr_offset == len + sizeof(buff->len);
-}
-
-/* returns:
- * -1 if recv call failed,
- * 0 if recv would block,
- * 1 if success
- */
-#ifdef WIN32
-static int recv_buffer(SOCKET fd, buffer_list_t *buff)
-#else
-static int recv_buffer(int fd, buffer_list_t *buff)
-#endif
-{
- int off = buff->curr_offset;
- int rc = 0;
- //fprintf(LOGSTREAM, "rc = %d, off = %d, line %d\n", rc, off, __LINE__);
-
- /* if buffer is less than 4, we are reading in the length */
- if (off < 4) {
- char *buffer = (char*)&(buff->len);
- rc = recv(fd, buffer+off, sizeof(int)-off, 0);
- //fprintf(LOGSTREAM, "rc = %d, off = %d, line %d\n", rc, off, __LINE__);
- switch(rc) {
- case 0:
- errno = EHOSTDOWN;
- case -1:
-#ifndef _WINDOWS
- if (errno == EAGAIN) {
-#else
- if (WSAGetLastError() == WSAEWOULDBLOCK) {
-#endif
- return 0;
- }
- return -1;
- default:
- buff->curr_offset += rc;
- }
- off = buff->curr_offset;
- if (buff->curr_offset == sizeof(buff->len)) {
- buff->len = ntohl(buff->len);
- buff->buffer = calloc(1, buff->len);
- }
- }
- if (buff->buffer) {
- /* want off to now represent the offset into the buffer */
- off -= sizeof(buff->len);
-
- rc = recv(fd, buff->buffer+off, buff->len-off, 0);
- switch(rc) {
- case 0:
- errno = EHOSTDOWN;
- case -1:
-#ifndef _WINDOWS
- if (errno == EAGAIN) {
-#else
- if (WSAGetLastError() == WSAEWOULDBLOCK) {
-#endif
- break;
- }
- return -1;
- default:
- buff->curr_offset += rc;
- }
- }
- return buff->curr_offset == buff->len + sizeof(buff->len);
-}
-
-void free_buffers(buffer_head_t *list)
-{
- while (remove_buffer(list))
- ;
-}
-
-void free_completions(zhandle_t *zh,int callCompletion,int reason)
-{
- completion_head_t tmp_list;
- struct oarchive *oa;
- struct ReplyHeader h;
- void_completion_t auth_completion = NULL;
- auth_completion_list_t a_list, *a_tmp;
-
- if (lock_completion_list(&zh->sent_requests) == 0) {
- tmp_list = zh->sent_requests;
- zh->sent_requests.head = 0;
- zh->sent_requests.last = 0;
- unlock_completion_list(&zh->sent_requests);
-
- while (tmp_list.head) {
- completion_list_t *cptr = tmp_list.head;
-
- tmp_list.head = cptr->next;
- if (cptr->c.data_result == SYNCHRONOUS_MARKER) {
- struct sync_completion
- *sc = (struct sync_completion*)cptr->data;
- sc->rc = reason;
- notify_sync_completion(sc);
- zh->outstanding_sync--;
- destroy_completion_entry(cptr);
- } else if (callCompletion) {
- // Fake the response
- buffer_list_t *bptr;
- h.xid = cptr->xid;
- h.zxid = -1;
- h.err = reason;
- oa = create_buffer_oarchive();
- serialize_ReplyHeader(oa, "header", &h);
- bptr = calloc(sizeof(*bptr), 1);
- assert(bptr);
- bptr->len = get_buffer_len(oa);
- bptr->buffer = get_buffer(oa);
- close_buffer_oarchive(&oa, 0);
- cptr->buffer = bptr;
- queue_completion(&zh->completions_to_process, cptr, 0);
- }
- }
- }
- if (zoo_lock_auth(zh) == 0) {
- a_list.completion = NULL;
- a_list.next = NULL;
-
- get_auth_completions(&zh->auth_h, &a_list);
- zoo_unlock_auth(zh);
-
- a_tmp = &a_list;
- // chain call user's completion function
- while (a_tmp->completion != NULL) {
- auth_completion = a_tmp->completion;
- auth_completion(reason, a_tmp->auth_data);
- a_tmp = a_tmp->next;
- if (a_tmp == NULL)
- break;
- }
- }
- free_auth_completion(&a_list);
-}
-
-static void cleanup_bufs(zhandle_t *zh,int callCompletion,int rc)
-{
- enter_critical(zh);
- free_buffers(&zh->to_send);
- free_buffers(&zh->to_process);
- free_completions(zh,callCompletion,rc);
- leave_critical(zh);
- if (zh->input_buffer && zh->input_buffer != &zh->primer_buffer) {
- free_buffer(zh->input_buffer);
- zh->input_buffer = 0;
- }
-}
-
-static void handle_error(zhandle_t *zh,int rc)
-{
- close(zh->fd);
- if (is_unrecoverable(zh)) {
- LOG_DEBUG(("Calling a watcher for a ZOO_SESSION_EVENT and the state=%s",
- state2String(zh->state)));
- PROCESS_SESSION_EVENT(zh, zh->state);
- } else if (zh->state == ZOO_CONNECTED_STATE) {
- LOG_DEBUG(("Calling a watcher for a ZOO_SESSION_EVENT and the state=CONNECTING_STATE"));
- PROCESS_SESSION_EVENT(zh, ZOO_CONNECTING_STATE);
- }
- cleanup_bufs(zh,1,rc);
- zh->fd = -1;
- zh->connect_index++;
- if (!is_unrecoverable(zh)) {
- zh->state = 0;
- }
- if (process_async(zh->outstanding_sync)) {
- process_completions(zh);
- }
-}
-
-static int handle_socket_error_msg(zhandle_t *zh, int line, int rc,
- const char* format, ...)
-{
- if(logLevel>=ZOO_LOG_LEVEL_ERROR){
- va_list va;
- char buf[1024];
- va_start(va,format);
- vsnprintf(buf, sizeof(buf)-1,format,va);
- log_message(ZOO_LOG_LEVEL_ERROR,line,__func__,
- format_log_message("Socket [%s] zk retcode=%d, errno=%d(%s): %s",
- format_current_endpoint_info(zh),rc,errno,strerror(errno),buf));
- va_end(va);
- }
- handle_error(zh,rc);
- return rc;
-}
-
-static void auth_completion_func(int rc, zhandle_t* zh)
-{
- void_completion_t auth_completion = NULL;
- auth_completion_list_t a_list;
- auth_completion_list_t *a_tmp;
-
- if(zh==NULL)
- return;
-
- zoo_lock_auth(zh);
-
- if(rc!=0){
- zh->state=ZOO_AUTH_FAILED_STATE;
- }else{
- //change state for all auths
- mark_active_auth(zh);
- }
- a_list.completion = NULL;
- a_list.next = NULL;
- get_auth_completions(&zh->auth_h, &a_list);
- zoo_unlock_auth(zh);
- if (rc) {
- LOG_ERROR(("Authentication scheme %s failed. Connection closed.",
- zh->auth_h.auth->scheme));
- }
- else {
- LOG_INFO(("Authentication scheme %s succeeded", zh->auth_h.auth->scheme));
- }
- a_tmp = &a_list;
- // chain call user's completion function
- while (a_tmp->completion != NULL) {
- auth_completion = a_tmp->completion;
- auth_completion(rc, a_tmp->auth_data);
- a_tmp = a_tmp->next;
- if (a_tmp == NULL)
- break;
- }
- free_auth_completion(&a_list);
-}
-
-static int send_info_packet(zhandle_t *zh, auth_info* auth) {
- struct oarchive *oa;
- struct RequestHeader h = { STRUCT_INITIALIZER(xid , AUTH_XID), STRUCT_INITIALIZER(type , ZOO_SETAUTH_OP)};
- struct AuthPacket req;
- int rc;
- oa = create_buffer_oarchive();
- rc = serialize_RequestHeader(oa, "header", &h);
- req.type=0; // ignored by the server
- req.scheme = auth->scheme;
- req.auth = auth->auth;
- rc = rc < 0 ? rc : serialize_AuthPacket(oa, "req", &req);
- /* add this buffer to the head of the send queue */
- rc = rc < 0 ? rc : queue_front_buffer_bytes(&zh->to_send, get_buffer(oa),
- get_buffer_len(oa));
- /* We queued the buffer, so don't free it */
- close_buffer_oarchive(&oa, 0);
-
- return rc;
-}
-
-/** send all auths, not just the last one **/
-static int send_auth_info(zhandle_t *zh) {
- int rc = 0;
- auth_info *auth = NULL;
-
- zoo_lock_auth(zh);
- auth = zh->auth_h.auth;
- if (auth == NULL) {
- zoo_unlock_auth(zh);
- return ZOK;
- }
- while (auth != NULL) {
- rc = send_info_packet(zh, auth);
- auth = auth->next;
- }
- zoo_unlock_auth(zh);
- LOG_DEBUG(("Sending all auth info request to %s", format_current_endpoint_info(zh)));
- return (rc <0) ? ZMARSHALLINGERROR:ZOK;
-}
-
-static int send_last_auth_info(zhandle_t *zh)
-{
- int rc = 0;
- auth_info *auth = NULL;
-
- zoo_lock_auth(zh);
- auth = get_last_auth(&zh->auth_h);
- if(auth==NULL) {
- zoo_unlock_auth(zh);
- return ZOK; // there is nothing to send
- }
- rc = send_info_packet(zh, auth);
- zoo_unlock_auth(zh);
- LOG_DEBUG(("Sending auth info request to %s",format_current_endpoint_info(zh)));
- return (rc < 0)?ZMARSHALLINGERROR:ZOK;
-}
-
-static void free_key_list(char **list, int count)
-{
- int i;
-
- for(i = 0; i < count; i++) {
- free(list[i]);
- }
- free(list);
-}
-
-static int send_set_watches(zhandle_t *zh)
-{
- struct oarchive *oa;
- struct RequestHeader h = { STRUCT_INITIALIZER(xid , SET_WATCHES_XID), STRUCT_INITIALIZER(type , ZOO_SETWATCHES_OP)};
- struct SetWatches req;
- int rc;
-
- req.relativeZxid = zh->last_zxid;
- req.dataWatches.data = collect_keys(zh->active_node_watchers, (int*)&req.dataWatches.count);
- req.existWatches.data = collect_keys(zh->active_exist_watchers, (int*)&req.existWatches.count);
- req.childWatches.data = collect_keys(zh->active_child_watchers, (int*)&req.childWatches.count);
-
- // return if there are no pending watches
- if (!req.dataWatches.count && !req.existWatches.count &&
- !req.childWatches.count) {
- free_key_list(req.dataWatches.data, req.dataWatches.count);
- free_key_list(req.existWatches.data, req.existWatches.count);
- free_key_list(req.childWatches.data, req.childWatches.count);
- return ZOK;
- }
-
-
- oa = create_buffer_oarchive();
- rc = serialize_RequestHeader(oa, "header", &h);
- rc = rc < 0 ? rc : serialize_SetWatches(oa, "req", &req);
- /* add this buffer to the head of the send queue */
- rc = rc < 0 ? rc : queue_front_buffer_bytes(&zh->to_send, get_buffer(oa),
- get_buffer_len(oa));
- /* We queued the buffer, so don't free it */
- close_buffer_oarchive(&oa, 0);
- free_key_list(req.dataWatches.data, req.dataWatches.count);
- free_key_list(req.existWatches.data, req.existWatches.count);
- free_key_list(req.childWatches.data, req.childWatches.count);
- LOG_DEBUG(("Sending set watches request to %s",format_current_endpoint_info(zh)));
- return (rc < 0)?ZMARSHALLINGERROR:ZOK;
-}
-
-static int serialize_prime_connect(struct connect_req *req, char* buffer){
- //this should be the order of serialization
- int offset = 0;
- req->protocolVersion = htonl(req->protocolVersion);
- memcpy(buffer + offset, &req->protocolVersion, sizeof(req->protocolVersion));
- offset = offset + sizeof(req->protocolVersion);
-
- req->lastZxidSeen = zoo_htonll(req->lastZxidSeen);
- memcpy(buffer + offset, &req->lastZxidSeen, sizeof(req->lastZxidSeen));
- offset = offset + sizeof(req->lastZxidSeen);
-
- req->timeOut = htonl(req->timeOut);
- memcpy(buffer + offset, &req->timeOut, sizeof(req->timeOut));
- offset = offset + sizeof(req->timeOut);
-
- req->sessionId = zoo_htonll(req->sessionId);
- memcpy(buffer + offset, &req->sessionId, sizeof(req->sessionId));
- offset = offset + sizeof(req->sessionId);
-
- req->passwd_len = htonl(req->passwd_len);
- memcpy(buffer + offset, &req->passwd_len, sizeof(req->passwd_len));
- offset = offset + sizeof(req->passwd_len);
-
- memcpy(buffer + offset, req->passwd, sizeof(req->passwd));
-
- return 0;
-}
-
- static int deserialize_prime_response(struct prime_struct *req, char* buffer){
- //this should be the order of deserialization
- int offset = 0;
- memcpy(&req->len, buffer + offset, sizeof(req->len));
- offset = offset + sizeof(req->len);
-
- req->len = ntohl(req->len);
- memcpy(&req->protocolVersion, buffer + offset, sizeof(req->protocolVersion));
- offset = offset + sizeof(req->protocolVersion);
-
- req->protocolVersion = ntohl(req->protocolVersion);
- memcpy(&req->timeOut, buffer + offset, sizeof(req->timeOut));
- offset = offset + sizeof(req->timeOut);
-
- req->timeOut = ntohl(req->timeOut);
- memcpy(&req->sessionId, buffer + offset, sizeof(req->sessionId));
- offset = offset + sizeof(req->sessionId);
-
- req->sessionId = zoo_htonll(req->sessionId);
- memcpy(&req->passwd_len, buffer + offset, sizeof(req->passwd_len));
- offset = offset + sizeof(req->passwd_len);
-
- req->passwd_len = ntohl(req->passwd_len);
- memcpy(req->passwd, buffer + offset, sizeof(req->passwd));
- return 0;
- }
-
-static int prime_connection(zhandle_t *zh)
-{
- int rc;
- /*this is the size of buffer to serialize req into*/
- char buffer_req[HANDSHAKE_REQ_SIZE];
- int len = sizeof(buffer_req);
- int hlen = 0;
- struct connect_req req;
- req.protocolVersion = 0;
- req.sessionId = zh->client_id.client_id;
- req.passwd_len = sizeof(req.passwd);
- memcpy(req.passwd, zh->client_id.passwd, sizeof(zh->client_id.passwd));
- req.timeOut = zh->recv_timeout;
- req.lastZxidSeen = zh->last_zxid;
- hlen = htonl(len);
- /* We are running fast and loose here, but this string should fit in the initial buffer! */
- rc=zookeeper_send(zh->fd, &hlen, sizeof(len));
- serialize_prime_connect(&req, buffer_req);
- rc=rc<0 ? rc : zookeeper_send(zh->fd, buffer_req, len);
- if (rc<0) {
- return handle_socket_error_msg(zh, __LINE__, ZCONNECTIONLOSS,
- "failed to send a handshake packet: %s", strerror(errno));
- }
- zh->state = ZOO_ASSOCIATING_STATE;
-
- zh->input_buffer = &zh->primer_buffer;
- /* This seems a bit weird to to set the offset to 4, but we already have a
- * length, so we skip reading the length (and allocating the buffer) by
- * saying that we are already at offset 4 */
- zh->input_buffer->curr_offset = 4;
-
- return ZOK;
-}
-
-static inline int calculate_interval(const struct timeval *start,
- const struct timeval *end)
-{
- int interval;
- struct timeval i = *end;
- i.tv_sec -= start->tv_sec;
- i.tv_usec -= start->tv_usec;
- interval = i.tv_sec * 1000 + (i.tv_usec/1000);
- return interval;
-}
-
-static struct timeval get_timeval(int interval)
-{
- struct timeval tv;
- if (interval < 0) {
- interval = 0;
- }
- tv.tv_sec = interval/1000;
- tv.tv_usec = (interval%1000)*1000;
- return tv;
-}
-
- static int add_void_completion(zhandle_t *zh, int xid, void_completion_t dc,
- const void *data);
- static int add_string_completion(zhandle_t *zh, int xid,
- string_completion_t dc, const void *data);
-
- int send_ping(zhandle_t* zh)
- {
- int rc;
- struct oarchive *oa = create_buffer_oarchive();
- struct RequestHeader h = { STRUCT_INITIALIZER(xid ,PING_XID), STRUCT_INITIALIZER (type , ZOO_PING_OP) };
-
- rc = serialize_RequestHeader(oa, "header", &h);
- enter_critical(zh);
- gettimeofday(&zh->last_ping, 0);
- rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa),
- get_buffer_len(oa));
- leave_critical(zh);
- close_buffer_oarchive(&oa, 0);
- return rc<0 ? rc : adaptor_send_queue(zh, 0);
-}
-
-#ifdef WIN32
-int zookeeper_interest(zhandle_t *zh, SOCKET *fd, int *interest,
- struct timeval *tv)
-{
-
- ULONG nonblocking_flag = 1;
-#else
-int zookeeper_interest(zhandle_t *zh, int *fd, int *interest,
- struct timeval *tv)
-{
-#endif
- struct timeval now;
- if(zh==0 || fd==0 ||interest==0 || tv==0)
- return ZBADARGUMENTS;
- if (is_unrecoverable(zh))
- return ZINVALIDSTATE;
- gettimeofday(&now, 0);
- if(zh->next_deadline.tv_sec!=0 || zh->next_deadline.tv_usec!=0){
- int time_left = calculate_interval(&zh->next_deadline, &now);
- if (time_left > 10)
- LOG_WARN(("Exceeded deadline by %dms", time_left));
- }
- api_prolog(zh);
- *fd = zh->fd;
- *interest = 0;
- tv->tv_sec = 0;
- tv->tv_usec = 0;
- if (*fd == -1) {
- if (zh->connect_index == zh->addrs_count) {
- /* Wait a bit before trying again so that we don't spin */
- zh->connect_index = 0;
- }else {
- int rc;
-#ifdef WIN32
- char enable_tcp_nodelay = 1;
-#else
- int enable_tcp_nodelay = 1;
-#endif
- int ssoresult;
-
- zh->fd = socket(zh->addrs[zh->connect_index].ss_family, SOCK_STREAM, 0);
- if (zh->fd < 0) {
- return api_epilog(zh,handle_socket_error_msg(zh,__LINE__,
- ZSYSTEMERROR, "socket() call failed"));
- }
- ssoresult = setsockopt(zh->fd, IPPROTO_TCP, TCP_NODELAY, &enable_tcp_nodelay, sizeof(enable_tcp_nodelay));
- if (ssoresult != 0) {
- LOG_WARN(("Unable to set TCP_NODELAY, operation latency may be effected"));
- }
-#ifdef WIN32
- ioctlsocket(zh->fd, FIONBIO, &nonblocking_flag);
-#else
- fcntl(zh->fd, F_SETFL, O_NONBLOCK|fcntl(zh->fd, F_GETFL, 0));
-#endif
-#if defined(AF_INET6)
- if (zh->addrs[zh->connect_index].ss_family == AF_INET6) {
- rc = connect(zh->fd, (struct sockaddr*) &zh->addrs[zh->connect_index], sizeof(struct sockaddr_in6));
- } else {
-#else
- LOG_DEBUG(("[zk] connect()\n"));
- {
-#endif
- rc = connect(zh->fd, (struct sockaddr*) &zh->addrs[zh->connect_index], sizeof(struct sockaddr_in));
-#ifdef WIN32
- errno = GetLastError();
-
-#ifndef EWOULDBLOCK
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#endif
-
-#ifndef EINPROGRESS
-#define EINPROGRESS WSAEINPROGRESS
-#endif
-
-#if _MSC_VER >= 1600
- switch (errno) {
- case WSAEWOULDBLOCK:
- errno = EWOULDBLOCK;
- break;
- case WSAEINPROGRESS:
- errno = EINPROGRESS;
- break;
- }
-#endif
-#endif
- }
- if (rc == -1) {
- /* we are handling the non-blocking connect according to
- * the description in section 16.3 "Non-blocking connect"
- * in UNIX Network Programming vol 1, 3rd edition */
- if (errno == EWOULDBLOCK || errno == EINPROGRESS)
- zh->state = ZOO_CONNECTING_STATE;
- else
- return api_epilog(zh,handle_socket_error_msg(zh,__LINE__,
- ZCONNECTIONLOSS,"connect() call failed"));
- } else {
- if((rc=prime_connection(zh))!=0)
- return api_epilog(zh,rc);
-
- LOG_INFO(("Initiated connection to server [%s]",
- format_endpoint_info(&zh->addrs[zh->connect_index])));
- }
- }
- *fd = zh->fd;
- *tv = get_timeval(zh->recv_timeout/3);
- zh->last_recv = now;
- zh->last_send = now;
- zh->last_ping = now;
- }
- if (zh->fd != -1) {
- int idle_recv = calculate_interval(&zh->last_recv, &now);
- int idle_send = calculate_interval(&zh->last_send, &now);
- int recv_to = zh->recv_timeout*2/3 - idle_recv;
- int send_to = zh->recv_timeout/3;
- // have we exceeded the receive timeout threshold?
- if (recv_to <= 0) {
- // We gotta cut our losses and connect to someone else
-#ifdef WIN32
- errno = WSAETIMEDOUT;
-#else
- errno = ETIMEDOUT;
-#endif
- *interest=0;
- *tv = get_timeval(0);
- return api_epilog(zh,handle_socket_error_msg(zh,
- __LINE__,ZOPERATIONTIMEOUT,
- "connection to %s timed out (exceeded timeout by %dms)",
- format_endpoint_info(&zh->addrs[zh->connect_index]),
- -recv_to));
-
- }
- // We only allow 1/3 of our timeout time to expire before sending
- // a PING
- if (zh->state==ZOO_CONNECTED_STATE) {
- send_to = zh->recv_timeout/3 - idle_send;
- if (send_to <= 0) {
- if (zh->sent_requests.head==0) {
-// LOG_DEBUG(("Sending PING to %s (exceeded idle by %dms)",
-// format_current_endpoint_info(zh),-send_to));
- int rc=send_ping(zh);
- if (rc < 0){
- LOG_ERROR(("failed to send PING request (zk retcode=%d)",rc));
- return api_epilog(zh,rc);
- }
- }
- send_to = zh->recv_timeout/3;
- }
- }
- // choose the lesser value as the timeout
- *tv = get_timeval(recv_to < send_to? recv_to:send_to);
- zh->next_deadline.tv_sec = now.tv_sec + tv->tv_sec;
- zh->next_deadline.tv_usec = now.tv_usec + tv->tv_usec;
- if (zh->next_deadline.tv_usec > 1000000) {
- zh->next_deadline.tv_sec += zh->next_deadline.tv_usec / 1000000;
- zh->next_deadline.tv_usec = zh->next_deadline.tv_usec % 1000000;
- }
- *interest = ZOOKEEPER_READ;
- /* we are interested in a write if we are connected and have something
- * to send, or we are waiting for a connect to finish. */
- if ((zh->to_send.head && (zh->state == ZOO_CONNECTED_STATE))
- || zh->state == ZOO_CONNECTING_STATE) {
- *interest |= ZOOKEEPER_WRITE;
- }
- }
- return api_epilog(zh,ZOK);
-}
-
-static int check_events(zhandle_t *zh, int events)
-{
- if (zh->fd == -1)
- return ZINVALIDSTATE;
- if ((events&ZOOKEEPER_WRITE)&&(zh->state == ZOO_CONNECTING_STATE)) {
- int rc, error;
- socklen_t len = sizeof(error);
- rc = getsockopt(zh->fd, SOL_SOCKET, SO_ERROR, &error, &len);
- /* the description in section 16.4 "Non-blocking connect"
- * in UNIX Network Programming vol 1, 3rd edition, points out
- * that sometimes the error is in errno and sometimes in error */
- if (rc < 0 || error) {
- if (rc == 0)
- errno = error;
- return handle_socket_error_msg(zh, __LINE__,ZCONNECTIONLOSS,
- "server refused to accept the client");
- }
- if((rc=prime_connection(zh))!=0)
- return rc;
- LOG_INFO(("initiated connection to server [%s]",
- format_endpoint_info(&zh->addrs[zh->connect_index])));
- return ZOK;
- }
- if (zh->to_send.head && (events&ZOOKEEPER_WRITE)) {
- /* make the flush call non-blocking by specifying a 0 timeout */
- int rc=flush_send_queue(zh,0);
- if (rc < 0)
- return handle_socket_error_msg(zh,__LINE__,ZCONNECTIONLOSS,
- "failed while flushing send queue");
- }
- if (events&ZOOKEEPER_READ) {
- int rc;
- if (zh->input_buffer == 0) {
- zh->input_buffer = allocate_buffer(0,0);
- }
-
- rc = recv_buffer(zh->fd, zh->input_buffer);
- if (rc < 0) {
- return handle_socket_error_msg(zh, __LINE__,ZCONNECTIONLOSS,
- "failed while receiving a server response");
- }
- if (rc > 0) {
- gettimeofday(&zh->last_recv, 0);
- if (zh->input_buffer != &zh->primer_buffer) {
- queue_buffer(&zh->to_process, zh->input_buffer, 0);
- } else {
- int64_t oldid,newid;
- //deserialize
- deserialize_prime_response(&zh->primer_storage, zh->primer_buffer.buffer);
- /* We are processing the primer_buffer, so we need to finish
- * the connection handshake */
- oldid = zh->client_id.client_id;
- newid = zh->primer_storage.sessionId;
- if (oldid != 0 && oldid != newid) {
- zh->state = ZOO_EXPIRED_SESSION_STATE;
- errno = ESTALE;
- return handle_socket_error_msg(zh,__LINE__,ZSESSIONEXPIRED,
- "sessionId=%#llx has expired.",oldid);
- } else {
- zh->recv_timeout = zh->primer_storage.timeOut;
- zh->client_id.client_id = newid;
-
- memcpy(zh->client_id.passwd, &zh->primer_storage.passwd,
- sizeof(zh->client_id.passwd));
- zh->state = ZOO_CONNECTED_STATE;
- LOG_INFO(("session establishment complete on server [%s], sessionId=%#llx, negotiated timeout=%d",
- format_endpoint_info(&zh->addrs[zh->connect_index]),
- newid, zh->recv_timeout));
- /* we want the auth to be sent for, but since both call push to front
- we need to call send_watch_set first */
- send_set_watches(zh);
- /* send the authentication packet now */
- send_auth_info(zh);
- LOG_DEBUG(("Calling a watcher for a ZOO_SESSION_EVENT and the state=ZOO_CONNECTED_STATE"));
- zh->input_buffer = 0; // just in case the watcher calls zookeeper_process() again
- PROCESS_SESSION_EVENT(zh, ZOO_CONNECTED_STATE);
- }
- }
- zh->input_buffer = 0;
- } else {
- // zookeeper_process was called but there was nothing to read
- // from the socket
- return ZNOTHING;
- }
- }
- return ZOK;
-}
-
-void api_prolog(zhandle_t* zh)
-{
- inc_ref_counter(zh,1);
-}
-
-int api_epilog(zhandle_t *zh,int rc)
-{
- if(inc_ref_counter(zh,-1)==0 && zh->close_requested!=0)
- zookeeper_close(zh);
- return rc;
-}
-
-static __attribute__((unused)) void print_completion_queue(zhandle_t *zh)
-{
- completion_list_t* cptr;
-
- if(logLevel<ZOO_LOG_LEVEL_DEBUG) return;
-
- fprintf(LOGSTREAM,"Completion queue: ");
- if (zh->sent_requests.head==0) {
- fprintf(LOGSTREAM,"empty\n");
- return;
- }
-
- cptr=zh->sent_requests.head;
- while(cptr){
- fprintf(LOGSTREAM,"%d,",cptr->xid);
- cptr=cptr->next;
- }
- fprintf(LOGSTREAM,"end\n");
-}
-
-//#ifdef THREADED
-// IO thread queues session events to be processed by the completion thread
-static int queue_session_event(zhandle_t *zh, int state)
-{
- int rc;
- struct WatcherEvent evt = { ZOO_SESSION_EVENT, state, "" };
- struct ReplyHeader hdr = { WATCHER_EVENT_XID, 0, 0 };
- struct oarchive *oa;
- completion_list_t *cptr;
-
- if ((oa=create_buffer_oarchive())==NULL) {
- LOG_ERROR(("out of memory"));
- goto error;
- }
- rc = serialize_ReplyHeader(oa, "hdr", &hdr);
- rc = rc<0?rc: serialize_WatcherEvent(oa, "event", &evt);
- if(rc<0){
- close_buffer_oarchive(&oa, 1);
- goto error;
- }
- cptr = create_completion_entry(WATCHER_EVENT_XID,-1,0,0,0,0);
- cptr->buffer = allocate_buffer(get_buffer(oa), get_buffer_len(oa));
- cptr->buffer->curr_offset = get_buffer_len(oa);
- if (!cptr->buffer) {
- free(cptr);
- close_buffer_oarchive(&oa, 1);
- goto error;
- }
- /* We queued the buffer, so don't free it */
- close_buffer_oarchive(&oa, 0);
- cptr->c.watcher_result = collectWatchers(zh, ZOO_SESSION_EVENT, "");
- queue_completion(&zh->completions_to_process, cptr, 0);
- if (process_async(zh->outstanding_sync)) {
- process_completions(zh);
- }
- return ZOK;
-error:
- errno=ENOMEM;
- return ZSYSTEMERROR;
-}
-//#endif
-
-completion_list_t *dequeue_completion(completion_head_t *list)
-{
- completion_list_t *cptr;
- lock_completion_list(list);
- cptr = list->head;
- if (cptr) {
- list->head = cptr->next;
- if (!list->head) {
- assert(list->last == cptr);
- list->last = 0;
- }
- }
- unlock_completion_list(list);
- return cptr;
-}
-
-static void process_sync_completion(
- completion_list_t *cptr,
- struct sync_completion *sc,
- struct iarchive *ia,
- zhandle_t *zh)
-{
- LOG_DEBUG(("Processing sync_completion with type=%d xid=%#x rc=%d",
- cptr->c.type, cptr->xid, sc->rc));
-
- switch(cptr->c.type) {
- case COMPLETION_DATA:
- if (sc->rc==0) {
- struct GetDataResponse res;
- int len;
- deserialize_GetDataResponse(ia, "reply", &res);
- if (res.data.len <= sc->u.data.buff_len) {
- len = res.data.len;
- } else {
- len = sc->u.data.buff_len;
- }
- sc->u.data.buff_len = len;
- // check if len is negative
- // just of NULL which is -1 int
- if (len == -1) {
- sc->u.data.buffer = NULL;
- } else {
- memcpy(sc->u.data.buffer, res.data.buff, len);
- }
- sc->u.data.stat = res.stat;
- deallocate_GetDataResponse(&res);
- }
- break;
- case COMPLETION_STAT:
- if (sc->rc==0) {
- struct SetDataResponse res;
- deserialize_SetDataResponse(ia, "reply", &res);
- sc->u.stat = res.stat;
- deallocate_SetDataResponse(&res);
- }
- break;
- case COMPLETION_STRINGLIST:
- if (sc->rc==0) {
- struct GetChildrenResponse res;
- deserialize_GetChildrenResponse(ia, "reply", &res);
- sc->u.strs2 = res.children;
- /* We don't deallocate since we are passing it back */
- // deallocate_GetChildrenResponse(&res);
- }
- break;
- case COMPLETION_STRINGLIST_STAT:
- if (sc->rc==0) {
- struct GetChildren2Response res;
- deserialize_GetChildren2Response(ia, "reply", &res);
- sc->u.strs_stat.strs2 = res.children;
- sc->u.strs_stat.stat2 = res.stat;
- /* We don't deallocate since we are passing it back */
- // deallocate_GetChildren2Response(&res);
- }
- break;
- case COMPLETION_STRING:
- if (sc->rc==0) {
- struct CreateResponse res;
- int len;
- const char * client_path;
- deserialize_CreateResponse(ia, "reply", &res);
- //ZOOKEEPER-1027
- client_path = sub_string(zh, res.path);
- len = strlen(client_path) + 1;if (len > sc->u.str.str_len) {
- len = sc->u.str.str_len;
- }
- if (len > 0) {
- memcpy(sc->u.str.str, client_path, len - 1);
- sc->u.str.str[len - 1] = '\0';
- }
- free_duplicate_path(client_path, res.path);
- deallocate_CreateResponse(&res);
- }
- break;
- case COMPLETION_ACLLIST:
- if (sc->rc==0) {
- struct GetACLResponse res;
- deserialize_GetACLResponse(ia, "reply", &res);
- sc->u.acl.acl = res.acl;
- sc->u.acl.stat = res.stat;
- /* We don't deallocate since we are passing it back */
- //deallocate_GetACLResponse(&res);
- }
- break;
- case COMPLETION_VOID:
- break;
- case COMPLETION_MULTI:
- sc->rc = deserialize_multi(cptr->xid, cptr, ia);
- break;
- default:
- LOG_DEBUG(("Unsupported completion type=%d", cptr->c.type));
- break;
- }
-}
-
-static int deserialize_multi(int xid, completion_list_t *cptr, struct iarchive *ia)
-{
- int rc = 0;
- completion_head_t *clist = &cptr->c.clist;
- struct MultiHeader mhdr = { STRUCT_INITIALIZER(type , 0), STRUCT_INITIALIZER(done , 0), STRUCT_INITIALIZER(err , 0) };
- assert(clist);
- deserialize_MultiHeader(ia, "multiheader", &mhdr);
- while (!mhdr.done) {
- completion_list_t *entry = dequeue_completion(clist);
- assert(entry);
-
- if (mhdr.type == -1) {
- struct ErrorResponse er;
- deserialize_ErrorResponse(ia, "error", &er);
- mhdr.err = er.err ;
- if (rc == 0 && er.err != 0 && er.err != ZRUNTIMEINCONSISTENCY) {
- rc = er.err;
- }
- }
-
- deserialize_response(entry->c.type, xid, mhdr.type == -1, mhdr.err, entry, ia);
- deserialize_MultiHeader(ia, "multiheader", &mhdr);
- //While deserializing the response we must destroy completion entry for each operation in
- //the zoo_multi transaction. Otherwise this results in memory leak when client invokes zoo_multi
- //operation.
- destroy_completion_entry(entry);
- }
-
- return rc;
-}
-
-static void deserialize_response(int type, int xid, int failed, int rc, completion_list_t *cptr, struct iarchive *ia)
-{
- switch (type) {
- case COMPLETION_DATA:
- LOG_DEBUG(("Calling COMPLETION_DATA for xid=%#x failed=%d rc=%d",
- cptr->xid, failed, rc));
- if (failed) {
- cptr->c.data_result(rc, 0, 0, 0, cptr->data);
- } else {
- struct GetDataResponse res;
- deserialize_GetDataResponse(ia, "reply", &res);
- cptr->c.data_result(rc, res.data.buff, res.data.len,
- &res.stat, cptr->data);
- deallocate_GetDataResponse(&res);
- }
- break;
- case COMPLETION_STAT:
- LOG_DEBUG(("Calling COMPLETION_STAT for xid=%#x failed=%d rc=%d",
- cptr->xid, failed, rc));
- if (failed) {
- cptr->c.stat_result(rc, 0, cptr->data);
- } else {
- struct SetDataResponse res;
- deserialize_SetDataResponse(ia, "reply", &res);
- cptr->c.stat_result(rc, &res.stat, cptr->data);
- deallocate_SetDataResponse(&res);
- }
- break;
- case COMPLETION_STRINGLIST:
- LOG_DEBUG(("Calling COMPLETION_STRINGLIST for xid=%#x failed=%d rc=%d",
- cptr->xid, failed, rc));
- if (failed) {
- cptr->c.strings_result(rc, 0, cptr->data);
- } else {
- struct GetChildrenResponse res;
- deserialize_GetChildrenResponse(ia, "reply", &res);
- cptr->c.strings_result(rc, &res.children, cptr->data);
- deallocate_GetChildrenResponse(&res);
- }
- break;
- case COMPLETION_STRINGLIST_STAT:
- LOG_DEBUG(("Calling COMPLETION_STRINGLIST_STAT for xid=%#x failed=%d rc=%d",
- cptr->xid, failed, rc));
- if (failed) {
- cptr->c.strings_stat_result(rc, 0, 0, cptr->data);
- } else {
- struct GetChildren2Response res;
- deserialize_GetChildren2Response(ia, "reply", &res);
- cptr->c.strings_stat_result(rc, &res.children, &res.stat, cptr->data);
- deallocate_GetChildren2Response(&res);
- }
- break;
- case COMPLETION_STRING:
- LOG_DEBUG(("Calling COMPLETION_STRING for xid=%#x failed=%d, rc=%d",
- cptr->xid, failed, rc));
- if (failed) {
- cptr->c.string_result(rc, 0, cptr->data);
- } else {
- struct CreateResponse res;
- memset(&res, 0, sizeof(res));
- deserialize_CreateResponse(ia, "reply", &res);
- cptr->c.string_result(rc, res.path, cptr->data);
- deallocate_CreateResponse(&res);
- }
- break;
- case COMPLETION_ACLLIST:
- LOG_DEBUG(("Calling COMPLETION_ACLLIST for xid=%#x failed=%d rc=%d",
- cptr->xid, failed, rc));
- if (failed) {
- cptr->c.acl_result(rc, 0, 0, cptr->data);
- } else {
- struct GetACLResponse res;
- deserialize_GetACLResponse(ia, "reply", &res);
- cptr->c.acl_result(rc, &res.acl, &res.stat, cptr->data);
- deallocate_GetACLResponse(&res);
- }
- break;
- case COMPLETION_VOID:
- LOG_DEBUG(("Calling COMPLETION_VOID for xid=%#x failed=%d rc=%d",
- cptr->xid, failed, rc));
- assert(cptr->c.void_result);
- cptr->c.void_result(rc, cptr->data);
- break;
- case COMPLETION_MULTI:
- LOG_DEBUG(("Calling COMPLETION_MULTI for xid=%#x failed=%d rc=%d",
- cptr->xid, failed, rc));
- rc = deserialize_multi(xid, cptr, ia);
- assert(cptr->c.void_result);
- cptr->c.void_result(rc, cptr->data);
- break;
- default:
- LOG_DEBUG(("Unsupported completion type=%d", cptr->c.type));
- }
-}
-
-
-/* handles async completion (both single- and multithreaded) */
-void process_completions(zhandle_t *zh)
-{
- completion_list_t *cptr;
- while ((cptr = dequeue_completion(&zh->completions_to_process)) != 0) {
- struct ReplyHeader hdr;
- buffer_list_t *bptr = cptr->buffer;
- struct iarchive *ia = create_buffer_iarchive(bptr->buffer,
- bptr->len);
- deserialize_ReplyHeader(ia, "hdr", &hdr);
-
- if (hdr.xid == WATCHER_EVENT_XID) {
- int type, state;
- struct WatcherEvent evt;
- deserialize_WatcherEvent(ia, "event", &evt);
- /* We are doing a notification, so there is no pending request */
- type = evt.type;
- state = evt.state;
- /* This is a notification so there aren't any pending requests */
- LOG_DEBUG(("Calling a watcher for node [%s], type = %d event=%s",
- (evt.path==NULL?"NULL":evt.path), cptr->c.type,
- watcherEvent2String(type)));
- deliverWatchers(zh,type,state,evt.path, &cptr->c.watcher_result);
- deallocate_WatcherEvent(&evt);
- } else {
- deserialize_response(cptr->c.type, hdr.xid, hdr.err != 0, hdr.err, cptr, ia);
- }
- destroy_completion_entry(cptr);
- close_buffer_iarchive(&ia);
- }
-}
-
-static void isSocketReadable(zhandle_t* zh)
-{
-#ifndef WIN32
- struct pollfd fds;
- fds.fd = zh->fd;
- fds.events = POLLIN;
- if (poll(&fds,1,0)<=0) {
- // socket not readable -- no more responses to process
- zh->socket_readable.tv_sec=zh->socket_readable.tv_usec=0;
- }
-#else
- fd_set rfds;
- struct timeval waittime = {0, 0};
- FD_ZERO(&rfds);
- FD_SET( zh->fd , &rfds);
- if (select(0, &rfds, NULL, NULL, &waittime) <= 0){
- // socket not readable -- no more responses to process
- zh->socket_readable.tv_sec=zh->socket_readable.tv_usec=0;
- }
-#endif
- else{
- gettimeofday(&zh->socket_readable,0);
- }
-}
-
-static void checkResponseLatency(zhandle_t* zh)
-{
- int delay;
- struct timeval now;
-
- if(zh->socket_readable.tv_sec==0)
- return;
-
- gettimeofday(&now,0);
- delay=calculate_interval(&zh->socket_readable, &now);
- if(delay>20)
- LOG_DEBUG(("The following server response has spent at least %dms sitting in the client socket recv buffer",delay));
-
- zh->socket_readable.tv_sec=zh->socket_readable.tv_usec=0;
-}
-
-int zookeeper_process(zhandle_t *zh, int events)
-{
- buffer_list_t *bptr;
- int rc;
-
- if (zh==NULL)
- return ZBADARGUMENTS;
- if (is_unrecoverable(zh))
- return ZINVALIDSTATE;
- api_prolog(zh);
- IF_DEBUG(checkResponseLatency(zh));
- rc = check_events(zh, events);
- if (rc!=ZOK)
- return api_epilog(zh, rc);
-
- IF_DEBUG(isSocketReadable(zh));
-
- while (rc >= 0 && (bptr=dequeue_buffer(&zh->to_process))) {
- struct ReplyHeader hdr;
- struct iarchive *ia = create_buffer_iarchive(
- bptr->buffer, bptr->curr_offset);
- deserialize_ReplyHeader(ia, "hdr", &hdr);
- if (hdr.zxid > 0) {
- zh->last_zxid = hdr.zxid;
- } else {
- // fprintf(stderr, "Got %#x for %#x\n", hdr.zxid, hdr.xid);
- }
-
- if (hdr.xid == PING_XID) {
- // Ping replies can arrive out-of-order
- int elapsed = 0;
- struct timeval now;
- gettimeofday(&now, 0);
- elapsed = calculate_interval(&zh->last_ping, &now);
- LOG_DEBUG(("Got ping response in %d ms", elapsed));
- free_buffer(bptr);
- } else if (hdr.xid == WATCHER_EVENT_XID) {
- struct WatcherEvent evt;
- int type = 0;
- char *path = NULL;
- completion_list_t *c = NULL;
-
- LOG_DEBUG(("Processing WATCHER_EVENT"));
-
- deserialize_WatcherEvent(ia, "event", &evt);
- type = evt.type;
- path = evt.path;
- /* We are doing a notification, so there is no pending request */
- c = create_completion_entry(WATCHER_EVENT_XID,-1,0,0,0,0);
- c->buffer = bptr;
- c->c.watcher_result = collectWatchers(zh, type, path);
-
- // We cannot free until now, otherwise path will become invalid
- deallocate_WatcherEvent(&evt);
- queue_completion(&zh->completions_to_process, c, 0);
- } else if (hdr.xid == SET_WATCHES_XID) {
- LOG_DEBUG(("Processing SET_WATCHES"));
- free_buffer(bptr);
- } else if (hdr.xid == AUTH_XID){
- LOG_DEBUG(("Processing AUTH_XID"));
-
- /* special handling for the AUTH response as it may come back
- * out-of-band */
- auth_completion_func(hdr.err,zh);
- free_buffer(bptr);
- /* authentication completion may change the connection state to
- * unrecoverable */
- if(is_unrecoverable(zh)){
- handle_error(zh, ZAUTHFAILED);
- close_buffer_iarchive(&ia);
- return api_epilog(zh, ZAUTHFAILED);
- }
- } else {
- int rc = hdr.err;
- /* Find the request corresponding to the response */
- completion_list_t *cptr = dequeue_completion(&zh->sent_requests);
-
- /* [ZOOKEEPER-804] Don't assert if zookeeper_close has been called. */
- if (zh->close_requested == 1 && cptr == NULL) {
- LOG_DEBUG(("Completion queue has been cleared by zookeeper_close()"));
- close_buffer_iarchive(&ia);
- free_buffer(bptr);
- return api_epilog(zh,ZINVALIDSTATE);
- }
- assert(cptr);
- /* The requests are going to come back in order */
- if (cptr->xid != hdr.xid) {
- LOG_DEBUG(("Processing unexpected or out-of-order response!"));
-
- // received unexpected (or out-of-order) response
- close_buffer_iarchive(&ia);
- free_buffer(bptr);
- // put the completion back on the queue (so it gets properly
- // signaled and deallocated) and disconnect from the server
- queue_completion(&zh->sent_requests,cptr,1);
- return api_epilog(zh,
- handle_socket_error_msg(zh, __LINE__,ZRUNTIMEINCONSISTENCY,
- "unexpected server response: expected %#x, but received %#x",
- hdr.xid,cptr->xid));
- }
-
- activateWatcher(zh, cptr->watcher, rc);
-
- if (cptr->c.void_result != SYNCHRONOUS_MARKER) {
- LOG_DEBUG(("Queueing asynchronous response"));
- cptr->buffer = bptr;
- queue_completion(&zh->completions_to_process, cptr, 0);
- } else {
- struct sync_completion
- *sc = (struct sync_completion*)cptr->data;
- sc->rc = rc;
-
- process_sync_completion(cptr, sc, ia, zh);
-
- notify_sync_completion(sc);
- free_buffer(bptr);
- zh->outstanding_sync--;
- destroy_completion_entry(cptr);
- }
- }
-
- close_buffer_iarchive(&ia);
-
- }
- if (process_async(zh->outstanding_sync)) {
- process_completions(zh);
- }
- return api_epilog(zh,ZOK);}
-
-int zoo_state(zhandle_t *zh)
-{
- if(zh!=0)
- return zh->state;
- return 0;
-}
-
-static watcher_registration_t* create_watcher_registration(const char* path,
- result_checker_fn checker,watcher_fn watcher,void* ctx){
- watcher_registration_t* wo;
- if(watcher==0)
- return 0;
- wo=calloc(1,sizeof(watcher_registration_t));
- wo->path=strdup(path);
- wo->watcher=watcher;
- wo->context=ctx;
- wo->checker=checker;
- return wo;
-}
-
-static void destroy_watcher_registration(watcher_registration_t* wo){
- if(wo!=0){
- free((void*)wo->path);
- free(wo);
- }
-}
-
-static completion_list_t* create_completion_entry(int xid, int completion_type,
- const void *dc, const void *data,watcher_registration_t* wo, completion_head_t *clist)
-{
- completion_list_t *c = calloc(1,sizeof(completion_list_t));
- if (!c) {
- LOG_ERROR(("out of memory"));
- return 0;
- }
- c->c.type = completion_type;
- c->data = data;
- switch(c->c.type) {
- case COMPLETION_VOID:
- c->c.void_result = (void_completion_t)dc;
- break;
- case COMPLETION_STRING:
- c->c.string_result = (string_completion_t)dc;
- break;
- case COMPLETION_DATA:
- c->c.data_result = (data_completion_t)dc;
- break;
- case COMPLETION_STAT:
- c->c.stat_result = (stat_completion_t)dc;
- break;
- case COMPLETION_STRINGLIST:
- c->c.strings_result = (strings_completion_t)dc;
- break;
- case COMPLETION_STRINGLIST_STAT:
- c->c.strings_stat_result = (strings_stat_completion_t)dc;
- break;
- case COMPLETION_ACLLIST:
- c->c.acl_result = (acl_completion_t)dc;
- break;
- case COMPLETION_MULTI:
- assert(clist);
- c->c.void_result = (void_completion_t)dc;
- c->c.clist = *clist;
- break;
- }
- c->xid = xid;
- c->watcher = wo;
-
- return c;
-}
-
-static void destroy_completion_entry(completion_list_t* c){
- if(c!=0){
- destroy_watcher_registration(c->watcher);
- if(c->buffer!=0)
- free_buffer(c->buffer);
- free(c);
- }
-}
-
-static void queue_completion_nolock(completion_head_t *list,
- completion_list_t *c,
- int add_to_front)
-{
- c->next = 0;
- /* appending a new entry to the back of the list */
- if (list->last) {
- assert(list->head);
- // List is not empty
- if (!add_to_front) {
- list->last->next = c;
- list->last = c;
- } else {
- c->next = list->head;
- list->head = c;
- }
- } else {
- // List is empty
- assert(!list->head);
- list->head = c;
- list->last = c;
- }
-}
-
-static void queue_completion(completion_head_t *list, completion_list_t *c,
- int add_to_front)
-{
-
- lock_completion_list(list);
- queue_completion_nolock(list, c, add_to_front);
- unlock_completion_list(list);
-}
-
-static int add_completion(zhandle_t *zh, int xid, int completion_type,
- const void *dc, const void *data, int add_to_front,
- watcher_registration_t* wo, completion_head_t *clist)
-{
- completion_list_t *c =create_completion_entry(xid, completion_type, dc,
- data, wo, clist);
- int rc = 0;
- if (!c)
- return ZSYSTEMERROR;
- lock_completion_list(&zh->sent_requests);
- if (zh->close_requested != 1) {
- queue_completion_nolock(&zh->sent_requests, c, add_to_front);
- if (dc == SYNCHRONOUS_MARKER) {
- zh->outstanding_sync++;
- }
- rc = ZOK;
- } else {
- free(c);
- rc = ZINVALIDSTATE;
- }
- unlock_completion_list(&zh->sent_requests);
- return rc;
-}
-
-static int add_data_completion(zhandle_t *zh, int xid, data_completion_t dc,
- const void *data,watcher_registration_t* wo)
-{
- return add_completion(zh, xid, COMPLETION_DATA, dc, data, 0, wo, 0);
-}
-
-static int add_stat_completion(zhandle_t *zh, int xid, stat_completion_t dc,
- const void *data,watcher_registration_t* wo)
-{
- return add_completion(zh, xid, COMPLETION_STAT, dc, data, 0, wo, 0);
-}
-
-static int add_strings_completion(zhandle_t *zh, int xid,
- strings_completion_t dc, const void *data,watcher_registration_t* wo)
-{
- return add_completion(zh, xid, COMPLETION_STRINGLIST, dc, data, 0, wo, 0);
-}
-
-static int add_strings_stat_completion(zhandle_t *zh, int xid,
- strings_stat_completion_t dc, const void *data,watcher_registration_t* wo)
-{
- return add_completion(zh, xid, COMPLETION_STRINGLIST_STAT, dc, data, 0, wo, 0);
-}
-
-static int add_acl_completion(zhandle_t *zh, int xid, acl_completion_t dc,
- const void *data)
-{
- return add_completion(zh, xid, COMPLETION_ACLLIST, dc, data, 0, 0, 0);
-}
-
-static int add_void_completion(zhandle_t *zh, int xid, void_completion_t dc,
- const void *data)
-{
- return add_completion(zh, xid, COMPLETION_VOID, dc, data, 0, 0, 0);
-}
-
-static int add_string_completion(zhandle_t *zh, int xid,
- string_completion_t dc, const void *data)
-{
- return add_completion(zh, xid, COMPLETION_STRING, dc, data, 0, 0, 0);
-}
-
-static int add_multi_completion(zhandle_t *zh, int xid, void_completion_t dc,
- const void *data, completion_head_t *clist)
-{
- return add_completion(zh, xid, COMPLETION_MULTI, dc, data, 0,0, clist);
-}
-
-int zookeeper_close(zhandle_t *zh)
-{
- int rc=ZOK;
- if (zh==0)
- return ZBADARGUMENTS;
-
- zh->close_requested=1;
- if (inc_ref_counter(zh,1)>1) {
- /* We have incremented the ref counter to prevent the
- * completions from calling zookeeper_close before we have
- * completed the adaptor_finish call below. */
-
- /* Signal any syncronous completions before joining the threads */
- enter_critical(zh);
- free_completions(zh,1,ZCLOSING);
- leave_critical(zh);
-
- adaptor_finish(zh);
- /* Now we can allow the handle to be cleaned up, if the completion
- * threads finished during the adaptor_finish call. */
- api_epilog(zh, 0);
- return ZOK;
- }
- /* No need to decrement the counter since we're just going to
- * destroy the handle later. */
- if(zh->state==ZOO_CONNECTED_STATE){
- struct oarchive *oa;
- struct RequestHeader h = { STRUCT_INITIALIZER (xid , get_xid()), STRUCT_INITIALIZER (type , ZOO_CLOSE_OP)};
- LOG_INFO(("Closing zookeeper sessionId=%#llx to [%s]\n",
- zh->client_id.client_id,format_current_endpoint_info(zh)));
- oa = create_buffer_oarchive();
- rc = serialize_RequestHeader(oa, "header", &h);
- rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa),
- get_buffer_len(oa));
- /* We queued the buffer, so don't free it */
- close_buffer_oarchive(&oa, 0);
- if (rc < 0) {
- rc = ZMARSHALLINGERROR;
- goto finish;
- }
-
- /* make sure the close request is sent; we set timeout to an arbitrary
- * (but reasonable) number of milliseconds since we want the call to block*/
- rc=adaptor_send_queue(zh, 3000);
- }else{
- LOG_INFO(("Freeing zookeeper resources for sessionId=%#llx\n",
- zh->client_id.client_id));
- rc = ZOK;
- }
-
-finish:
- destroy(zh);
- adaptor_destroy(zh);
- free(zh);
-#ifdef WIN32
- Win32WSACleanup();
-#endif
- return rc;
-}
-
-static int isValidPath(const char* path, const int flags) {
- int len = 0;
- char lastc = '/';
- char c;
- int i = 0;
-
- if (path == 0)
- return 0;
- len = strlen(path);
- if (len == 0)
- return 0;
- if (path[0] != '/')
- return 0;
- if (len == 1) // done checking - it's the root
- return 1;
- if (path[len - 1] == '/' && !(flags & ZOO_SEQUENCE))
- return 0;
-
- i = 1;
- for (; i < len; lastc = path[i], i++) {
- c = path[i];
-
- if (c == 0) {
- return 0;
- } else if (c == '/' && lastc == '/') {
- return 0;
- } else if (c == '.' && lastc == '.') {
- if (path[i-2] == '/' && (((i + 1 == len) && !(flags & ZOO_SEQUENCE))
- || path[i+1] == '/')) {
- return 0;
- }
- } else if (c == '.') {
- if ((path[i-1] == '/') && (((i + 1 == len) && !(flags & ZOO_SEQUENCE))
- || path[i+1] == '/')) {
- return 0;
- }
- } else if (c > 0x00 && c < 0x1f) {
- return 0;
- }
- }
-
- return 1;
-}
-
-/*---------------------------------------------------------------------------*
- * REQUEST INIT HELPERS
- *---------------------------------------------------------------------------*/
-/* Common Request init helper functions to reduce code duplication */
-static int Request_path_init(zhandle_t *zh, int flags,
- char **path_out, const char *path)
-{
- assert(path_out);
-
- *path_out = prepend_string(zh, path);
- if (zh == NULL || !isValidPath(*path_out, flags)) {
- free_duplicate_path(*path_out, path);
- return ZBADARGUMENTS;
- }
- if (is_unrecoverable(zh)) {
- free_duplicate_path(*path_out, path);
- return ZINVALIDSTATE;
- }
-
- return ZOK;
-}
-
-static int Request_path_watch_init(zhandle_t *zh, int flags,
- char **path_out, const char *path,
- int32_t *watch_out, uint32_t watch)
-{
- int rc = Request_path_init(zh, flags, path_out, path);
- if (rc != ZOK) {
- return rc;
- }
- *watch_out = watch;
- return ZOK;
-}
-
-/*---------------------------------------------------------------------------*
- * ASYNC API
- *---------------------------------------------------------------------------*/
-int zoo_aget(zhandle_t *zh, const char *path, int watch, data_completion_t dc,
- const void *data)
-{
- return zoo_awget(zh,path,watch?zh->watcher:0,zh->context,dc,data);
-}
-
-int zoo_awget(zhandle_t *zh, const char *path,
- watcher_fn watcher, void* watcherCtx,
- data_completion_t dc, const void *data)
-{
- struct oarchive *oa;
- char *server_path = prepend_string(zh, path);
- struct RequestHeader h = { STRUCT_INITIALIZER (xid , get_xid()), STRUCT_INITIALIZER (type ,ZOO_GETDATA_OP)};
- struct GetDataRequest req = { (char*)server_path, watcher!=0 };
- int rc;
-
- if (zh==0 || !isValidPath(server_path, 0)) {
- free_duplicate_path(server_path, path);
- return ZBADARGUMENTS;
- }
- if (is_unrecoverable(zh)) {
- free_duplicate_path(server_path, path);
- return ZINVALIDSTATE;
- }
- oa=create_buffer_oarchive();
- rc = serialize_RequestHeader(oa, "header", &h);
- rc = rc < 0 ? rc : serialize_GetDataRequest(oa, "req", &req);
- enter_critical(zh);
- rc = rc < 0 ? rc : add_data_completion(zh, h.xid, dc, data,
- create_watcher_registration(server_path,data_result_checker,watcher,watcherCtx));
- rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa),
- get_buffer_len(oa));
- leave_critical(zh);
- free_duplicate_path(server_path, path);
- /* We queued the buffer, so don't free it */
- close_buffer_oarchive(&oa, 0);
-
- LOG_DEBUG(("Sending request xid=%#x for path [%s] to %s",h.xid,path,
- format_current_endpoint_info(zh)));
- /* make a best (non-blocking) effort to send the requests asap */
- adaptor_send_queue(zh, 0);
- return (rc < 0)?ZMARSHALLINGERROR:ZOK;
-}
-
-static int SetDataRequest_init(zhandle_t *zh, struct SetDataRequest *req,
- const char *path, const char *buffer, int buflen, int version)
-{
- int rc;
- assert(req);
- rc = Request_path_init(zh, 0, &req->path, path);
- if (rc != ZOK) {
- return rc;
- }
- req->data.buff = (char*)buffer;
- req->data.len = buflen;
- req->version = version;
-
- return ZOK;
-}
-
-int zoo_aset(zhandle_t *zh, const char *path, const char *buffer, int buflen,
- int version, stat_completion_t dc, const void *data)
-{
- struct oarchive *oa;
- struct RequestHeader h = { STRUCT_INITIALIZER(xid , get_xid()), STRUCT_INITIALIZER (type , ZOO_SETDATA_OP)};
- struct SetDataRequest req;
- int rc = SetDataRequest_init(zh, &req, path, buffer, buflen, version);
- if (rc != ZOK) {
- return rc;
- }
- oa = create_buffer_oarchive();
- rc = serialize_RequestHeader(oa, "header", &h);
- rc = rc < 0 ? rc : serialize_SetDataRequest(oa, "req", &req);
- enter_critical(zh);
- rc = rc < 0 ? rc : add_stat_completion(zh, h.xid, dc, data,0);
- rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa),
- get_buffer_len(oa));
- leave_criti
<TRUNCATED>
[13/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/TestClient.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/TestClient.cc b/src/c/tests/TestClient.cc
deleted file mode 100644
index 154fbed..0000000
--- a/src/c/tests/TestClient.cc
+++ /dev/null
@@ -1,1135 +0,0 @@
-/**
- * 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 <cppunit/extensions/HelperMacros.h>
-#include "CppAssertHelper.h"
-
-#include <signal.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/select.h>
-
-#include "CollectionUtil.h"
-#include "ThreadingUtil.h"
-
-using namespace Util;
-
-#include "Vector.h"
-using namespace std;
-
-#include <cstring>
-#include <list>
-
-#include <zookeeper.h>
-#include <errno.h>
-#include <recordio.h>
-#include "Util.h"
-
-struct buff_struct_2 {
- int32_t len;
- int32_t off;
- char *buffer;
-};
-
-static int Stat_eq(struct Stat* a, struct Stat* b)
-{
- if (a->czxid != b->czxid) return 0;
- if (a->mzxid != b->mzxid) return 0;
- if (a->ctime != b->ctime) return 0;
- if (a->mtime != b->mtime) return 0;
- if (a->version != b->version) return 0;
- if (a->cversion != b->cversion) return 0;
- if (a->aversion != b->aversion) return 0;
- if (a->ephemeralOwner != b->ephemeralOwner) return 0;
- if (a->dataLength != b->dataLength) return 0;
- if (a->numChildren != b->numChildren) return 0;
- if (a->pzxid != b->pzxid) return 0;
- return 1;
-}
-#ifdef THREADED
- static void yield(zhandle_t *zh, int i)
- {
- sleep(i);
- }
-#else
- static void yield(zhandle_t *zh, int seconds)
- {
- int fd;
- int interest;
- int events;
- struct timeval tv;
- int rc;
- time_t expires = time(0) + seconds;
- time_t timeLeft = seconds;
- fd_set rfds, wfds, efds;
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- FD_ZERO(&efds);
-
- while(timeLeft >= 0) {
- 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);
- if (tv.tv_sec > timeLeft) {
- tv.tv_sec = timeLeft;
- }
- rc = select(fd+1, &rfds, &wfds, &efds, &tv);
- timeLeft = expires - time(0);
- events = 0;
- if (FD_ISSET(fd, &rfds)) {
- events |= ZOOKEEPER_READ;
- }
- if (FD_ISSET(fd, &wfds)) {
- events |= ZOOKEEPER_WRITE;
- }
- zookeeper_process(zh, events);
- }
- }
-#endif
-
-typedef struct evt {
- string path;
- int type;
-} evt_t;
-
-typedef struct watchCtx {
-private:
- list<evt_t> events;
- watchCtx(const watchCtx&);
- watchCtx& operator=(const watchCtx&);
-public:
- bool connected;
- zhandle_t *zh;
- Mutex mutex;
-
- watchCtx() {
- connected = false;
- zh = 0;
- }
- ~watchCtx() {
- if (zh) {
- zookeeper_close(zh);
- zh = 0;
- }
- }
-
- evt_t getEvent() {
- evt_t evt;
- mutex.acquire();
- CPPUNIT_ASSERT( events.size() > 0);
- evt = events.front();
- events.pop_front();
- mutex.release();
- return evt;
- }
-
- int countEvents() {
- int count;
- mutex.acquire();
- count = events.size();
- mutex.release();
- return count;
- }
-
- void putEvent(evt_t evt) {
- mutex.acquire();
- events.push_back(evt);
- mutex.release();
- }
-
- bool waitForConnected(zhandle_t *zh) {
- time_t expires = time(0) + 10;
- while(!connected && time(0) < expires) {
- yield(zh, 1);
- }
- return connected;
- }
- bool waitForDisconnected(zhandle_t *zh) {
- time_t expires = time(0) + 15;
- while(connected && time(0) < expires) {
- yield(zh, 1);
- }
- return !connected;
- }
-} watchctx_t;
-
-class Zookeeper_simpleSystem : public CPPUNIT_NS::TestFixture
-{
- CPPUNIT_TEST_SUITE(Zookeeper_simpleSystem);
- CPPUNIT_TEST(testAsyncWatcherAutoReset);
- CPPUNIT_TEST(testDeserializeString);
- CPPUNIT_TEST(testFirstServerDown);
-#ifdef THREADED
- CPPUNIT_TEST(testNullData);
-#ifdef ZOO_IPV6_ENABLED
- CPPUNIT_TEST(testIPV6);
-#endif
- CPPUNIT_TEST(testPath);
- CPPUNIT_TEST(testPathValidation);
- CPPUNIT_TEST(testPing);
- CPPUNIT_TEST(testAcl);
- CPPUNIT_TEST(testChroot);
- CPPUNIT_TEST(testAuth);
- CPPUNIT_TEST(testHangingClient);
- CPPUNIT_TEST(testWatcherAutoResetWithGlobal);
- CPPUNIT_TEST(testWatcherAutoResetWithLocal);
- CPPUNIT_TEST(testGetChildren2);
-#endif
- CPPUNIT_TEST_SUITE_END();
-
- static void watcher(zhandle_t *, int type, int state, const char *path,void*v){
- watchctx_t *ctx = (watchctx_t*)v;
-
- if (state == ZOO_CONNECTED_STATE) {
- ctx->connected = true;
- } else {
- ctx->connected = false;
- }
- if (type != ZOO_SESSION_EVENT) {
- evt_t evt;
- evt.path = path;
- evt.type = type;
- ctx->putEvent(evt);
- }
- }
-
- static const char hostPorts[];
-
- const char *getHostPorts() {
- return hostPorts;
- }
-
- zhandle_t *createClient(watchctx_t *ctx) {
- return createClient(hostPorts, ctx);
- }
-
- zhandle_t *createClient(const char *hp, watchctx_t *ctx) {
- zhandle_t *zk = zookeeper_init(hp, watcher, 10000, 0, ctx, 0);
- ctx->zh = zk;
- sleep(1);
- return zk;
- }
-
- zhandle_t *createchClient(watchctx_t *ctx, const char* chroot) {
- zhandle_t *zk = zookeeper_init(chroot, watcher, 10000, 0, ctx, 0);
- ctx->zh = zk;
- sleep(1);
- return zk;
- }
-
- FILE *logfile;
-public:
-
- Zookeeper_simpleSystem() {
- logfile = openlogfile("Zookeeper_simpleSystem");
- }
-
- ~Zookeeper_simpleSystem() {
- if (logfile) {
- fflush(logfile);
- fclose(logfile);
- logfile = 0;
- }
- }
-
- void setUp()
- {
- zoo_set_log_stream(logfile);
- }
-
-
- void startServer() {
- char cmd[1024];
- sprintf(cmd, "%s start %s", ZKSERVER_CMD, getHostPorts());
- CPPUNIT_ASSERT(system(cmd) == 0);
- }
-
- void stopServer() {
- char cmd[1024];
- sprintf(cmd, "%s stop %s", ZKSERVER_CMD, getHostPorts());
- CPPUNIT_ASSERT(system(cmd) == 0);
- }
-
- void tearDown()
- {
- }
-
- /** have a callback in the default watcher **/
- static void default_zoo_watcher(zhandle_t *zzh, int type, int state, const char *path, void *context){
- int zrc = 0;
- struct String_vector str_vec = {0, NULL};
- zrc = zoo_wget_children(zzh, "/mytest", default_zoo_watcher, NULL, &str_vec);
- }
-
- /** ZOOKEEPER-1057 This checks that the client connects to the second server when the first is not reachable **/
- void testFirstServerDown() {
- watchctx_t ctx;
-
- zoo_deterministic_conn_order(true);
-
- zhandle_t* zk = createClient("127.0.0.1:22182,127.0.0.1:22181", &ctx);
- CPPUNIT_ASSERT(zk != 0);
- CPPUNIT_ASSERT(ctx.waitForConnected(zk));
- }
-
- /** this checks for a deadlock in calling zookeeper_close and calls from a default watcher that might get triggered just when zookeeper_close() is in progress **/
- void testHangingClient() {
- int zrc = 0;
- char buff[10] = "testall";
- char path[512];
- watchctx_t *ctx;
- struct String_vector str_vec = {0, NULL};
- zhandle_t *zh = zookeeper_init(hostPorts, NULL, 10000, 0, ctx, 0);
- sleep(1);
- zrc = zoo_create(zh, "/mytest", buff, 10, &ZOO_OPEN_ACL_UNSAFE, 0, path, 512);
- zrc = zoo_wget_children(zh, "/mytest", default_zoo_watcher, NULL, &str_vec);
- zrc = zoo_create(zh, "/mytest/test1", buff, 10, &ZOO_OPEN_ACL_UNSAFE, 0, path, 512);
- zrc = zoo_wget_children(zh, "/mytest", default_zoo_watcher, NULL, &str_vec);
- zrc = zoo_delete(zh, "/mytest/test1", -1);
- zookeeper_close(zh);
- }
-
-
- void testPing()
- {
- watchctx_t ctxIdle;
- watchctx_t ctxWC;
- zhandle_t *zkIdle = createClient(&ctxIdle);
- zhandle_t *zkWatchCreator = createClient(&ctxWC);
-
- CPPUNIT_ASSERT(zkIdle);
- CPPUNIT_ASSERT(zkWatchCreator);
-
- char path[80];
- sprintf(path, "/testping");
- int rc = zoo_create(zkWatchCreator, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- for(int i = 0; i < 30; i++) {
- sprintf(path, "/testping/%i", i);
- rc = zoo_create(zkWatchCreator, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- }
-
- for(int i = 0; i < 30; i++) {
- sprintf(path, "/testping/%i", i);
- struct Stat stat;
- rc = zoo_exists(zkIdle, path, 1, &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- }
-
- for(int i = 0; i < 30; i++) {
- sprintf(path, "/testping/%i", i);
- usleep(500000);
- rc = zoo_delete(zkWatchCreator, path, -1);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- }
- struct Stat stat;
- CPPUNIT_ASSERT_EQUAL((int)ZNONODE, zoo_exists(zkIdle, "/testping/0", 0, &stat));
- }
-
- bool waitForEvent(zhandle_t *zh, watchctx_t *ctx, int seconds) {
- time_t expires = time(0) + seconds;
- while(ctx->countEvents() == 0 && time(0) < expires) {
- yield(zh, 1);
- }
- return ctx->countEvents() > 0;
- }
-
-#define COUNT 100
-
- static zhandle_t *async_zk;
- static volatile int count;
- static const char* hp_chroot;
-
- static void statCompletion(int rc, const struct Stat *stat, const void *data) {
- int tmp = (int) (long) data;
- CPPUNIT_ASSERT_EQUAL(tmp, rc);
- }
-
- static void stringCompletion(int rc, const char *value, const void *data) {
- char *path = (char*)data;
-
- if (rc == ZCONNECTIONLOSS && path) {
- // Try again
- rc = zoo_acreate(async_zk, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, stringCompletion, 0);
- } else if (rc != ZOK) {
- // fprintf(stderr, "rc = %d with path = %s\n", rc, (path ? path : "null"));
- }
- if (path) {
- free(path);
- }
- }
-
- static void create_completion_fn(int rc, const char* value, const void *data) {
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- count++;
- }
-
- static void waitForCreateCompletion(int seconds) {
- time_t expires = time(0) + seconds;
- while(count == 0 && time(0) < expires) {
- sleep(1);
- }
- count--;
- }
-
- static void watcher_chroot_fn(zhandle_t *zh, int type,
- int state, const char *path,void *watcherCtx) {
- // check for path
- char *client_path = (char *) watcherCtx;
- CPPUNIT_ASSERT(strcmp(client_path, path) == 0);
- count ++;
- }
-
- static void waitForChrootWatch(int seconds) {
- time_t expires = time(0) + seconds;
- while (count == 0 && time(0) < expires) {
- sleep(1);
- }
- count--;
- }
-
- static void waitForVoidCompletion(int seconds) {
- time_t expires = time(0) + seconds;
- while(count == 0 && time(0) < expires) {
- sleep(1);
- }
- count--;
- }
-
- static void voidCompletion(int rc, const void *data) {
- int tmp = (int) (long) data;
- CPPUNIT_ASSERT_EQUAL(tmp, rc);
- count++;
- }
-
- static void verifyCreateFails(const char *path, zhandle_t *zk) {
- CPPUNIT_ASSERT_EQUAL((int)ZBADARGUMENTS, zoo_create(zk,
- path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0));
- }
-
- static void verifyCreateOk(const char *path, zhandle_t *zk) {
- CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_create(zk,
- path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0));
- }
-
- static void verifyCreateFailsSeq(const char *path, zhandle_t *zk) {
- CPPUNIT_ASSERT_EQUAL((int)ZBADARGUMENTS, zoo_create(zk,
- path, "", 0, &ZOO_OPEN_ACL_UNSAFE, ZOO_SEQUENCE, 0, 0));
- }
-
- static void verifyCreateOkSeq(const char *path, zhandle_t *zk) {
- CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_create(zk,
- path, "", 0, &ZOO_OPEN_ACL_UNSAFE, ZOO_SEQUENCE, 0, 0));
- }
-
-
- /**
- returns false if the vectors dont match
- **/
- bool compareAcl(struct ACL_vector acl1, struct ACL_vector acl2) {
- if (acl1.count != acl2.count) {
- return false;
- }
- struct ACL *aclval1 = acl1.data;
- struct ACL *aclval2 = acl2.data;
- if (aclval1->perms != aclval2->perms) {
- return false;
- }
- struct Id id1 = aclval1->id;
- struct Id id2 = aclval2->id;
- if (strcmp(id1.scheme, id2.scheme) != 0) {
- return false;
- }
- if (strcmp(id1.id, id2.id) != 0) {
- return false;
- }
- return true;
- }
-
- void testDeserializeString() {
- char *val_str;
- int rc = 0;
- int val = -1;
- struct iarchive *ia;
- struct buff_struct_2 *b;
- struct oarchive *oa = create_buffer_oarchive();
- oa->serialize_Int(oa, "int", &val);
- b = (struct buff_struct_2 *) oa->priv;
- ia = create_buffer_iarchive(b->buffer, b->len);
- rc = ia->deserialize_String(ia, "string", &val_str);
- CPPUNIT_ASSERT_EQUAL(-EINVAL, rc);
- }
-
- void testAcl() {
- int rc;
- struct ACL_vector aclvec;
- struct Stat stat;
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
- rc = zoo_create(zk, "/acl", "", 0,
- &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- rc = zoo_get_acl(zk, "/acl", &aclvec, &stat );
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- bool cmp = compareAcl(ZOO_OPEN_ACL_UNSAFE, aclvec);
- CPPUNIT_ASSERT_EQUAL(true, cmp);
- rc = zoo_set_acl(zk, "/acl", -1, &ZOO_READ_ACL_UNSAFE);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- rc = zoo_get_acl(zk, "/acl", &aclvec, &stat);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- cmp = compareAcl(ZOO_READ_ACL_UNSAFE, aclvec);
- CPPUNIT_ASSERT_EQUAL(true, cmp);
- }
-
-
- void testAuth() {
- int rc;
- count = 0;
- watchctx_t ctx1, ctx2, ctx3, ctx4, ctx5;
- zhandle_t *zk = createClient(&ctx1);
- struct ACL_vector nodeAcl;
- struct ACL acl_val;
- rc = zoo_add_auth(0, "", 0, 0, voidCompletion, (void*)-1);
- CPPUNIT_ASSERT_EQUAL((int) ZBADARGUMENTS, rc);
-
- rc = zoo_add_auth(zk, 0, 0, 0, voidCompletion, (void*)-1);
- CPPUNIT_ASSERT_EQUAL((int) ZBADARGUMENTS, rc);
-
- // auth as pat, create /tauth1, close session
- rc = zoo_add_auth(zk, "digest", "pat:passwd", 10, voidCompletion,
- (void*)ZOK);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- waitForVoidCompletion(3);
- CPPUNIT_ASSERT(count == 0);
-
- rc = zoo_create(zk, "/tauth1", "", 0, &ZOO_CREATOR_ALL_ACL, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- {
- //create a new client
- zk = createClient(&ctx4);
- rc = zoo_add_auth(zk, "digest", "", 0, voidCompletion, (void*)ZOK);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- waitForVoidCompletion(3);
- CPPUNIT_ASSERT(count == 0);
-
- rc = zoo_add_auth(zk, "digest", "", 0, voidCompletion, (void*)ZOK);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- waitForVoidCompletion(3);
- CPPUNIT_ASSERT(count == 0);
- }
-
- //create a new client
- zk = createClient(&ctx2);
-
- rc = zoo_add_auth(zk, "digest", "pat:passwd2", 11, voidCompletion,
- (void*)ZOK);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- waitForVoidCompletion(3);
- CPPUNIT_ASSERT(count == 0);
-
- char buf[1024];
- int blen = sizeof(buf);
- struct Stat stat;
- rc = zoo_get(zk, "/tauth1", 0, buf, &blen, &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZNOAUTH, rc);
- // add auth pat w/correct pass verify success
- rc = zoo_add_auth(zk, "digest", "pat:passwd", 10, voidCompletion,
- (void*)ZOK);
-
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- rc = zoo_get(zk, "/tauth1", 0, buf, &blen, &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- waitForVoidCompletion(3);
- CPPUNIT_ASSERT(count == 0);
- //create a new client
- zk = createClient(&ctx3);
- rc = zoo_add_auth(zk, "digest", "pat:passwd", 10, voidCompletion, (void*) ZOK);
- waitForVoidCompletion(3);
- CPPUNIT_ASSERT(count == 0);
- rc = zoo_add_auth(zk, "ip", "none", 4, voidCompletion, (void*)ZOK);
- //make the server forget the auths
- waitForVoidCompletion(3);
- CPPUNIT_ASSERT(count == 0);
-
- stopServer();
- CPPUNIT_ASSERT(ctx3.waitForDisconnected(zk));
- startServer();
- CPPUNIT_ASSERT(ctx3.waitForConnected(zk));
- // now try getting the data
- rc = zoo_get(zk, "/tauth1", 0, buf, &blen, &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- // also check for get
- rc = zoo_get_acl(zk, "/", &nodeAcl, &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- // check if the acl has all the perms
- CPPUNIT_ASSERT_EQUAL((int)1, (int)nodeAcl.count);
- acl_val = *(nodeAcl.data);
- CPPUNIT_ASSERT_EQUAL((int) acl_val.perms, ZOO_PERM_ALL);
- // verify on root node
- rc = zoo_set_acl(zk, "/", -1, &ZOO_CREATOR_ALL_ACL);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
-
- rc = zoo_set_acl(zk, "/", -1, &ZOO_OPEN_ACL_UNSAFE);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
-
- //[ZOOKEEPER-1108], test that auth info is sent to server, if client is not
- //connected to server when zoo_add_auth was called.
- zhandle_t *zk_auth = zookeeper_init(hostPorts, NULL, 10000, 0, NULL, 0);
- rc = zoo_add_auth(zk_auth, "digest", "pat:passwd", 10, voidCompletion, (void*)ZOK);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- sleep(2);
- CPPUNIT_ASSERT(count == 1);
- count = 0;
- CPPUNIT_ASSERT_EQUAL((int) ZOK, zookeeper_close(zk_auth));
-
- // [ZOOKEEPER-800] zoo_add_auth should return ZINVALIDSTATE if
- // the connection is closed.
- zhandle_t *zk2 = zookeeper_init(hostPorts, NULL, 10000, 0, NULL, 0);
- sleep(1);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, zookeeper_close(zk2));
- CPPUNIT_ASSERT_EQUAL(0, zoo_state(zk2)); // 0 ==> ZOO_CLOSED_STATE
- rc = zoo_add_auth(zk2, "digest", "pat:passwd", 10, voidCompletion, (void*)ZOK);
- CPPUNIT_ASSERT_EQUAL((int) ZINVALIDSTATE, rc);
-
- struct sockaddr addr;
- socklen_t addr_len = sizeof(addr);
- zk = createClient(&ctx5);
- stopServer();
- CPPUNIT_ASSERT(ctx5.waitForDisconnected(zk));
- CPPUNIT_ASSERT(zookeeper_get_connected_host(zk, &addr, &addr_len) == NULL);
- addr_len = sizeof(addr);
- startServer();
- CPPUNIT_ASSERT(ctx5.waitForConnected(zk));
- CPPUNIT_ASSERT(zookeeper_get_connected_host(zk, &addr, &addr_len) != NULL);
- }
-
- void testGetChildren2() {
- int rc;
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
-
- rc = zoo_create(zk, "/parent", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- rc = zoo_create(zk, "/parent/child_a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- rc = zoo_create(zk, "/parent/child_b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- rc = zoo_create(zk, "/parent/child_c", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- rc = zoo_create(zk, "/parent/child_d", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- struct String_vector strings;
- struct Stat stat_a, stat_b;
-
- rc = zoo_get_children2(zk, "/parent", 0, &strings, &stat_a);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- rc = zoo_exists(zk, "/parent", 0, &stat_b);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- CPPUNIT_ASSERT(Stat_eq(&stat_a, &stat_b));
- CPPUNIT_ASSERT(stat_a.numChildren == 4);
- }
-
- void testIPV6() {
- watchctx_t ctx;
- zhandle_t *zk = createClient("::1:22181", &ctx);
- CPPUNIT_ASSERT(zk);
- int rc = 0;
- rc = zoo_create(zk, "/ipv6", NULL, -1,
- &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- }
-
- void testNullData() {
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
- CPPUNIT_ASSERT(zk);
- int rc = 0;
- rc = zoo_create(zk, "/mahadev", NULL, -1,
- &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- char buffer[512];
- struct Stat stat;
- int len = 512;
- rc = zoo_wget(zk, "/mahadev", NULL, NULL, buffer, &len, &stat);
- CPPUNIT_ASSERT_EQUAL( -1, len);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- rc = zoo_set(zk, "/mahadev", NULL, -1, -1);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- rc = zoo_wget(zk, "/mahadev", NULL, NULL, buffer, &len, &stat);
- CPPUNIT_ASSERT_EQUAL( -1, len);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- }
-
- void testPath() {
- watchctx_t ctx;
- char pathbuf[20];
- zhandle_t *zk = createClient(&ctx);
- CPPUNIT_ASSERT(zk);
- int rc = 0;
-
- memset(pathbuf, 'X', 20);
- rc = zoo_create(zk, "/testpathpath0", "", 0,
- &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 0);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- CPPUNIT_ASSERT_EQUAL('X', pathbuf[0]);
-
- rc = zoo_create(zk, "/testpathpath1", "", 0,
- &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 1);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- CPPUNIT_ASSERT(strlen(pathbuf) == 0);
-
- rc = zoo_create(zk, "/testpathpath2", "", 0,
- &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 2);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- CPPUNIT_ASSERT(strcmp(pathbuf, "/") == 0);
-
- rc = zoo_create(zk, "/testpathpath3", "", 0,
- &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 3);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- CPPUNIT_ASSERT(strcmp(pathbuf, "/t") == 0);
-
- rc = zoo_create(zk, "/testpathpath7", "", 0,
- &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 15);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- CPPUNIT_ASSERT(strcmp(pathbuf, "/testpathpath7") == 0);
-
- rc = zoo_create(zk, "/testpathpath8", "", 0,
- &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 16);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- CPPUNIT_ASSERT(strcmp(pathbuf, "/testpathpath8") == 0);
- }
-
- void testPathValidation() {
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
- CPPUNIT_ASSERT(zk);
-
- verifyCreateFails(0, zk);
- verifyCreateFails("", zk);
- verifyCreateFails("//", zk);
- verifyCreateFails("///", zk);
- verifyCreateFails("////", zk);
- verifyCreateFails("/.", zk);
- verifyCreateFails("/..", zk);
- verifyCreateFails("/./", zk);
- verifyCreateFails("/../", zk);
- verifyCreateFails("/foo/./", zk);
- verifyCreateFails("/foo/../", zk);
- verifyCreateFails("/foo/.", zk);
- verifyCreateFails("/foo/..", zk);
- verifyCreateFails("/./.", zk);
- verifyCreateFails("/../..", zk);
- verifyCreateFails("/foo/bar/", zk);
- verifyCreateFails("/foo//bar", zk);
- verifyCreateFails("/foo/bar//", zk);
-
- verifyCreateFails("foo", zk);
- verifyCreateFails("a", zk);
-
- // verify that trailing fails, except for seq which adds suffix
- verifyCreateOk("/createseq", zk);
- verifyCreateFails("/createseq/", zk);
- verifyCreateOkSeq("/createseq/", zk);
- verifyCreateOkSeq("/createseq/.", zk);
- verifyCreateOkSeq("/createseq/..", zk);
- verifyCreateFailsSeq("/createseq//", zk);
- verifyCreateFailsSeq("/createseq/./", zk);
- verifyCreateFailsSeq("/createseq/../", zk);
-
- verifyCreateOk("/.foo", zk);
- verifyCreateOk("/.f.", zk);
- verifyCreateOk("/..f", zk);
- verifyCreateOk("/..f..", zk);
- verifyCreateOk("/f.c", zk);
- verifyCreateOk("/f", zk);
- verifyCreateOk("/f/.f", zk);
- verifyCreateOk("/f/f.", zk);
- verifyCreateOk("/f/..f", zk);
- verifyCreateOk("/f/f..", zk);
- verifyCreateOk("/f/.f/f", zk);
- verifyCreateOk("/f/f./f", zk);
- }
-
- void testChroot() {
- // the c client async callbacks do
- // not callback with the path, so
- // we dont need to test taht for now
- // we should fix that though soon!
- watchctx_t ctx, ctx_ch;
- zhandle_t *zk, *zk_ch;
- char buf[60];
- int rc, len;
- struct Stat stat;
- const char* data = "garbage";
- const char* retStr = "/chroot";
- const char* root= "/";
- zk_ch = createchClient(&ctx_ch, "127.0.0.1:22181/testch1/mahadev");
- CPPUNIT_ASSERT(zk_ch != NULL);
- zk = createClient(&ctx);
- // first test with a NULL zk handle, make sure client library does not
- // dereference a null pointer, but instead returns ZBADARGUMENTS
- rc = zoo_create(NULL, "/testch1", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int) ZBADARGUMENTS, rc);
- rc = zoo_create(zk, "/testch1", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- rc = zoo_create(zk, "/testch1/mahadev", data, 7, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- // try an exists with /
- len = 60;
- rc = zoo_get(zk_ch, "/", 0, buf, &len, &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- //check if the data is the same
- CPPUNIT_ASSERT(strncmp(buf, data, 7) == 0);
- //check for watches
- rc = zoo_wexists(zk_ch, "/chroot", watcher_chroot_fn, (void *) retStr, &stat);
- //now check if we can do create/delete/get/sets/acls/getChildren and others
- //check create
- rc = zoo_create(zk_ch, "/chroot", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0,0);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- waitForChrootWatch(3);
- CPPUNIT_ASSERT(count == 0);
- rc = zoo_create(zk_ch, "/chroot/child", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- rc = zoo_exists(zk, "/testch1/mahadev/chroot/child", 0, &stat);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
-
- rc = zoo_delete(zk_ch, "/chroot/child", -1);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- rc = zoo_exists(zk, "/testch1/mahadev/chroot/child", 0, &stat);
- CPPUNIT_ASSERT_EQUAL((int) ZNONODE, rc);
- rc = zoo_wget(zk_ch, "/chroot", watcher_chroot_fn, (char*) retStr,
- buf, &len, &stat);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- rc = zoo_set(zk_ch, "/chroot",buf, 3, -1);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- waitForChrootWatch(3);
- CPPUNIT_ASSERT(count == 0);
- // check for getchildren
- struct String_vector children;
- rc = zoo_get_children(zk_ch, "/", 0, &children);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- CPPUNIT_ASSERT_EQUAL((int)1, (int)children.count);
- //check if te child if chroot
- CPPUNIT_ASSERT(strcmp((retStr+1), children.data[0]) == 0);
- // check for get/set acl
- struct ACL_vector acl;
- rc = zoo_get_acl(zk_ch, "/", &acl, &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- CPPUNIT_ASSERT_EQUAL((int)1, (int)acl.count);
- CPPUNIT_ASSERT_EQUAL((int)ZOO_PERM_ALL, (int)acl.data->perms);
- // set acl
- rc = zoo_set_acl(zk_ch, "/chroot", -1, &ZOO_READ_ACL_UNSAFE);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- // see if you add children
- rc = zoo_create(zk_ch, "/chroot/child1", "",0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZNOAUTH, rc);
- //add wget children test
- rc = zoo_wget_children(zk_ch, "/", watcher_chroot_fn, (char*) root, &children);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- //now create a node
- rc = zoo_create(zk_ch, "/child2", "",0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- waitForChrootWatch(3);
- CPPUNIT_ASSERT(count == 0);
- //check for one async call just to make sure
- rc = zoo_acreate(zk_ch, "/child3", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0,
- create_completion_fn, 0);
- waitForCreateCompletion(3);
- CPPUNIT_ASSERT(count == 0);
-
- //ZOOKEEPER-1027 correctly return path_buffer without prefixed chroot
- const char* path = "/zookeeper1027";
- char path_buffer[1024];
- int path_buffer_len=sizeof(path_buffer);
- rc = zoo_create(zk_ch, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, path_buffer, path_buffer_len);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- CPPUNIT_ASSERT_EQUAL(string(path), string(path_buffer));
- }
-
- void testAsyncWatcherAutoReset()
- {
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
- watchctx_t lctx[COUNT];
- int i;
- char path[80];
- int rc;
- evt_t evt;
-
- async_zk = zk;
- for(i = 0; i < COUNT; i++) {
- sprintf(path, "/awar%d", i);
- rc = zoo_awexists(zk, path, watcher, &lctx[i], statCompletion, (void*)ZNONODE);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- }
-
- yield(zk, 0);
-
- for(i = 0; i < COUNT/2; i++) {
- sprintf(path, "/awar%d", i);
- rc = zoo_acreate(zk, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, stringCompletion, strdup(path));
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- }
-
- yield(zk, 3);
- for(i = 0; i < COUNT/2; i++) {
- sprintf(path, "/awar%d", i);
- CPPUNIT_ASSERT_MESSAGE(path, waitForEvent(zk, &lctx[i], 5));
- evt = lctx[i].getEvent();
- CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path.c_str(), ZOO_CREATED_EVENT, evt.type);
- CPPUNIT_ASSERT_EQUAL(string(path), evt.path);
- }
-
- for(i = COUNT/2 + 1; i < COUNT*10; i++) {
- sprintf(path, "/awar%d", i);
- rc = zoo_acreate(zk, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, stringCompletion, strdup(path));
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- }
-
- yield(zk, 1);
- stopServer();
- CPPUNIT_ASSERT(ctx.waitForDisconnected(zk));
- startServer();
- CPPUNIT_ASSERT(ctx.waitForConnected(zk));
- yield(zk, 3);
- for(i = COUNT/2+1; i < COUNT; i++) {
- sprintf(path, "/awar%d", i);
- CPPUNIT_ASSERT_MESSAGE(path, waitForEvent(zk, &lctx[i], 5));
- evt = lctx[i].getEvent();
- CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CREATED_EVENT, evt.type);
- CPPUNIT_ASSERT_EQUAL(string(path), evt.path);
- }
- }
-
- void testWatcherAutoReset(zhandle_t *zk, watchctx_t *ctxGlobal,
- watchctx_t *ctxLocal)
- {
- bool isGlobal = (ctxGlobal == ctxLocal);
- int rc;
- struct Stat stat;
- char buf[1024];
- int blen;
- struct String_vector strings;
- const char *testName;
-
- rc = zoo_create(zk, "/watchtest", "", 0,
- &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- rc = zoo_create(zk, "/watchtest/child", "", 0,
- &ZOO_OPEN_ACL_UNSAFE, ZOO_EPHEMERAL, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- if (isGlobal) {
- testName = "GlobalTest";
- rc = zoo_get_children(zk, "/watchtest", 1, &strings);
- deallocate_String_vector(&strings);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- blen = sizeof(buf);
- rc = zoo_get(zk, "/watchtest/child", 1, buf, &blen, &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- rc = zoo_exists(zk, "/watchtest/child2", 1, &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
- } else {
- testName = "LocalTest";
- rc = zoo_wget_children(zk, "/watchtest", watcher, ctxLocal,
- &strings);
- deallocate_String_vector(&strings);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- blen = sizeof(buf);
- rc = zoo_wget(zk, "/watchtest/child", watcher, ctxLocal,
- buf, &blen, &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- rc = zoo_wexists(zk, "/watchtest/child2", watcher, ctxLocal,
- &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
- }
-
- CPPUNIT_ASSERT(ctxLocal->countEvents() == 0);
-
- stopServer();
- CPPUNIT_ASSERT_MESSAGE(testName, ctxGlobal->waitForDisconnected(zk));
- startServer();
- CPPUNIT_ASSERT_MESSAGE(testName, ctxLocal->waitForConnected(zk));
-
- CPPUNIT_ASSERT(ctxLocal->countEvents() == 0);
-
- rc = zoo_set(zk, "/watchtest/child", "1", 1, -1);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- struct Stat stat1, stat2;
- rc = zoo_set2(zk, "/watchtest/child", "1", 1, -1, &stat1);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- CPPUNIT_ASSERT(stat1.version >= 0);
- rc = zoo_set2(zk, "/watchtest/child", "1", 1, stat1.version, &stat2);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- rc = zoo_set(zk, "/watchtest/child", "1", 1, stat2.version);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- rc = zoo_create(zk, "/watchtest/child2", "", 0,
- &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
-
- evt_t evt = ctxLocal->getEvent();
- CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CHANGED_EVENT, evt.type);
- CPPUNIT_ASSERT_EQUAL(string("/watchtest/child"), evt.path);
-
- CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
- // The create will trigget the get children and the
- // exists watches
- evt = ctxLocal->getEvent();
- CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CREATED_EVENT, evt.type);
- CPPUNIT_ASSERT_EQUAL(string("/watchtest/child2"), evt.path);
- CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
- evt = ctxLocal->getEvent();
- CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CHILD_EVENT, evt.type);
- CPPUNIT_ASSERT_EQUAL(string("/watchtest"), evt.path);
-
- // Make sure Pings are giving us problems
- sleep(5);
-
- CPPUNIT_ASSERT(ctxLocal->countEvents() == 0);
-
- stopServer();
- CPPUNIT_ASSERT_MESSAGE(testName, ctxGlobal->waitForDisconnected(zk));
- startServer();
- CPPUNIT_ASSERT_MESSAGE(testName, ctxGlobal->waitForConnected(zk));
-
- if (isGlobal) {
- testName = "GlobalTest";
- rc = zoo_get_children(zk, "/watchtest", 1, &strings);
- deallocate_String_vector(&strings);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- blen = sizeof(buf);
- rc = zoo_get(zk, "/watchtest/child", 1, buf, &blen, &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- rc = zoo_exists(zk, "/watchtest/child2", 1, &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- } else {
- testName = "LocalTest";
- rc = zoo_wget_children(zk, "/watchtest", watcher, ctxLocal,
- &strings);
- deallocate_String_vector(&strings);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- blen = sizeof(buf);
- rc = zoo_wget(zk, "/watchtest/child", watcher, ctxLocal,
- buf, &blen, &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- rc = zoo_wexists(zk, "/watchtest/child2", watcher, ctxLocal,
- &stat);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- }
-
- zoo_delete(zk, "/watchtest/child2", -1);
-
- CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
-
- evt = ctxLocal->getEvent();
- CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_DELETED_EVENT, evt.type);
- CPPUNIT_ASSERT_EQUAL(string("/watchtest/child2"), evt.path);
-
- CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
- evt = ctxLocal->getEvent();
- CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CHILD_EVENT, evt.type);
- CPPUNIT_ASSERT_EQUAL(string("/watchtest"), evt.path);
-
- stopServer();
- CPPUNIT_ASSERT_MESSAGE(testName, ctxGlobal->waitForDisconnected(zk));
- startServer();
- CPPUNIT_ASSERT_MESSAGE(testName, ctxLocal->waitForConnected(zk));
-
- zoo_delete(zk, "/watchtest/child", -1);
- zoo_delete(zk, "/watchtest", -1);
-
- CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
-
- evt = ctxLocal->getEvent();
- CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_DELETED_EVENT, evt.type);
- CPPUNIT_ASSERT_EQUAL(string("/watchtest/child"), evt.path);
-
- // Make sure nothing is straggling
- sleep(1);
- CPPUNIT_ASSERT(ctxLocal->countEvents() == 0);
- }
-
- void testWatcherAutoResetWithGlobal()
- {
- {
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
- int rc = zoo_create(zk, "/testarwg", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- rc = zoo_create(zk, "/testarwg/arwg", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- }
-
- {
- watchctx_t ctx;
- zhandle_t *zk = createchClient(&ctx, "127.0.0.1:22181/testarwg/arwg");
-
- testWatcherAutoReset(zk, &ctx, &ctx);
- }
- }
-
- void testWatcherAutoResetWithLocal()
- {
- {
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
- int rc = zoo_create(zk, "/testarwl", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- rc = zoo_create(zk, "/testarwl/arwl", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- }
-
- {
- watchctx_t ctx;
- watchctx_t lctx;
- zhandle_t *zk = createchClient(&ctx, "127.0.0.1:22181/testarwl/arwl");
- testWatcherAutoReset(zk, &ctx, &lctx);
- }
- }
-};
-
-volatile int Zookeeper_simpleSystem::count;
-zhandle_t *Zookeeper_simpleSystem::async_zk;
-const char Zookeeper_simpleSystem::hostPorts[] = "127.0.0.1:22181";
-CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_simpleSystem);
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/TestClientRetry.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/TestClientRetry.cc b/src/c/tests/TestClientRetry.cc
deleted file mode 100644
index 41d5179..0000000
--- a/src/c/tests/TestClientRetry.cc
+++ /dev/null
@@ -1,273 +0,0 @@
-/**
- * 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 <cppunit/extensions/HelperMacros.h>
-#include "CppAssertHelper.h"
-
-#include <signal.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/select.h>
-
-#include "CollectionUtil.h"
-#include "ThreadingUtil.h"
-
-using namespace Util;
-
-#include "Vector.h"
-using namespace std;
-
-#include <cstring>
-#include <list>
-
-#include <zookeeper.h>
-
-#include "Util.h"
-
-#ifdef THREADED
- static void yield(zhandle_t *zh, int i)
- {
- sleep(i);
- }
-#else
- static void yield(zhandle_t *zh, int seconds)
- {
- int fd;
- int interest;
- int events;
- struct timeval tv;
- int rc;
- time_t expires = time(0) + seconds;
- time_t timeLeft = seconds;
- fd_set rfds, wfds, efds;
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- FD_ZERO(&efds);
-
- while(timeLeft >= 0) {
- 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);
- if (tv.tv_sec > timeLeft) {
- tv.tv_sec = timeLeft;
- }
- rc = select(fd+1, &rfds, &wfds, &efds, &tv);
- timeLeft = expires - time(0);
- events = 0;
- if (FD_ISSET(fd, &rfds)) {
- events |= ZOOKEEPER_READ;
- }
- if (FD_ISSET(fd, &wfds)) {
- events |= ZOOKEEPER_WRITE;
- }
- zookeeper_process(zh, events);
- }
- }
-#endif
-
-typedef struct evt {
- string path;
- int type;
-} evt_t;
-
-typedef struct watchCtx {
-private:
- list<evt_t> events;
-public:
- bool connected;
- zhandle_t *zh;
- Mutex mutex;
-
- watchCtx() {
- connected = false;
- zh = 0;
- }
- ~watchCtx() {
- if (zh) {
- zookeeper_close(zh);
- zh = 0;
- }
- }
-
- evt_t getEvent() {
- evt_t evt;
- mutex.acquire();
- CPPUNIT_ASSERT( events.size() > 0);
- evt = events.front();
- events.pop_front();
- mutex.release();
- return evt;
- }
-
- int countEvents() {
- int count;
- mutex.acquire();
- count = events.size();
- mutex.release();
- return count;
- }
-
- void putEvent(evt_t evt) {
- mutex.acquire();
- events.push_back(evt);
- mutex.release();
- }
-
- bool waitForConnected(zhandle_t *zh) {
- time_t expires = time(0) + 10;
- while(!connected && time(0) < expires) {
- yield(zh, 1);
- }
- return connected;
- }
- bool waitForDisconnected(zhandle_t *zh) {
- time_t expires = time(0) + 15;
- while(connected && time(0) < expires) {
- yield(zh, 1);
- }
- return !connected;
- }
-} watchctx_t;
-
-class Zookeeper_clientretry : public CPPUNIT_NS::TestFixture
-{
- CPPUNIT_TEST_SUITE(Zookeeper_clientretry);
-#ifdef THREADED
- CPPUNIT_TEST(testRetry);
-#endif
- CPPUNIT_TEST_SUITE_END();
-
- static void watcher(zhandle_t *, int type, int state, const char *path,void*v){
- watchctx_t *ctx = (watchctx_t*)v;
-
- if (state == ZOO_CONNECTED_STATE) {
- ctx->connected = true;
- } else {
- ctx->connected = false;
- }
- if (type != ZOO_SESSION_EVENT) {
- evt_t evt;
- evt.path = path;
- evt.type = type;
- ctx->putEvent(evt);
- }
- }
-
- static const char hostPorts[];
-
- const char *getHostPorts() {
- return hostPorts;
- }
-
- zhandle_t *createClient(watchctx_t *ctx) {
- zhandle_t *zk = zookeeper_init(hostPorts, watcher, 10000, 0,
- ctx, 0);
- ctx->zh = zk;
- sleep(1);
- return zk;
- }
-
- FILE *logfile;
-public:
-
- Zookeeper_clientretry() {
- logfile = openlogfile("Zookeeper_clientretry");
- }
-
- ~Zookeeper_clientretry() {
- if (logfile) {
- fflush(logfile);
- fclose(logfile);
- logfile = 0;
- }
- }
-
- void setUp()
- {
- zoo_set_log_stream(logfile);
-
- char cmd[1024];
- sprintf(cmd, "%s stop %s", ZKSERVER_CMD, getHostPorts());
- CPPUNIT_ASSERT(system(cmd) == 0);
-
- /* we are testing that if max cnxns is exceeded the server does the right thing */
- sprintf(cmd, "export ZKMAXCNXNS=1;%s startClean %s", ZKSERVER_CMD, getHostPorts());
- CPPUNIT_ASSERT(system(cmd) == 0);
-
- struct sigaction act;
- act.sa_handler = SIG_IGN;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- CPPUNIT_ASSERT(sigaction(SIGPIPE, &act, NULL) == 0);
- }
-
- void tearDown()
- {
- char cmd[1024];
- sprintf(cmd, "%s stop %s", ZKSERVER_CMD, getHostPorts());
- CPPUNIT_ASSERT(system(cmd) == 0);
-
- /* restart the server in "normal" mode */
- sprintf(cmd, "%s startClean %s", ZKSERVER_CMD, getHostPorts());
- CPPUNIT_ASSERT(system(cmd) == 0);
-
- struct sigaction act;
- act.sa_handler = SIG_IGN;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- CPPUNIT_ASSERT(sigaction(SIGPIPE, &act, NULL) == 0);
- }
-
- bool waitForEvent(zhandle_t *zh, watchctx_t *ctx, int seconds) {
- time_t expires = time(0) + seconds;
- while(ctx->countEvents() == 0 && time(0) < expires) {
- yield(zh, 1);
- }
- return ctx->countEvents() > 0;
- }
-
- static zhandle_t *async_zk;
-
- void testRetry()
- {
- watchctx_t ctx1, ctx2;
- zhandle_t *zk1 = createClient(&ctx1);
- CPPUNIT_ASSERT_EQUAL(true, ctx1.waitForConnected(zk1));
- zhandle_t *zk2 = createClient(&ctx2);
- zookeeper_close(zk1);
- CPPUNIT_ASSERT_EQUAL(true, ctx2.waitForConnected(zk2));
- ctx1.zh = 0;
- }
-};
-
-zhandle_t *Zookeeper_clientretry::async_zk;
-const char Zookeeper_clientretry::hostPorts[] = "127.0.0.1:22181";
-CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_clientretry);
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/TestDriver.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/TestDriver.cc b/src/c/tests/TestDriver.cc
deleted file mode 100644
index d60db69..0000000
--- a/src/c/tests/TestDriver.cc
+++ /dev/null
@@ -1,173 +0,0 @@
-/**
- * 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 <string>
-#include <cppunit/TestRunner.h>
-#include <cppunit/CompilerOutputter.h>
-#include <cppunit/TestResult.h>
-#include <cppunit/TestResultCollector.h>
-#include <cppunit/TextTestProgressListener.h>
-#include <cppunit/BriefTestProgressListener.h>
-#include <cppunit/extensions/TestFactoryRegistry.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <stdexcept>
-#include <unistd.h>
-#include <sys/select.h>
-#include <cppunit/Exception.h>
-#include <cppunit/TestFailure.h>
-#include <cppunit/XmlOutputter.h>
-#include <cppunit/TestAssert.h>
-#include <fstream>
-#include <time.h>
-
-#include "Util.h"
-#include "zookeeper_log.h"
-
-using namespace std;
-
-CPPUNIT_NS_BEGIN
-
-class EclipseOutputter: public CompilerOutputter
-{
-public:
- EclipseOutputter(TestResultCollector *result,ostream &stream):
- CompilerOutputter(result,stream,"%p:%l: "),stream_(stream)
- {
- }
- virtual void printFailedTestName( TestFailure *failure ){}
- virtual void printFailureMessage( TestFailure *failure )
- {
- stream_<<": ";
- Message msg = failure->thrownException()->message();
- stream_<< msg.shortDescription();
-
- string text;
- for(int i=0; i<msg.detailCount();i++){
- text+=msg.detailAt(i);
- if(i+1!=msg.detailCount())
- text+=", ";
- }
- if(text.length()!=0)
- stream_ <<" ["<<text<<"]";
- stream_<<"\n";
- }
- ostream& stream_;
-};
-
-CPPUNIT_NS_END
-
-class TimingListener : public CPPUNIT_NS::BriefTestProgressListener {
- public:
- void startTest( CPPUNIT_NS::Test *test )
- {
- gettimeofday(&_start_time, NULL);
-
- CPPUNIT_NS::BriefTestProgressListener::startTest(test);
- }
-
- void endTest( CPPUNIT_NS::Test *test )
- {
- struct timeval end;
- gettimeofday(&end, NULL);
-
- long seconds = end.tv_sec - _start_time.tv_sec;
- long useconds = end.tv_usec - _start_time.tv_usec;
-
- long mtime = seconds * 1000 + useconds/1000.0;
- CPPUNIT_NS::stdCOut() << " : elapsed " << mtime;
- CPPUNIT_NS::BriefTestProgressListener::endTest(test);
- }
-
- private:
- struct timeval _start_time;
-};
-
-class ZKServer {
-public:
- ZKServer() {
- char cmd[1024];
- sprintf(cmd, "%s startClean %s", ZKSERVER_CMD, "127.0.0.1:22181");
- CPPUNIT_ASSERT(system(cmd) == 0);
-
- struct sigaction act;
- act.sa_handler = SIG_IGN;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- CPPUNIT_ASSERT(sigaction(SIGPIPE, &act, NULL) == 0);
- }
- virtual ~ZKServer(){
- char cmd[1024];
- sprintf(cmd, "%s stop %s", ZKSERVER_CMD, "127.0.0.1:22181");
- CPPUNIT_ASSERT(system(cmd) == 0);
- }
-};
-
-int main( int argc, char* argv[] ) {
- // if command line contains "-ide" then this is the post build check
- // => the output must be in the compiler error format.
- //bool selfTest = (argc > 1) && (std::string("-ide") == argv[1]);
- globalTestConfig.addConfigFromCmdLine(argc,argv);
-
- ZKServer zkserver;
-
- // Create the event manager and test controller
- CPPUNIT_NS::TestResult controller;
- // Add a listener that colllects test result
- CPPUNIT_NS::TestResultCollector result;
- controller.addListener( &result );
-
- // A listener that print dots as tests run.
- // CPPUNIT_NS::TextTestProgressListener progress;
- // CPPUNIT_NS::BriefTestProgressListener progress;
-
- // brief + elapsed time
- TimingListener progress;
- controller.addListener( &progress );
-
- CPPUNIT_NS::TestRunner runner;
- runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );
-
- try {
- CPPUNIT_NS::stdCOut() << endl << "Running " << endl;
-
- zoo_set_debug_level(ZOO_LOG_LEVEL_INFO);
- //zoo_set_debug_level(ZOO_LOG_LEVEL_DEBUG);
-
- runner.run( controller, globalTestConfig.getTestName());
-
- // Print test in a compiler compatible format.
- CPPUNIT_NS::EclipseOutputter outputter( &result,cout);
- outputter.write();
-
- // Uncomment this for XML output
-#ifdef ENABLE_XML_OUTPUT
- std::ofstream file( "tests.xml" );
- CPPUNIT_NS::XmlOutputter xml( &result, file );
- xml.setStyleSheet( "report.xsl" );
- xml.write();
- file.close();
-#endif
- } catch ( std::invalid_argument &e ) {
- // Test path not resolved
- cout<<"\nERROR: "<<e.what()<<endl;
- return 0;
- }
-
- return result.wasSuccessful() ? 0 : 1;
- }
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/TestMulti.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/TestMulti.cc b/src/c/tests/TestMulti.cc
deleted file mode 100644
index a54e047..0000000
--- a/src/c/tests/TestMulti.cc
+++ /dev/null
@@ -1,703 +0,0 @@
-/**
- * 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 <cppunit/extensions/HelperMacros.h>
-#include "CppAssertHelper.h"
-
-#include <signal.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/select.h>
-
-#include "CollectionUtil.h"
-#include "ThreadingUtil.h"
-
-using namespace Util;
-
-#include "Vector.h"
-using namespace std;
-
-#include <cstring>
-#include <list>
-
-#include <zookeeper.h>
-#include <errno.h>
-#include <recordio.h>
-#include "Util.h"
-
-#ifdef THREADED
- static void yield(zhandle_t *zh, int i)
- {
- sleep(i);
- }
-#else
- static void yield(zhandle_t *zh, int seconds)
- {
- int fd;
- int interest;
- int events;
- struct timeval tv;
- int rc;
- time_t expires = time(0) + seconds;
- time_t timeLeft = seconds;
- fd_set rfds, wfds, efds;
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- FD_ZERO(&efds);
-
- while(timeLeft >= 0) {
- 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);
- if (tv.tv_sec > timeLeft) {
- tv.tv_sec = timeLeft;
- }
- rc = select(fd+1, &rfds, &wfds, &efds, &tv);
- timeLeft = expires - time(0);
- events = 0;
- if (FD_ISSET(fd, &rfds)) {
- events |= ZOOKEEPER_READ;
- }
- if (FD_ISSET(fd, &wfds)) {
- events |= ZOOKEEPER_WRITE;
- }
- zookeeper_process(zh, events);
- }
- }
-#endif
-
-typedef struct evt {
- string path;
- int type;
-} evt_t;
-
-typedef struct watchCtx {
-private:
- list<evt_t> events;
- watchCtx(const watchCtx&);
- watchCtx& operator=(const watchCtx&);
-public:
- bool connected;
- zhandle_t *zh;
- Mutex mutex;
-
- watchCtx() {
- connected = false;
- zh = 0;
- }
- ~watchCtx() {
- if (zh) {
- zookeeper_close(zh);
- zh = 0;
- }
- }
-
- evt_t getEvent() {
- evt_t evt;
- mutex.acquire();
- CPPUNIT_ASSERT( events.size() > 0);
- evt = events.front();
- events.pop_front();
- mutex.release();
- return evt;
- }
-
- int countEvents() {
- int count;
- mutex.acquire();
- count = events.size();
- mutex.release();
- return count;
- }
-
- void putEvent(evt_t evt) {
- mutex.acquire();
- events.push_back(evt);
- mutex.release();
- }
-
- bool waitForConnected(zhandle_t *zh) {
- time_t expires = time(0) + 10;
- while(!connected && time(0) < expires) {
- yield(zh, 1);
- }
- return connected;
- }
- bool waitForDisconnected(zhandle_t *zh) {
- time_t expires = time(0) + 15;
- while(connected && time(0) < expires) {
- yield(zh, 1);
- }
- return !connected;
- }
-} watchctx_t;
-
-class Zookeeper_multi : public CPPUNIT_NS::TestFixture
-{
- CPPUNIT_TEST_SUITE(Zookeeper_multi);
-//FIXME: None of these tests pass in single-threaded mode. It seems to be a
-//flaw in the test suite setup.
-#ifdef THREADED
- CPPUNIT_TEST(testCreate);
- CPPUNIT_TEST(testCreateDelete);
- CPPUNIT_TEST(testInvalidVersion);
- CPPUNIT_TEST(testNestedCreate);
- CPPUNIT_TEST(testSetData);
- CPPUNIT_TEST(testUpdateConflict);
- CPPUNIT_TEST(testDeleteUpdateConflict);
- CPPUNIT_TEST(testAsyncMulti);
- CPPUNIT_TEST(testMultiFail);
- CPPUNIT_TEST(testCheck);
- CPPUNIT_TEST(testWatch);
- CPPUNIT_TEST(testSequentialNodeCreateInAsyncMulti);
-#endif
- CPPUNIT_TEST_SUITE_END();
-
- static void watcher(zhandle_t *, int type, int state, const char *path,void*v){
- watchctx_t *ctx = (watchctx_t*)v;
-
- if (state == ZOO_CONNECTED_STATE) {
- ctx->connected = true;
- } else {
- ctx->connected = false;
- }
- if (type != ZOO_SESSION_EVENT) {
- evt_t evt;
- evt.path = path;
- evt.type = type;
- ctx->putEvent(evt);
- }
- }
-
- static const char hostPorts[];
-
- const char *getHostPorts() {
- return hostPorts;
- }
-
- zhandle_t *createClient(watchctx_t *ctx) {
- return createClient(hostPorts, ctx);
- }
-
- zhandle_t *createClient(const char *hp, watchctx_t *ctx) {
- zhandle_t *zk = zookeeper_init(hp, watcher, 10000, 0, ctx, 0);
- ctx->zh = zk;
- CPPUNIT_ASSERT_EQUAL(true, ctx->waitForConnected(zk));
- return zk;
- }
-
- FILE *logfile;
-public:
-
- Zookeeper_multi() {
- logfile = openlogfile("Zookeeper_multi");
- }
-
- ~Zookeeper_multi() {
- if (logfile) {
- fflush(logfile);
- fclose(logfile);
- logfile = 0;
- }
- }
-
- void setUp()
- {
- zoo_set_log_stream(logfile);
- }
-
- void tearDown()
- {
- }
-
- static volatile int count;
-
- static void multi_completion_fn(int rc, const void *data) {
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
- count++;
- }
-
- static void multi_completion_fn_no_assert(int rc, const void *data) {
- count++;
- }
-
- static void waitForMultiCompletion(int seconds) {
- time_t expires = time(0) + seconds;
- while(count == 0 && time(0) < expires) {
- sleep(1);
- }
- count--;
- }
-
- static void resetCounter() {
- count = 0;
- }
-
- /**
- * Test basic multi-op create functionality
- */
- void testCreate() {
- int rc;
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
-
- int sz = 512;
- char p1[sz];
- char p2[sz];
- char p3[sz];
- p1[0] = p2[0] = p3[0] = '\0';
-
- int nops = 3 ;
- zoo_op_t ops[nops];
- zoo_op_result_t results[nops];
-
- zoo_create_op_init(&ops[0], "/multi1", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
- zoo_create_op_init(&ops[1], "/multi1/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p2, sz);
- zoo_create_op_init(&ops[2], "/multi1/b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p3, sz);
-
- rc = zoo_multi(zk, nops, ops, results);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- CPPUNIT_ASSERT(strcmp(p1, "/multi1") == 0);
- CPPUNIT_ASSERT(strcmp(p2, "/multi1/a") == 0);
- CPPUNIT_ASSERT(strcmp(p3, "/multi1/b") == 0);
-
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1].err);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[2].err);
- }
-
- /**
- * Test create followed by delete
- */
- void testCreateDelete() {
- int rc;
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
- int sz = 512;
- char p1[sz];
- p1[0] = '\0';
- int nops = 2 ;
- zoo_op_t ops[nops];
- zoo_op_result_t results[nops];
-
- zoo_create_op_init(&ops[0], "/multi2", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
- zoo_delete_op_init(&ops[1], "/multi2", 0);
-
- rc = zoo_multi(zk, nops, ops, results);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- // '/multi2' should have been deleted
- rc = zoo_exists(zk, "/multi2", 0, NULL);
- CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
- }
-
- /**
- * Test invalid versions
- */
- void testInvalidVersion() {
- int rc;
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
- int nops = 4;
- zoo_op_t ops[nops];
- zoo_op_result_t results[nops];
-
- zoo_create_op_init(&ops[0], "/multi3", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
- zoo_delete_op_init(&ops[1], "/multi3", 1);
- zoo_create_op_init(&ops[2], "/multi3", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
- zoo_create_op_init(&ops[3], "/multi3/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
-
- rc = zoo_multi(zk, nops, ops, results);
- CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, rc);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
- CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, results[1].err);
- CPPUNIT_ASSERT_EQUAL((int)ZRUNTIMEINCONSISTENCY, results[2].err);
- CPPUNIT_ASSERT_EQUAL((int)ZRUNTIMEINCONSISTENCY, results[3].err);
- }
-
- /**
- * Test nested creates that rely on state in earlier op in multi
- */
- void testNestedCreate() {
- int rc;
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
- int sz = 512;
- char p1[sz];
- p1[0] = '\0';
- int nops = 6;
- zoo_op_t ops[nops];
- zoo_op_result_t results[nops];
-
- /* Create */
- zoo_create_op_init(&ops[0], "/multi4", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
- zoo_create_op_init(&ops[1], "/multi4/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
- zoo_create_op_init(&ops[2], "/multi4/a/1", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
-
- /* Delete */
- zoo_delete_op_init(&ops[3], "/multi4/a/1", 0);
- zoo_delete_op_init(&ops[4], "/multi4/a", 0);
- zoo_delete_op_init(&ops[5], "/multi4", 0);
-
- rc = zoo_multi(zk, nops, ops, results);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- // Verify tree deleted
- rc = zoo_exists(zk, "/multi4/a/1", 0, NULL);
- CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
-
- rc = zoo_exists(zk, "/multi4/a", 0, NULL);
- CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
-
- rc = zoo_exists(zk, "/multi4", 0, NULL);
- CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
- }
-
- /**
- * Test setdata functionality
- */
- void testSetData() {
- int rc;
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
- int sz = 512;
- struct Stat s1;
-
- char buf[sz];
- int blen = sz ;
-
- char p1[sz], p2[sz];
-
- int nops = 2;
- zoo_op_t ops[nops];
- zoo_op_result_t results[nops];
-
- zoo_create_op_init(&ops[0], "/multi5", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
- zoo_create_op_init(&ops[1], "/multi5/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p2, sz);
-
- rc = zoo_multi(zk, nops, ops, results);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- yield(zk, 5);
-
- zoo_op_t setdata_ops[nops];
- zoo_op_result_t setdata_results[nops];
-
- zoo_set_op_init(&setdata_ops[0], "/multi5", "1", 1, 0, &s1);
- zoo_set_op_init(&setdata_ops[1], "/multi5/a", "2", 1, 0, &s1);
-
- rc = zoo_multi(zk, nops, setdata_ops, setdata_results);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1].err);
-
- memset(buf, '\0', blen);
- rc = zoo_get(zk, "/multi5", 0, buf, &blen, &s1);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- CPPUNIT_ASSERT_EQUAL(1, blen);
- CPPUNIT_ASSERT(strcmp("1", buf) == 0);
-
- memset(buf, '\0', blen);
- rc = zoo_get(zk, "/multi5/a", 0, buf, &blen, &s1);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- CPPUNIT_ASSERT_EQUAL(1, blen);
- CPPUNIT_ASSERT(strcmp("2", buf) == 0);
- }
-
- /**
- * Test update conflicts
- */
- void testUpdateConflict() {
- int rc;
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
- int sz = 512;
- char buf[sz];
- int blen = sz;
- char p1[sz];
- p1[0] = '\0';
- struct Stat s1;
- int nops = 3;
- zoo_op_t ops[nops];
- zoo_op_result_t results[nops];
-
- zoo_create_op_init(&ops[0], "/multi6", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
- zoo_set_op_init(&ops[1], "/multi6", "X", 1, 0, &s1);
- zoo_set_op_init(&ops[2], "/multi6", "Y", 1, 0, &s1);
-
- rc = zoo_multi(zk, nops, ops, results);
- CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, rc);
-
- //Updating version solves conflict -- order matters
- ops[2].set_op.version = 1;
- rc = zoo_multi(zk, nops, ops, results);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- memset(buf, 0, sz);
- rc = zoo_get(zk, "/multi6", 0, buf, &blen, &s1);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- CPPUNIT_ASSERT_EQUAL(blen, 1);
- CPPUNIT_ASSERT(strncmp(buf, "Y", 1) == 0);
- }
-
- /**
- * Test delete-update conflicts
- */
- void testDeleteUpdateConflict() {
- int rc;
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
- int sz = 512;
- char buf[sz];
- int blen;
- char p1[sz];
- p1[0] = '\0';
- struct Stat stat;
- int nops = 3;
- zoo_op_t ops[nops];
- zoo_op_result_t results[nops];
-
- zoo_create_op_init(&ops[0], "/multi7", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
- zoo_delete_op_init(&ops[1], "/multi7", 0);
- zoo_set_op_init(&ops[2], "/multi7", "Y", 1, 0, &stat);
-
- rc = zoo_multi(zk, nops, ops, results);
- CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
-
- // '/multi' should never have been created as entire op should fail
- rc = zoo_exists(zk, "/multi7", 0, NULL);
- CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
- }
-
- void testAsyncMulti() {
- int rc;
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
-
- int sz = 512;
- char p1[sz], p2[sz], p3[sz];
- p1[0] = '\0';
- p2[0] = '\0';
- p3[0] = '\0';
-
- int nops = 3;
- zoo_op_t ops[nops];
- zoo_op_result_t results[nops];
-
- zoo_create_op_init(&ops[0], "/multi8", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
- zoo_create_op_init(&ops[1], "/multi8/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p2, sz);
- zoo_create_op_init(&ops[2], "/multi8/b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p3, sz);
-
- rc = zoo_amulti(zk, nops, ops, results, multi_completion_fn, 0);
- waitForMultiCompletion(10);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- CPPUNIT_ASSERT(strcmp(p1, "/multi8") == 0);
- CPPUNIT_ASSERT(strcmp(p2, "/multi8/a") == 0);
- CPPUNIT_ASSERT(strcmp(p3, "/multi8/b") == 0);
-
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1].err);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[2].err);
- }
-
- void testMultiFail() {
- int rc;
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
-
- int sz = 512;
- char p1[sz], p2[sz], p3[sz];
-
- p1[0] = '\0';
- p2[0] = '\0';
- p3[0] = '\0';
-
- int nops = 3;
- zoo_op_t ops[nops];
- zoo_op_result_t results[nops];
-
- zoo_create_op_init(&ops[0], "/multi9", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
- zoo_create_op_init(&ops[1], "/multi9", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p2, sz);
- zoo_create_op_init(&ops[2], "/multi9/b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p3, sz);
-
- rc = zoo_multi(zk, nops, ops, results);
- CPPUNIT_ASSERT_EQUAL((int)ZNODEEXISTS, rc);
- }
-
- /**
- * Test basic multi-op check functionality
- */
- void testCheck() {
- int rc;
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
- int sz = 512;
- char p1[sz];
- p1[0] = '\0';
- struct Stat s1;
-
- rc = zoo_create(zk, "/multi0", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- // Conditionally create /multi0/a' only if '/multi0' at version 0
- int nops = 2;
- zoo_op_t ops[nops];
- zoo_op_result_t results[nops];
-
- zoo_check_op_init(&ops[0], "/multi0", 0);
- zoo_create_op_init(&ops[1], "/multi0/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
-
- rc = zoo_multi(zk, nops, ops, results);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1].err);
-
- // '/multi0/a' should have been created as it passed version check
- rc = zoo_exists(zk, "/multi0/a", 0, NULL);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- // Only create '/multi0/b' if '/multi0' at version 10 (which it's not)
- zoo_op_t ops2[nops];
- zoo_check_op_init(&ops2[0], "/multi0", 10);
- zoo_create_op_init(&ops2[1], "/multi0/b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
-
- rc = zoo_multi(zk, nops, ops2, results);
- CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, rc);
-
- CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, results[0].err);
- CPPUNIT_ASSERT_EQUAL((int)ZRUNTIMEINCONSISTENCY, results[1].err);
-
- // '/multi0/b' should NOT have been created
- rc = zoo_exists(zk, "/multi0/b", 0, NULL);
- CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
- }
-
- /**
- * Do a multi op inside a watch callback context.
- */
- static void doMultiInWatch(zhandle_t *zk, int type, int state, const char *path, void *ctx) {
- int rc;
- int sz = 512;
- char p1[sz];
- p1[0] = '\0';
- struct Stat s1;
-
- int nops = 1;
- zoo_op_t ops[nops];
- zoo_op_result_t results[nops];
-
- zoo_set_op_init(&ops[0], "/multiwatch", "1", 1, -1, NULL);
-
- rc = zoo_multi(zk, nops, ops, results);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
-
- memset(p1, '\0', sz);
- rc = zoo_get(zk, "/multiwatch", 0, p1, &sz, &s1);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- CPPUNIT_ASSERT_EQUAL(1, sz);
- CPPUNIT_ASSERT(strcmp("1", p1) == 0);
- count++;
- }
-
- /**
- * Test multi-op called from a watch
- */
- void testWatch() {
- int rc;
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
- int sz = 512;
- char p1[sz];
- p1[0] = '\0';
-
- rc = zoo_create(zk, "/multiwatch", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
-
- // create a watch on node '/multiwatch'
- rc = zoo_wget(zk, "/multiwatch", doMultiInWatch, &ctx, p1, &sz, NULL);
-
- // setdata on node '/multiwatch' this should trip the watch
- rc = zoo_set(zk, "/multiwatch", NULL, -1, -1);
- CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
-
- // wait for multi completion in doMultiInWatch
- waitForMultiCompletion(5);
- }
-
- /**
- * ZOOKEEPER-1624: PendingChanges of create sequential node request didn't
- * get rollbacked correctly when multi-op failed. This caused
- * create sequential node request in subsequent multi-op to failed because
- * sequential node name generation is incorrect.
- *
- * The check is to make sure that each request in multi-op failed with
- * the correct reason.
- */
- void testSequentialNodeCreateInAsyncMulti() {
- int rc;
- watchctx_t ctx;
- zhandle_t *zk = createClient(&ctx);
-
- int iteration = 4;
- int nops = 2;
-
- zoo_op_result_t results[iteration][nops];
- zoo_op_t ops[nops];
- zoo_create_op_init(&ops[0], "/node-", "", 0, &ZOO_OPEN_ACL_UNSAFE, ZOO_SEQUENCE, NULL, 0);
- zoo_create_op_init(&ops[1], "/dup", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
- for (int i = 0; i < iteration ; ++i) {
- rc = zoo_amulti(zk, nops, ops, results[i], multi_completion_fn_no_assert, 0);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
- }
-
- waitForMultiCompletion(10);
-
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0][0].err);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1][0].err);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[2][0].err);
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[3][0].err);
-
- CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0][1].err);
- CPPUNIT_ASSERT_EQUAL((int)ZNODEEXISTS, results[1][1].err);
- CPPUNIT_ASSERT_EQUAL((int)ZNODEEXISTS, results[2][1].err);
- CPPUNIT_ASSERT_EQUAL((int)ZNODEEXISTS, results[3][1].err);
-
- resetCounter();
- }
-};
-
-volatile int Zookeeper_multi::count;
-const char Zookeeper_multi::hostPorts[] = "127.0.0.1:22181";
-CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_multi);
[06/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/src/recordio.c
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/recordio.c b/zookeeper-client/zookeeper-client-c/src/recordio.c
new file mode 100644
index 0000000..0fcf48e
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/recordio.c
@@ -0,0 +1,366 @@
+/**
+ * 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 <recordio.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#ifndef WIN32
+#include <netinet/in.h>
+#else
+#include <winsock2.h> /* for _htonl and _ntohl */
+#endif
+
+void deallocate_String(char **s)
+{
+ if (*s)
+ free(*s);
+ *s = 0;
+}
+
+void deallocate_Buffer(struct buffer *b)
+{
+ if (b->buff)
+ free(b->buff);
+ b->buff = 0;
+}
+
+struct buff_struct {
+ int32_t len;
+ int32_t off;
+ char *buffer;
+};
+
+static int resize_buffer(struct buff_struct *s, int newlen)
+{
+ char *buffer= NULL;
+ while (s->len < newlen) {
+ s->len *= 2;
+ }
+ buffer = (char*)realloc(s->buffer, s->len);
+ if (!buffer) {
+ s->buffer = 0;
+ return -ENOMEM;
+ }
+ s->buffer = buffer;
+ return 0;
+}
+
+int oa_start_record(struct oarchive *oa, const char *tag)
+{
+ return 0;
+}
+int oa_end_record(struct oarchive *oa, const char *tag)
+{
+ return 0;
+}
+int oa_serialize_int(struct oarchive *oa, const char *tag, const int32_t *d)
+{
+ struct buff_struct *priv = oa->priv;
+ int32_t i = htonl(*d);
+ if ((priv->len - priv->off) < sizeof(i)) {
+ int rc = resize_buffer(priv, priv->len + sizeof(i));
+ if (rc < 0) return rc;
+ }
+ memcpy(priv->buffer+priv->off, &i, sizeof(i));
+ priv->off+=sizeof(i);
+ return 0;
+}
+int64_t zoo_htonll(int64_t v)
+{
+ int i = 0;
+ char *s = (char *)&v;
+ if (htonl(1) == 1) {
+ return v;
+ }
+ for (i = 0; i < 4; i++) {
+ int tmp = s[i];
+ s[i] = s[8-i-1];
+ s[8-i-1] = tmp;
+ }
+
+ return v;
+}
+
+int oa_serialize_long(struct oarchive *oa, const char *tag, const int64_t *d)
+{
+ const int64_t i = zoo_htonll(*d);
+ struct buff_struct *priv = oa->priv;
+ if ((priv->len - priv->off) < sizeof(i)) {
+ int rc = resize_buffer(priv, priv->len + sizeof(i));
+ if (rc < 0) return rc;
+ }
+ memcpy(priv->buffer+priv->off, &i, sizeof(i));
+ priv->off+=sizeof(i);
+ return 0;
+}
+int oa_start_vector(struct oarchive *oa, const char *tag, const int32_t *count)
+{
+ return oa_serialize_int(oa, tag, count);
+}
+int oa_end_vector(struct oarchive *oa, const char *tag)
+{
+ return 0;
+}
+int oa_serialize_bool(struct oarchive *oa, const char *name, const int32_t *i)
+{
+ //return oa_serialize_int(oa, name, i);
+ struct buff_struct *priv = oa->priv;
+ if ((priv->len - priv->off) < 1) {
+ int rc = resize_buffer(priv, priv->len + 1);
+ if (rc < 0)
+ return rc;
+ }
+ priv->buffer[priv->off] = (*i == 0 ? '\0' : '\1');
+ priv->off++;
+ return 0;
+}
+static const int32_t negone = -1;
+int oa_serialize_buffer(struct oarchive *oa, const char *name,
+ const struct buffer *b)
+{
+ struct buff_struct *priv = oa->priv;
+ int rc;
+ if (!b) {
+ return oa_serialize_int(oa, "len", &negone);
+ }
+ rc = oa_serialize_int(oa, "len", &b->len);
+ if (rc < 0)
+ return rc;
+ // this means a buffer of NUll
+ // with size of -1. This is
+ // waht we use in java serialization for NULL
+ if (b->len == -1) {
+ return rc;
+ }
+ if ((priv->len - priv->off) < b->len) {
+ rc = resize_buffer(priv, priv->len + b->len);
+ if (rc < 0)
+ return rc;
+ }
+ memcpy(priv->buffer+priv->off, b->buff, b->len);
+ priv->off += b->len;
+ return 0;
+}
+int oa_serialize_string(struct oarchive *oa, const char *name, char **s)
+{
+ struct buff_struct *priv = oa->priv;
+ int32_t len;
+ int rc;
+ if (!*s) {
+ oa_serialize_int(oa, "len", &negone);
+ return 0;
+ }
+ len = strlen(*s);
+ rc = oa_serialize_int(oa, "len", &len);
+ if (rc < 0)
+ return rc;
+ if ((priv->len - priv->off) < len) {
+ rc = resize_buffer(priv, priv->len + len);
+ if (rc < 0)
+ return rc;
+ }
+ memcpy(priv->buffer+priv->off, *s, len);
+ priv->off += len;
+ return 0;
+}
+int ia_start_record(struct iarchive *ia, const char *tag)
+{
+ return 0;
+}
+int ia_end_record(struct iarchive *ia, const char *tag)
+{
+ return 0;
+}
+int ia_deserialize_int(struct iarchive *ia, const char *tag, int32_t *count)
+{
+ struct buff_struct *priv = ia->priv;
+ if ((priv->len - priv->off) < sizeof(*count)) {
+ return -E2BIG;
+ }
+ memcpy(count, priv->buffer+priv->off, sizeof(*count));
+ priv->off+=sizeof(*count);
+ *count = ntohl(*count);
+ return 0;
+}
+
+int ia_deserialize_long(struct iarchive *ia, const char *tag, int64_t *count)
+{
+ struct buff_struct *priv = ia->priv;
+ int64_t v = 0;
+ if ((priv->len - priv->off) < sizeof(*count)) {
+ return -E2BIG;
+ }
+ memcpy(count, priv->buffer+priv->off, sizeof(*count));
+ priv->off+=sizeof(*count);
+ v = zoo_htonll(*count); // htonll and ntohll do the same
+ *count = v;
+ return 0;
+}
+int ia_start_vector(struct iarchive *ia, const char *tag, int32_t *count)
+{
+ return ia_deserialize_int(ia, tag, count);
+}
+int ia_end_vector(struct iarchive *ia, const char *tag)
+{
+ return 0;
+}
+int ia_deserialize_bool(struct iarchive *ia, const char *name, int32_t *v)
+{
+ struct buff_struct *priv = ia->priv;
+ //fprintf(stderr, "Deserializing bool %d\n", priv->off);
+ //return ia_deserialize_int(ia, name, v);
+ if ((priv->len - priv->off) < 1) {
+ return -E2BIG;
+ }
+ *v = priv->buffer[priv->off];
+ priv->off+=1;
+ //fprintf(stderr, "Deserializing bool end %d\n", priv->off);
+ return 0;
+}
+int ia_deserialize_buffer(struct iarchive *ia, const char *name,
+ struct buffer *b)
+{
+ struct buff_struct *priv = ia->priv;
+ int rc = ia_deserialize_int(ia, "len", &b->len);
+ if (rc < 0)
+ return rc;
+ if ((priv->len - priv->off) < b->len) {
+ return -E2BIG;
+ }
+ // set the buffer to null
+ if (b->len == -1) {
+ b->buff = NULL;
+ return rc;
+ }
+ b->buff = malloc(b->len);
+ if (!b->buff) {
+ return -ENOMEM;
+ }
+ memcpy(b->buff, priv->buffer+priv->off, b->len);
+ priv->off += b->len;
+ return 0;
+}
+int ia_deserialize_string(struct iarchive *ia, const char *name, char **s)
+{
+ struct buff_struct *priv = ia->priv;
+ int32_t len;
+ int rc = ia_deserialize_int(ia, "len", &len);
+ if (rc < 0)
+ return rc;
+ if ((priv->len - priv->off) < len) {
+ return -E2BIG;
+ }
+ if (len < 0) {
+ return -EINVAL;
+ }
+ *s = malloc(len+1);
+ if (!*s) {
+ return -ENOMEM;
+ }
+ memcpy(*s, priv->buffer+priv->off, len);
+ (*s)[len] = '\0';
+ priv->off += len;
+ return 0;
+}
+
+static struct iarchive ia_default = { STRUCT_INITIALIZER (start_record ,ia_start_record),
+ STRUCT_INITIALIZER (end_record ,ia_end_record), STRUCT_INITIALIZER (start_vector , ia_start_vector),
+ STRUCT_INITIALIZER (end_vector ,ia_end_vector), STRUCT_INITIALIZER (deserialize_Bool , ia_deserialize_bool),
+ STRUCT_INITIALIZER (deserialize_Int ,ia_deserialize_int),
+ STRUCT_INITIALIZER (deserialize_Long , ia_deserialize_long) ,
+ STRUCT_INITIALIZER (deserialize_Buffer, ia_deserialize_buffer),
+ STRUCT_INITIALIZER (deserialize_String, ia_deserialize_string) };
+
+static struct oarchive oa_default = { STRUCT_INITIALIZER (start_record , oa_start_record),
+ STRUCT_INITIALIZER (end_record , oa_end_record), STRUCT_INITIALIZER (start_vector , oa_start_vector),
+ STRUCT_INITIALIZER (end_vector , oa_end_vector), STRUCT_INITIALIZER (serialize_Bool , oa_serialize_bool),
+ STRUCT_INITIALIZER (serialize_Int , oa_serialize_int),
+ STRUCT_INITIALIZER (serialize_Long , oa_serialize_long) ,
+ STRUCT_INITIALIZER (serialize_Buffer , oa_serialize_buffer),
+ STRUCT_INITIALIZER (serialize_String , oa_serialize_string) };
+
+struct iarchive *create_buffer_iarchive(char *buffer, int len)
+{
+ struct iarchive *ia;
+ struct buff_struct *buff;
+ ia = malloc(sizeof(*ia));
+ if (!ia) return 0;
+ buff = malloc(sizeof(struct buff_struct));
+ if (!buff) {
+ free(ia);
+ return 0;
+ }
+ *ia = ia_default;
+ buff->off = 0;
+ buff->buffer = buffer;
+ buff->len = len;
+ ia->priv = buff;
+ return ia;
+}
+
+struct oarchive *create_buffer_oarchive()
+{
+ struct oarchive *oa;
+ struct buff_struct *buff;
+ oa = malloc(sizeof(*oa));
+ if (!oa) return 0;
+ buff = malloc(sizeof(struct buff_struct));
+ if (!buff) {
+ free(oa);
+ return 0;
+ }
+ *oa = oa_default;
+ buff->off = 0;
+ buff->buffer = malloc(128);
+ buff->len = 128;
+ oa->priv = buff;
+ return oa;
+}
+
+void close_buffer_iarchive(struct iarchive **ia)
+{
+ free((*ia)->priv);
+ free(*ia);
+ *ia = 0;
+}
+
+void close_buffer_oarchive(struct oarchive **oa, int free_buffer)
+{
+ if (free_buffer) {
+ struct buff_struct *buff = (struct buff_struct *)(*oa)->priv;
+ if (buff->buffer) {
+ free(buff->buffer);
+ }
+ }
+ free((*oa)->priv);
+ free(*oa);
+ *oa = 0;
+}
+
+char *get_buffer(struct oarchive *oa)
+{
+ struct buff_struct *buff = oa->priv;
+ return buff->buffer;
+}
+int get_buffer_len(struct oarchive *oa)
+{
+ struct buff_struct *buff = oa->priv;
+ return buff->off;
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/src/st_adaptor.c
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/st_adaptor.c b/zookeeper-client/zookeeper-client-c/src/st_adaptor.c
new file mode 100644
index 0000000..23573b3
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/st_adaptor.c
@@ -0,0 +1,113 @@
+/**
+ * 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 DLL_EXPORT
+# define USE_STATIC_LIB
+#endif
+
+#include "zk_adaptor.h"
+#include <stdlib.h>
+#include <time.h>
+
+int zoo_lock_auth(zhandle_t *zh)
+{
+ return 0;
+}
+int zoo_unlock_auth(zhandle_t *zh)
+{
+ return 0;
+}
+int lock_buffer_list(buffer_head_t *l)
+{
+ return 0;
+}
+int unlock_buffer_list(buffer_head_t *l)
+{
+ return 0;
+}
+int lock_completion_list(completion_head_t *l)
+{
+ return 0;
+}
+int unlock_completion_list(completion_head_t *l)
+{
+ return 0;
+}
+struct sync_completion *alloc_sync_completion(void)
+{
+ return (struct sync_completion*)calloc(1, sizeof(struct sync_completion));
+}
+int wait_sync_completion(struct sync_completion *sc)
+{
+ return 0;
+}
+
+void free_sync_completion(struct sync_completion *sc)
+{
+ free(sc);
+}
+
+void notify_sync_completion(struct sync_completion *sc)
+{
+}
+
+int process_async(int outstanding_sync)
+{
+ return outstanding_sync == 0;
+}
+
+int adaptor_init(zhandle_t *zh)
+{
+ return 0;
+}
+
+void adaptor_finish(zhandle_t *zh){}
+
+void adaptor_destroy(zhandle_t *zh){}
+
+int flush_send_queue(zhandle_t *, int);
+
+int adaptor_send_queue(zhandle_t *zh, int timeout)
+{
+ return flush_send_queue(zh, timeout);
+}
+
+int32_t inc_ref_counter(zhandle_t* zh,int i)
+{
+ zh->ref_counter+=(i<0?-1:(i>0?1:0));
+ return zh->ref_counter;
+}
+
+int32_t get_xid()
+{
+ static int32_t xid = -1;
+ if (xid == -1) {
+ xid = time(0);
+ }
+ return xid++;
+}
+
+int enter_critical(zhandle_t* zh)
+{
+ return 0;
+}
+
+int leave_critical(zhandle_t* zh)
+{
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/src/winport.c
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/winport.c b/zookeeper-client/zookeeper-client-c/src/winport.c
new file mode 100644
index 0000000..3592ea1
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/winport.c
@@ -0,0 +1,302 @@
+/**
+ * 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.
+ */
+
+#ifdef WIN32
+#include "winport.h"
+#include <stdlib.h>
+#include <stdint.h> /* for int64_t */
+#include <winsock2.h> /* must always be included before ws2tcpip.h */
+#include <ws2tcpip.h> /* for SOCKET */
+
+int pthread_mutex_lock(pthread_mutex_t* _mutex ){
+ int rc = WaitForSingleObject( *_mutex, // handle to mutex
+ INFINITE); // no time-out interval
+ return ((rc == WAIT_OBJECT_0) ? 0: rc);
+}
+
+int pthread_mutex_unlock( pthread_mutex_t* _mutex ){
+ int rc = ReleaseMutex(*_mutex);
+ return ((rc != 0)? 0: GetLastError());
+}
+
+int pthread_mutex_init(pthread_mutex_t* _mutex, void* ignoredAttr){
+ //use CreateMutex as we are using the HANDLES in pthread_cond
+ *_mutex = CreateMutex(
+ NULL, // default security attributes
+ FALSE, // initially not owned
+ NULL); // unnamed mutex
+ return ((*_mutex == NULL) ? GetLastError() : 0);
+}
+
+int pthread_mutex_destroy(pthread_mutex_t* _mutex)
+{
+ int rc = CloseHandle(*_mutex);
+ return ((rc != 0)? 0: GetLastError());
+}
+
+int pthread_create(pthread_t *thread, const pthread_attr_t *attr, unsigned (__stdcall* start_routine)(void* a), void *arg)
+{
+ int _intThreadId;
+ (*thread).thread_handle = (HANDLE)_beginthreadex( NULL, 0, start_routine , arg, 0, (unsigned int*)&_intThreadId );
+ (*thread).thread_id = _intThreadId;
+ return (((*thread).thread_handle == 0 ) ? errno : 0 );
+}
+
+
+int pthread_equal(pthread_t t1, pthread_t t2){
+//Is there a better way to do this? GetThreadId(handle) is only supported Windows 2003 n above.
+ return ((t1.thread_id == t2.thread_id) ? 1:0);
+}
+
+pthread_t pthread_self(){
+ pthread_t thread_self;
+ thread_self.thread_handle = GetCurrentThread();
+ thread_self.thread_id = GetCurrentThreadId();
+ return thread_self;
+}
+
+int pthread_join(pthread_t _thread, void** ignore)
+{
+ int rc = WaitForSingleObject( _thread.thread_handle, INFINITE );
+ return ((rc == WAIT_OBJECT_0) ? 0: rc);
+}
+
+int pthread_detach(pthread_t _thread)
+{
+ int rc = CloseHandle(_thread.thread_handle) ;
+ return (rc != 0) ? 0: GetLastError();
+}
+
+void pthread_mutexattr_init(pthread_mutexattr_t* ignore){}
+void pthread_mutexattr_settype(pthread_mutexattr_t* ingore_attr, int ignore){}
+void pthread_mutexattr_destroy(pthread_mutexattr_t* ignore_attr){}
+
+int
+pthread_cond_init (pthread_cond_t *cv,
+ const pthread_condattr_t * ignore)
+{
+ cv->waiters_count_ = 0;
+ cv->was_broadcast_ = 0;
+ cv->sema_ = CreateSemaphore (NULL, // no security
+ 0, // initially 0
+ 0x7fffffff, // max count
+ NULL); // unnamed
+ if (cv->sema_ == NULL )
+ return GetLastError();
+ InitializeCriticalSection (&cv->waiters_count_lock_);
+ cv->waiters_done_ = CreateEvent (NULL, // no security
+ FALSE, // auto-reset
+ FALSE, // non-signaled initially
+ NULL); // unnamed
+ return (cv->waiters_done_ == NULL) ? GetLastError() : 0;
+
+}
+
+
+int pthread_cond_destroy(pthread_cond_t *cond)
+{
+ CloseHandle( cond->sema_);
+ DeleteCriticalSection(&cond->waiters_count_lock_);
+ return (CloseHandle( cond->waiters_done_ ) == 0)? GetLastError(): 0 ;
+}
+
+
+int
+pthread_cond_signal (pthread_cond_t *cv)
+{
+ int have_waiters;
+ EnterCriticalSection (& (cv->waiters_count_lock_));
+ have_waiters = cv->waiters_count_ > 0;
+ LeaveCriticalSection (&cv->waiters_count_lock_);
+
+ // If there aren't any waiters, then this is a no-op.
+ if (have_waiters){
+ return (ReleaseSemaphore (cv->sema_, 1, 0) == 0 ) ? GetLastError() : 0 ;
+ }else
+ return 0;
+}
+
+
+int
+pthread_cond_broadcast (pthread_cond_t *cv)
+{
+ // This is needed to ensure that <waiters_count_> and <was_broadcast_> are
+ // consistent relative to each other.
+ int have_waiters = 0;
+ EnterCriticalSection (&cv->waiters_count_lock_);
+
+ if (cv->waiters_count_ > 0) {
+ // We are broadcasting, even if there is just one waiter...
+ // Record that we are broadcasting, which helps optimize
+ // <pthread_cond_wait> for the non-broadcast case.
+ cv->was_broadcast_ = 1;
+ have_waiters = 1;
+ }
+
+ if (have_waiters) {
+ // Wake up all the waiters atomically.
+ ReleaseSemaphore (cv->sema_, cv->waiters_count_, 0);
+
+ LeaveCriticalSection (&cv->waiters_count_lock_);
+
+ // Wait for all the awakened threads to acquire the counting
+ // semaphore.
+ WaitForSingleObject (cv->waiters_done_, INFINITE);
+ // This assignment is okay, even without the <waiters_count_lock_> held
+ // because no other waiter threads can wake up to access it.
+ cv->was_broadcast_ = 0;
+ }
+ else
+ LeaveCriticalSection (&cv->waiters_count_lock_);
+}
+
+
+int
+pthread_cond_wait (pthread_cond_t *cv,
+ pthread_mutex_t *external_mutex)
+{
+ int last_waiter;
+ // Avoid race conditions.
+ EnterCriticalSection (&cv->waiters_count_lock_);
+ cv->waiters_count_++;
+ LeaveCriticalSection (&cv->waiters_count_lock_);
+
+ // This call atomically releases the mutex and waits on the
+ // semaphore until <pthread_cond_signal> or <pthread_cond_broadcast>
+ // are called by another thread.
+ SignalObjectAndWait (*external_mutex, cv->sema_, INFINITE, FALSE);
+
+ // Reacquire lock to avoid race conditions.
+ EnterCriticalSection (&cv->waiters_count_lock_);
+
+ // We're no longer waiting...
+ cv->waiters_count_--;
+
+ // Check to see if we're the last waiter after <pthread_cond_broadcast>.
+ last_waiter = cv->was_broadcast_ && cv->waiters_count_ == 0;
+
+ LeaveCriticalSection (&cv->waiters_count_lock_);
+
+ // If we're the last waiter thread during this particular broadcast
+ // then let all the other threads proceed.
+ if (last_waiter)
+ // This call atomically signals the <waiters_done_> event and waits until
+ // it can acquire the <external_mutex>. This is required to ensure fairness.
+ SignalObjectAndWait (cv->waiters_done_, *external_mutex, INFINITE, FALSE);
+ else
+ // Always regain the external mutex since that's the guarantee we
+ // give to our callers.
+ WaitForSingleObject (*external_mutex, INFINITE);
+}
+
+int pthread_key_create(pthread_key_t *key, void (*destructor)(void *) )
+{
+ int result = 0;
+ pthread_key_t* newkey;
+
+ if ((newkey = (pthread_key_t*) calloc (1, sizeof (pthread_key_t))) == NULL)
+ {
+ result = ENOMEM;
+ }
+ else if ((newkey->key = TlsAlloc ()) == TLS_OUT_OF_INDEXES)
+ {
+ result = EAGAIN;
+ free (newkey);
+ newkey = NULL;
+ }
+ else if (destructor != NULL)
+ {
+ //--we have to store the function pointer for destructor, so that we can call it
+ //--to free up the user allocated storage--
+ newkey->destructor = destructor;
+ }
+ key = newkey;
+ return (result);
+}
+
+int pthread_key_delete(pthread_key_t key)
+{
+ int rc = 0;
+ LPVOID lpvData = TlsGetValue(key.key);
+ rc = TlsFree (key.key);
+ rc = (rc != 0 ) ? 0 : GetLastError();
+ if (key.destructor != NULL && lpvData != 0){
+ key.destructor(lpvData); //we take control of calling destructor, instead of calling it on thread exit.
+ }
+ free (&key);
+ return (rc);
+}
+
+void *pthread_getspecific(pthread_key_t key)
+{
+ LPVOID lpvData = TlsGetValue(key.key);
+ if ((lpvData == 0) && (GetLastError() != ERROR_SUCCESS))
+ return NULL;
+ else
+ return lpvData;
+}
+
+int pthread_setspecific(pthread_key_t key, const void *value)
+{
+ int rc = TlsSetValue (key.key, value);
+ return ((rc != 0 ) ? 0 : GetLastError());
+}
+
+int gettimeofday(struct timeval *tp, void *tzp) {
+ int64_t now = 0;
+ if (tzp != 0) { errno = EINVAL; return -1; }
+ GetSystemTimeAsFileTime( (LPFILETIME)&now );
+ tp->tv_sec = (long)(now / 10000000 - 11644473600LL);
+ tp->tv_usec = (now / 10) % 1000000;
+ return 0;
+}
+
+int close(SOCKET fd) {
+ return closesocket(fd);
+}
+
+int Win32WSAStartup()
+{
+ WORD wVersionRq;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRq = MAKEWORD(2,0);
+ err = WSAStartup(wVersionRq, &wsaData);
+ if (err != 0)
+ return 1;
+
+ // confirm the version information
+ if ((LOBYTE(wsaData.wVersion) != 2) ||
+ (HIBYTE(wsaData.wVersion) != 0))
+ {
+ Win32WSACleanup();
+ return 1;
+ }
+ return 0;
+}
+
+void Win32WSACleanup()
+{
+ WSACleanup();
+}
+
+#endif //WIN32
+
+
+
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/src/winport.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/winport.h b/zookeeper-client/zookeeper-client-c/src/winport.h
new file mode 100644
index 0000000..da6028c
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/winport.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.
+ */
+
+/**
+ * This header file is to port pthread lib , sockets and other utility methods on windows.
+ * Specifically the threads function, mutexes, keys, and socket initialization.
+ */
+
+#ifndef WINPORT_H_
+#define WINPORT_H_
+
+#ifdef WIN32
+#include "winconfig.h"
+
+#define _WINSOCK_DEPRECATED_NO_WARNINGS
+#include <winsock2.h> /* must always be included before ws2tcpip.h */
+#include <ws2tcpip.h> /* for struct sock_addr used in zookeeper.h */
+
+/* POSIX names are deprecated, use ISO conformant names instead. */
+#define strdup _strdup
+#define getcwd _getcwd
+#define getpid _getpid
+
+/* Windows "secure" versions of POSIX reentrant functions */
+#define strtok_r strtok_s
+#define localtime_r(a,b) localtime_s(b,a)
+
+/* After this version of MSVC, snprintf became a defined function,
+ and so cannot be redefined, nor can #ifndef be used to guard it. */
+#if ((defined(_MSC_VER) && _MSC_VER < 1900) || !defined(_MSC_VER))
+#define snprintf _snprintf
+#endif
+
+
+#include <errno.h>
+#include <process.h>
+#include <stdint.h> /* for int64_t */
+#include <stdlib.h>
+#include <malloc.h>
+
+
+typedef int ssize_t;
+typedef HANDLE pthread_mutex_t;
+
+struct pthread_t_
+{
+ HANDLE thread_handle;
+ DWORD thread_id;
+};
+
+typedef struct pthread_t_ pthread_t;
+typedef int pthread_mutexattr_t;
+typedef int pthread_condattr_t;
+typedef int pthread_attr_t;
+#define PTHREAD_MUTEX_RECURSIVE 0
+
+int pthread_mutex_lock(pthread_mutex_t* _mutex );
+int pthread_mutex_unlock( pthread_mutex_t* _mutex );
+int pthread_mutex_init(pthread_mutex_t* _mutex, void* ignoredAttr);
+int pthread_mutex_destroy(pthread_mutex_t* _mutex);
+int pthread_create(pthread_t *thread, const pthread_attr_t *attr, unsigned (__stdcall* start_routine)(void* a), void *arg);
+int pthread_equal(pthread_t t1, pthread_t t2);
+pthread_t pthread_self();
+int pthread_join(pthread_t _thread, void** ignore);
+int pthread_detach(pthread_t _thread);
+
+void pthread_mutexattr_init(pthread_mutexattr_t* ignore);
+void pthread_mutexattr_settype(pthread_mutexattr_t* ingore_attr, int ignore);
+void pthread_mutexattr_destroy(pthread_mutexattr_t* ignore_attr);
+
+
+// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
+
+typedef struct
+{
+ int waiters_count_;
+ // Number of waiting threads.
+
+ CRITICAL_SECTION waiters_count_lock_;
+ // Serialize access to <waiters_count_>.
+
+ HANDLE sema_;
+ // Semaphore used to queue up threads waiting for the condition to
+ // become signaled.
+
+ HANDLE waiters_done_;
+ // An auto-reset event used by the broadcast/signal thread to wait
+ // for all the waiting thread(s) to wake up and be released from the
+ // semaphore.
+
+ size_t was_broadcast_;
+ // Keeps track of whether we were broadcasting or signaling. This
+ // allows us to optimize the code if we're just signaling.
+}pthread_cond_t;
+
+int pthread_cond_init (pthread_cond_t *cv,const pthread_condattr_t * ignore);
+int pthread_cond_destroy(pthread_cond_t *cond);
+int pthread_cond_signal (pthread_cond_t *cv);
+int pthread_cond_broadcast (pthread_cond_t *cv);
+int pthread_cond_wait (pthread_cond_t *cv, pthread_mutex_t *external_mutex);
+
+
+struct pthread_key_t_
+{
+ DWORD key;
+ void (*destructor) (void *);
+};
+
+typedef struct pthread_key_t_ pthread_key_t;
+int pthread_key_create(pthread_key_t *key, void (*destructor)(void *) );
+int pthread_key_delete(pthread_key_t key);
+void *pthread_getspecific(pthread_key_t key);
+int pthread_setspecific(pthread_key_t key, const void *value);
+
+int gettimeofday(struct timeval *tp, void *tzp);
+int close(SOCKET fd);
+int Win32WSAStartup();
+void Win32WSACleanup();
+#endif //WIN32
+
+
+
+#endif //WINPORT_H_
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/src/zk_adaptor.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/zk_adaptor.h b/zookeeper-client/zookeeper-client-c/src/zk_adaptor.h
new file mode 100644
index 0000000..b990779
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/zk_adaptor.h
@@ -0,0 +1,276 @@
+/**
+ * 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_ADAPTOR_H_
+#define ZK_ADAPTOR_H_
+#include <zookeeper.jute.h>
+#ifdef THREADED
+#ifndef WIN32
+#include <pthread.h>
+#else
+#include "winport.h"
+#endif
+#endif
+#include "zookeeper.h"
+#include "zk_hashtable.h"
+
+/* predefined xid's values recognized as special by the server */
+#define WATCHER_EVENT_XID -1
+#define PING_XID -2
+#define AUTH_XID -4
+#define SET_WATCHES_XID -8
+
+/* zookeeper state constants */
+#define EXPIRED_SESSION_STATE_DEF -112
+#define AUTH_FAILED_STATE_DEF -113
+#define CONNECTING_STATE_DEF 1
+#define ASSOCIATING_STATE_DEF 2
+#define CONNECTED_STATE_DEF 3
+#define NOTCONNECTED_STATE_DEF 999
+
+/* zookeeper event type constants */
+#define CREATED_EVENT_DEF 1
+#define DELETED_EVENT_DEF 2
+#define CHANGED_EVENT_DEF 3
+#define CHILD_EVENT_DEF 4
+#define SESSION_EVENT_DEF -1
+#define NOTWATCHING_EVENT_DEF -2
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _buffer_list;
+struct _completion_list;
+
+typedef struct _buffer_head {
+ struct _buffer_list *volatile head;
+ struct _buffer_list *last;
+#ifdef THREADED
+ pthread_mutex_t lock;
+#endif
+} buffer_head_t;
+
+typedef struct _completion_head {
+ struct _completion_list *volatile head;
+ struct _completion_list *last;
+#ifdef THREADED
+ pthread_cond_t cond;
+ pthread_mutex_t lock;
+#endif
+} completion_head_t;
+
+int lock_buffer_list(buffer_head_t *l);
+int unlock_buffer_list(buffer_head_t *l);
+int lock_completion_list(completion_head_t *l);
+int unlock_completion_list(completion_head_t *l);
+
+struct sync_completion {
+ int rc;
+ union {
+ struct {
+ char *str;
+ int str_len;
+ } str;
+ struct Stat stat;
+ struct {
+ char *buffer;
+ int buff_len;
+ struct Stat stat;
+ } data;
+ struct {
+ struct ACL_vector acl;
+ struct Stat stat;
+ } acl;
+ struct String_vector strs2;
+ struct {
+ struct String_vector strs2;
+ struct Stat stat2;
+ } strs_stat;
+ } u;
+ int complete;
+#ifdef THREADED
+ pthread_cond_t cond;
+ pthread_mutex_t lock;
+#endif
+};
+
+typedef struct _auth_info {
+ int state; /* 0=>inactive, >0 => active */
+ char* scheme;
+ struct buffer auth;
+ void_completion_t completion;
+ const char* data;
+ struct _auth_info *next;
+} auth_info;
+
+/**
+ * This structure represents a packet being read or written.
+ */
+typedef struct _buffer_list {
+ char *buffer;
+ int len; /* This represents the length of sizeof(header) + length of buffer */
+ int curr_offset; /* This is the offset into the header followed by offset into the buffer */
+ struct _buffer_list *next;
+} buffer_list_t;
+
+/* the size of connect request */
+#define HANDSHAKE_REQ_SIZE 44
+/* connect request */
+struct connect_req {
+ int32_t protocolVersion;
+ int64_t lastZxidSeen;
+ int32_t timeOut;
+ int64_t sessionId;
+ int32_t passwd_len;
+ char passwd[16];
+};
+
+/* the connect response */
+struct prime_struct {
+ int32_t len;
+ int32_t protocolVersion;
+ int32_t timeOut;
+ int64_t sessionId;
+ int32_t passwd_len;
+ char passwd[16];
+};
+
+#ifdef THREADED
+/* this is used by mt_adaptor internally for thread management */
+struct adaptor_threads {
+ pthread_t io;
+ pthread_t completion;
+ int threadsToWait; // barrier
+ pthread_cond_t cond; // barrier's conditional
+ pthread_mutex_t lock; // ... and a lock
+ pthread_mutex_t zh_lock; // critical section lock
+#ifdef WIN32
+ SOCKET self_pipe[2];
+#else
+ int self_pipe[2];
+#endif
+};
+#endif
+
+/** the auth list for adding auth */
+typedef struct _auth_list_head {
+ auth_info *auth;
+#ifdef THREADED
+ pthread_mutex_t lock;
+#endif
+} auth_list_head_t;
+
+/**
+ * This structure represents the connection to zookeeper.
+ */
+
+struct _zhandle {
+#ifdef WIN32
+ SOCKET fd; /* the descriptor used to talk to zookeeper */
+#else
+ int fd; /* the descriptor used to talk to zookeeper */
+#endif
+ char *hostname; /* the hostname of zookeeper */
+ struct sockaddr_storage *addrs; /* the addresses that correspond to the hostname */
+ int addrs_count; /* The number of addresses in the addrs array */
+ watcher_fn watcher; /* the registered watcher */
+ struct timeval last_recv; /* The time that the last message was received */
+ struct timeval last_send; /* The time that the last message was sent */
+ struct timeval last_ping; /* The time that the last PING was sent */
+ struct timeval next_deadline; /* The time of the next deadline */
+ int recv_timeout; /* The maximum amount of time that can go by without
+ receiving anything from the zookeeper server */
+ buffer_list_t *input_buffer; /* the current buffer being read in */
+ buffer_head_t to_process; /* The buffers that have been read and are ready to be processed. */
+ buffer_head_t to_send; /* The packets queued to send */
+ completion_head_t sent_requests; /* The outstanding requests */
+ completion_head_t completions_to_process; /* completions that are ready to run */
+ int connect_index; /* The index of the address to connect to */
+ clientid_t client_id;
+ long long last_zxid;
+ int outstanding_sync; /* Number of outstanding synchronous requests */
+ struct _buffer_list primer_buffer; /* The buffer used for the handshake at the start of a connection */
+ struct prime_struct primer_storage; /* the connect response */
+ char primer_storage_buffer[40]; /* the true size of primer_storage */
+ volatile int state;
+ void *context;
+ auth_list_head_t auth_h; /* authentication data list */
+ /* zookeeper_close is not reentrant because it de-allocates the zhandler.
+ * This guard variable is used to defer the destruction of zhandle till
+ * right before top-level API call returns to the caller */
+ int32_t ref_counter;
+ volatile int close_requested;
+ void *adaptor_priv;
+ /* Used for debugging only: non-zero value indicates the time when the zookeeper_process
+ * call returned while there was at least one unprocessed server response
+ * available in the socket recv buffer */
+ struct timeval socket_readable;
+
+ zk_hashtable* active_node_watchers;
+ zk_hashtable* active_exist_watchers;
+ zk_hashtable* active_child_watchers;
+ /** used for chroot path at the client side **/
+ char *chroot;
+};
+
+
+int adaptor_init(zhandle_t *zh);
+void adaptor_finish(zhandle_t *zh);
+void adaptor_destroy(zhandle_t *zh);
+struct sync_completion *alloc_sync_completion(void);
+int wait_sync_completion(struct sync_completion *sc);
+void free_sync_completion(struct sync_completion *sc);
+void notify_sync_completion(struct sync_completion *sc);
+int adaptor_send_queue(zhandle_t *zh, int timeout);
+int process_async(int outstanding_sync);
+void process_completions(zhandle_t *zh);
+int flush_send_queue(zhandle_t*zh, int timeout);
+char* sub_string(zhandle_t *zh, const char* server_path);
+void free_duplicate_path(const char* free_path, const char* path);
+int zoo_lock_auth(zhandle_t *zh);
+int zoo_unlock_auth(zhandle_t *zh);
+
+// critical section guards
+int enter_critical(zhandle_t* zh);
+int leave_critical(zhandle_t* zh);
+// zhandle object reference counting
+void api_prolog(zhandle_t* zh);
+int api_epilog(zhandle_t *zh, int rc);
+int32_t get_xid();
+// returns the new value of the ref counter
+int32_t inc_ref_counter(zhandle_t* zh,int i);
+
+#ifdef THREADED
+// atomic post-increment
+int32_t fetch_and_add(volatile int32_t* operand, int incr);
+// in mt mode process session event asynchronously by the completion thread
+#define PROCESS_SESSION_EVENT(zh,newstate) queue_session_event(zh,newstate)
+#else
+// in single-threaded mode process session event immediately
+//#define PROCESS_SESSION_EVENT(zh,newstate) deliverWatchers(zh,ZOO_SESSION_EVENT,newstate,0)
+#define PROCESS_SESSION_EVENT(zh,newstate) queue_session_event(zh,newstate)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*ZK_ADAPTOR_H_*/
+
+
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/src/zk_hashtable.c
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/zk_hashtable.c b/zookeeper-client/zookeeper-client-c/src/zk_hashtable.c
new file mode 100644
index 0000000..0efc5aa
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/zk_hashtable.c
@@ -0,0 +1,337 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "zk_hashtable.h"
+#include "zk_adaptor.h"
+#include "hashtable/hashtable.h"
+#include "hashtable/hashtable_itr.h"
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+typedef struct _watcher_object {
+ watcher_fn watcher;
+ void* context;
+ struct _watcher_object* next;
+} watcher_object_t;
+
+
+struct _zk_hashtable {
+ struct hashtable* ht;
+};
+
+struct watcher_object_list {
+ watcher_object_t* head;
+};
+
+/* the following functions are for testing only */
+typedef struct hashtable hashtable_impl;
+
+hashtable_impl* getImpl(zk_hashtable* ht){
+ return ht->ht;
+}
+
+watcher_object_t* getFirstWatcher(zk_hashtable* ht,const char* path)
+{
+ watcher_object_list_t* wl=hashtable_search(ht->ht,(void*)path);
+ if(wl!=0)
+ return wl->head;
+ return 0;
+}
+/* end of testing functions */
+
+watcher_object_t* clone_watcher_object(watcher_object_t* wo)
+{
+ watcher_object_t* res=calloc(1,sizeof(watcher_object_t));
+ assert(res);
+ res->watcher=wo->watcher;
+ res->context=wo->context;
+ return res;
+}
+
+static unsigned int string_hash_djb2(void *str)
+{
+ unsigned int hash = 5381;
+ int c;
+ const char* cstr = (const char*)str;
+ while ((c = *cstr++))
+ hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
+
+ return hash;
+}
+
+static int string_equal(void *key1,void *key2)
+{
+ return strcmp((const char*)key1,(const char*)key2)==0;
+}
+
+static watcher_object_t* create_watcher_object(watcher_fn watcher,void* ctx)
+{
+ watcher_object_t* wo=calloc(1,sizeof(watcher_object_t));
+ assert(wo);
+ wo->watcher=watcher;
+ wo->context=ctx;
+ return wo;
+}
+
+static watcher_object_list_t* create_watcher_object_list(watcher_object_t* head)
+{
+ watcher_object_list_t* wl=calloc(1,sizeof(watcher_object_list_t));
+ assert(wl);
+ wl->head=head;
+ return wl;
+}
+
+static void destroy_watcher_object_list(watcher_object_list_t* list)
+{
+ watcher_object_t* e = NULL;
+
+ if(list==0)
+ return;
+ e=list->head;
+ while(e!=0){
+ watcher_object_t* this=e;
+ e=e->next;
+ free(this);
+ }
+ free(list);
+}
+
+zk_hashtable* create_zk_hashtable()
+{
+ struct _zk_hashtable *ht=calloc(1,sizeof(struct _zk_hashtable));
+ assert(ht);
+ ht->ht=create_hashtable(32,string_hash_djb2,string_equal);
+ return ht;
+}
+
+static void do_clean_hashtable(zk_hashtable* ht)
+{
+ struct hashtable_itr *it;
+ int hasMore;
+ if(hashtable_count(ht->ht)==0)
+ return;
+ it=hashtable_iterator(ht->ht);
+ do {
+ watcher_object_list_t* w=hashtable_iterator_value(it);
+ destroy_watcher_object_list(w);
+ hasMore=hashtable_iterator_remove(it);
+ } while(hasMore);
+ free(it);
+}
+
+void destroy_zk_hashtable(zk_hashtable* ht)
+{
+ if(ht!=0){
+ do_clean_hashtable(ht);
+ hashtable_destroy(ht->ht,0);
+ free(ht);
+ }
+}
+
+// searches for a watcher object instance in a watcher object list;
+// two watcher objects are equal if their watcher function and context pointers
+// are equal
+static watcher_object_t* search_watcher(watcher_object_list_t** wl,watcher_object_t* wo)
+{
+ watcher_object_t* wobj=(*wl)->head;
+ while(wobj!=0){
+ if(wobj->watcher==wo->watcher && wobj->context==wo->context)
+ return wobj;
+ wobj=wobj->next;
+ }
+ return 0;
+}
+
+static int add_to_list(watcher_object_list_t **wl, watcher_object_t *wo,
+ int clone)
+{
+ if (search_watcher(wl, wo)==0) {
+ watcher_object_t* cloned=wo;
+ if (clone) {
+ cloned = clone_watcher_object(wo);
+ assert(cloned);
+ }
+ cloned->next = (*wl)->head;
+ (*wl)->head = cloned;
+ return 1;
+ } else if (!clone) {
+ // If it's here and we aren't supposed to clone, we must destroy
+ free(wo);
+ }
+ return 0;
+}
+
+static int do_insert_watcher_object(zk_hashtable *ht, const char *path, watcher_object_t* wo)
+{
+ int res=1;
+ watcher_object_list_t* wl;
+
+ wl=hashtable_search(ht->ht,(void*)path);
+ if(wl==0){
+ int res;
+ /* inserting a new path element */
+ res=hashtable_insert(ht->ht,strdup(path),create_watcher_object_list(wo));
+ assert(res);
+ }else{
+ /*
+ * Path already exists; check if the watcher already exists.
+ * Don't clone the watcher since it's allocated on the heap --- avoids
+ * a memory leak and saves a clone operation (calloc + copy).
+ */
+ res = add_to_list(&wl, wo, 0);
+ }
+ return res;
+}
+
+
+char **collect_keys(zk_hashtable *ht, int *count)
+{
+ char **list;
+ struct hashtable_itr *it;
+ int i;
+
+ *count = hashtable_count(ht->ht);
+ list = calloc(*count, sizeof(char*));
+ it=hashtable_iterator(ht->ht);
+ for(i = 0; i < *count; i++) {
+ list[i] = strdup(hashtable_iterator_key(it));
+ hashtable_iterator_advance(it);
+ }
+ free(it);
+ return list;
+}
+
+static int insert_watcher_object(zk_hashtable *ht, const char *path,
+ watcher_object_t* wo)
+{
+ int res;
+ res=do_insert_watcher_object(ht,path,wo);
+ return res;
+}
+
+static void copy_watchers(watcher_object_list_t *from, watcher_object_list_t *to, int clone)
+{
+ watcher_object_t* wo=from->head;
+ while(wo){
+ watcher_object_t *next = wo->next;
+ add_to_list(&to, wo, clone);
+ wo=next;
+ }
+}
+
+static void copy_table(zk_hashtable *from, watcher_object_list_t *to) {
+ struct hashtable_itr *it;
+ int hasMore;
+ if(hashtable_count(from->ht)==0)
+ return;
+ it=hashtable_iterator(from->ht);
+ do {
+ watcher_object_list_t *w = hashtable_iterator_value(it);
+ copy_watchers(w, to, 1);
+ hasMore=hashtable_iterator_advance(it);
+ } while(hasMore);
+ free(it);
+}
+
+static void collect_session_watchers(zhandle_t *zh,
+ watcher_object_list_t **list)
+{
+ copy_table(zh->active_node_watchers, *list);
+ copy_table(zh->active_exist_watchers, *list);
+ copy_table(zh->active_child_watchers, *list);
+}
+
+static void add_for_event(zk_hashtable *ht, char *path, watcher_object_list_t **list)
+{
+ watcher_object_list_t* wl;
+ wl = (watcher_object_list_t*)hashtable_remove(ht->ht, path);
+ if (wl) {
+ copy_watchers(wl, *list, 0);
+ // Since we move, not clone the watch_objects, we just need to free the
+ // head pointer
+ free(wl);
+ }
+}
+
+static void do_foreach_watcher(watcher_object_t* wo,zhandle_t* zh,
+ const char* path,int type,int state)
+{
+ // session event's don't have paths
+ const char *client_path =
+ (type != ZOO_SESSION_EVENT ? sub_string(zh, path) : path);
+ while(wo!=0){
+ wo->watcher(zh,type,state,client_path,wo->context);
+ wo=wo->next;
+ }
+ free_duplicate_path(client_path, path);
+}
+
+watcher_object_list_t *collectWatchers(zhandle_t *zh,int type, char *path)
+{
+ struct watcher_object_list *list = create_watcher_object_list(0);
+
+ if(type==ZOO_SESSION_EVENT){
+ watcher_object_t defWatcher;
+ defWatcher.watcher=zh->watcher;
+ defWatcher.context=zh->context;
+ add_to_list(&list, &defWatcher, 1);
+ collect_session_watchers(zh, &list);
+ return list;
+ }
+ switch(type){
+ case CREATED_EVENT_DEF:
+ case CHANGED_EVENT_DEF:
+ // look up the watchers for the path and move them to a delivery list
+ add_for_event(zh->active_node_watchers,path,&list);
+ add_for_event(zh->active_exist_watchers,path,&list);
+ break;
+ case CHILD_EVENT_DEF:
+ // look up the watchers for the path and move them to a delivery list
+ add_for_event(zh->active_child_watchers,path,&list);
+ break;
+ case DELETED_EVENT_DEF:
+ // look up the watchers for the path and move them to a delivery list
+ add_for_event(zh->active_node_watchers,path,&list);
+ add_for_event(zh->active_exist_watchers,path,&list);
+ add_for_event(zh->active_child_watchers,path,&list);
+ break;
+ }
+ return list;
+}
+
+void deliverWatchers(zhandle_t *zh, int type,int state, char *path, watcher_object_list_t **list)
+{
+ if (!list || !(*list)) return;
+ do_foreach_watcher((*list)->head, zh, path, type, state);
+ destroy_watcher_object_list(*list);
+ *list = 0;
+}
+
+void activateWatcher(zhandle_t *zh, watcher_registration_t* reg, int rc)
+{
+ if(reg){
+ /* in multithreaded lib, this code is executed
+ * by the IO thread */
+ zk_hashtable *ht = reg->checker(zh, rc);
+ if(ht){
+ insert_watcher_object(ht,reg->path,
+ create_watcher_object(reg->watcher, reg->context));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/src/zk_hashtable.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/zk_hashtable.h b/zookeeper-client/zookeeper-client-c/src/zk_hashtable.h
new file mode 100644
index 0000000..31109c1
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/zk_hashtable.h
@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ZK_HASHTABLE_H_
+#define ZK_HASHTABLE_H_
+
+#include <zookeeper.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef struct watcher_object_list watcher_object_list_t;
+typedef struct _zk_hashtable zk_hashtable;
+
+/**
+ * The function must return a non-zero value if the watcher object can be activated
+ * as a result of the server response. Normally, a watch can only be activated
+ * if the server returns a success code (ZOK). However in the case when zoo_exists()
+ * returns a ZNONODE code the watcher should be activated nevertheless.
+ */
+typedef zk_hashtable *(*result_checker_fn)(zhandle_t *, int rc);
+
+/**
+ * A watcher object gets temporarily stored with the completion entry until
+ * the server response comes back at which moment the watcher object is moved
+ * to the active watchers map.
+ */
+typedef struct _watcher_registration {
+ watcher_fn watcher;
+ void* context;
+ result_checker_fn checker;
+ const char* path;
+} watcher_registration_t;
+
+zk_hashtable* create_zk_hashtable();
+void destroy_zk_hashtable(zk_hashtable* ht);
+
+char **collect_keys(zk_hashtable *ht, int *count);
+
+/**
+ * check if the completion has a watcher object associated
+ * with it. If it does, move the watcher object to the map of
+ * active watchers (only if the checker allows to do so)
+ */
+ void activateWatcher(zhandle_t *zh, watcher_registration_t* reg, int rc);
+ watcher_object_list_t *collectWatchers(zhandle_t *zh,int type, char *path);
+ void deliverWatchers(zhandle_t *zh, int type, int state, char *path, struct watcher_object_list **list);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*ZK_HASHTABLE_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/src/zk_log.c
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/zk_log.c b/zookeeper-client/zookeeper-client-c/src/zk_log.c
new file mode 100644
index 0000000..6b4fdfa
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/zk_log.c
@@ -0,0 +1,180 @@
+/**
+ * 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.
+ */
+
+#if !defined(DLL_EXPORT) && !defined(USE_STATIC_LIB)
+# define USE_STATIC_LIB
+#endif
+
+#include "zookeeper_log.h"
+#ifndef WIN32
+#include <unistd.h>
+#else
+typedef DWORD pid_t;
+#include <process.h> /* for getpid */
+#endif
+
+#include <stdarg.h>
+#include <time.h>
+
+#define TIME_NOW_BUF_SIZE 1024
+#define FORMAT_LOG_BUF_SIZE 4096
+
+#ifdef THREADED
+#ifndef WIN32
+#include <pthread.h>
+#else
+#include "winport.h"
+#endif
+
+static pthread_key_t time_now_buffer;
+static pthread_key_t format_log_msg_buffer;
+
+void freeBuffer(void* p){
+ if(p) free(p);
+}
+
+__attribute__((constructor)) void prepareTSDKeys() {
+ pthread_key_create (&time_now_buffer, freeBuffer);
+ pthread_key_create (&format_log_msg_buffer, freeBuffer);
+}
+
+char* getTSData(pthread_key_t key,int size){
+ char* p=pthread_getspecific(key);
+ if(p==0){
+ int res;
+ p=calloc(1,size);
+ res=pthread_setspecific(key,p);
+ if(res!=0){
+ fprintf(stderr,"Failed to set TSD key: %d",res);
+ }
+ }
+ return p;
+}
+
+char* get_time_buffer(){
+ return getTSData(time_now_buffer,TIME_NOW_BUF_SIZE);
+}
+
+char* get_format_log_buffer(){
+ return getTSData(format_log_msg_buffer,FORMAT_LOG_BUF_SIZE);
+}
+#else
+char* get_time_buffer(){
+ static char buf[TIME_NOW_BUF_SIZE];
+ return buf;
+}
+
+char* get_format_log_buffer(){
+ static char buf[FORMAT_LOG_BUF_SIZE];
+ return buf;
+}
+
+#endif
+
+ZooLogLevel logLevel=ZOO_LOG_LEVEL_INFO;
+
+static FILE* logStream=0;
+FILE* getLogStream(){
+ if(logStream==0)
+ logStream=stderr;
+ return logStream;
+}
+
+void zoo_set_log_stream(FILE* stream){
+ logStream=stream;
+}
+
+static const char* time_now(char* now_str){
+ struct timeval tv;
+ struct tm lt;
+ time_t now = 0;
+ size_t len = 0;
+
+ gettimeofday(&tv,0);
+
+ now = tv.tv_sec;
+ localtime_r(&now, <);
+
+ // clone the format used by log4j ISO8601DateFormat
+ // specifically: "yyyy-MM-dd HH:mm:ss,SSS"
+
+ len = strftime(now_str, TIME_NOW_BUF_SIZE,
+ "%Y-%m-%d %H:%M:%S",
+ <);
+
+ len += snprintf(now_str + len,
+ TIME_NOW_BUF_SIZE - len,
+ ",%03d",
+ (int)(tv.tv_usec/1000));
+
+ return now_str;
+}
+
+void log_message(ZooLogLevel curLevel,int line,const char* funcName,
+ const char* message)
+{
+ static const char* dbgLevelStr[]={"ZOO_INVALID","ZOO_ERROR","ZOO_WARN",
+ "ZOO_INFO","ZOO_DEBUG"};
+ static pid_t pid=0;
+#ifdef WIN32
+ char timebuf [TIME_NOW_BUF_SIZE];
+#endif
+ if(pid==0)pid=getpid();
+#ifndef THREADED
+ // pid_t is long on Solaris
+ fprintf(LOGSTREAM, "%s:%ld:%s@%s@%d: %s\n", time_now(get_time_buffer()),(long)pid,
+ dbgLevelStr[curLevel],funcName,line,message);
+#else
+#ifdef WIN32
+ fprintf(LOGSTREAM, "%s:%d(0x%lx):%s@%s@%d: %s\n", time_now(timebuf),pid,
+ (unsigned long int)(pthread_self().thread_id),
+ dbgLevelStr[curLevel],funcName,line,message);
+#else
+ fprintf(LOGSTREAM, "%s:%ld(0x%lx):%s@%s@%d: %s\n", time_now(get_time_buffer()),(long)pid,
+ (unsigned long int)pthread_self(),
+ dbgLevelStr[curLevel],funcName,line,message);
+#endif
+#endif
+ fflush(LOGSTREAM);
+}
+
+const char* format_log_message(const char* format,...)
+{
+ va_list va;
+ char* buf=get_format_log_buffer();
+ if(!buf)
+ return "format_log_message: Unable to allocate memory buffer";
+
+ va_start(va,format);
+ vsnprintf(buf, FORMAT_LOG_BUF_SIZE-1,format,va);
+ va_end(va);
+ return buf;
+}
+
+void zoo_set_debug_level(ZooLogLevel level)
+{
+ if(level==0){
+ // disable logging (unit tests do this)
+ logLevel=(ZooLogLevel)0;
+ return;
+ }
+ if(level<ZOO_LOG_LEVEL_ERROR)level=ZOO_LOG_LEVEL_ERROR;
+ if(level>ZOO_LOG_LEVEL_DEBUG)level=ZOO_LOG_LEVEL_DEBUG;
+ logLevel=level;
+}
+
[20/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
ZOOKEEPER-3031: 3.4: MAVEN MIGRATION - move client dir
Separate PR for branch 3.5, code change based on 176bd68222f3a3bddac9deb412eee7f538cb01ca
Author: Norbert Kalmar <nk...@yahoo.com>
Reviewers: andor@apache.org
Closes #603 from nkalmar/ZOOKEEPER-3031_3.4
Project: http://git-wip-us.apache.org/repos/asf/zookeeper/repo
Commit: http://git-wip-us.apache.org/repos/asf/zookeeper/commit/5694559d
Tree: http://git-wip-us.apache.org/repos/asf/zookeeper/tree/5694559d
Diff: http://git-wip-us.apache.org/repos/asf/zookeeper/diff/5694559d
Branch: refs/heads/branch-3.4
Commit: 5694559d797b60f3d8428bf44cc3c29354fb3b4f
Parents: f90e4a4
Author: Norbert Kalmar <nk...@yahoo.com>
Authored: Thu Aug 23 16:11:36 2018 +0200
Committer: Andor Molnar <an...@apache.org>
Committed: Thu Aug 23 16:11:36 2018 +0200
----------------------------------------------------------------------
.gitignore | 36 +-
build.xml | 17 +-
src/c/CMakeLists.txt | 237 --
src/c/ChangeLog | 116 -
src/c/INSTALL | 234 --
src/c/LICENSE | 202 -
src/c/Makefile.am | 128 -
src/c/NOTICE.txt | 41 -
src/c/README | 156 -
src/c/acinclude.m4 | 312 --
src/c/aminclude.am | 186 -
src/c/c-doc.Doxyfile | 1252 ------
src/c/cmake_config.h.in | 154 -
src/c/configure.ac | 165 -
src/c/include/proto.h | 47 -
src/c/include/recordio.h | 83 -
src/c/include/winconfig.h | 15 -
src/c/include/zookeeper.h | 1589 --------
src/c/include/zookeeper_log.h | 51 -
src/c/include/zookeeper_version.h | 33 -
src/c/src/cli.c | 697 ----
src/c/src/hashtable/LICENSE.txt | 30 -
src/c/src/hashtable/hashtable.c | 274 --
src/c/src/hashtable/hashtable.h | 209 -
src/c/src/hashtable/hashtable_itr.c | 176 -
src/c/src/hashtable/hashtable_itr.h | 119 -
src/c/src/hashtable/hashtable_private.h | 85 -
src/c/src/load_gen.c | 282 --
src/c/src/mt_adaptor.c | 519 ---
src/c/src/recordio.c | 366 --
src/c/src/st_adaptor.c | 113 -
src/c/src/winport.c | 302 --
src/c/src/winport.h | 138 -
src/c/src/zk_adaptor.h | 276 --
src/c/src/zk_hashtable.c | 337 --
src/c/src/zk_hashtable.h | 69 -
src/c/src/zk_log.c | 180 -
src/c/src/zookeeper.c | 3767 ------------------
src/c/tests/CollectionUtil.h | 195 -
src/c/tests/CppAssertHelper.h | 37 -
src/c/tests/LibCMocks.cc | 333 --
src/c/tests/LibCMocks.h | 408 --
src/c/tests/LibCSymTable.cc | 83 -
src/c/tests/LibCSymTable.h | 107 -
src/c/tests/MocksBase.cc | 36 -
src/c/tests/MocksBase.h | 36 -
src/c/tests/PthreadMocks.cc | 106 -
src/c/tests/PthreadMocks.h | 449 ---
src/c/tests/TestClient.cc | 1135 ------
src/c/tests/TestClientRetry.cc | 273 --
src/c/tests/TestDriver.cc | 173 -
src/c/tests/TestMulti.cc | 703 ----
src/c/tests/TestOperations.cc | 710 ----
src/c/tests/TestWatchers.cc | 773 ----
src/c/tests/TestZookeeperClose.cc | 472 ---
src/c/tests/TestZookeeperInit.cc | 301 --
src/c/tests/ThreadingUtil.cc | 87 -
src/c/tests/ThreadingUtil.h | 261 --
src/c/tests/Util.cc | 51 -
src/c/tests/Util.h | 137 -
src/c/tests/Vector.h | 37 -
src/c/tests/ZKMocks.cc | 519 ---
src/c/tests/ZKMocks.h | 509 ---
src/c/tests/wrappers-mt.opt | 3 -
src/c/tests/wrappers.opt | 7 -
src/c/tests/zkServer.sh | 161 -
.../zookeeper-client-c/CMakeLists.txt | 237 ++
zookeeper-client/zookeeper-client-c/ChangeLog | 116 +
zookeeper-client/zookeeper-client-c/INSTALL | 234 ++
zookeeper-client/zookeeper-client-c/LICENSE | 202 +
zookeeper-client/zookeeper-client-c/Makefile.am | 128 +
zookeeper-client/zookeeper-client-c/NOTICE.txt | 41 +
zookeeper-client/zookeeper-client-c/README | 157 +
.../zookeeper-client-c/acinclude.m4 | 312 ++
.../zookeeper-client-c/aminclude.am | 186 +
.../zookeeper-client-c/c-doc.Doxyfile | 1252 ++++++
.../zookeeper-client-c/cmake_config.h.in | 154 +
.../zookeeper-client-c/configure.ac | 165 +
.../zookeeper-client-c/include/proto.h | 47 +
.../zookeeper-client-c/include/recordio.h | 83 +
.../zookeeper-client-c/include/winconfig.h | 15 +
.../zookeeper-client-c/include/zookeeper.h | 1589 ++++++++
.../zookeeper-client-c/include/zookeeper_log.h | 51 +
.../include/zookeeper_version.h | 33 +
zookeeper-client/zookeeper-client-c/src/cli.c | 697 ++++
.../src/hashtable/LICENSE.txt | 30 +
.../src/hashtable/hashtable.c | 274 ++
.../src/hashtable/hashtable.h | 209 +
.../src/hashtable/hashtable_itr.c | 176 +
.../src/hashtable/hashtable_itr.h | 119 +
.../src/hashtable/hashtable_private.h | 85 +
.../zookeeper-client-c/src/load_gen.c | 282 ++
.../zookeeper-client-c/src/mt_adaptor.c | 519 +++
.../zookeeper-client-c/src/recordio.c | 366 ++
.../zookeeper-client-c/src/st_adaptor.c | 113 +
.../zookeeper-client-c/src/winport.c | 302 ++
.../zookeeper-client-c/src/winport.h | 138 +
.../zookeeper-client-c/src/zk_adaptor.h | 276 ++
.../zookeeper-client-c/src/zk_hashtable.c | 337 ++
.../zookeeper-client-c/src/zk_hashtable.h | 69 +
.../zookeeper-client-c/src/zk_log.c | 180 +
.../zookeeper-client-c/src/zookeeper.c | 3767 ++++++++++++++++++
.../zookeeper-client-c/tests/CollectionUtil.h | 195 +
.../zookeeper-client-c/tests/CppAssertHelper.h | 37 +
.../zookeeper-client-c/tests/LibCMocks.cc | 333 ++
.../zookeeper-client-c/tests/LibCMocks.h | 408 ++
.../zookeeper-client-c/tests/LibCSymTable.cc | 83 +
.../zookeeper-client-c/tests/LibCSymTable.h | 107 +
.../zookeeper-client-c/tests/MocksBase.cc | 36 +
.../zookeeper-client-c/tests/MocksBase.h | 36 +
.../zookeeper-client-c/tests/PthreadMocks.cc | 106 +
.../zookeeper-client-c/tests/PthreadMocks.h | 449 +++
.../zookeeper-client-c/tests/TestClient.cc | 1135 ++++++
.../zookeeper-client-c/tests/TestClientRetry.cc | 273 ++
.../zookeeper-client-c/tests/TestDriver.cc | 173 +
.../zookeeper-client-c/tests/TestMulti.cc | 703 ++++
.../zookeeper-client-c/tests/TestOperations.cc | 710 ++++
.../zookeeper-client-c/tests/TestWatchers.cc | 773 ++++
.../tests/TestZookeeperClose.cc | 472 +++
.../tests/TestZookeeperInit.cc | 301 ++
.../zookeeper-client-c/tests/ThreadingUtil.cc | 87 +
.../zookeeper-client-c/tests/ThreadingUtil.h | 261 ++
.../zookeeper-client-c/tests/Util.cc | 51 +
.../zookeeper-client-c/tests/Util.h | 137 +
.../zookeeper-client-c/tests/Vector.h | 37 +
.../zookeeper-client-c/tests/ZKMocks.cc | 519 +++
.../zookeeper-client-c/tests/ZKMocks.h | 509 +++
.../zookeeper-client-c/tests/wrappers-mt.opt | 3 +
.../zookeeper-client-c/tests/wrappers.opt | 7 +
.../zookeeper-client-c/tests/zkServer.sh | 161 +
.../src/python/setup.py | 8 +-
.../content/xdocs/zookeeperProgrammers.xml | 10 +-
.../src/main/c/configure.ac | 4 +-
.../src/main/c/configure.ac | 4 +-
134 files changed, 21083 insertions(+), 21081 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index c5bd7f5..78c9ed4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,24 +59,24 @@ tags
.cproject
.project
obj
-src/c/core.*
-src/c/TEST-*.txt
-src/c/*.la
-src/c/*.lo
-src/c/*.o
-src/c/generated/
+zookeeper-client/zookeeper-client-c/core.*
+zookeeper-client/zookeeper-client-c/TEST-*.txt
+zookeeper-client/zookeeper-client-c/*.la
+zookeeper-client/zookeeper-client-c/*.lo
+zookeeper-client/zookeeper-client-c/*.o
+zookeeper-client/zookeeper-client-c/generated/
src/java/generated/
src/java/lib/ant-eclipse-*
src/java/lib/ivy-*
-src/c/Makefile.in
-src/c/aclocal.m4
-src/c/autom4te.cache/
-src/c/compile
-src/c/config.guess
-src/c/config.h.in
-src/c/config.sub
-src/c/configure
-src/c/depcomp
-src/c/install-sh
-src/c/ltmain.sh
-src/c/missing
+zookeeper-client/zookeeper-client-c/Makefile.in
+zookeeper-client/zookeeper-client-c/aclocal.m4
+zookeeper-client/zookeeper-client-c/autom4te.cache/
+zookeeper-client/zookeeper-client-c/compile
+szookeeper-client/zookeeper-client-c/config.guess
+zookeeper-client/zookeeper-client-c/config.h.in
+zookeeper-client/zookeeper-client-c/config.sub
+zookeeper-client/zookeeper-client-c/configure
+zookeeper-client/zookeeper-client-c/depcomp
+zookeeper-client/zookeeper-client-c/install-sh
+zookeeper-client/zookeeper-client-c/ltmain.sh
+zookeeper-client/zookeeper-client-c/missing
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/build.xml
----------------------------------------------------------------------
diff --git a/build.xml b/build.xml
index 0131468..021c9b6 100644
--- a/build.xml
+++ b/build.xml
@@ -99,7 +99,7 @@ xmlns:cs="antlib:com.puppycrawl.tools.checkstyle">
<property name="build.dir" value="${basedir}/build" />
<property name="distribution" value="${basedir}/distribution" />
<property name="src_generated.dir" value="${src.dir}/java/generated" />
- <property name="c.src.dir" value="${src.dir}/c" />
+ <property name="c.src.dir" value="${basedir}/zookeeper-client/zookeeper-client-c" />
<property name="csrc_generated.dir" value="${c.src.dir}/generated" />
<property name="jute.file" value="${src.dir}/zookeeper.jute" />
@@ -328,7 +328,7 @@ xmlns:cs="antlib:com.puppycrawl.tools.checkstyle">
<java classname="org.apache.jute.compiler.generated.Rcc" fork="true" dir="${src_generated.dir}">
<arg value="-l" />
<arg value="java" />
- <arg value="../../zookeeper.jute" />
+ <arg value="../../zookeeper.jute" />
<classpath>
<pathelement path="${build.classes}" />
</classpath>
@@ -337,7 +337,7 @@ xmlns:cs="antlib:com.puppycrawl.tools.checkstyle">
<java classname="org.apache.jute.compiler.generated.Rcc" fork="true" dir="${csrc_generated.dir}">
<arg value="-l" />
<arg value="c" />
- <arg value="../../zookeeper.jute" />
+ <arg value="../../../src/zookeeper.jute" />
<classpath>
<pathelement path="${build.classes}" />
</classpath>
@@ -833,6 +833,7 @@ xmlns:cs="antlib:com.puppycrawl.tools.checkstyle">
<include name="zookeeper-recipes/**"/>
<include name="zookeeper-docs/**"/>
<include name="zookeeper-contrib/**"/>
+ <include name="zookeeper-client/**"/>
</fileset>
<fileset file="src/pom.template"/>
</copy>
@@ -1027,8 +1028,8 @@ xmlns:cs="antlib:com.puppycrawl.tools.checkstyle">
<macro_tar param.destfile="${build.dir}/${final.name}-bin.tar.gz">
<param.listofitems>
<tarfileset dir="${build.dir}" mode="664">
- <include name="${final.name}/src/c/**" />
- <exclude name="${final.name}/src/c/generated/**" />
+ <include name="${final.name}/zookeeper-client/zookeeper-client-c/**" />
+ <exclude name="${final.name}/zookeeper-client/zookeeper-client-c/generated/**" />
</tarfileset>
<tarfileset dir="${build.dir}" mode="664">
<exclude name="${final.name}/bin/*" />
@@ -1811,9 +1812,9 @@ xmlns:cs="antlib:com.puppycrawl.tools.checkstyle">
<exclude name="**/docs/"/>
<exclude name="**/zookeeper-docs/"/>
<exclude name="**/lib/jdiff/"/>
- <exclude name="src/c/autom4te.cache/**"/>
- <exclude name="src/c/config**"/>
- <exclude name="src/c/src/hashtable/"/>
+ <exclude name="src/zookeeper-client/zookeeper-client-c/autom4te.cache/**"/>
+ <exclude name="src/zookeeper-client/zookeeper-client-c/config**"/>
+ <exclude name="src/zookeeper-client/zookeeper-client-c/src/hashtable/"/>
<exclude name="src/java/generated/.generated/"/>
<exclude name="src/java/test/checkstyle*.xml"/>
<exclude name="src/java/test/checkstyle*.xsl"/>
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/src/c/CMakeLists.txt b/src/c/CMakeLists.txt
deleted file mode 100644
index e7dfbeb..0000000
--- a/src/c/CMakeLists.txt
+++ /dev/null
@@ -1,237 +0,0 @@
-# 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.
-
-cmake_minimum_required(VERSION 3.6)
-
-project(zookeeper VERSION 3.4.13)
-set(email user@zookeeper.apache.org)
-set(description "zookeeper C client")
-
-# general options
-include_directories(include tests generated ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
-if(UNIX)
- add_compile_options(-Wall -fPIC)
-elseif(WIN32)
- add_compile_options(/W3)
-endif()
-add_definitions(-DUSE_STATIC_LIB)
-
-# TODO: Enable /WX and /W4 on Windows. Currently there are ~1000 warnings.
-# TODO: Add Solaris support.
-# TODO: Add a shared library option.
-# TODO: Specify symbols to export.
-# TODO: Generate doxygen documentation.
-
-# Sync API option
-option(WANT_SYNCAPI "Enables Sync API support" ON)
-if(WANT_SYNCAPI)
- add_definitions(-DTHREADED)
- if(WIN32)
- # Note that the generator expression ensures that `/MTd` is used when Debug
- # configurations are built.
- add_compile_options(/MT$<$<CONFIG:Debug>:d>)
- endif()
-endif()
-
-# CppUnit option
-if(WIN32 OR APPLE)
- # The tests do not yet compile on Windows or macOS,
- # so we set this to off by default.
- #
- # Note that CMake does not have expressions except in conditionals,
- # so we're left with this if/else/endif pattern.
- set(DEFAULT_WANT_CPPUNIT OFF)
-else()
- set(DEFAULT_WANT_CPPUNIT ON)
-endif()
-option(WANT_CPPUNIT "Enables CppUnit and tests" ${DEFAULT_WANT_CPPUNIT})
-
-# The function `to_have(in out)` converts a header name like `arpa/inet.h`
-# into an Autotools style preprocessor definition `HAVE_ARPA_INET_H`.
-# This is then set or unset in `configure_file()` step.
-#
-# Note that CMake functions do not have return values; instead an "out"
-# variable must be passed, and explicitly set with parent scope.
-function(to_have in out)
- string(TOUPPER ${in} str)
- string(REGEX REPLACE "/|\\." "_" str ${str})
- set(${out} "HAVE_${str}" PARENT_SCOPE)
-endfunction()
-
-# include file checks
-foreach(f generated/zookeeper.jute.h generated/zookeeper.jute.c)
- if(EXISTS "${CMAKE_SOURCE_DIR}/${f}")
- to_have(${f} name)
- set(${name} 1)
- else()
- message(FATAL_ERROR
- "jute files are missing!\n"
- "Please run 'ant compile_jute' while in the ZooKeeper top level directory.")
- endif()
-endforeach()
-
-# header checks
-include(CheckIncludeFile)
-set(check_headers
- arpa/inet.h
- dlfcn.h
- fcntl.h
- inttypes.h
- memory.h
- netdb.h
- netinet/in.h
- stdint.h
- stdlib.h
- string.h
- strings.h
- sys/socket.h
- sys/stat.h
- sys/time.h
- sys/types.h
- unistd.h
- sys/utsname.h)
-
-foreach(f ${check_headers})
- to_have(${f} name)
- check_include_file(${f} ${name})
-endforeach()
-
-# function checks
-include(CheckFunctionExists)
-set(check_functions
- getcwd
- gethostbyname
- gethostname
- getlogin
- getpwuid_r
- gettimeofday
- getuid
- memmove
- memset
- poll
- socket
- strchr
- strdup
- strerror
- strtol)
-
-foreach(fn ${check_functions})
- to_have(${fn} name)
- check_function_exists(${fn} ${name})
-endforeach()
-
-# library checks
-set(check_libraries rt m pthread)
-foreach(lib ${check_libraries})
- to_have("lib${lib}" name)
- find_library(${name} ${lib})
-endforeach()
-
-# IPv6 check
-include(CheckStructHasMember)
-check_struct_has_member("struct sockaddr_in6" sin6_addr "netinet/in.h" ZOO_IPV6_ENABLED)
-
-# configure
-configure_file(cmake_config.h.in ${CMAKE_SOURCE_DIR}/include/config.h)
-
-# hashtable library
-set(hashtable_sources src/hashtable/hashtable_itr.c src/hashtable/hashtable.c)
-add_library(hashtable STATIC ${hashtable_sources})
-target_link_libraries(hashtable PUBLIC $<$<PLATFORM_ID:Linux>:m>)
-
-# zookeeper library
-set(zookeeper_sources
- src/zookeeper.c
- src/recordio.c
- generated/zookeeper.jute.c
- src/zk_log.c
- src/zk_hashtable.c)
-
-if(WANT_SYNCAPI)
- list(APPEND zookeeper_sources src/mt_adaptor.c)
-else()
- list(APPEND zookeeper_sources src/st_adaptor.c)
-endif()
-
-if(WIN32)
- list(APPEND zookeeper_sources src/winport.c)
-endif()
-
-add_library(zookeeper STATIC ${zookeeper_sources})
-target_link_libraries(zookeeper PUBLIC
- hashtable
- $<$<PLATFORM_ID:Linux>:rt> # clock_gettime
- $<$<PLATFORM_ID:Windows>:ws2_32>) # Winsock 2.0
-
-if(WANT_SYNCAPI AND NOT WIN32)
- find_package(Threads REQUIRED)
- target_link_libraries(zookeeper PUBLIC Threads::Threads)
-endif()
-
-# cli executable
-add_executable(cli src/cli.c)
-target_link_libraries(cli zookeeper)
-
-# load_gen executable
-if(WANT_SYNCAPI AND NOT WIN32)
- add_executable(load_gen src/load_gen.c)
- target_link_libraries(load_gen zookeeper)
-endif()
-
-# tests
-set(test_sources
- tests/TestDriver.cc
- tests/LibCMocks.cc
- tests/LibCSymTable.cc
- tests/MocksBase.cc
- tests/ZKMocks.cc
- tests/Util.cc
- tests/ThreadingUtil.cc
- tests/TestZookeeperInit.cc
- tests/TestZookeeperClose.cc
- tests/TestClientRetry.cc
- tests/TestOperations.cc
- tests/TestMulti.cc
- tests/TestWatchers.cc
- tests/TestClient.cc)
-
-if(WANT_SYNCAPI)
- list(APPEND test_sources tests/PthreadMocks.cc)
-endif()
-
-if(WANT_CPPUNIT)
- add_executable(zktest ${test_sources})
- target_compile_definitions(zktest
- PRIVATE -DZKSERVER_CMD="${CMAKE_SOURCE_DIR}/tests/zkServer.sh")
- # TODO: Use `find_library()` for `cppunit`.
- target_link_libraries(zktest zookeeper cppunit dl)
-
- # This reads the link flags from the file `tests/wrappers.opt` into
- # the variable `symbol_wrappers` for use in `target_link_libraries`.
- # It is a holdover from the original build system.
- file(STRINGS tests/wrappers.opt symbol_wrappers)
- if(WANT_SYNCAPI)
- file(STRINGS tests/wrappers-mt.opt symbol_wrappers_mt)
- endif()
-
- target_link_libraries(zktest ${symbol_wrappers} ${symbol_wrappers_mt})
-
- enable_testing()
- add_test(NAME zktest_runner COMMAND zktest)
- set_property(TEST zktest_runner PROPERTY ENVIRONMENT
- "ZKROOT=${CMAKE_SOURCE_DIR}/../.."
- "CLASSPATH=$CLASSPATH:$CLOVER_HOME/lib/clover.jar")
-endif()
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/ChangeLog
----------------------------------------------------------------------
diff --git a/src/c/ChangeLog b/src/c/ChangeLog
deleted file mode 100644
index c85a6c0..0000000
--- a/src/c/ChangeLog
+++ /dev/null
@@ -1,116 +0,0 @@
-Release 2.1.1
-2008-04-30 Andrew Kornev <ak...@users.sourceforge.net>
-
- * changed the distributino package name to "c-client-src"
-
-Release 2.1.0
-2008-04-30 Andrew Kornev <ak...@users.sourceforge.net>
-
- * added the client latency diagnostics; the client prints a warning when the
- reponse latency exceeds 20ms
-
- * modified logging format to report the znode path for which the zookeeper
- operation is called
-
- * fixed a minor bug where error messages were missing for some of the newer
- zookeeper error codes (ZCLOSING and ZNOTHING).
-
- * improved logging by adding the XID to the message to make it easy to match
- requests to responses
-
- * fixed the bug causing sporadic session termination and timeouts
-
- * added a new return code to zookeeper_process() -- ZNOTHING --
- that indicates that the socket has no more data to read
-
- * more unit tests added
-
-Release 1.1.3
-2008-02-07 Andrew Kornev <ak...@users.sourceforge.net>
-
- * get_xid() is not thread-safe (xid initialization race condition
- in the multi-threaded mode).
-
- * the I/O thread doesn�t automatically terminate on AUTH_FAILURE and
- SESSION_EXPIRED events.
-
- * all session events should be processed on the completion thread.
-
- * PING operation doesn�t atomically enqueue the completion and
- send buffers like other operations do.
-
- * corrected zookeeper_init() doxygen docs.
-
- * new unit tests added.
-
-
-Release 1.1.2
-2008-01-24 Andrew Kornev <ak...@users.sourceforge.net>
-
- * fixed a race condition caused by the code in zookeeper_process()
- and free_completions() setting sc->complete to 1 without proper
- synchronization;
-
- * fixed zoo_get() not updating buffer_len value with the actual
- buffer length on return; added missing enter_critical/leave_critical
- calls to the async ZK operations.
-
- * Replaced select() with poll() to fix the problem with the FD_SET
- macro causing stack corruption for FDs higher than 1024
-
- * Added zoo_set_log_stream() to the public API. The function allows
- applications to specify a different log file.
-
- * Removed unused declarations from zookeeper.h (ACL related)
-
- * changed zoo_get() signature to take a pointer to buffer length.
- The function sets the parameter to the actual data length upon return.
-
- * the watcher callback now takes the zhandle as its first parameter. This
- is to avoid a race condition in the multi-threaded client when a watcher
- is called before zookeeper_init() has returned.
-
- * fixed zookeeper_close() resource leaks and race conditions,
- fixed the race condition causing xid mismatch.
-
- * added support for cppunit, added new targets: "check" and "run-check"
- to build and run unit tests.
-
- * Changed the signature of zookeeper_init(): it now takes a context pointer
- as a parameter. This is to avoid a race condition in the multi-threaded client.
-
- * Using a self-pipe rather than SIGUSR1 to wake up select() in the I/O thread
-
- * Added the doxygen target to the autoconf scripts
-
- * Pulled out the logging functionality from zookeeper.c to zk_log.c/.h.
- Fixed a minor issue with PING responses being unnecessarily put on
- the completion queue rather than simply dropped. Make use of DLL_EXPORT
- symbol for building shared lib on cygwin.
-
- * Implemented new Zookeeper operation sync() to flush the leader channel
- to ensure that all updates have reached the followers.
-
- * Synchronous methods not being handled properly on disconnect
-
- * breed: fixed an incorrect parameter passed to zookeeper API by
- the Sync API wrapper functions
-
- * breed: the set and delete commands now support both Sync and Async API.
- Prefix the command name with an 'a' to call the Async API: aset, adelete
-
- * Make sure mutexes and condition variables are properly initialized
- and destroyed
-
- * Fixed zookeeper_close() causing core dumps with mt_adaptor
-
-
-Release 1.0.0
-2007-11-27 Andrew Kornev <ak...@users.sourceforge.net>
-
- * configure.ac and Makefile.am added support for GNU autotools
-
- * recordio.c/.h updated jute IO routines to use bit-explicit integer types
- (int32_t vs. int, and int64_t vs. long long)
-
- * README rough draft
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/INSTALL
----------------------------------------------------------------------
diff --git a/src/c/INSTALL b/src/c/INSTALL
deleted file mode 100644
index 5458714..0000000
--- a/src/c/INSTALL
+++ /dev/null
@@ -1,234 +0,0 @@
-Installation Instructions
-*************************
-
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
-2006 Free Software Foundation, Inc.
-
-This file is free documentation; the Free Software Foundation gives
-unlimited permission to copy, distribute and modify it.
-
-Basic Installation
-==================
-
-Briefly, the shell commands `./configure; make; make install' should
-configure, build, and install this package. The following
-more-detailed instructions are generic; see the `README' file for
-instructions specific to this package.
-
- The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation. It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions. Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
- It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring. Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.
-
- If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release. If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
- The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'. You need `configure.ac' if
-you want to change it or regenerate `configure' using a newer version
-of `autoconf'.
-
-The simplest way to compile this package is:
-
- 1. `cd' to the directory containing the package's source code and type
- `./configure' to configure the package for your system.
-
- Running `configure' might take a while. While running, it prints
- some messages telling which features it is checking for.
-
- 2. Type `make' to compile the package.
-
- 3. Optionally, type `make check' to run any self-tests that come with
- the package.
-
- 4. Type `make install' to install the programs and any data files and
- documentation.
-
- 5. You can remove the program binaries and object files from the
- source code directory by typing `make clean'. To also remove the
- files that `configure' created (so you can compile the package for
- a different kind of computer), type `make distclean'. There is
- also a `make maintainer-clean' target, but that is intended mainly
- for the package's developers. If you use it, you may have to get
- all sorts of other programs in order to regenerate files that came
- with the distribution.
-
-Compilers and Options
-=====================
-
-Some systems require unusual options for compilation or linking that the
-`configure' script does not know about. Run `./configure --help' for
-details on some of the pertinent environment variables.
-
- You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment. Here
-is an example:
-
- ./configure CC=c99 CFLAGS=-g LIBS=-lposix
-
- *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
-You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory. To do this, you can use GNU `make'. `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script. `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
-
- With a non-GNU `make', it is safer to compile the package for one
-architecture at a time in the source code directory. After you have
-installed the package for one architecture, use `make distclean' before
-reconfiguring for another architecture.
-
-Installation Names
-==================
-
-By default, `make install' installs the package's commands under
-`/usr/local/bin', include files under `/usr/local/include', etc. You
-can specify an installation prefix other than `/usr/local' by giving
-`configure' the option `--prefix=PREFIX'.
-
- You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files. If you
-pass the option `--exec-prefix=PREFIX' to `configure', the package uses
-PREFIX as the prefix for installing programs and libraries.
-Documentation and other data files still use the regular prefix.
-
- In addition, if you use an unusual directory layout you can give
-options like `--bindir=DIR' to specify different values for particular
-kinds of files. Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.
-
- If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
-Optional Features
-=================
-
-Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System). The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
- For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
-Specifying the System Type
-==========================
-
-There may be some features `configure' cannot figure out automatically,
-but needs to determine by the type of machine the package will run on.
-Usually, assuming the package is built to be run on the _same_
-architectures, `configure' can figure that out, but if it prints a
-message saying it cannot guess the machine type, give it the
-`--build=TYPE' option. TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
- CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
- OS KERNEL-OS
-
- See the file `config.sub' for the possible values of each field. If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
- If you are _building_ compiler tools for cross-compiling, you should
-use the option `--target=TYPE' to select the type of system they will
-produce code for.
-
- If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
-If you want to set default values for `configure' scripts to share, you
-can create a site shell script called `config.site' that gives default
-values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists. Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
-Variables not defined in a site shell script can be set in the
-environment passed to `configure'. However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost. In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'. For example:
-
- ./configure CC=/usr/local2/bin/gcc
-
-causes the specified `gcc' to be used as the C compiler (unless it is
-overridden in the site shell script).
-
-Unfortunately, this technique does not work for `CONFIG_SHELL' due to
-an Autoconf bug. Until the bug is fixed you can use this workaround:
-
- CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
-
-`configure' Invocation
-======================
-
-`configure' recognizes the following options to control how it operates.
-
-`--help'
-`-h'
- Print a summary of the options to `configure', and exit.
-
-`--version'
-`-V'
- Print the version of Autoconf used to generate the `configure'
- script, and exit.
-
-`--cache-file=FILE'
- Enable the cache: use and save the results of the tests in FILE,
- traditionally `config.cache'. FILE defaults to `/dev/null' to
- disable caching.
-
-`--config-cache'
-`-C'
- Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
- Do not print messages saying which checks are being made. To
- suppress all normal output, redirect it to `/dev/null' (any error
- messages will still be shown).
-
-`--srcdir=DIR'
- Look for the package's source code in directory DIR. Usually
- `configure' can determine that directory automatically.
-
-`configure' also accepts some other, not widely useful, options. Run
-`configure --help' for more details.
-
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/LICENSE
----------------------------------------------------------------------
diff --git a/src/c/LICENSE b/src/c/LICENSE
deleted file mode 100644
index d645695..0000000
--- a/src/c/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed 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.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/Makefile.am
----------------------------------------------------------------------
diff --git a/src/c/Makefile.am b/src/c/Makefile.am
deleted file mode 100644
index 5993098..0000000
--- a/src/c/Makefile.am
+++ /dev/null
@@ -1,128 +0,0 @@
-# need this for Doxygen integration
-include $(top_srcdir)/aminclude.am
-
-if SOLARIS
- SOLARIS_CPPFLAGS = -D_POSIX_PTHREAD_SEMANTICS
- SOLARIS_LIB_LDFLAGS = -lnsl -lsocket
-endif
-AM_CPPFLAGS = -I${srcdir}/include -I${srcdir}/tests -I${srcdir}/generated $(SOLARIS_CPPFLAGS)
-AM_CFLAGS = -Wall -Werror
-AM_CXXFLAGS = -Wall $(USEIPV6)
-
-# Additional flags for coverage testing (if enabled)
-if ENABLEGCOV
- AM_CFLAGS += -fprofile-arcs -ftest-coverage
- AM_LDFLAGS = -lgcov
-endif
-
-LIB_LDFLAGS = -no-undefined -version-info 2 $(SOLARIS_LIB_LDFLAGS)
-
-pkginclude_HEADERS = include/zookeeper.h include/zookeeper_version.h include/zookeeper_log.h include/proto.h include/recordio.h generated/zookeeper.jute.h
-EXTRA_DIST=LICENSE
-
-HASHTABLE_SRC = src/hashtable/hashtable_itr.h src/hashtable/hashtable_itr.c \
- src/hashtable/hashtable_private.h src/hashtable/hashtable.h src/hashtable/hashtable.c
-
-noinst_LTLIBRARIES = libhashtable.la
-libhashtable_la_SOURCES = $(HASHTABLE_SRC)
-
-COMMON_SRC = src/zookeeper.c include/zookeeper.h include/zookeeper_version.h include/zookeeper_log.h\
- src/recordio.c include/recordio.h include/proto.h \
- src/zk_adaptor.h generated/zookeeper.jute.c \
- src/zookeeper_log.h src/zk_log.c src/zk_hashtable.h src/zk_hashtable.c
-
-# These are the symbols (classes, mostly) we want to export from our library.
-EXPORT_SYMBOLS = '(zoo_|zookeeper_|zhandle|Z|format_log_message|log_message|logLevel|deallocate_|allocate_|zerror|is_unrecoverable)'
-noinst_LTLIBRARIES += libzkst.la
-libzkst_la_SOURCES =$(COMMON_SRC) src/st_adaptor.c
-libzkst_la_LIBADD = -lm
-
-lib_LTLIBRARIES = libzookeeper_st.la
-libzookeeper_st_la_SOURCES =
-libzookeeper_st_la_LIBADD=libzkst.la libhashtable.la
-libzookeeper_st_la_DEPENDENCIES=libzkst.la libhashtable.la
-libzookeeper_st_la_LDFLAGS = $(LIB_LDFLAGS) -export-symbols-regex $(EXPORT_SYMBOLS)
-
-if WANT_SYNCAPI
-noinst_LTLIBRARIES += libzkmt.la
-libzkmt_la_SOURCES =$(COMMON_SRC) src/mt_adaptor.c
-libzkmt_la_CFLAGS = -DTHREADED
-libzkmt_la_LIBADD = -lm
-
-lib_LTLIBRARIES += libzookeeper_mt.la
-libzookeeper_mt_la_SOURCES =
-libzookeeper_mt_la_LIBADD=libzkmt.la libhashtable.la -lpthread
-libzookeeper_mt_la_DEPENDENCIES=libzkmt.la libhashtable.la
-libzookeeper_mt_la_LDFLAGS = $(LIB_LDFLAGS) -export-symbols-regex $(EXPORT_SYMBOLS)
-endif
-
-bin_PROGRAMS = cli_st
-
-cli_st_SOURCES = src/cli.c
-cli_st_LDADD = libzookeeper_st.la
-
-if WANT_SYNCAPI
-bin_PROGRAMS += cli_mt load_gen
-
-cli_mt_SOURCES = src/cli.c
-cli_mt_LDADD = libzookeeper_mt.la
-cli_mt_CFLAGS = -DTHREADED
-
-load_gen_SOURCES = src/load_gen.c
-load_gen_LDADD = libzookeeper_mt.la
-load_gen_CFLAGS = -DTHREADED
-
-endif
-
-#########################################################################
-# build and run unit tests
-
-EXTRA_DIST+=$(wildcard ${srcdir}/tests/*.cc) $(wildcard ${srcdir}/tests/*.h) \
- ${srcdir}/tests/wrappers.opt ${srcdir}/tests/wrappers-mt.opt
-
-TEST_SOURCES = tests/TestDriver.cc tests/LibCMocks.cc tests/LibCSymTable.cc \
- tests/MocksBase.cc tests/ZKMocks.cc tests/Util.cc tests/ThreadingUtil.cc \
- tests/TestClientRetry.cc \
- tests/TestOperations.cc tests/TestZookeeperInit.cc \
- tests/TestZookeeperClose.cc tests/TestClient.cc \
- tests/TestMulti.cc tests/TestWatchers.cc
-
-
-if SOLARIS
- SHELL_SYMBOL_WRAPPERS = cat ${srcdir}/tests/wrappers.opt
- SYMBOL_WRAPPERS=$(SHELL_SYMBOL_WRAPPERS:sh)
-else
- SYMBOL_WRAPPERS=$(shell cat ${srcdir}/tests/wrappers.opt)
-endif
-
-check_PROGRAMS = zktest-st
-nodist_zktest_st_SOURCES = $(TEST_SOURCES)
-zktest_st_LDADD = libzkst.la libhashtable.la $(CPPUNIT_LIBS)
-zktest_st_CXXFLAGS = -DUSE_STATIC_LIB $(CPPUNIT_CFLAGS) $(USEIPV6) $(SOLARIS_CPPFLAGS)
-zktest_st_LDFLAGS = -static-libtool-libs $(SYMBOL_WRAPPERS) $(SOLARIS_LIB_LDFLAGS)
-
-if WANT_SYNCAPI
- check_PROGRAMS += zktest-mt
- nodist_zktest_mt_SOURCES = $(TEST_SOURCES) tests/PthreadMocks.cc
- zktest_mt_LDADD = libzkmt.la libhashtable.la -lpthread $(CPPUNIT_LIBS)
- zktest_mt_CXXFLAGS = -DUSE_STATIC_LIB -DTHREADED $(CPPUNIT_CFLAGS) $(USEIPV6)
-if SOLARIS
- SHELL_SYMBOL_WRAPPERS_MT = cat ${srcdir}/tests/wrappers-mt.opt
- SYMBOL_WRAPPERS_MT=$(SYMBOL_WRAPPERS) $(SHELL_SYMBOL_WRAPPERS_MT:sh)
-else
- SYMBOL_WRAPPERS_MT=$(SYMBOL_WRAPPERS) $(shell cat ${srcdir}/tests/wrappers-mt.opt)
-endif
- zktest_mt_LDFLAGS = -static-libtool-libs $(SYMBOL_WRAPPERS_MT) $(SOLARIS_LIB_LDFLAGS)
-endif
-
-run-check: check
- ./zktest-st $(TEST_OPTIONS)
-if WANT_SYNCAPI
- ./zktest-mt $(TEST_OPTIONS)
-endif
-
-clean-local: clean-check
- $(RM) $(DX_CLEANFILES)
-
-clean-check:
- $(RM) $(nodist_zktest_st_OBJECTS) $(nodist_zktest_mt_OBJECTS)
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/NOTICE.txt
----------------------------------------------------------------------
diff --git a/src/c/NOTICE.txt b/src/c/NOTICE.txt
deleted file mode 100644
index dcd9d53..0000000
--- a/src/c/NOTICE.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-Apache ZooKeeper
-Copyright 2009-2018 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-
-----------
-include/winstdint.h is included only for Windows Client support, as follows:
-
-// ISO C9x compliant stdint.h for Microsoft Visual Studio
-// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
-//
-// Copyright (c) 2006-2008 Alexander Chemeris
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// 2. 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.
-//
-// 3. The name of the author may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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/5694559d/src/c/README
----------------------------------------------------------------------
diff --git a/src/c/README b/src/c/README
deleted file mode 100644
index 5115845..0000000
--- a/src/c/README
+++ /dev/null
@@ -1,156 +0,0 @@
- Zookeeper C client library
-
-
-This package provides a C client interface to Zookeeper server.
-
-For the latest information about ZooKeeper, please visit our website at:
- http://zookeeper.apache.org/
-and our wiki, at:
- https://cwiki.apache.org/confluence/display/ZOOKEEPER
-
-Full documentation for this release can also be found in ../../docs/index.html
-
-
-OVERVIEW
-
-The client supports two types of APIs -- synchronous and asynchronous.
-
-Asynchronous API provides non-blocking operations with completion callbacks and
-relies on the application to implement event multiplexing on its behalf.
-
-On the other hand, Synchronous API provides a blocking flavor of
-zookeeper operations and runs its own event loop in a separate thread.
-
-Sync and Async APIs can be mixed and matched within the same application.
-
-The package includes two shared libraries: zookeeper_st and
-zookeeper_mt. The former only provides the Async API and is not
-thread-safe. The only reason this library exists is to support the
-platforms were pthread library is not available or unstable
-(i.e. FreeBSD 4.x). In all other cases the application developers are
-advised to link against zookeeper_mt as it includes support for both
-Sync and Async API.
-
-
-INSTALLATION
-
-If you're building the client from a source checkout you need to
-follow the steps outlined below. If you're building from a release
-tar downloaded from Apache please skip to step 2.
-
-1) do a "ant compile_jute" from the zookeeper top level directory (.../trunk).
- This will create a directory named "generated" under src/c. Skip to step 3.
-2) unzip/untar the source tarball and cd to the zookeeper-x.x.x/src/c directory
-3) change directory to src/c and do a "autoreconf -if" to bootstrap
- autoconf, automake and libtool. Please make sure you have autoconf
- version 2.59 or greater installed. If cppunit is installed in a non-standard
- directory, you need to specify where to find cppunit.m4. For example, if
- cppunit is installed under /usr/local, run:
-
- ACLOCAL="aclocal -I /usr/local/share/aclocal" autoreconf -if
-
-4) do a "./configure [OPTIONS]" to generate the makefile. See INSTALL
- for general information about running configure. Additionally, the
- configure supports the following options:
- --enable-debug enables optimization and enables debug info compiler
- options, disabled by default
- --without-syncapi disables Sync API support; zookeeper_mt library won't
- be built, enabled by default
- --disable-static do not build static libraries, enabled by default
- --disable-shared do not build shared libraries, enabled by default
- --without-cppunit do not build the test library, enabled by default.
-
-5) do a "make" or "make install" to build the libraries and install them.
- Alternatively, you can also build and run a unit test suite (and
- you probably should). Please make sure you have cppunit-1.10.x or
- higher installed before you execute step 4. Once ./configure has
- finished, do a "make run-check". It will build the libraries, build
- the tests and run them.
-6) to generate doxygen documentation do a "make doxygen-doc". All
- documentations will be placed to a new subfolder named docs. By
- default only HTML documentation is generated. For information on
- other document formats please use "./configure --help"
-
-Alternatively you can use the CMake build system. On Windows, this is required.
-Follow steps 1 and 2 above, and then continue here.
-
-1) do a "cmake [OPTIONS]" to generate the makefile or msbuild files (the correct
- build system will be generated based on your platform). Some options from above
- are supported:
- -DCMAKE_BUILD_TYPE Debug by default, Release enables optimzation etc.
- -DWANT_SYNCAPI ON by default, OFF disables the Sync API support
- -DWANT_CPPUNIT ON except on Windows, OFF disables the tests
- -DBUILD_SHARED_LIBS not yet supported, only static libraries are built
- other CMake options see "cmake --help" for generic options, such as generator
-
-2) do a "cmake --build ." to build the default targets. Alternatively you can
- invoke "make" or "msbuild" manually. If the tests were enabled, use "ctest -V"
- to run them.
-
-Current limitations of the CMake build system include lack of Solaris support,
-no shared library option, no explicitly exported symbols (all are exported by
-default), no versions on the libraries, and no documentation generation.
-Features of CMake include a single, easily consumed cross-platform build system
-to generate the ZooKeeper C Client libraries for any project, with little to no
-configuration.
-
-EXAMPLE/SAMPLE C CLIENT SHELL
-
-NOTE: the ZooKeeper C client shell (cli_st and cli_mt) is meant as a
-example/sample of ZooKeeper C client API usage. It is not a full
-fledged client and not meant for production usage - see the Java
-client shell for a fully featured shell.
-
-You can test your client by running a zookeeper server (see
-instructions on the project wiki page on how to run it) and connecting
-to it using the zookeeper shell application cli that is built as part
-of the installation procedure.
-
-cli_mt (multithreaded, built against zookeeper_mt library) is shown in
-this example, but you could also use cli_st (singlethreaded, built
-against zookeeper_st library):
-
-$ cli_mt zookeeper_host:9876
-
-This is a client application that gives you a shell for executing
-simple zookeeper commands. Once successfully started and connected to
-the server it displays a shell prompt.
-
-You can now enter zookeeper commands. For example, to create a node:
-
-> create /my_new_node
-
-To verify that the node's been created:
-
-> ls /
-
-You should see a list of nodes who are the children of the root node "/".
-
-Here's a list of command supported by the cli shell:
-
-ls <path> -- list children of a znode identified by <path>. The
- command set a children watch on the znode.
-get <path> -- get the value of a znode at <path>
-set <path> <value> -- set the value of a znode at <path> to <value>
-create [+e|+s] <path> -- create a znode as a child of znode <path>;
- use +e option to create an ephemeral znode,
- use +s option to create a znode with a sequence number
- appended to the name. The operation will fail if
- the parent znode (the one identified by <path>) doesn't
- exist.
-delete <path> -- delete the znode at <path>. The command will fail if the znode
- has children.
-sync <path> -- make sure all pending updates have been applied to znode at <path>
-exists <path> -- returns a result code indicating whether the znode at <path>
- exists. The command also sets a znode watch.
-myid -- prints out the current zookeeper session id.
-quit -- exit the shell.
-
-In order to be able to use the zookeeper API in your application you have to
-1) remember to include the zookeeper header
- #include <zookeeper/zookeeper.h>
-2) use -DTHREADED compiler option to enable Sync API; in this case you should
- be linking your code against zookeeper_mt library
-
-Please take a look at cli.c to understand how to use the two API types.
-(TODO: some kind of short tutorial would be helpful, I guess)
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/acinclude.m4
----------------------------------------------------------------------
diff --git a/src/c/acinclude.m4 b/src/c/acinclude.m4
deleted file mode 100644
index d0041d8..0000000
--- a/src/c/acinclude.m4
+++ /dev/null
@@ -1,312 +0,0 @@
-# This file is part of Autoconf. -*- Autoconf -*-
-
-# Copyright (C) 2004 Oren Ben-Kiki
-# This file is distributed under the same terms as the Autoconf macro files.
-
-# Generate automatic documentation using Doxygen. Works in concert with the
-# aminclude.m4 file and a compatible doxygen configuration file. Defines the
-# following public macros:
-#
-# DX_???_FEATURE(ON|OFF) - control the default setting fo a Doxygen feature.
-# Supported features are 'DOXYGEN' itself, 'DOT' for generating graphics,
-# 'HTML' for plain HTML, 'CHM' for compressed HTML help (for MS users), 'CHI'
-# for generating a seperate .chi file by the .chm file, and 'MAN', 'RTF',
-# 'XML', 'PDF' and 'PS' for the appropriate output formats. The environment
-# variable DOXYGEN_PAPER_SIZE may be specified to override the default 'a4wide'
-# paper size.
-#
-# By default, HTML, PDF and PS documentation is generated as this seems to be
-# the most popular and portable combination. MAN pages created by Doxygen are
-# usually problematic, though by picking an appropriate subset and doing some
-# massaging they might be better than nothing. CHM and RTF are specific for MS
-# (note that you can't generate both HTML and CHM at the same time). The XML is
-# rather useless unless you apply specialized post-processing to it.
-#
-# The macro mainly controls the default state of the feature. The use can
-# override the default by specifying --enable or --disable. The macros ensure
-# that contradictory flags are not given (e.g., --enable-doxygen-html and
-# --enable-doxygen-chm, --enable-doxygen-anything with --disable-doxygen, etc.)
-# Finally, each feature will be automatically disabled (with a warning) if the
-# required programs are missing.
-#
-# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN with
-# the following parameters: a one-word name for the project for use as a
-# filename base etc., an optional configuration file name (the default is
-# 'Doxyfile', the same as Doxygen's default), and an optional output directory
-# name (the default is 'doxygen-doc').
-
-## ----------##
-## Defaults. ##
-## ----------##
-
-DX_ENV=""
-AC_DEFUN([DX_FEATURE_doc], ON)
-AC_DEFUN([DX_FEATURE_dot], ON)
-AC_DEFUN([DX_FEATURE_man], OFF)
-AC_DEFUN([DX_FEATURE_html], ON)
-AC_DEFUN([DX_FEATURE_chm], OFF)
-AC_DEFUN([DX_FEATURE_chi], OFF)
-AC_DEFUN([DX_FEATURE_rtf], OFF)
-AC_DEFUN([DX_FEATURE_xml], OFF)
-AC_DEFUN([DX_FEATURE_pdf], ON)
-AC_DEFUN([DX_FEATURE_ps], ON)
-
-## --------------- ##
-## Private macros. ##
-## --------------- ##
-
-# DX_ENV_APPEND(VARIABLE, VALUE)
-# ------------------------------
-# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen.
-AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])])
-
-# DX_DIRNAME_EXPR
-# ---------------
-# Expand into a shell expression prints the directory part of a path.
-AC_DEFUN([DX_DIRNAME_EXPR],
- [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
-
-# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
-# -------------------------------------
-# Expands according to the M4 (static) status of the feature.
-AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
-
-# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
-# ----------------------------------
-# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
-AC_DEFUN([DX_REQUIRE_PROG], [
-AC_PATH_TOOL([$1], [$2])
-if test "$DX_FLAG_$[DX_CURRENT_FEATURE$$1]" = 1; then
- AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
- AC_SUBST([DX_FLAG_]DX_CURRENT_FEATURE, 0)
-fi
-])
-
-# DX_TEST_FEATURE(FEATURE)
-# ------------------------
-# Expand to a shell expression testing whether the feature is active.
-AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
-
-# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
-# -------------------------------------------------
-# Verify that a required features has the right state before trying to turn on
-# the DX_CURRENT_FEATURE.
-AC_DEFUN([DX_CHECK_DEPEND], [
-test "$DX_FLAG_$1" = "$2" \
-|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
- requires, contradicts) doxygen-DX_CURRENT_FEATURE])
-])
-
-# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
-# ----------------------------------------------------------
-# Turn off the DX_CURRENT_FEATURE if the required feature is off.
-AC_DEFUN([DX_CLEAR_DEPEND], [
-test "$DX_FLAG_$1" = "$2" || AC_SUBST([DX_FLAG_]DX_CURRENT_FEATURE, 0)
-])
-
-# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
-# CHECK_DEPEND, CLEAR_DEPEND,
-# REQUIRE, DO-IF-ON, DO-IF-OFF)
-# --------------------------------------------
-# Parse the command-line option controlling a feature. CHECK_DEPEND is called
-# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
-# otherwise CLEAR_DEPEND is called to turn off the default state if a required
-# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
-# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
-# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
-AC_DEFUN([DX_ARG_ABLE], [
- AC_DEFUN([DX_CURRENT_FEATURE], [$1])
- AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
- AC_ARG_ENABLE(doxygen-$1,
- [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
- [--enable-doxygen-$1]),
- DX_IF_FEATURE([$1], [don't $2], [$2]))],
- [
-case "$enableval" in
-#(
-y|Y|yes|Yes|YES)
- AC_SUBST([DX_FLAG_$1], 1)
- $3
-;; #(
-n|N|no|No|NO)
- AC_SUBST([DX_FLAG_$1], 0)
-;; #(
-*)
- AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
-;;
-esac
-], [
-AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
-$4
-])
-if DX_TEST_FEATURE([$1]); then
- $5
- :
-fi
-if DX_TEST_FEATURE([$1]); then
- AM_CONDITIONAL(DX_COND_$1, :)
- $6
- :
-else
- AM_CONDITIONAL(DX_COND_$1, false)
- $7
- :
-fi
-])
-
-## -------------- ##
-## Public macros. ##
-## -------------- ##
-
-# DX_XXX_FEATURE(DEFAULT_STATE)
-# -----------------------------
-AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])])
-AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])])
-AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])])
-AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])])
-AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])])
-AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])])
-AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
-AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
-AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])])
-AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])])
-
-# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR])
-# ---------------------------------------------------------
-# PROJECT also serves as the base name for the documentation files.
-# The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc".
-AC_DEFUN([DX_INIT_DOXYGEN], [
-
-# Files:
-AC_SUBST([DX_PROJECT], [$1])
-AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])])
-AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])])
-
-# Environment variables used inside doxygen.cfg:
-DX_ENV_APPEND(SRCDIR, $srcdir)
-DX_ENV_APPEND(PROJECT, $DX_PROJECT)
-DX_ENV_APPEND(DOCDIR, $DX_DOCDIR)
-DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
-
-# Doxygen itself:
-DX_ARG_ABLE(doc, [generate any doxygen documentation],
- [],
- [],
- [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
- DX_REQUIRE_PROG([DX_PERL], perl)],
- [DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
-
-# Dot for graphics:
-DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [DX_REQUIRE_PROG([DX_DOT], dot)],
- [DX_ENV_APPEND(HAVE_DOT, YES)
- DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
- [DX_ENV_APPEND(HAVE_DOT, NO)])
-
-# Man pages generation:
-DX_ARG_ABLE(man, [generate doxygen manual pages],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [],
- [DX_ENV_APPEND(GENERATE_MAN, YES)],
- [DX_ENV_APPEND(GENERATE_MAN, NO)])
-
-# RTF file generation:
-DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [],
- [DX_ENV_APPEND(GENERATE_RTF, YES)],
- [DX_ENV_APPEND(GENERATE_RTF, NO)])
-
-# XML file generation:
-DX_ARG_ABLE(xml, [generate doxygen XML documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [],
- [DX_ENV_APPEND(GENERATE_XML, YES)],
- [DX_ENV_APPEND(GENERATE_XML, NO)])
-
-# (Compressed) HTML help generation:
-DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [DX_REQUIRE_PROG([DX_HHC], hhc)],
- [DX_ENV_APPEND(HHC_PATH, $DX_HHC)
- DX_ENV_APPEND(GENERATE_HTML, YES)
- DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
- [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
-
-# Seperate CHI file generation.
-DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file],
- [DX_CHECK_DEPEND(chm, 1)],
- [DX_CLEAR_DEPEND(chm, 1)],
- [],
- [DX_ENV_APPEND(GENERATE_CHI, YES)],
- [DX_ENV_APPEND(GENERATE_CHI, NO)])
-
-# Plain HTML pages generation:
-DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
- [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
- [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
- [],
- [DX_ENV_APPEND(GENERATE_HTML, YES)],
- [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
-
-# PostScript file generation:
-DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [DX_REQUIRE_PROG([DX_LATEX], latex)
- DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
- DX_REQUIRE_PROG([DX_DVIPS], dvips)
- DX_REQUIRE_PROG([DX_EGREP], egrep)])
-
-# PDF file generation:
-DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
- DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
- DX_REQUIRE_PROG([DX_EGREP], egrep)])
-
-# LaTeX generation for PS and/or PDF:
-if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
- AM_CONDITIONAL(DX_COND_latex, :)
- DX_ENV_APPEND(GENERATE_LATEX, YES)
-else
- AM_CONDITIONAL(DX_COND_latex, false)
- DX_ENV_APPEND(GENERATE_LATEX, NO)
-fi
-
-# Paper size for PS and/or PDF:
-AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
- [a4wide (default), a4, letter, legal or executive])
-case "$DOXYGEN_PAPER_SIZE" in
-#(
-"")
- AC_SUBST(DOXYGEN_PAPER_SIZE, "")
-;; #(
-a4wide|a4|letter|legal|executive)
- DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
-;; #(
-*)
- AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
-;;
-esac
-
-#For debugging:
-#echo DX_FLAG_doc=$DX_FLAG_doc
-#echo DX_FLAG_dot=$DX_FLAG_dot
-#echo DX_FLAG_man=$DX_FLAG_man
-#echo DX_FLAG_html=$DX_FLAG_html
-#echo DX_FLAG_chm=$DX_FLAG_chm
-#echo DX_FLAG_chi=$DX_FLAG_chi
-#echo DX_FLAG_rtf=$DX_FLAG_rtf
-#echo DX_FLAG_xml=$DX_FLAG_xml
-#echo DX_FLAG_pdf=$DX_FLAG_pdf
-#echo DX_FLAG_ps=$DX_FLAG_ps
-#echo DX_ENV=$DX_ENV
-])
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/aminclude.am
----------------------------------------------------------------------
diff --git a/src/c/aminclude.am b/src/c/aminclude.am
deleted file mode 100644
index 420049e..0000000
--- a/src/c/aminclude.am
+++ /dev/null
@@ -1,186 +0,0 @@
-# Copyright (C) 2004 Oren Ben-Kiki
-# This file is distributed under the same terms as the Automake macro files.
-
-# Generate automatic documentation using Doxygen. Goals and variables values
-# are controlled by the various DX_COND_??? conditionals set by autoconf.
-#
-# The provided goals are:
-# doxygen-doc: Generate all doxygen documentation.
-# doxygen-run: Run doxygen, which will generate some of the documentation
-# (HTML, CHM, CHI, MAN, RTF, XML) but will not do the post
-# processing required for the rest of it (PS, PDF, and some MAN).
-# doxygen-man: Rename some doxygen generated man pages.
-# doxygen-ps: Generate doxygen PostScript documentation.
-# doxygen-pdf: Generate doxygen PDF documentation.
-#
-# Note that by default these are not integrated into the automake goals. If
-# doxygen is used to generate man pages, you can achieve this integration by
-# setting man3_MANS to the list of man pages generated and then adding the
-# dependency:
-#
-# $(man3_MANS): doxygen-doc
-#
-# This will cause make to run doxygen and generate all the documentation.
-#
-# The following variable is intended for use in Makefile.am:
-#
-# DX_CLEANFILES = everything to clean.
-#
-# This is usually added to MOSTLYCLEANFILES.
-
-## --------------------------------- ##
-## Format-independent Doxygen rules. ##
-## --------------------------------- ##
-
-if DX_COND_doc
-
-## ------------------------------- ##
-## Rules specific for HTML output. ##
-## ------------------------------- ##
-
-if DX_COND_html
-
-DX_CLEAN_HTML = @DX_DOCDIR@/html
-
-endif DX_COND_html
-
-## ------------------------------ ##
-## Rules specific for CHM output. ##
-## ------------------------------ ##
-
-if DX_COND_chm
-
-DX_CLEAN_CHM = @DX_DOCDIR@/chm
-
-if DX_COND_chi
-
-DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi
-
-endif DX_COND_chi
-
-endif DX_COND_chm
-
-## ------------------------------ ##
-## Rules specific for MAN output. ##
-## ------------------------------ ##
-
-if DX_COND_man
-
-DX_CLEAN_MAN = @DX_DOCDIR@/man
-
-endif DX_COND_man
-
-## ------------------------------ ##
-## Rules specific for RTF output. ##
-## ------------------------------ ##
-
-if DX_COND_rtf
-
-DX_CLEAN_RTF = @DX_DOCDIR@/rtf
-
-endif DX_COND_rtf
-
-## ------------------------------ ##
-## Rules specific for XML output. ##
-## ------------------------------ ##
-
-if DX_COND_xml
-
-DX_CLEAN_XML = @DX_DOCDIR@/xml
-
-endif DX_COND_xml
-
-## ----------------------------- ##
-## Rules specific for PS output. ##
-## ----------------------------- ##
-
-if DX_COND_ps
-
-DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps
-
-DX_PS_GOAL = doxygen-ps
-
-doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps
-
-@DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag
- cd @DX_DOCDIR@/latex; \
- rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
- $(DX_LATEX) refman.tex; \
- $(MAKEINDEX_PATH) refman.idx; \
- $(DX_LATEX) refman.tex; \
- countdown=5; \
- while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
- refman.log > /dev/null 2>&1 \
- && test $$countdown -gt 0; do \
- $(DX_LATEX) refman.tex; \
- countdown=`expr $$countdown - 1`; \
- done; \
- $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi
-
-endif DX_COND_ps
-
-## ------------------------------ ##
-## Rules specific for PDF output. ##
-## ------------------------------ ##
-
-if DX_COND_pdf
-
-DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf
-
-DX_PDF_GOAL = doxygen-pdf
-
-doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf
-
-@DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag
- cd @DX_DOCDIR@/latex; \
- rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
- $(DX_PDFLATEX) refman.tex; \
- $(DX_MAKEINDEX) refman.idx; \
- $(DX_PDFLATEX) refman.tex; \
- countdown=5; \
- while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
- refman.log > /dev/null 2>&1 \
- && test $$countdown -gt 0; do \
- $(DX_PDFLATEX) refman.tex; \
- countdown=`expr $$countdown - 1`; \
- done; \
- mv refman.pdf ../@PACKAGE@.pdf
-
-endif DX_COND_pdf
-
-## ------------------------------------------------- ##
-## Rules specific for LaTeX (shared for PS and PDF). ##
-## ------------------------------------------------- ##
-
-if DX_COND_latex
-
-DX_CLEAN_LATEX = @DX_DOCDIR@/latex
-
-endif DX_COND_latex
-
-.PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL)
-
-.INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
-
-doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag
-
-doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
-
-@DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS)
- rm -rf @DX_DOCDIR@
- $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
-
-DX_CLEANFILES = \
- @DX_DOCDIR@/@PACKAGE@.tag \
- -r \
- $(DX_CLEAN_HTML) \
- $(DX_CLEAN_CHM) \
- $(DX_CLEAN_CHI) \
- $(DX_CLEAN_MAN) \
- $(DX_CLEAN_RTF) \
- $(DX_CLEAN_XML) \
- $(DX_CLEAN_PS) \
- $(DX_CLEAN_PDF) \
- $(DX_CLEAN_LATEX)
-
-endif DX_COND_doc
[17/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/src/cli.c
----------------------------------------------------------------------
diff --git a/src/c/src/cli.c b/src/c/src/cli.c
deleted file mode 100644
index ef32a10..0000000
--- a/src/c/src/cli.c
+++ /dev/null
@@ -1,697 +0,0 @@
-/**
- * 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_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_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, " 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, " 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 (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++;
- if (async) {
- rc = zoo_aset(zh, line, ptr, strlen(ptr), -1, my_stat_completion,
- strdup(line));
- } else {
- struct Stat stat;
- rc = zoo_set2(zh, line, ptr, strlen(ptr), -1, &stat);
- }
- 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 ")) {
- int flags = 0;
- line += 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));
-// }
- 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;
- }
- if (async) {
- rc = zoo_adelete(zh, line, -1, my_void_completion, strdup(line));
- } else {
- rc = zoo_delete(zh, line, -1);
- }
- 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;
- FILE *fh;
-
- if (argc < 2) {
- fprintf(stderr,
- "USAGE %s zookeeper_host_list [clientid_file|cmd:(ls|ls2|create|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);
- }
- }
- }
-#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, 0, 0);
- 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 (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/5694559d/src/c/src/hashtable/LICENSE.txt
----------------------------------------------------------------------
diff --git a/src/c/src/hashtable/LICENSE.txt b/src/c/src/hashtable/LICENSE.txt
deleted file mode 100644
index 674a624..0000000
--- a/src/c/src/hashtable/LICENSE.txt
+++ /dev/null
@@ -1,30 +0,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/5694559d/src/c/src/hashtable/hashtable.c
----------------------------------------------------------------------
diff --git a/src/c/src/hashtable/hashtable.c b/src/c/src/hashtable/hashtable.c
deleted file mode 100644
index 763357e..0000000
--- a/src/c/src/hashtable/hashtable.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/* Copyright (C) 2004 Christopher Clark <fi...@cl.cam.ac.uk> */
-
-#include "hashtable.h"
-#include "hashtable_private.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-
-/*
-Credit for primes table: Aaron Krowne
- http://br.endernet.org/~akrowne/
- http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
-*/
-static const unsigned int primes[] = {
-53, 97, 193, 389,
-769, 1543, 3079, 6151,
-12289, 24593, 49157, 98317,
-196613, 393241, 786433, 1572869,
-3145739, 6291469, 12582917, 25165843,
-50331653, 100663319, 201326611, 402653189,
-805306457, 1610612741
-};
-const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
-const float max_load_factor = 0.65;
-
-/*****************************************************************************/
-struct hashtable *
-create_hashtable(unsigned int minsize,
- unsigned int (*hashf) (void*),
- int (*eqf) (void*,void*))
-{
- struct hashtable *h;
- unsigned int pindex, size = primes[0];
- /* Check requested hashtable isn't too large */
- if (minsize > (1u << 30)) return NULL;
- /* Enforce size as prime */
- for (pindex=0; pindex < prime_table_length; pindex++) {
- if (primes[pindex] > minsize) { size = primes[pindex]; break; }
- }
- h = (struct hashtable *)malloc(sizeof(struct hashtable));
- if (NULL == h) return NULL; /*oom*/
- h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
- if (NULL == h->table) { free(h); return NULL; } /*oom*/
- memset(h->table, 0, size * sizeof(struct entry *));
- h->tablelength = size;
- h->primeindex = pindex;
- h->entrycount = 0;
- h->hashfn = hashf;
- h->eqfn = eqf;
- h->loadlimit = (unsigned int) ceil(size * max_load_factor);
- return h;
-}
-
-/*****************************************************************************/
-unsigned int
-hash(struct hashtable *h, void *k)
-{
- /* Aim to protect against poor hash functions by adding logic here
- * - logic taken from java 1.4 hashtable source */
- unsigned int i = h->hashfn(k);
- i += ~(i << 9);
- i ^= ((i >> 14) | (i << 18)); /* >>> */
- i += (i << 4);
- i ^= ((i >> 10) | (i << 22)); /* >>> */
- return i;
-}
-
-/*****************************************************************************/
-static int
-hashtable_expand(struct hashtable *h)
-{
- /* Double the size of the table to accomodate more entries */
- struct entry **newtable;
- struct entry *e;
- struct entry **pE;
- unsigned int newsize, i, index;
- /* Check we're not hitting max capacity */
- if (h->primeindex == (prime_table_length - 1)) return 0;
- newsize = primes[++(h->primeindex)];
-
- newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
- if (NULL != newtable)
- {
- memset(newtable, 0, newsize * sizeof(struct entry *));
- /* This algorithm is not 'stable'. ie. it reverses the list
- * when it transfers entries between the tables */
- for (i = 0; i < h->tablelength; i++) {
- while (NULL != (e = h->table[i])) {
- h->table[i] = e->next;
- index = indexFor(newsize,e->h);
- e->next = newtable[index];
- newtable[index] = e;
- }
- }
- free(h->table);
- h->table = newtable;
- }
- /* Plan B: realloc instead */
- else
- {
- newtable = (struct entry **)
- realloc(h->table, newsize * sizeof(struct entry *));
- if (NULL == newtable) { (h->primeindex)--; return 0; }
- h->table = newtable;
- memset(newtable[h->tablelength], 0, newsize - h->tablelength);
- for (i = 0; i < h->tablelength; i++) {
- for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
- index = indexFor(newsize,e->h);
- if (index == i)
- {
- pE = &(e->next);
- }
- else
- {
- *pE = e->next;
- e->next = newtable[index];
- newtable[index] = e;
- }
- }
- }
- }
- h->tablelength = newsize;
- h->loadlimit = (unsigned int) ceil(newsize * max_load_factor);
- return -1;
-}
-
-/*****************************************************************************/
-unsigned int
-hashtable_count(struct hashtable *h)
-{
- return h->entrycount;
-}
-
-/*****************************************************************************/
-int
-hashtable_insert(struct hashtable *h, void *k, void *v)
-{
- /* This method allows duplicate keys - but they shouldn't be used */
- unsigned int index;
- struct entry *e;
- if (++(h->entrycount) > h->loadlimit)
- {
- /* Ignore the return value. If expand fails, we should
- * still try cramming just this value into the existing table
- * -- we may not have memory for a larger table, but one more
- * element may be ok. Next time we insert, we'll try expanding again.*/
- hashtable_expand(h);
- }
- e = (struct entry *)malloc(sizeof(struct entry));
- if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
- e->h = hash(h,k);
- index = indexFor(h->tablelength,e->h);
- e->k = k;
- e->v = v;
- e->next = h->table[index];
- h->table[index] = e;
- return -1;
-}
-
-/*****************************************************************************/
-void * /* returns value associated with key */
-hashtable_search(struct hashtable *h, void *k)
-{
- struct entry *e;
- unsigned int hashvalue, index;
- hashvalue = hash(h,k);
- index = indexFor(h->tablelength,hashvalue);
- e = h->table[index];
- while (NULL != e)
- {
- /* Check hash value to short circuit heavier comparison */
- if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
- e = e->next;
- }
- return NULL;
-}
-
-/*****************************************************************************/
-void * /* returns value associated with key */
-hashtable_remove(struct hashtable *h, void *k)
-{
- /* TODO: consider compacting the table when the load factor drops enough,
- * or provide a 'compact' method. */
-
- struct entry *e;
- struct entry **pE;
- void *v;
- unsigned int hashvalue, index;
-
- hashvalue = hash(h,k);
- index = indexFor(h->tablelength,hash(h,k));
- pE = &(h->table[index]);
- e = *pE;
- while (NULL != e)
- {
- /* Check hash value to short circuit heavier comparison */
- if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
- {
- *pE = e->next;
- h->entrycount--;
- v = e->v;
- freekey(e->k);
- free(e);
- return v;
- }
- pE = &(e->next);
- e = e->next;
- }
- return NULL;
-}
-
-/*****************************************************************************/
-/* destroy */
-void
-hashtable_destroy(struct hashtable *h, int free_values)
-{
- unsigned int i;
- struct entry *e, *f;
- struct entry **table = h->table;
- if (free_values)
- {
- for (i = 0; i < h->tablelength; i++)
- {
- e = table[i];
- while (NULL != e)
- { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
- }
- }
- else
- {
- for (i = 0; i < h->tablelength; i++)
- {
- e = table[i];
- while (NULL != e)
- { f = e; e = e->next; freekey(f->k); free(f); }
- }
- }
- free(h->table);
- free(h);
-}
-
-/*
- * Copyright (c) 2002, Christopher Clark
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/src/hashtable/hashtable.h
----------------------------------------------------------------------
diff --git a/src/c/src/hashtable/hashtable.h b/src/c/src/hashtable/hashtable.h
deleted file mode 100644
index cbead18..0000000
--- a/src/c/src/hashtable/hashtable.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/* 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/5694559d/src/c/src/hashtable/hashtable_itr.c
----------------------------------------------------------------------
diff --git a/src/c/src/hashtable/hashtable_itr.c b/src/c/src/hashtable/hashtable_itr.c
deleted file mode 100644
index defac69..0000000
--- a/src/c/src/hashtable/hashtable_itr.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/* 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/5694559d/src/c/src/hashtable/hashtable_itr.h
----------------------------------------------------------------------
diff --git a/src/c/src/hashtable/hashtable_itr.h b/src/c/src/hashtable/hashtable_itr.h
deleted file mode 100644
index 30379c7..0000000
--- a/src/c/src/hashtable/hashtable_itr.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* 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/5694559d/src/c/src/hashtable/hashtable_private.h
----------------------------------------------------------------------
diff --git a/src/c/src/hashtable/hashtable_private.h b/src/c/src/hashtable/hashtable_private.h
deleted file mode 100644
index 3e95f60..0000000
--- a/src/c/src/hashtable/hashtable_private.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* 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/5694559d/src/c/src/load_gen.c
----------------------------------------------------------------------
diff --git a/src/c/src/load_gen.c b/src/c/src/load_gen.c
deleted file mode 100644
index 546d5d1..0000000
--- a/src/c/src/load_gen.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/**
- * 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){
- 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(("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(("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(("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(("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(("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(("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(("Deleting %s",root));
- rc=zoo_delete(zh,root,-1);
- if(rc!=ZOK){
- LOG_ERROR(("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(("Checking server connection..."));
- ensureConnected();
- if(cleaning==1){
- int rc = 0;
- deletedCounter=0;
- rc=recursiveDelete(argv[2]);
- if(rc==ZOK){
- LOG_INFO(("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(("Creating children for path %s",argv[2]));
- doCreateNodes(argv[2],nodeCount);
- waitCounter();
-
- LOG_INFO(("Starting the write cycle for path %s",argv[2]));
- doWrites(argv[2],nodeCount);
- waitCounter();
- LOG_INFO(("Starting the read cycle for path %s",argv[2]));
- doReads(argv[2],nodeCount);
- waitCounter();
-
- LOG_INFO(("Starting the delete cycle for path %s",argv[2]));
- doDeletes(argv[2],nodeCount);
- waitCounter();
- }
- zookeeper_close(zh);
- return 0;
-}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/src/mt_adaptor.c
----------------------------------------------------------------------
diff --git a/src/c/src/mt_adaptor.c b/src/c/src/mt_adaptor.c
deleted file mode 100644
index 52d86d5..0000000
--- a/src/c/src/mt_adaptor.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/**
- * 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 THREADED
-#define THREADED
-#endif
-
-#if !defined(DLL_EXPORT) && !defined(USE_STATIC_LIB)
-# define USE_STATIC_LIB
-#endif
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include "zk_adaptor.h"
-#include "zookeeper_log.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <errno.h>
-
-#ifndef WIN32
-#include <signal.h>
-#include <poll.h>
-#include <unistd.h>
-#include <sys/time.h>
-#endif
-
-int zoo_lock_auth(zhandle_t *zh)
-{
- return pthread_mutex_lock(&zh->auth_h.lock);
-}
-int zoo_unlock_auth(zhandle_t *zh)
-{
- return pthread_mutex_unlock(&zh->auth_h.lock);
-}
-int lock_buffer_list(buffer_head_t *l)
-{
- return pthread_mutex_lock(&l->lock);
-}
-int unlock_buffer_list(buffer_head_t *l)
-{
- return pthread_mutex_unlock(&l->lock);
-}
-int lock_completion_list(completion_head_t *l)
-{
- return pthread_mutex_lock(&l->lock);
-}
-int unlock_completion_list(completion_head_t *l)
-{
- pthread_cond_broadcast(&l->cond);
- return pthread_mutex_unlock(&l->lock);
-}
-struct sync_completion *alloc_sync_completion(void)
-{
- struct sync_completion *sc = (struct sync_completion*)calloc(1, sizeof(struct sync_completion));
- if (sc) {
- pthread_cond_init(&sc->cond, 0);
- pthread_mutex_init(&sc->lock, 0);
- }
- return sc;
-}
-int wait_sync_completion(struct sync_completion *sc)
-{
- pthread_mutex_lock(&sc->lock);
- while (!sc->complete) {
- pthread_cond_wait(&sc->cond, &sc->lock);
- }
- pthread_mutex_unlock(&sc->lock);
- return 0;
-}
-
-void free_sync_completion(struct sync_completion *sc)
-{
- if (sc) {
- pthread_mutex_destroy(&sc->lock);
- pthread_cond_destroy(&sc->cond);
- free(sc);
- }
-}
-
-void notify_sync_completion(struct sync_completion *sc)
-{
- pthread_mutex_lock(&sc->lock);
- sc->complete = 1;
- pthread_cond_broadcast(&sc->cond);
- pthread_mutex_unlock(&sc->lock);
-}
-
-int process_async(int outstanding_sync)
-{
- return 0;
-}
-
-#ifdef WIN32
-unsigned __stdcall do_io( void * );
-unsigned __stdcall do_completion( void * );
-
-int handle_error(SOCKET sock, char* message)
-{
- LOG_ERROR(("%s. %d",message, WSAGetLastError()));
- closesocket (sock);
- return -1;
-}
-
-//--create socket pair for interupting selects.
-int create_socket_pair(SOCKET fds[2])
-{
- struct sockaddr_in inaddr;
- struct sockaddr addr;
- int yes=1;
- int len=0;
-
- SOCKET lst=socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
- if (lst == INVALID_SOCKET ){
- LOG_ERROR(("Error creating socket. %d",WSAGetLastError()));
- return -1;
- }
- memset(&inaddr, 0, sizeof(inaddr));
- memset(&addr, 0, sizeof(addr));
- inaddr.sin_family = AF_INET;
- inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- inaddr.sin_port = 0; //--system assigns the port
-
- if ( setsockopt(lst,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes)) == SOCKET_ERROR ) {
- return handle_error(lst,"Error trying to set socket option.");
- }
- if (bind(lst,(struct sockaddr *)&inaddr,sizeof(inaddr)) == SOCKET_ERROR){
- return handle_error(lst,"Error trying to bind socket.");
- }
- if (listen(lst,1) == SOCKET_ERROR){
- return handle_error(lst,"Error trying to listen on socket.");
- }
- len=sizeof(inaddr);
- getsockname(lst, &addr,&len);
- fds[0]=socket(AF_INET, SOCK_STREAM,0);
- if (connect(fds[0],&addr,len) == SOCKET_ERROR){
- return handle_error(lst, "Error while connecting to socket.");
- }
- if ((fds[1]=accept(lst,0,0)) == INVALID_SOCKET){
- closesocket(fds[0]);
- return handle_error(lst, "Error while accepting socket connection.");
- }
- closesocket(lst);
- return 0;
-}
-#else
-void *do_io(void *);
-void *do_completion(void *);
-#endif
-
-
-int wakeup_io_thread(zhandle_t *zh);
-
-#ifdef WIN32
-static int set_nonblock(SOCKET fd){
- ULONG nonblocking_flag = 1;
- if (ioctlsocket(fd, FIONBIO, &nonblocking_flag) == 0)
- return 1;
- else
- return -1;
-}
-#else
-static int set_nonblock(int fd){
- long l = fcntl(fd, F_GETFL);
- if(l & O_NONBLOCK) return 0;
- return fcntl(fd, F_SETFL, l | O_NONBLOCK);
-}
-#endif
-
-void wait_for_others(zhandle_t* zh)
-{
- struct adaptor_threads* adaptor=zh->adaptor_priv;
- pthread_mutex_lock(&adaptor->lock);
- while(adaptor->threadsToWait>0)
- pthread_cond_wait(&adaptor->cond,&adaptor->lock);
- pthread_mutex_unlock(&adaptor->lock);
-}
-
-void notify_thread_ready(zhandle_t* zh)
-{
- struct adaptor_threads* adaptor=zh->adaptor_priv;
- pthread_mutex_lock(&adaptor->lock);
- adaptor->threadsToWait--;
- pthread_cond_broadcast(&adaptor->cond);
- while(adaptor->threadsToWait>0)
- pthread_cond_wait(&adaptor->cond,&adaptor->lock);
- pthread_mutex_unlock(&adaptor->lock);
-}
-
-
-void start_threads(zhandle_t* zh)
-{
- int rc = 0;
- struct adaptor_threads* adaptor=zh->adaptor_priv;
- pthread_cond_init(&adaptor->cond,0);
- pthread_mutex_init(&adaptor->lock,0);
- adaptor->threadsToWait=2; // wait for 2 threads before opening the barrier
-
- // use api_prolog() to make sure zhandle doesn't get destroyed
- // while initialization is in progress
- api_prolog(zh);
- LOG_DEBUG(("starting threads..."));
- rc=pthread_create(&adaptor->io, 0, do_io, zh);
- assert("pthread_create() failed for the IO thread"&&!rc);
- rc=pthread_create(&adaptor->completion, 0, do_completion, zh);
- assert("pthread_create() failed for the completion thread"&&!rc);
- wait_for_others(zh);
- api_epilog(zh, 0);
-}
-
-int adaptor_init(zhandle_t *zh)
-{
- pthread_mutexattr_t recursive_mx_attr;
- struct adaptor_threads *adaptor_threads = calloc(1, sizeof(*adaptor_threads));
- if (!adaptor_threads) {
- LOG_ERROR(("Out of memory"));
- return -1;
- }
-
- /* We use a pipe for interrupting select() in unix/sol and socketpair in windows. */
-#ifdef WIN32
- if (create_socket_pair(adaptor_threads->self_pipe) == -1){
- LOG_ERROR(("Can't make a socket."));
-#else
- if(pipe(adaptor_threads->self_pipe)==-1) {
- LOG_ERROR(("Can't make a pipe %d",errno));
-#endif
- free(adaptor_threads);
- return -1;
- }
- set_nonblock(adaptor_threads->self_pipe[1]);
- set_nonblock(adaptor_threads->self_pipe[0]);
-
- pthread_mutex_init(&zh->auth_h.lock,0);
-
- zh->adaptor_priv = adaptor_threads;
- pthread_mutex_init(&zh->to_process.lock,0);
- pthread_mutex_init(&adaptor_threads->zh_lock,0);
- // to_send must be recursive mutex
- pthread_mutexattr_init(&recursive_mx_attr);
- pthread_mutexattr_settype(&recursive_mx_attr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&zh->to_send.lock,&recursive_mx_attr);
- pthread_mutexattr_destroy(&recursive_mx_attr);
-
- pthread_mutex_init(&zh->sent_requests.lock,0);
- pthread_cond_init(&zh->sent_requests.cond,0);
- pthread_mutex_init(&zh->completions_to_process.lock,0);
- pthread_cond_init(&zh->completions_to_process.cond,0);
- start_threads(zh);
- return 0;
-}
-
-void adaptor_finish(zhandle_t *zh)
-{
- struct adaptor_threads *adaptor_threads;
- // make sure zh doesn't get destroyed until after we're done here
- api_prolog(zh);
- adaptor_threads = zh->adaptor_priv;
- if(adaptor_threads==0) {
- api_epilog(zh,0);
- return;
- }
-
- if(!pthread_equal(adaptor_threads->io,pthread_self())){
- wakeup_io_thread(zh);
- pthread_join(adaptor_threads->io, 0);
- }else
- pthread_detach(adaptor_threads->io);
-
- if(!pthread_equal(adaptor_threads->completion,pthread_self())){
- pthread_mutex_lock(&zh->completions_to_process.lock);
- pthread_cond_broadcast(&zh->completions_to_process.cond);
- pthread_mutex_unlock(&zh->completions_to_process.lock);
- pthread_join(adaptor_threads->completion, 0);
- }else
- pthread_detach(adaptor_threads->completion);
-
- api_epilog(zh,0);
-}
-
-void adaptor_destroy(zhandle_t *zh)
-{
- struct adaptor_threads *adaptor = zh->adaptor_priv;
- if(adaptor==0) return;
-
- pthread_cond_destroy(&adaptor->cond);
- pthread_mutex_destroy(&adaptor->lock);
- pthread_mutex_destroy(&zh->to_process.lock);
- pthread_mutex_destroy(&zh->to_send.lock);
- pthread_mutex_destroy(&zh->sent_requests.lock);
- pthread_cond_destroy(&zh->sent_requests.cond);
- pthread_mutex_destroy(&zh->completions_to_process.lock);
- pthread_cond_destroy(&zh->completions_to_process.cond);
- pthread_mutex_destroy(&adaptor->zh_lock);
-
- pthread_mutex_destroy(&zh->auth_h.lock);
-
- close(adaptor->self_pipe[0]);
- close(adaptor->self_pipe[1]);
- free(adaptor);
- zh->adaptor_priv=0;
-}
-
-int wakeup_io_thread(zhandle_t *zh)
-{
- struct adaptor_threads *adaptor_threads = zh->adaptor_priv;
- char c=0;
-#ifndef WIN32
- return write(adaptor_threads->self_pipe[1],&c,1)==1? ZOK: ZSYSTEMERROR;
-#else
- return send(adaptor_threads->self_pipe[1], &c, 1, 0)==1? ZOK: ZSYSTEMERROR;
-#endif
-}
-
-int adaptor_send_queue(zhandle_t *zh, int timeout)
-{
- if(!zh->close_requested)
- return wakeup_io_thread(zh);
- // don't rely on the IO thread to send the messages if the app has
- // requested to close
- return flush_send_queue(zh, timeout);
-}
-
-/* These two are declared here because we will run the event loop
- * and not the client */
-#ifdef WIN32
-int zookeeper_interest(zhandle_t *zh, SOCKET *fd, int *interest,
- struct timeval *tv);
-#else
-int zookeeper_interest(zhandle_t *zh, int *fd, int *interest,
- struct timeval *tv);
-#endif
-int zookeeper_process(zhandle_t *zh, int events);
-
-#ifdef WIN32
-unsigned __stdcall do_io( void * v)
-#else
-void *do_io(void *v)
-#endif
-{
- zhandle_t *zh = (zhandle_t*)v;
-#ifndef WIN32
- struct pollfd fds[2];
- struct adaptor_threads *adaptor_threads = zh->adaptor_priv;
-
- api_prolog(zh);
- notify_thread_ready(zh);
- LOG_DEBUG(("started IO thread"));
- fds[0].fd=adaptor_threads->self_pipe[0];
- fds[0].events=POLLIN;
- while(!zh->close_requested) {
- struct timeval tv;
- int fd;
- int interest;
- int timeout;
- int maxfd=1;
-
- zookeeper_interest(zh, &fd, &interest, &tv);
- if (fd != -1) {
- fds[1].fd=fd;
- fds[1].events=(interest&ZOOKEEPER_READ)?POLLIN:0;
- fds[1].events|=(interest&ZOOKEEPER_WRITE)?POLLOUT:0;
- maxfd=2;
- }
- timeout=tv.tv_sec * 1000 + (tv.tv_usec/1000);
-
- poll(fds,maxfd,timeout);
- if (fd != -1) {
- interest=(fds[1].revents&POLLIN)?ZOOKEEPER_READ:0;
- interest|=((fds[1].revents&POLLOUT)||(fds[1].revents&POLLHUP))?ZOOKEEPER_WRITE:0;
- }
- if(fds[0].revents&POLLIN){
- // flush the pipe
- char b[128];
- while(read(adaptor_threads->self_pipe[0],b,sizeof(b))==sizeof(b)){}
- }
-#else
- fd_set rfds, wfds, efds;
- struct adaptor_threads *adaptor_threads = zh->adaptor_priv;
- api_prolog(zh);
- notify_thread_ready(zh);
- LOG_DEBUG(("started IO thread"));
- FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds);
- while(!zh->close_requested) {
- struct timeval tv;
- SOCKET fd;
- SOCKET maxfd=adaptor_threads->self_pipe[0];
- int interest;
- 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);
- }
- }
- FD_SET( adaptor_threads->self_pipe[0] ,&rfds );
- rc = select((int)maxfd, &rfds, &wfds, &efds, &tv);
- if (fd != -1)
- {
- interest = (FD_ISSET(fd, &rfds))? ZOOKEEPER_READ:0;
- interest|= (FD_ISSET(fd, &wfds))? ZOOKEEPER_WRITE:0;
- }
-
- if (FD_ISSET(adaptor_threads->self_pipe[0], &rfds)){
- // flush the pipe/socket
- char b[128];
- while(recv(adaptor_threads->self_pipe[0],b,sizeof(b), 0)==sizeof(b)){}
- }
-#endif
- // dispatch zookeeper events
- zookeeper_process(zh, interest);
- // check the current state of the zhandle and terminate
- // if it is_unrecoverable()
- if(is_unrecoverable(zh))
- break;
- }
- api_epilog(zh, 0);
- LOG_DEBUG(("IO thread terminated"));
- return 0;
-}
-
-#ifdef WIN32
-unsigned __stdcall do_completion( void * v)
-#else
-void *do_completion(void *v)
-#endif
-{
- zhandle_t *zh = v;
- api_prolog(zh);
- notify_thread_ready(zh);
- LOG_DEBUG(("started completion thread"));
- while(!zh->close_requested) {
- pthread_mutex_lock(&zh->completions_to_process.lock);
- while(!zh->completions_to_process.head && !zh->close_requested) {
- pthread_cond_wait(&zh->completions_to_process.cond, &zh->completions_to_process.lock);
- }
- pthread_mutex_unlock(&zh->completions_to_process.lock);
- process_completions(zh);
- }
- api_epilog(zh, 0);
- LOG_DEBUG(("completion thread terminated"));
- return 0;
-}
-
-int32_t inc_ref_counter(zhandle_t* zh,int i)
-{
- int incr=(i<0?-1:(i>0?1:0));
- // fetch_and_add implements atomic post-increment
- int v=fetch_and_add(&zh->ref_counter,incr);
- // inc_ref_counter wants pre-increment
- v+=incr; // simulate pre-increment
- return v;
-}
-
-int32_t fetch_and_add(volatile int32_t* operand, int incr)
-{
-#ifndef WIN32
- return __sync_fetch_and_add(operand, incr);
-#else
- return InterlockedExchangeAdd(operand, incr);
-#endif
-}
-
-// make sure the static xid is initialized before any threads started
-__attribute__((constructor)) int32_t get_xid()
-{
- static int32_t xid = -1;
- if (xid == -1) {
- xid = time(0);
- }
- return fetch_and_add(&xid,1);
-}
-
-int enter_critical(zhandle_t* zh)
-{
- struct adaptor_threads *adaptor = zh->adaptor_priv;
- if (adaptor) {
- return pthread_mutex_lock(&adaptor->zh_lock);
- } else {
- return 0;
- }
-}
-
-int leave_critical(zhandle_t* zh)
-{
- struct adaptor_threads *adaptor = zh->adaptor_priv;
- if (adaptor) {
- return pthread_mutex_unlock(&adaptor->zh_lock);
- } else {
- return 0;
- }
-}
[04/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/CollectionUtil.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/CollectionUtil.h b/zookeeper-client/zookeeper-client-c/tests/CollectionUtil.h
new file mode 100644
index 0000000..dd34811
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/CollectionUtil.h
@@ -0,0 +1,195 @@
+/**
+ * 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 _COLLECTION_UTIL_H_
+#define _COLLECTION_UTIL_H_
+
+/**
+ * \file
+ * CollectionBuilder and DictionaryBuilder classes and collection utility functions
+ */
+
+namespace Util
+{
+
+// *********************************************************
+/** A shortcut to use for building collections.
+ * This class is a wrapper around standard STL collection containers such as vector.
+ * It allows one to conveniently build collections at the variable initialization time:
+ * \code
+ * #include "CollectionUtil.h"
+ * #include "Vector.h" // for ostream << operator overload for STL vector
+ * using Util;
+ *
+ * int main()
+ * {
+ * typedef vector<string> MyVector;
+ * MyVector myVector=CollectionBuilder<MyVector>()("str1")("str2")("str3");
+ * cout<<myVector;
+ * // the following output will be produced:
+ * // [str1,str2,str3]
+ * }
+ * \endcode
+ */
+template <class CONT>
+class CollectionBuilder
+{
+public:
+ /// Type of the collection container.
+ typedef CONT CollectionType;
+ /// Container's value type.
+ typedef typename CollectionType::value_type value_type;
+ /// Container's constant iterator type.
+ typedef typename CollectionType::const_iterator const_iterator;
+ /// Container's size type.
+ typedef typename CollectionType::size_type size_type;
+
+ /** Operator function call overload to allow call chaining.
+ * \param value the value to be inserted into the container
+ */
+ CollectionBuilder<CONT>& operator()(const value_type& value){
+ return push_back(value);
+ }
+ /** Same as regular STL push_back() but allows call chaining.
+ * \param value the value to be inserted into the container
+ */
+ CollectionBuilder<CONT>& push_back(const value_type& value){
+ collection_.push_back(value);
+ return *this;
+ }
+ /// \name Standard STL container interface
+ /// @{
+ const_iterator begin() const{return collection_.begin();}
+ const_iterator end() const{return collection_.end();}
+ size_type size() const{return collection_.size();}
+ void clear() {collection_.clear();}
+ ///@}
+ /// Explicit typecast operator.
+ operator const CollectionType&() const {return collection_;}
+private:
+ /// \cond PRIVATE
+ CollectionType collection_;
+ /// \endcond
+};
+
+
+// *********************************************************
+/** A shortcut to use for building dictionaries.
+ * This class is a wrapper around standard STL associative containers such as map.
+ * It allows one to conveniently build dictionaries at the variable initialization time:
+ * \code
+ * #include "CollectionUtil.h"
+ * #include "Map.h" // for ostream << operator overload for STL map
+ * using Util;
+ *
+ * int main()
+ * {
+ * typedef map<string,int> MyMap;
+ * MyMap myMap=DictionaryBuilder<MyMap>()("str1",1)("str2",2)("str3",3);
+ * cout<<myMap;
+ * // the following output will be produced:
+ * // [str1=1,str2=2,str3=3]
+ * }
+ * \endcode
+ */
+template <class CONT>
+class DictionaryBuilder
+{
+public:
+ /// The type of the associative container
+ typedef CONT DictionaryType;
+ /// Container's element type (usually a pair<key_type,mapped_type>)
+ typedef typename DictionaryType::value_type value_type;
+ /// Container's key type
+ typedef typename DictionaryType::key_type key_type;
+ /// Container's value type
+ typedef typename DictionaryType::mapped_type mapped_type;
+ /// Container's constant iterator type
+ typedef typename DictionaryType::const_iterator const_iterator;
+ /// Container's writable iterator type
+ typedef typename DictionaryType::iterator iterator;
+ /// Container's size type
+ typedef typename DictionaryType::size_type size_type;
+
+ /** Operator function call overload to allow call chaining.
+ * \param key the value key to be inserted
+ * \param value the value to be inserted into the container
+ * \return a non-const reference to self
+ */
+ DictionaryBuilder<CONT>& operator()(const key_type& key,const mapped_type& value){
+ dict_.insert(value_type(key,value));
+ return *this;
+ }
+ /** Lookup value by key.
+ * \param key the key associated with the value.
+ * \return a non-const iterator pointing to the element whose key matched the \a key parameter
+ */
+ iterator find(const key_type& key){
+ return dict_.find(key);
+ }
+ /** Lookup value by key.
+ * \param key the key associated with the value.
+ * \return a const iterator pointing to the element whose key matched the \a key parameter
+ */
+ const_iterator find(const key_type& key) const{
+ return dict_.find(key);
+ }
+
+ /// \name Standard STL container interface
+ /// @{
+ const_iterator begin() const{return dict_.begin();}
+ const_iterator end() const{return dict_.end();}
+ size_type size() const{return dict_.size();}
+ void clear() {dict_.clear();}
+ ///@}
+ /// Explicit typecast operator.
+ operator const DictionaryType&() const {return dict_;}
+private:
+ DictionaryType dict_;
+};
+
+
+// ***********************************************************
+/** Deletes all dynamically allocated elements of a collection.
+ * C::value_type is expected to be a pointer to a dynamically allocated object, or it won't compile.
+ * The function will iterate over all container elements and call delete for each of them.
+ * \param c a collection (vector,set) whose elements are being deleted.
+ */
+template <class C>
+void clearCollection(C& c){
+ for(typename C::const_iterator it=c.begin();it!=c.end();++it)
+ delete *it;
+ c.clear();
+}
+
+/** Deletes all dynamically allocated values of the assotiative container.
+ * The function expects the M::value_type to be a pair<..., ptr_to_type>, or it won't compile.
+ * It first deletes the objects pointed to by ptr_to_type
+ * and then clears (calls m.clear()) the container.
+ * \param m an associative container (map,hash_map) whose elements are being deleted.
+ */
+template <class M>
+void clearMap(M& m){
+ for(typename M::const_iterator it=m.begin();it!=m.end();++it)
+ delete it->second;
+ m.clear();
+}
+
+} // namespace Util
+
+
+#endif // _COLLECTION_UTIL_H_
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/CppAssertHelper.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/CppAssertHelper.h b/zookeeper-client/zookeeper-client-c/tests/CppAssertHelper.h
new file mode 100644
index 0000000..3926f51
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/CppAssertHelper.h
@@ -0,0 +1,37 @@
+/**
+ * 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 CPPASSERTHELPER_H_
+#define CPPASSERTHELPER_H_
+
+#include <cppunit/TestAssert.h>
+
+// make it possible to specify location of the ASSERT call
+#define CPPUNIT_ASSERT_EQUAL_LOC(expected,actual,file,line) \
+ ( CPPUNIT_NS::assertEquals( (expected), \
+ (actual), \
+ CPPUNIT_NS::SourceLine(file,line), \
+ "" ) )
+
+#define CPPUNIT_ASSERT_EQUAL_MESSAGE_LOC(message,expected,actual,file,line) \
+ ( CPPUNIT_NS::assertEquals( (expected), \
+ (actual), \
+ CPPUNIT_NS::SourceLine(file,line), \
+ (message) ) )
+
+#endif /*CPPASSERTHELPER_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/LibCMocks.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/LibCMocks.cc b/zookeeper-client/zookeeper-client-c/tests/LibCMocks.cc
new file mode 100644
index 0000000..5db4553
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/LibCMocks.cc
@@ -0,0 +1,333 @@
+/**
+ * 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 <cstdlib>
+#include <cstdarg>
+#include <iostream>
+#include <stdarg.h>
+
+#include "Util.h"
+#include "LibCMocks.h"
+
+#undef USING_DUMA
+
+using namespace std;
+
+// *****************************************************************************
+// gethostbyname
+
+struct hostent* gethostbyname(const char *name) {
+ if(!Mock_gethostbyname::mock_)
+ return LIBC_SYMBOLS.gethostbyname(name);
+ return Mock_gethostbyname::mock_->call(name);
+}
+
+Mock_gethostbyname* Mock_gethostbyname::mock_=0;
+
+Mock_gethostbyname::~Mock_gethostbyname(){
+ mock_=0;
+ for(unsigned int i=0;i<gethostbynameReturns.size();i++)
+ delete gethostbynameReturns[i];
+}
+
+Mock_gethostbyname::HostEntry& Mock_gethostbyname::addHostEntry(
+ const char* hostName, short addrtype) {
+ gethostbynameReturns.push_back(new HostEntry(hostName, addrtype));
+ return *gethostbynameReturns.back();
+}
+
+hostent* Mock_gethostbyname::call(const char* name) {
+ assert("Must add one or more mock hostent entries first"&&
+ (gethostbynameReturns.size()!=0));
+ return gethostbynameReturns[current++ % gethostbynameReturns.size()];
+}
+
+static char** appendString(char **list,const char* str,int len=0){
+ const int SIZE_INCREMENT=16;
+ if(list==0)
+ list=(char**)LIBC_SYMBOLS.calloc(SIZE_INCREMENT,sizeof(char*));
+ // find the first available slot
+ int count=0;
+ for(char** ptr=list; *ptr!=0; ptr++,count++);
+ if(((count+1)%SIZE_INCREMENT)==0){
+ list=(char**)LIBC_SYMBOLS.realloc(list,(count+1+SIZE_INCREMENT)*sizeof(char*));
+ memset(list+count+1,0,SIZE_INCREMENT*sizeof(char*));
+ }
+ if(len==0){
+ len=strlen(str)+1;
+ }
+ char* ptr=(char*)malloc(len);
+ memcpy(ptr,str,len);
+ list[count]=ptr;
+ return list;
+}
+
+static void freeList(char **list){
+ if(list==0) return;
+ for(char** ptr=list; *ptr!=0; ptr++)
+ LIBC_SYMBOLS.free((void*)*ptr);
+ LIBC_SYMBOLS.free((void*)list);
+}
+
+Mock_gethostbyname::HostEntry::HostEntry(const char* hostName, short addrtype) {
+ h_name=strdup(hostName);
+ h_addrtype=addrtype;
+ if(addrtype==AF_INET)
+ h_length=4;
+ else{
+#ifdef AF_INET6
+ h_length=6; // TODO: not really sure, verify!
+#else
+ assert("AF_INET6 not supported yet"&&false);
+#endif
+ }
+ h_aliases=h_addr_list=0;
+}
+
+Mock_gethostbyname::HostEntry::~HostEntry(){
+ if(h_name) LIBC_SYMBOLS.free((void*)h_name);
+ freeList(h_aliases); h_aliases=0;
+ freeList(h_addr_list); h_addr_list=0;
+}
+
+Mock_gethostbyname::HostEntry& Mock_gethostbyname::HostEntry::addAlias(
+ const char* alias) {
+ h_aliases=appendString(h_aliases,alias);
+ return *this;
+}
+
+Mock_gethostbyname::HostEntry& Mock_gethostbyname::HostEntry::addAddress(
+ const char* addr4) {
+ h_addr_list=appendString(h_addr_list,addr4,4);
+ return *this;
+}
+
+
+// *****************************************************************************
+// calloc
+#ifndef USING_DUMA
+DECLARE_WRAPPER(void*,calloc,(size_t p1, size_t p2)){
+ if(!Mock_calloc::mock_)
+ return CALL_REAL(calloc,(p1,p2));
+ return Mock_calloc::mock_->call(p1,p2);
+}
+#endif
+
+void* Mock_calloc::call(size_t p1, size_t p2){
+#ifndef USING_DUMA
+ if(counter++ ==callsBeforeFailure){
+ counter=0;
+ errno=errnoOnFailure;
+ return 0;
+ }
+ return CALL_REAL(calloc,(p1,p2));
+#else
+ return 0;
+#endif
+}
+
+Mock_calloc* Mock_calloc::mock_=0;
+
+// *****************************************************************************
+// realloc
+
+#ifndef USING_DUMA
+DECLARE_WRAPPER(void*,realloc,(void* p, size_t s)){
+ if(!Mock_realloc::mock_)
+ return LIBC_SYMBOLS.realloc(p,s);
+ return Mock_realloc::mock_->call(p,s);
+}
+#endif
+
+Mock_realloc* Mock_realloc::mock_=0;
+
+void* Mock_realloc::call(void* p, size_t s){
+ if(counter++ ==callsBeforeFailure){
+ counter=0;
+ errno=errnoOnFailure;
+ return 0;
+ }
+ return LIBC_SYMBOLS.realloc(p,s);
+}
+
+// *****************************************************************************
+// random
+RANDOM_RET_TYPE random(){
+ if(!Mock_random::mock_)
+ return LIBC_SYMBOLS.random();
+ return Mock_random::mock_->call();
+}
+
+void srandom(unsigned long seed){
+ if (!Mock_random::mock_)
+ LIBC_SYMBOLS.srandom(seed);
+ else
+ Mock_random::mock_->setSeed(seed);
+}
+
+Mock_random* Mock_random::mock_=0;
+
+int Mock_random::call(){
+ assert("Must specify one or more random integers"&&(randomReturns.size()!=0));
+ return randomReturns[currentIdx++ % randomReturns.size()];
+}
+
+// *****************************************************************************
+// free
+#ifndef USING_DUMA
+DECLARE_WRAPPER(void,free,(void* p)){
+ if(Mock_free_noop::mock_ && !Mock_free_noop::mock_->nested)
+ Mock_free_noop::mock_->call(p);
+ else
+ CALL_REAL(free,(p));
+}
+#endif
+
+void Mock_free_noop::call(void* p){
+ // on cygwin libc++ is linked statically
+ // push_back() may call free(), hence the nesting guards
+ synchronized(mx);
+ nested++;
+ callCounter++;
+ requested.push_back(p);
+ nested--;
+}
+void Mock_free_noop::freeRequested(){
+#ifndef USING_DUMA
+ synchronized(mx);
+ for(unsigned i=0; i<requested.size();i++)
+ CALL_REAL(free,(requested[i]));
+#endif
+}
+
+int Mock_free_noop::getFreeCount(void* p){
+ int cnt=0;
+ synchronized(mx);
+ for(unsigned i=0;i<requested.size();i++)
+ if(requested[i]==p)cnt++;
+ return cnt;
+}
+
+bool Mock_free_noop::isFreed(void* p){
+ synchronized(mx);
+ for(unsigned i=0;i<requested.size();i++)
+ if(requested[i]==p)return true;
+ return false;
+}
+
+Mock_free_noop* Mock_free_noop::mock_=0;
+
+// *****************************************************************************
+// socket
+int socket(int domain, int type, int protocol){
+ if (!Mock_socket::mock_)
+ return LIBC_SYMBOLS.socket(domain,type,protocol);
+ return Mock_socket::mock_->callSocket(domain,type,protocol);
+}
+
+int close(int fd){
+ if (!Mock_socket::mock_)
+ return LIBC_SYMBOLS.close(fd);
+ return Mock_socket::mock_->callClose(fd);
+}
+
+int getsockopt(int s,int level,int optname,void *optval,socklen_t *optlen){
+ if (!Mock_socket::mock_)
+ return LIBC_SYMBOLS.getsockopt(s,level,optname,optval,optlen);
+ return Mock_socket::mock_->callGet(s,level,optname,optval,optlen);
+}
+
+int setsockopt(int s,int level,int optname,const void *optval,socklen_t optlen){
+ if (!Mock_socket::mock_)
+ return LIBC_SYMBOLS.setsockopt(s,level,optname,optval,optlen);
+ return Mock_socket::mock_->callSet(s,level,optname,optval,optlen);
+}
+int connect(int s,const struct sockaddr *addr,socklen_t len){
+ if (!Mock_socket::mock_)
+ return LIBC_SYMBOLS.connect(s,addr,len);
+ return Mock_socket::mock_->callConnect(s,addr,len);
+}
+ssize_t send(int s,const void *buf,size_t len,int flags){
+ if (!Mock_socket::mock_)
+ return LIBC_SYMBOLS.send(s,buf,len,flags);
+ return Mock_socket::mock_->callSend(s,buf,len,flags);
+}
+
+ssize_t recv(int s,void *buf,size_t len,int flags){
+ if (!Mock_socket::mock_)
+ return LIBC_SYMBOLS.recv(s,buf,len,flags);
+ return Mock_socket::mock_->callRecv(s,buf,len,flags);
+}
+
+Mock_socket* Mock_socket::mock_=0;
+
+// *****************************************************************************
+// fcntl
+extern "C" int fcntl(int fd,int cmd,...){
+ va_list va;
+ va_start(va,cmd);
+ void* arg = va_arg(va, void *);
+ va_end (va);
+ if (!Mock_fcntl::mock_)
+ return LIBC_SYMBOLS.fcntl(fd,cmd,arg);
+ return Mock_fcntl::mock_->call(fd,cmd,arg);
+}
+
+Mock_fcntl* Mock_fcntl::mock_=0;
+
+// *****************************************************************************
+// select
+int select(int nfds,fd_set *rfds,fd_set *wfds,fd_set *efds,struct timeval *timeout){
+ if (!Mock_select::mock_)
+ return LIBC_SYMBOLS.select(nfds,rfds,wfds,efds,timeout);
+ return Mock_select::mock_->call(nfds,rfds,wfds,efds,timeout);
+}
+
+Mock_select* Mock_select::mock_=0;
+
+// *****************************************************************************
+// poll
+Mock_poll* Mock_poll::mock_=0;
+int poll(struct pollfd *fds, POLL_NFDS_TYPE nfds, int timeout){
+ if (!Mock_poll::mock_)
+ return LIBC_SYMBOLS.poll(fds,nfds,timeout);
+ return Mock_poll::mock_->call(fds,nfds,timeout);
+
+}
+
+/*
+ * Recent gcc with -O2 and glibc FORTIFY feature may cause our poll
+ * mock to be ignored.
+ */
+#if __USE_FORTIFY_LEVEL > 0
+int __poll_chk (struct pollfd *__fds, nfds_t __nfds, int __timeout,
+ __SIZE_TYPE__ __fdslen) {
+ return poll(__fds, __nfds, __timeout);
+}
+#endif
+
+// *****************************************************************************
+// gettimeofday
+int gettimeofday(struct timeval *tp, GETTIMEOFDAY_ARG2_TYPE tzp){
+ if (!Mock_gettimeofday::mock_)
+ return LIBC_SYMBOLS.gettimeofday(tp,tzp);
+ return Mock_gettimeofday::mock_->call(tp,tzp);
+}
+
+Mock_gettimeofday* Mock_gettimeofday::mock_=0;
+
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/LibCMocks.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/LibCMocks.h b/zookeeper-client/zookeeper-client-c/tests/LibCMocks.h
new file mode 100644
index 0000000..5b07cda
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/LibCMocks.h
@@ -0,0 +1,408 @@
+/**
+ * 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 LIBCMOCKS_H_
+#define LIBCMOCKS_H_
+
+#include <string>
+#include <vector>
+#include <deque>
+
+#include <errno.h>
+#include <string.h>
+
+#include "MocksBase.h"
+#include "LibCSymTable.h"
+#include "ThreadingUtil.h"
+
+// *****************************************************************************
+// gethostbyname
+
+class Mock_gethostbyname: public Mock
+{
+public:
+ struct HostEntry: public hostent {
+ HostEntry(const char* hostName,short addrtype);
+ ~HostEntry();
+ HostEntry& addAlias(const char* alias);
+ HostEntry& addAddress(const char* addr4);
+ };
+
+ Mock_gethostbyname():current(0){mock_=this;}
+ virtual ~Mock_gethostbyname();
+ HostEntry& addHostEntry(const char* hostName,short addrtype=AF_INET);
+ virtual hostent* call(const char* name);
+
+ typedef std::vector<HostEntry*> HostEntryCollection;
+ HostEntryCollection gethostbynameReturns;
+ int current;
+ static Mock_gethostbyname* mock_;
+};
+
+class MockFailed_gethostbyname: public Mock_gethostbyname
+{
+public:
+ MockFailed_gethostbyname():h_errnoReturn(HOST_NOT_FOUND) {}
+
+ int h_errnoReturn;
+ virtual hostent* call(const char* name) {
+ h_errno=h_errnoReturn;
+ return 0;
+ }
+};
+
+// *****************************************************************************
+// calloc
+
+class Mock_calloc: public Mock
+{
+public:
+ Mock_calloc():errnoOnFailure(ENOMEM),callsBeforeFailure(-1),counter(0) {
+ mock_=this;
+ }
+ virtual ~Mock_calloc() {mock_=0;}
+
+ int errnoOnFailure;
+ int callsBeforeFailure;
+ int counter;
+ virtual void* call(size_t p1, size_t p2);
+
+ static Mock_calloc* mock_;
+};
+
+// *****************************************************************************
+// realloc
+
+class Mock_realloc: public Mock
+{
+public:
+ Mock_realloc():errnoOnFailure(ENOMEM),callsBeforeFailure(-1),counter(0) {
+ mock_=this;
+ }
+ virtual ~Mock_realloc() {mock_=0;}
+
+ int errnoOnFailure;
+ int callsBeforeFailure;
+ int counter;
+ virtual void* call(void* p, size_t s);
+
+ static Mock_realloc* mock_;
+};
+
+// *****************************************************************************
+// random
+
+class Mock_random: public Mock
+{
+public:
+ Mock_random():currentIdx(0) {mock_=this;}
+ virtual ~Mock_random() {mock_=0;}
+
+ int currentIdx;
+ std::vector<int> randomReturns;
+ virtual int call();
+ void setSeed(unsigned long){currentIdx=0;}
+
+ static Mock_random* mock_;
+};
+
+// *****************************************************************************
+// no-op free; keeps track of all deallocation requests
+class Mock_free_noop: public Mock
+{
+ Mutex mx;
+ std::vector<void*> requested;
+public:
+ Mock_free_noop():nested(0),callCounter(0){mock_=this;}
+ virtual ~Mock_free_noop(){
+ mock_=0;
+ freeRequested();
+ }
+
+ int nested;
+ int callCounter;
+ virtual void call(void* p);
+ void freeRequested();
+ void disable(){mock_=0;}
+ // returns number of times the pointer was freed
+ int getFreeCount(void*);
+ bool isFreed(void*);
+
+ static Mock_free_noop* mock_;
+};
+
+// *****************************************************************************
+// socket and related system calls
+
+class Mock_socket: public Mock
+{
+public:
+ static const int FD=63;
+ Mock_socket():socketReturns(FD),closeReturns(0),getsocketoptReturns(0),
+ optvalSO_ERROR(0),
+ setsockoptReturns(0),connectReturns(0),connectErrno(0),
+ sendErrno(0),recvErrno(0)
+ {
+ mock_=this;
+ }
+ virtual ~Mock_socket(){mock_=0;}
+
+ int socketReturns;
+ virtual int callSocket(int domain, int type, int protocol){
+ return socketReturns;
+ }
+ int closeReturns;
+ virtual int callClose(int fd){
+ return closeReturns;
+ }
+ int getsocketoptReturns;
+ int optvalSO_ERROR;
+ virtual int callGet(int s,int level,int optname,void *optval,socklen_t *len){
+ if(level==SOL_SOCKET && optname==SO_ERROR){
+ setSO_ERROR(optval,*len);
+ }
+ return getsocketoptReturns;
+ }
+ virtual void setSO_ERROR(void *optval,socklen_t len){
+ memcpy(optval,&optvalSO_ERROR,len);
+ }
+
+ int setsockoptReturns;
+ virtual int callSet(int s,int level,int optname,const void *optval,socklen_t len){
+ return setsockoptReturns;
+ }
+ int connectReturns;
+ int connectErrno;
+ virtual int callConnect(int s,const struct sockaddr *addr,socklen_t len){
+ errno=connectErrno;
+ return connectReturns;
+ }
+
+ virtual void notifyBufferSent(const std::string& buffer){}
+
+ int sendErrno;
+ std::string sendBuffer;
+ virtual ssize_t callSend(int s,const void *buf,size_t len,int flags){
+ if(sendErrno!=0){
+ errno=sendErrno;
+ return -1;
+ }
+ // first call to send() is always the length of the buffer to follow
+ bool sendingLength=sendBuffer.size()==0;
+ // overwrite the length bytes
+ sendBuffer.assign((const char*)buf,len);
+ if(!sendingLength){
+ notifyBufferSent(sendBuffer);
+ sendBuffer.erase();
+ }
+ return len;
+ }
+
+ int recvErrno;
+ std::string recvReturnBuffer;
+ virtual ssize_t callRecv(int s,void *buf,size_t len,int flags){
+ if(recvErrno!=0){
+ errno=recvErrno;
+ return -1;
+ }
+ int k=std::min(len,recvReturnBuffer.length());
+ if(k==0)
+ return 0;
+ memcpy(buf,recvReturnBuffer.data(),k);
+ recvReturnBuffer.erase(0,k);
+ return k;
+ }
+ virtual bool hasMoreRecv() const{
+ return recvReturnBuffer.size()!=0;
+ }
+ static Mock_socket* mock_;
+};
+
+// *****************************************************************************
+// fcntl
+class Mock_fcntl: public Mock
+{
+public:
+ Mock_fcntl():callReturns(0),trapFD(-1){mock_=this;}
+ ~Mock_fcntl(){mock_=0;}
+
+ int callReturns;
+ int trapFD;
+ virtual int call(int fd, int cmd, void* arg){
+ if(trapFD==-1)
+ return LIBC_SYMBOLS.fcntl(fd,cmd,arg);
+ return callReturns;
+ }
+
+ static Mock_fcntl* mock_;
+};
+
+// *****************************************************************************
+// select
+class Mock_select: public Mock
+{
+public:
+ Mock_select(Mock_socket* s,int fd):sock(s),
+ callReturns(0),myFD(fd),timeout(50)
+ {
+ mock_=this;
+ }
+ ~Mock_select(){mock_=0;}
+
+ Mock_socket* sock;
+ int callReturns;
+ int myFD;
+ int timeout; //in millis
+ virtual int call(int nfds,fd_set *rfds,fd_set *wfds,fd_set *efds,struct timeval *tv){
+ bool isWritableRequested=(wfds && FD_ISSET(myFD,wfds));
+ if(rfds) FD_CLR(myFD,rfds);
+ if(wfds) FD_CLR(myFD,wfds);
+ // this timeout is only to prevent a tight loop
+ timeval myTimeout={0,0};
+ if(!isWritableRequested && !isFDReadable()){
+ myTimeout.tv_sec=timeout/1000;
+ myTimeout.tv_usec=(timeout%1000)*1000;
+ }
+ LIBC_SYMBOLS.select(nfds,rfds,wfds,efds,&myTimeout);
+ // myFD is always writable
+ if(isWritableRequested) FD_SET(myFD,wfds);
+ // myFD is only readable if the socket has anything to read
+ if(isFDReadable() && rfds) FD_SET(myFD,rfds);
+ return callReturns;
+ }
+
+ virtual bool isFDReadable() const {
+ return sock->hasMoreRecv();
+ }
+
+ static Mock_select* mock_;
+};
+
+// *****************************************************************************
+// poll
+// the last element of the pollfd array is expected to be test FD
+class Mock_poll: public Mock
+{
+public:
+ Mock_poll(Mock_socket* s,int fd):sock(s),
+ callReturns(1),myFD(fd),timeout(50)
+ {
+ mock_=this;
+ }
+ ~Mock_poll(){mock_=0;}
+
+ Mock_socket* sock;
+ int callReturns;
+ int myFD;
+ int timeout; //in millis
+ virtual int call(struct pollfd *fds, POLL_NFDS_TYPE nfds, int to) {
+ pollfd* myPoll=0;
+ if(fds[nfds-1].fd==myFD)
+ myPoll=&fds[nfds-1];
+ bool isWritableRequested=false;
+ if(myPoll!=0){
+ isWritableRequested=myPoll->events&POLLOUT;
+ nfds--;
+ }
+ LIBC_SYMBOLS.poll(fds,nfds,(!isWritableRequested&&!isFDReadable())?timeout:0);
+ if(myPoll!=0){
+ // myFD is always writable if requested
+ myPoll->revents=isWritableRequested?POLLOUT:0;
+ // myFD is only readable if the socket has anything to read
+ myPoll->revents|=isFDReadable()?POLLIN:0;
+ }
+ return callReturns;
+ }
+
+ virtual bool isFDReadable() const {
+ return sock->hasMoreRecv();
+ }
+
+ static Mock_poll* mock_;
+};
+
+// *****************************************************************************
+// gettimeofday
+class Mock_gettimeofday: public Mock
+{
+public:
+ Mock_gettimeofday(){
+ LIBC_SYMBOLS.gettimeofday(&tv,0);
+ mock_=this;
+ }
+ Mock_gettimeofday(const Mock_gettimeofday& other):tv(other.tv){}
+ Mock_gettimeofday(int32_t sec,int32_t usec){
+ tv.tv_sec=sec;
+ tv.tv_usec=usec;
+ }
+ ~Mock_gettimeofday(){mock_=0;}
+
+ timeval tv;
+ virtual int call(struct timeval *tp, GETTIMEOFDAY_ARG2_TYPE tzp){
+ *tp=tv;
+ return 0;
+ }
+ operator timeval() const{
+ return tv;
+ }
+ // advance secs
+ virtual void tick(int howmuch=1){tv.tv_sec+=howmuch;}
+ // advance milliseconds
+ // can move the clock forward as well as backward by providing a negative
+ // number
+ virtual void millitick(int howmuch=1){
+ int ms=tv.tv_usec/1000+howmuch;
+ tv.tv_sec+=ms/1000;
+ // going backward?
+ if(ms<0){
+ ms=1000-(-ms%1000); //wrap millis around
+ }
+ tv.tv_usec=(ms%1000)*1000;
+ }
+ virtual void tick(const timeval& howmuch){
+ // add milliseconds (discarding microsecond portion)
+ long ms=tv.tv_usec/1000+howmuch.tv_usec/1000;
+ tv.tv_sec+=howmuch.tv_sec+ms/1000;
+ tv.tv_usec=(ms%1000)*1000;
+ }
+ static Mock_gettimeofday* mock_;
+};
+
+// discard microseconds!
+inline bool operator==(const timeval& lhs, const timeval& rhs){
+ return rhs.tv_sec==lhs.tv_sec && rhs.tv_usec/1000==lhs.tv_usec/1000;
+}
+
+// simplistic implementation: no normalization, assume lhs >= rhs,
+// discarding microseconds
+inline timeval operator-(const timeval& lhs, const timeval& rhs){
+ timeval res;
+ res.tv_sec=lhs.tv_sec-rhs.tv_sec;
+ res.tv_usec=(lhs.tv_usec/1000-rhs.tv_usec/1000)*1000;
+ if(res.tv_usec<0){
+ res.tv_sec--;
+ res.tv_usec=1000000+res.tv_usec%1000000; // wrap the millis around
+ }
+ return res;
+}
+
+inline int32_t toMilliseconds(const timeval& tv){
+ return tv.tv_sec*1000+tv.tv_usec/1000;
+}
+
+#endif /*LIBCMOCKS_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/LibCSymTable.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/LibCSymTable.cc b/zookeeper-client/zookeeper-client-c/tests/LibCSymTable.cc
new file mode 100644
index 0000000..5378579
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/LibCSymTable.cc
@@ -0,0 +1,83 @@
+/**
+ * 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 "LibCSymTable.h"
+
+#define LOAD_SYM(sym) \
+ sym=(sym##_sig)dlsym(handle,#sym); \
+ assert("Unable to load "#sym" from libc"&&sym)
+
+
+LibCSymTable& LibCSymTable::instance(){
+ static LibCSymTable tbl;
+ return tbl;
+}
+
+//******************************************************************************
+// preload original libc symbols
+LibCSymTable::LibCSymTable()
+{
+ void* handle=getHandle();
+ LOAD_SYM(gethostbyname);
+ LOAD_SYM(calloc);
+ LOAD_SYM(realloc);
+ LOAD_SYM(free);
+ LOAD_SYM(random);
+ LOAD_SYM(srandom);
+ LOAD_SYM(printf);
+ LOAD_SYM(socket);
+ LOAD_SYM(close);
+ LOAD_SYM(getsockopt);
+ LOAD_SYM(setsockopt);
+ LOAD_SYM(fcntl);
+ LOAD_SYM(connect);
+ LOAD_SYM(send);
+ LOAD_SYM(recv);
+ LOAD_SYM(select);
+ LOAD_SYM(poll);
+ LOAD_SYM(gettimeofday);
+#ifdef THREADED
+ LOAD_SYM(pthread_create);
+ LOAD_SYM(pthread_detach);
+ LOAD_SYM(pthread_cond_broadcast);
+ LOAD_SYM(pthread_cond_destroy);
+ LOAD_SYM(pthread_cond_init);
+ LOAD_SYM(pthread_cond_signal);
+ LOAD_SYM(pthread_cond_timedwait);
+ LOAD_SYM(pthread_cond_wait);
+ LOAD_SYM(pthread_join);
+ LOAD_SYM(pthread_mutex_destroy);
+ LOAD_SYM(pthread_mutex_init);
+ LOAD_SYM(pthread_mutex_lock);
+ LOAD_SYM(pthread_mutex_trylock);
+ LOAD_SYM(pthread_mutex_unlock);
+#endif
+}
+
+void* LibCSymTable::getHandle(){
+ static void* handle=0;
+ if(!handle){
+#ifdef __CYGWIN__
+ handle=dlopen("cygwin1.dll",RTLD_LAZY);
+ assert("Unable to dlopen global sym table"&&handle);
+#else
+ handle=RTLD_NEXT;
+#endif
+ }
+ return handle;
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/LibCSymTable.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/LibCSymTable.h b/zookeeper-client/zookeeper-client-c/tests/LibCSymTable.h
new file mode 100644
index 0000000..2f7e0c2
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/LibCSymTable.h
@@ -0,0 +1,107 @@
+/**
+ * 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 LIBCSYMTABLE_H_
+#define LIBCSYMTABLE_H_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stddef.h>
+#include <dlfcn.h>
+#include <cassert>
+#include <poll.h>
+
+#ifdef THREADED
+#include <pthread.h>
+#endif
+
+#include "config.h"
+
+// TODO: move all these macros to config.h (generated by autoconf)
+#ifdef __CYGWIN__
+#if (CYGWIN_VERSION_DLL_MAJOR < 1007)
+#define RANDOM_RET_TYPE int
+#else
+#define RANDOM_RET_TYPE long int
+#endif
+#define GETTIMEOFDAY_ARG2_TYPE void*
+#else
+#define RANDOM_RET_TYPE long int
+#define GETTIMEOFDAY_ARG2_TYPE struct timezone*
+#endif
+
+#define DECLARE_SYM(ret,sym,sig) \
+ typedef ret (*sym##_sig)sig; \
+ static sym##_sig preload_##sym () { \
+ static sym##_sig ptr=0;\
+ if(!ptr){ void* h=getHandle(); ptr=(sym##_sig)dlsym(h,#sym); } \
+ assert("Unable to load "#sym" from libc"&&ptr); \
+ return ptr; \
+ } \
+ sym##_sig sym
+
+#define LIBC_SYMBOLS LibCSymTable::instance()
+
+//******************************************************************************
+// preload original libc symbols
+struct LibCSymTable
+{
+ DECLARE_SYM(hostent*,gethostbyname,(const char*));
+ DECLARE_SYM(void*,calloc,(size_t, size_t));
+ DECLARE_SYM(void*,realloc,(void*, size_t));
+ DECLARE_SYM(void,free,(void*));
+ DECLARE_SYM(RANDOM_RET_TYPE,random,(void));
+ DECLARE_SYM(void,srandom,(unsigned long));
+ DECLARE_SYM(int,printf,(const char*, ...));
+ DECLARE_SYM(int,socket,(int,int,int));
+ DECLARE_SYM(int,close,(int));
+ DECLARE_SYM(int,getsockopt,(int,int,int,void*,socklen_t*));
+ DECLARE_SYM(int,setsockopt,(int,int,int,const void*,socklen_t));
+ DECLARE_SYM(int,fcntl,(int,int,...));
+ DECLARE_SYM(int,connect,(int,const struct sockaddr*,socklen_t));
+ DECLARE_SYM(ssize_t,send,(int,const void*,size_t,int));
+ DECLARE_SYM(ssize_t,recv,(int,const void*,size_t,int));
+ DECLARE_SYM(int,select,(int,fd_set*,fd_set*,fd_set*,struct timeval*));
+ DECLARE_SYM(int,poll,(struct pollfd*,POLL_NFDS_TYPE,int));
+ DECLARE_SYM(int,gettimeofday,(struct timeval*,GETTIMEOFDAY_ARG2_TYPE));
+#ifdef THREADED
+ DECLARE_SYM(int,pthread_create,(pthread_t *, const pthread_attr_t *,
+ void *(*)(void *), void *));
+ DECLARE_SYM(int,pthread_detach,(pthread_t));
+ DECLARE_SYM(int,pthread_cond_broadcast,(pthread_cond_t *));
+ DECLARE_SYM(int,pthread_cond_destroy,(pthread_cond_t *));
+ DECLARE_SYM(int,pthread_cond_init,(pthread_cond_t *, const pthread_condattr_t *));
+ DECLARE_SYM(int,pthread_cond_signal,(pthread_cond_t *));
+ DECLARE_SYM(int,pthread_cond_timedwait,(pthread_cond_t *,
+ pthread_mutex_t *, const struct timespec *));
+ DECLARE_SYM(int,pthread_cond_wait,(pthread_cond_t *, pthread_mutex_t *));
+ DECLARE_SYM(int,pthread_join,(pthread_t, void **));
+ DECLARE_SYM(int,pthread_mutex_destroy,(pthread_mutex_t *));
+ DECLARE_SYM(int,pthread_mutex_init,(pthread_mutex_t *, const pthread_mutexattr_t *));
+ DECLARE_SYM(int,pthread_mutex_lock,(pthread_mutex_t *));
+ DECLARE_SYM(int,pthread_mutex_trylock,(pthread_mutex_t *));
+ DECLARE_SYM(int,pthread_mutex_unlock,(pthread_mutex_t *));
+#endif
+ LibCSymTable();
+
+ static void* getHandle();
+ static LibCSymTable& instance();
+};
+
+#endif /*LIBCSYMTABLE_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/MocksBase.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/MocksBase.cc b/zookeeper-client/zookeeper-client-c/tests/MocksBase.cc
new file mode 100644
index 0000000..60b2c75
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/MocksBase.cc
@@ -0,0 +1,36 @@
+/**
+ * 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 <cstdlib>
+#include <new>
+
+#include "MocksBase.h"
+#include "LibCSymTable.h"
+
+// *****************************************************************************
+// Mock base
+void* Mock::operator new(std::size_t s){
+ void* p=malloc(s);
+ if(!p)
+ throw std::bad_alloc();
+ return p;
+}
+
+void Mock::operator delete(void* p){
+ LIBC_SYMBOLS.free(p);
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/MocksBase.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/MocksBase.h b/zookeeper-client/zookeeper-client-c/tests/MocksBase.h
new file mode 100644
index 0000000..5b54251
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/MocksBase.h
@@ -0,0 +1,36 @@
+/**
+ * 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 MOCKSBASE_H_
+#define MOCKSBASE_H_
+
+#include <cstddef>
+
+// *****************************************************************************
+// Mock base
+
+class Mock
+{
+public:
+ virtual ~Mock(){}
+
+ static void* operator new(std::size_t s);
+ static void operator delete(void* p);
+};
+
+#endif /*MOCKSBASE_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/PthreadMocks.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/PthreadMocks.cc b/zookeeper-client/zookeeper-client-c/tests/PthreadMocks.cc
new file mode 100644
index 0000000..490cebf
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/PthreadMocks.cc
@@ -0,0 +1,106 @@
+/**
+ * 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 "PthreadMocks.h"
+
+MockPthreadsBase* MockPthreadsBase::mock_=0;
+
+#undef USING_DUMA
+
+#ifndef USING_DUMA
+int pthread_cond_broadcast (pthread_cond_t *c){
+ if(!MockPthreadsBase::mock_)
+ return LIBC_SYMBOLS.pthread_cond_broadcast(c);
+ return MockPthreadsBase::mock_->pthread_cond_broadcast(c);
+}
+int pthread_cond_destroy (pthread_cond_t *c){
+ if(!MockPthreadsBase::mock_)
+ return LIBC_SYMBOLS.pthread_cond_destroy(c);
+ return MockPthreadsBase::mock_->pthread_cond_destroy(c);
+}
+int pthread_cond_init (pthread_cond_t *c, const pthread_condattr_t *a){
+ if(!MockPthreadsBase::mock_)
+ return LIBC_SYMBOLS.pthread_cond_init(c,a);
+ return MockPthreadsBase::mock_->pthread_cond_init(c,a);
+}
+int pthread_cond_signal (pthread_cond_t *c){
+ if(!MockPthreadsBase::mock_)
+ return LIBC_SYMBOLS.pthread_cond_signal(c);
+ return MockPthreadsBase::mock_->pthread_cond_signal(c);
+}
+int pthread_cond_timedwait (pthread_cond_t *c,
+ pthread_mutex_t *m, const struct timespec *t){
+ if(!MockPthreadsBase::mock_)
+ return LIBC_SYMBOLS.pthread_cond_timedwait(c,m,t);
+ return MockPthreadsBase::mock_->pthread_cond_timedwait(c,m,t);
+}
+int pthread_cond_wait (pthread_cond_t *c, pthread_mutex_t *m){
+ if(!MockPthreadsBase::mock_)
+ return LIBC_SYMBOLS.pthread_cond_wait(c,m);
+ return MockPthreadsBase::mock_->pthread_cond_wait(c,m);
+}
+int pthread_create (pthread_t *t, const pthread_attr_t *a,
+ void *(*f)(void *), void *d){
+ if(!MockPthreadsBase::mock_)
+ return LIBC_SYMBOLS.pthread_create(t,a,f,d);
+ return MockPthreadsBase::mock_->pthread_create(t,a,f,d);
+}
+int pthread_detach(pthread_t t){
+ if(!MockPthreadsBase::mock_)
+ return LIBC_SYMBOLS.pthread_detach(t);
+ return MockPthreadsBase::mock_->pthread_detach(t);
+}
+int pthread_join (pthread_t t, void **r){
+ if(!MockPthreadsBase::mock_)
+ return LIBC_SYMBOLS.pthread_join(t,r);
+ return MockPthreadsBase::mock_->pthread_join(t,r);
+}
+int pthread_mutex_destroy (pthread_mutex_t *m){
+ if(!MockPthreadsBase::mock_)
+ return LIBC_SYMBOLS.pthread_mutex_destroy(m);
+ return MockPthreadsBase::mock_->pthread_mutex_destroy(m);
+}
+int pthread_mutex_init (pthread_mutex_t *m, const pthread_mutexattr_t *a){
+ if(!MockPthreadsBase::mock_)
+ return LIBC_SYMBOLS.pthread_mutex_init(m,a);
+ return MockPthreadsBase::mock_->pthread_mutex_init(m,a);
+}
+
+DECLARE_WRAPPER(int,pthread_mutex_lock,(pthread_mutex_t *m)){
+ if(!MockPthreadsBase::mock_)
+ return CALL_REAL(pthread_mutex_lock,(m));
+ return MockPthreadsBase::mock_->pthread_mutex_lock(m);
+}
+
+int pthread_mutex_trylock (pthread_mutex_t *m){
+ if(!MockPthreadsBase::mock_)
+ return LIBC_SYMBOLS.pthread_mutex_trylock(m);
+ return MockPthreadsBase::mock_->pthread_mutex_trylock(m);
+}
+
+DECLARE_WRAPPER(int,pthread_mutex_unlock,(pthread_mutex_t *m)){
+ if(!MockPthreadsBase::mock_)
+ return CALL_REAL(pthread_mutex_unlock,(m));
+ return MockPthreadsBase::mock_->pthread_mutex_unlock(m);
+}
+#endif
+
+CheckedPthread::ThreadMap CheckedPthread::tmap_;
+CheckedPthread::MutexMap CheckedPthread::mmap_;
+CheckedPthread::CVMap CheckedPthread::cvmap_;
+Mutex CheckedPthread::mx;
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/PthreadMocks.h
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/PthreadMocks.h b/zookeeper-client/zookeeper-client-c/tests/PthreadMocks.h
new file mode 100644
index 0000000..8db8815
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/PthreadMocks.h
@@ -0,0 +1,449 @@
+/**
+ * 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 PTHREADMOCKS_H_
+#define PTHREADMOCKS_H_
+
+#include <pthread.h>
+#include <string.h>
+#include <errno.h>
+
+#include "src/zk_adaptor.h"
+
+#include "Util.h"
+#include "MocksBase.h"
+#include "LibCSymTable.h"
+#include "ThreadingUtil.h"
+
+// an ABC for pthreads
+class MockPthreadsBase: public Mock
+{
+public:
+ MockPthreadsBase(){mock_=this;}
+ virtual ~MockPthreadsBase(){mock_=0;}
+
+ virtual int pthread_create(pthread_t * t, const pthread_attr_t *a,
+ void *(*f)(void *), void *d) =0;
+ virtual int pthread_join(pthread_t t, void ** r) =0;
+ virtual int pthread_detach(pthread_t t) =0;
+ virtual int pthread_cond_broadcast(pthread_cond_t *c) =0;
+ virtual int pthread_cond_destroy(pthread_cond_t *c) =0;
+ virtual int pthread_cond_init(pthread_cond_t *c, const pthread_condattr_t *a) =0;
+ virtual int pthread_cond_signal(pthread_cond_t *c) =0;
+ virtual int pthread_cond_timedwait(pthread_cond_t *c,
+ pthread_mutex_t *m, const struct timespec *t) =0;
+ virtual int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m) =0;
+ virtual int pthread_mutex_destroy(pthread_mutex_t *m) =0;
+ virtual int pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a) =0;
+ virtual int pthread_mutex_lock(pthread_mutex_t *m) =0;
+ virtual int pthread_mutex_trylock(pthread_mutex_t *m) =0;
+ virtual int pthread_mutex_unlock(pthread_mutex_t *m) =0;
+
+ static MockPthreadsBase* mock_;
+};
+
+// all pthread functions simply return an error code
+// and increment their invocation counter. No actual threads are spawned.
+class MockPthreadsNull: public MockPthreadsBase
+{
+public:
+ MockPthreadsNull():
+ pthread_createReturns(0),pthread_createCounter(0),
+ pthread_joinReturns(0),pthread_joinCounter(0),pthread_joinResultReturn(0),
+ pthread_detachReturns(0),pthread_detachCounter(0),
+ pthread_cond_broadcastReturns(0),pthread_cond_broadcastCounter(0),
+ pthread_cond_destroyReturns(0),pthread_cond_destroyCounter(0),
+ pthread_cond_initReturns(0),pthread_cond_initCounter(0),
+ pthread_cond_signalReturns(0),pthread_cond_signalCounter(0),
+ pthread_cond_timedwaitReturns(0),pthread_cond_timedwaitCounter(0),
+ pthread_cond_waitReturns(0),pthread_cond_waitCounter(0),
+ pthread_mutex_destroyReturns(0),pthread_mutex_destroyCounter(0),
+ pthread_mutex_initReturns(0),pthread_mutex_initCounter(0),
+ pthread_mutex_lockReturns(0),pthread_mutex_lockCounter(0),
+ pthread_mutex_trylockReturns(0),pthread_mutex_trylockCounter(0),
+ pthread_mutex_unlockReturns(0),pthread_mutex_unlockCounter(0)
+ {
+ memset(threads,0,sizeof(threads));
+ }
+
+ short threads[512];
+
+ int pthread_createReturns;
+ int pthread_createCounter;
+ virtual int pthread_create(pthread_t * t, const pthread_attr_t *a,
+ void *(*f)(void *), void *d){
+ char* p=(char*)&threads[pthread_createCounter++];
+ p[0]='i'; // mark as created
+ *t=(pthread_t)p;
+ return pthread_createReturns;
+ }
+ int pthread_joinReturns;
+ int pthread_joinCounter;
+ void* pthread_joinResultReturn;
+ virtual int pthread_join(pthread_t t, void ** r){
+ pthread_joinCounter++;
+ if(r!=0)
+ *r=pthread_joinResultReturn;
+ char* p=(char*)t;
+ p[0]='x';p[1]+=1;
+ return pthread_joinReturns;
+ }
+ int pthread_detachReturns;
+ int pthread_detachCounter;
+ virtual int pthread_detach(pthread_t t){
+ pthread_detachCounter++;
+ char* p=(char*)t;
+ p[0]='x';p[1]+=1;
+ return pthread_detachReturns;
+ }
+
+ template<class T>
+ static bool isInitialized(const T& t){
+ return ((char*)t)[0]=='i';
+ }
+ template<class T>
+ static bool isDestroyed(const T& t){
+ return ((char*)t)[0]=='x';
+ }
+ template<class T>
+ static int getDestroyCounter(const T& t){
+ return ((char*)t)[1];
+ }
+ template<class T>
+ static int getInvalidAccessCounter(const T& t){
+ return ((char*)t)[2];
+ }
+ int pthread_cond_broadcastReturns;
+ int pthread_cond_broadcastCounter;
+ virtual int pthread_cond_broadcast(pthread_cond_t *c){
+ pthread_cond_broadcastCounter++;
+ if(isDestroyed(c))((char*)c)[2]++;
+ return pthread_cond_broadcastReturns;
+ }
+ int pthread_cond_destroyReturns;
+ int pthread_cond_destroyCounter;
+ virtual int pthread_cond_destroy(pthread_cond_t *c){
+ pthread_cond_destroyCounter++;
+ char* p=(char*)c;
+ p[0]='x';p[1]+=1;
+ return pthread_cond_destroyReturns;
+ }
+ int pthread_cond_initReturns;
+ int pthread_cond_initCounter;
+ virtual int pthread_cond_init(pthread_cond_t *c, const pthread_condattr_t *a){
+ pthread_cond_initCounter++;
+ char* p=(char*)c;
+ p[0]='i'; // mark as created
+ p[1]=0; // destruction counter
+ p[2]=0; // access after destruction counter
+ return pthread_cond_initReturns;
+ }
+ int pthread_cond_signalReturns;
+ int pthread_cond_signalCounter;
+ virtual int pthread_cond_signal(pthread_cond_t *c){
+ pthread_cond_signalCounter++;
+ if(isDestroyed(c))((char*)c)[2]++;
+ return pthread_cond_signalReturns;
+ }
+ int pthread_cond_timedwaitReturns;
+ int pthread_cond_timedwaitCounter;
+ virtual int pthread_cond_timedwait(pthread_cond_t *c,
+ pthread_mutex_t *m, const struct timespec *t){
+ pthread_cond_timedwaitCounter++;
+ if(isDestroyed(c))((char*)c)[2]++;
+ return pthread_cond_timedwaitReturns;
+ }
+ int pthread_cond_waitReturns;
+ int pthread_cond_waitCounter;
+ virtual int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m){
+ pthread_cond_waitCounter++;
+ if(isDestroyed(c))((char*)c)[2]++;
+ return pthread_cond_waitReturns;
+ }
+ int pthread_mutex_destroyReturns;
+ int pthread_mutex_destroyCounter;
+ virtual int pthread_mutex_destroy(pthread_mutex_t *m){
+ pthread_mutex_destroyCounter++;
+ char* p=(char*)m;
+ p[0]='x';p[1]+=1;
+ return pthread_mutex_destroyReturns;
+ }
+ int pthread_mutex_initReturns;
+ int pthread_mutex_initCounter;
+ virtual int pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a){
+ pthread_mutex_initCounter++;
+ char* p=(char*)m;
+ p[0]='i'; // mark as created
+ p[1]=0; // destruction counter
+ p[2]=0; // access after destruction counter
+ return pthread_mutex_initReturns;
+ }
+ int pthread_mutex_lockReturns;
+ int pthread_mutex_lockCounter;
+ virtual int pthread_mutex_lock(pthread_mutex_t *m){
+ pthread_mutex_lockCounter++;
+ if(isDestroyed(m))((char*)m)[2]++;
+ return pthread_mutex_lockReturns;
+ }
+ int pthread_mutex_trylockReturns;
+ int pthread_mutex_trylockCounter;
+ virtual int pthread_mutex_trylock(pthread_mutex_t *m){
+ pthread_mutex_trylockCounter++;
+ if(isDestroyed(m))((char*)m)[2]++;
+ return pthread_mutex_trylockReturns;
+ }
+ int pthread_mutex_unlockReturns;
+ int pthread_mutex_unlockCounter;
+ virtual int pthread_mutex_unlock(pthread_mutex_t *m){
+ pthread_mutex_unlockCounter++;
+ if(isDestroyed(m))((char*)m)[2]++;
+ return pthread_mutex_unlockReturns;
+ }
+};
+
+// simulates the way zookeeper threads make use of api_prolog/epilog and
+//
+class MockPthreadZKNull: public MockPthreadsNull
+{
+ typedef std::map<pthread_t,zhandle_t*> Map;
+ Map map_;
+public:
+ virtual int pthread_create(pthread_t * t, const pthread_attr_t *a,
+ void *(*f)(void *), void *d){
+ int ret=MockPthreadsNull::pthread_create(t,a,f,d);
+ zhandle_t* zh=(zhandle_t*)d;
+ adaptor_threads* ad=(adaptor_threads*)zh->adaptor_priv;
+ api_prolog(zh);
+ ad->threadsToWait--;
+ putValue(map_,*t,zh);
+ return ret;
+ }
+ virtual int pthread_join(pthread_t t, void ** r){
+ zhandle_t* zh=0;
+ if(getValue(map_,t,zh))
+ api_epilog(zh,0);
+ return MockPthreadsNull::pthread_join(t,r);
+ }
+};
+
+struct ThreadInfo{
+ typedef enum {RUNNING,TERMINATED} ThreadState;
+
+ ThreadInfo():
+ destructionCounter_(0),invalidAccessCounter_(0),state_(RUNNING)
+ {
+ }
+
+ ThreadInfo& incDestroyed() {
+ destructionCounter_++;
+ return *this;
+ }
+ ThreadInfo& incInvalidAccess(){
+ invalidAccessCounter_++;
+ return *this;
+ }
+ ThreadInfo& setTerminated(){
+ state_=TERMINATED;
+ return *this;
+ }
+ int destructionCounter_;
+ int invalidAccessCounter_;
+ ThreadState state_;
+};
+
+class CheckedPthread: public MockPthreadsBase
+{
+ // first => destruction counter
+ // second => invalid access counter
+ //typedef std::pair<int,int> Entry;
+ typedef ThreadInfo Entry;
+ typedef std::map<pthread_t,Entry> ThreadMap;
+ static ThreadMap tmap_;
+ static ThreadMap& getMap(const TypeOp<pthread_t>::BareT&){return tmap_;}
+ typedef std::map<pthread_mutex_t*,Entry> MutexMap;
+ static MutexMap mmap_;
+ static MutexMap& getMap(const TypeOp<pthread_mutex_t>::BareT&){return mmap_;}
+ typedef std::map<pthread_cond_t*,Entry> CVMap;
+ static CVMap cvmap_;
+ static CVMap& getMap(const TypeOp<pthread_cond_t>::BareT&){return cvmap_;}
+
+ static Mutex mx;
+
+ template<class T>
+ static void markDestroyed(T& t){
+ typedef typename TypeOp<T>::BareT Type;
+ Entry e;
+ synchronized(mx);
+ if(getValue(getMap(Type()),t,e)){
+ putValue(getMap(Type()),t,Entry(e).incDestroyed());
+ }else{
+ putValue(getMap(Type()),t,Entry().incDestroyed());
+ }
+ }
+ template<class T>
+ static void markCreated(T& t){
+ typedef typename TypeOp<T>::BareT Type;
+ Entry e;
+ synchronized(mx);
+ if(!getValue(getMap(Type()),t,e))
+ putValue(getMap(Type()),t,Entry());
+ }
+ template<class T>
+ static void checkAccessed(T& t){
+ typedef typename TypeOp<T>::BareT Type;
+ Entry e;
+ synchronized(mx);
+ if(getValue(getMap(Type()),t,e) && e.destructionCounter_>0)
+ putValue(getMap(Type()),t,Entry(e).incInvalidAccess());
+ }
+ static void setTerminated(pthread_t t){
+ Entry e;
+ synchronized(mx);
+ if(getValue(tmap_,t,e))
+ putValue(tmap_,t,Entry(e).setTerminated());
+ }
+public:
+ bool verbose;
+ CheckedPthread():verbose(false){
+ tmap_.clear();
+ mmap_.clear();
+ cvmap_.clear();
+ mx.release();
+ }
+ template <class T>
+ static bool isInitialized(const T& t){
+ typedef typename TypeOp<T>::BareT Type;
+ Entry e;
+ synchronized(mx);
+ return getValue(getMap(Type()),t,e) && e.destructionCounter_==0;
+ }
+ template <class T>
+ static bool isDestroyed(const T& t){
+ typedef typename TypeOp<T>::BareT Type;
+ Entry e;
+ synchronized(mx);
+ return getValue(getMap(Type()),t,e) && e.destructionCounter_>0;
+ }
+ static bool isTerminated(pthread_t t){
+ Entry e;
+ synchronized(mx);
+ return getValue(tmap_,t,e) && e.state_==ThreadInfo::TERMINATED;
+ }
+ template <class T>
+ static int getDestroyCounter(const T& t){
+ typedef typename TypeOp<T>::BareT Type;
+ Entry e;
+ synchronized(mx);
+ return getValue(getMap(Type()),t,e)?e.destructionCounter_:-1;
+ }
+ template<class T>
+ static int getInvalidAccessCounter(const T& t){
+ typedef typename TypeOp<T>::BareT Type;
+ Entry e;
+ synchronized(mx);
+ return getValue(getMap(Type()),t,e)?e.invalidAccessCounter_:-1;
+ }
+
+ struct ThreadContext{
+ typedef void *(*ThreadFunc)(void *);
+
+ ThreadContext(ThreadFunc func,void* param):func_(func),param_(param){}
+ ThreadFunc func_;
+ void* param_;
+ };
+ static void* threadFuncWrapper(void* v){
+ ThreadContext* ctx=(ThreadContext*)v;
+ pthread_t t=pthread_self();
+ markCreated(t);
+ void* res=ctx->func_(ctx->param_);
+ setTerminated(pthread_self());
+ delete ctx;
+ return res;
+ }
+ virtual int pthread_create(pthread_t * t, const pthread_attr_t *a,
+ void *(*f)(void *), void *d)
+ {
+ int ret=LIBC_SYMBOLS.pthread_create(t,a,threadFuncWrapper,
+ new ThreadContext(f,d));
+ if(verbose)
+ TEST_TRACE(("thread created %p",*t));
+ return ret;
+ }
+ virtual int pthread_join(pthread_t t, void ** r){
+ if(verbose) TEST_TRACE(("thread joined %p",t));
+ int ret=LIBC_SYMBOLS.pthread_join(t,r);
+ if(ret==0)
+ markDestroyed(t);
+ return ret;
+ }
+ virtual int pthread_detach(pthread_t t){
+ if(verbose) TEST_TRACE(("thread detached %p",t));
+ int ret=LIBC_SYMBOLS.pthread_detach(t);
+ if(ret==0)
+ markDestroyed(t);
+ return ret;
+ }
+ virtual int pthread_cond_broadcast(pthread_cond_t *c){
+ checkAccessed(c);
+ return LIBC_SYMBOLS.pthread_cond_broadcast(c);
+ }
+ virtual int pthread_cond_destroy(pthread_cond_t *c){
+ markDestroyed(c);
+ return LIBC_SYMBOLS.pthread_cond_destroy(c);
+ }
+ virtual int pthread_cond_init(pthread_cond_t *c, const pthread_condattr_t *a){
+ markCreated(c);
+ return LIBC_SYMBOLS.pthread_cond_init(c,a);
+ }
+ virtual int pthread_cond_signal(pthread_cond_t *c){
+ checkAccessed(c);
+ return LIBC_SYMBOLS.pthread_cond_signal(c);
+ }
+ virtual int pthread_cond_timedwait(pthread_cond_t *c,
+ pthread_mutex_t *m, const struct timespec *t){
+ checkAccessed(c);
+ return LIBC_SYMBOLS.pthread_cond_timedwait(c,m,t);
+ }
+ virtual int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m){
+ checkAccessed(c);
+ return LIBC_SYMBOLS.pthread_cond_wait(c,m);
+ }
+ virtual int pthread_mutex_destroy(pthread_mutex_t *m){
+ markDestroyed(m);
+ return LIBC_SYMBOLS.pthread_mutex_destroy(m);
+ }
+ virtual int pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a){
+ markCreated(m);
+ return LIBC_SYMBOLS.pthread_mutex_init(m,a);
+ }
+ virtual int pthread_mutex_lock(pthread_mutex_t *m){
+ checkAccessed(m);
+ return LIBC_SYMBOLS.pthread_mutex_lock(m);
+ }
+ virtual int pthread_mutex_trylock(pthread_mutex_t *m){
+ checkAccessed(m);
+ return LIBC_SYMBOLS.pthread_mutex_trylock(m);
+ }
+ virtual int pthread_mutex_unlock(pthread_mutex_t *m){
+ checkAccessed(m);
+ return LIBC_SYMBOLS.pthread_mutex_unlock(m);
+ }
+};
+
+#endif /*PTHREADMOCKS_H_*/
+
[02/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/TestOperations.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/TestOperations.cc b/zookeeper-client/zookeeper-client-c/tests/TestOperations.cc
new file mode 100644
index 0000000..27d9270
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/TestOperations.cc
@@ -0,0 +1,710 @@
+/**
+ * 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 <cppunit/extensions/HelperMacros.h>
+#include "CppAssertHelper.h"
+
+#include "ZKMocks.h"
+#include <proto.h>
+
+using namespace std;
+
+class Zookeeper_operations : public CPPUNIT_NS::TestFixture
+{
+ CPPUNIT_TEST_SUITE(Zookeeper_operations);
+#ifndef THREADED
+ CPPUNIT_TEST(testPing);
+ CPPUNIT_TEST(testUnsolicitedPing);
+ CPPUNIT_TEST(testTimeoutCausedByWatches1);
+ CPPUNIT_TEST(testTimeoutCausedByWatches2);
+#else
+ CPPUNIT_TEST(testAsyncWatcher1);
+ CPPUNIT_TEST(testAsyncGetOperation);
+#endif
+ CPPUNIT_TEST(testOperationsAndDisconnectConcurrently1);
+ CPPUNIT_TEST(testOperationsAndDisconnectConcurrently2);
+ CPPUNIT_TEST(testConcurrentOperations1);
+ CPPUNIT_TEST_SUITE_END();
+ zhandle_t *zh;
+ FILE *logfile;
+
+ static void watcher(zhandle_t *, int, int, const char *,void*){}
+public:
+ Zookeeper_operations() {
+ logfile = openlogfile("Zookeeper_operations");
+ }
+
+ ~Zookeeper_operations() {
+ if (logfile) {
+ fflush(logfile);
+ fclose(logfile);
+ logfile = 0;
+ }
+ }
+
+ void setUp()
+ {
+ zoo_set_log_stream(logfile);
+
+ zoo_deterministic_conn_order(0);
+ zh=0;
+ }
+
+ void tearDown()
+ {
+ zookeeper_close(zh);
+ }
+
+ class AsyncGetOperationCompletion: public AsyncCompletion{
+ public:
+ AsyncGetOperationCompletion():called_(false),rc_(ZAPIERROR){}
+ virtual void dataCompl(int rc, const char *value, int len, const Stat *stat){
+ synchronized(mx_);
+ called_=true;
+ rc_=rc;
+ value_.erase();
+ if(rc!=ZOK) return;
+ value_.assign(value,len);
+ if(stat)
+ stat_=*stat;
+ }
+ bool operator()()const{
+ synchronized(mx_);
+ return called_;
+ }
+ mutable Mutex mx_;
+ bool called_;
+ int rc_;
+ string value_;
+ NodeStat stat_;
+ };
+#ifndef THREADED
+ // send two get data requests; verify that the corresponding completions called
+ void testConcurrentOperations1()
+ {
+ Mock_gettimeofday timeMock;
+ ZookeeperServer zkServer;
+ // must call zookeeper_close() while all the mocks are in scope
+ CloseFinally guard(&zh);
+
+ zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // simulate connected state
+ forceConnected(zh);
+
+ int fd=0;
+ int interest=0;
+ timeval tv;
+ // first operation
+ AsyncGetOperationCompletion res1;
+ zkServer.addOperationResponse(new ZooGetResponse("1",1));
+ int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // second operation
+ AsyncGetOperationCompletion res2;
+ zkServer.addOperationResponse(new ZooGetResponse("2",1));
+ rc=zoo_aget(zh,"/x/y/2",0,asyncCompletion,&res2);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // process the send queue
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ while((rc=zookeeper_process(zh,interest))==ZOK) {
+ millisleep(100);
+ //printf("%d\n", rc);
+ }
+ //printf("RC = %d", rc);
+ CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
+
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,res1.rc_);
+ CPPUNIT_ASSERT_EQUAL(string("1"),res1.value_);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,res2.rc_);
+ CPPUNIT_ASSERT_EQUAL(string("2"),res2.value_);
+ }
+ // send two getData requests and disconnect while the second request is
+ // outstanding;
+ // verify the completions are called
+ void testOperationsAndDisconnectConcurrently1()
+ {
+ Mock_gettimeofday timeMock;
+ ZookeeperServer zkServer;
+ // must call zookeeper_close() while all the mocks are in scope
+ CloseFinally guard(&zh);
+
+ zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // simulate connected state
+ forceConnected(zh);
+
+ int fd=0;
+ int interest=0;
+ timeval tv;
+ // first operation
+ AsyncGetOperationCompletion res1;
+ zkServer.addOperationResponse(new ZooGetResponse("1",1));
+ int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // second operation
+ AsyncGetOperationCompletion res2;
+ zkServer.addOperationResponse(new ZooGetResponse("2",1));
+ rc=zoo_aget(zh,"/x/y/2",0,asyncCompletion,&res2);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // process the send queue
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // simulate a disconnect
+ zkServer.setConnectionLost();
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZCONNECTIONLOSS,rc);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,res1.rc_);
+ CPPUNIT_ASSERT_EQUAL(string("1"),res1.value_);
+ CPPUNIT_ASSERT_EQUAL((int)ZCONNECTIONLOSS,res2.rc_);
+ CPPUNIT_ASSERT_EQUAL(string(""),res2.value_);
+ }
+ // send two getData requests and simulate timeout while the both request
+ // are pending;
+ // verify the completions are called
+ void testOperationsAndDisconnectConcurrently2()
+ {
+ Mock_gettimeofday timeMock;
+ ZookeeperServer zkServer;
+ // must call zookeeper_close() while all the mocks are in scope
+ CloseFinally guard(&zh);
+
+ zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // simulate connected state
+ forceConnected(zh);
+
+ int fd=0;
+ int interest=0;
+ timeval tv;
+ // first operation
+ AsyncGetOperationCompletion res1;
+ zkServer.addOperationResponse(new ZooGetResponse("1",1));
+ int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // second operation
+ AsyncGetOperationCompletion res2;
+ zkServer.addOperationResponse(new ZooGetResponse("2",1));
+ rc=zoo_aget(zh,"/x/y/2",0,asyncCompletion,&res2);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // simulate timeout
+ timeMock.tick(+10); // advance system time by 10 secs
+ // the next call to zookeeper_interest should return ZOPERATIONTIMEOUT
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOPERATIONTIMEOUT,rc);
+ // make sure the completions have been called
+ CPPUNIT_ASSERT_EQUAL((int)ZOPERATIONTIMEOUT,res1.rc_);
+ CPPUNIT_ASSERT_EQUAL((int)ZOPERATIONTIMEOUT,res2.rc_);
+ }
+
+ class PingCountingServer: public ZookeeperServer{
+ public:
+ PingCountingServer():pingCount_(0){}
+ // called when a client request is received
+ virtual void onMessageReceived(const RequestHeader& rh, iarchive* ia){
+ if(rh.type==ZOO_PING_OP){
+ pingCount_++;
+ }
+ }
+ int pingCount_;
+ };
+
+ // establish a connection; idle for a while
+ // verify ping was sent at least once
+ void testPing()
+ {
+ const int TIMEOUT=9; // timeout in secs
+ Mock_gettimeofday timeMock;
+ PingCountingServer zkServer;
+ // must call zookeeper_close() while all the mocks are in scope
+ CloseFinally guard(&zh);
+
+ // receive timeout is in milliseconds
+ zh=zookeeper_init("localhost:1234",watcher,TIMEOUT*1000,TEST_CLIENT_ID,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // simulate connected state
+ forceConnected(zh);
+
+ int fd=0;
+ int interest=0;
+ timeval tv;
+ // Round 1.
+ int rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // simulate waiting for the select() call to timeout;
+ // advance the system clock accordingly
+ timeMock.tick(tv);
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
+ // verify no ping sent
+ CPPUNIT_ASSERT(zkServer.pingCount_==0);
+
+ // Round 2.
+ // the client should have the idle threshold exceeded, by now
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // assume the socket is writable, so no idling here; move on to
+ // zookeeper_process immediately
+ rc=zookeeper_process(zh,interest);
+ // ZNOTHING means the client hasn't received a ping response yet
+ CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
+ // verify a ping is sent
+ CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
+
+ // Round 3.
+ // we're going to receive a server PING response and make sure
+ // that the client has updated its last_recv timestamp
+ zkServer.addRecvResponse(new PingResponse);
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // pseudo-sleep for a short while (10 ms)
+ timeMock.millitick(10);
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // only one ping so far?
+ CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
+ CPPUNIT_ASSERT(timeMock==zh->last_recv);
+
+ // Round 4
+ // make sure that a ping is not sent if something is outstanding
+ AsyncGetOperationCompletion res1;
+ rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ timeMock.tick(tv);
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // pseudo-sleep for a short while (10 ms)
+ timeMock.millitick(10);
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
+ // only one ping so far?
+ CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
+ }
+
+ // ZOOKEEPER-2253: Permit unsolicited pings
+ void testUnsolicitedPing()
+ {
+ const int TIMEOUT=9; // timeout in secs
+ Mock_gettimeofday timeMock;
+ PingCountingServer zkServer;
+ // must call zookeeper_close() while all the mocks are in scope
+ CloseFinally guard(&zh);
+
+ // receive timeout is in milliseconds
+ zh=zookeeper_init("localhost:1234",watcher,TIMEOUT*1000,TEST_CLIENT_ID,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // simulate connected state
+ forceConnected(zh);
+
+ int fd=0;
+ int interest=0;
+ timeval tv;
+
+ int rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ // verify no ping sent
+ CPPUNIT_ASSERT(zkServer.pingCount_==0);
+
+ // we're going to receive a unsolicited PING response; ensure
+ // that the client has updated its last_recv timestamp
+ timeMock.tick(tv);
+ zkServer.addRecvResponse(new PingResponse);
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ CPPUNIT_ASSERT(timeMock==zh->last_recv);
+ }
+
+ // simulate a watch arriving right before a ping is due
+ // assert the ping is sent nevertheless
+ void testTimeoutCausedByWatches1()
+ {
+ const int TIMEOUT=9; // timeout in secs
+ Mock_gettimeofday timeMock;
+ PingCountingServer zkServer;
+ // must call zookeeper_close() while all the mocks are in scope
+ CloseFinally guard(&zh);
+
+ // receive timeout is in milliseconds
+ zh=zookeeper_init("localhost:1234",watcher,TIMEOUT*1000,TEST_CLIENT_ID,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // simulate connected state
+ forceConnected(zh);
+
+ int fd=0;
+ int interest=0;
+ timeval tv;
+ // Round 1.
+ int rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // simulate waiting for the select() call to timeout;
+ // advance the system clock accordingly
+ timeMock.tick(tv);
+ timeMock.tick(-1); // set the clock to a millisecond before a ping is due
+ // trigger a watch now
+ zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/x/y/z"));
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // arrival of a watch sets the last_recv to the current time
+ CPPUNIT_ASSERT(timeMock==zh->last_recv);
+ // spend 1 millisecond by processing the watch
+ timeMock.tick(1);
+
+ // Round 2.
+ // a ping is due; zookeeper_interest() must send it now
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // no delay here -- as if the socket is immediately writable
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
+ // verify a ping is sent
+ CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
+ }
+
+ // similar to testTimeoutCausedByWatches1, but this time the watch is
+ // triggered while the client has an outstanding request
+ // assert the ping is sent on time
+ void testTimeoutCausedByWatches2()
+ {
+ const int TIMEOUT=9; // timeout in secs
+ Mock_gettimeofday now;
+ PingCountingServer zkServer;
+ // must call zookeeper_close() while all the mocks are in scope
+ CloseFinally guard(&zh);
+
+ // receive timeout is in milliseconds
+ zh=zookeeper_init("localhost:1234",watcher,TIMEOUT*1000,TEST_CLIENT_ID,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // simulate connected state
+ forceConnected(zh);
+
+ // queue up a request; keep it pending (as if the server is busy or has died)
+ AsyncGetOperationCompletion res1;
+ zkServer.addOperationResponse(new ZooGetResponse("2",1));
+ int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
+
+ int fd=0;
+ int interest=0;
+ timeval tv;
+ // Round 1.
+ // send the queued up zoo_aget() request
+ Mock_gettimeofday beginningOfTimes(now); // remember when we started
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // no delay -- the socket is writable
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ // Round 2.
+ // what's next?
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // no response from the server yet -- waiting in the select() call
+ now.tick(tv);
+ // a watch has arrived, thus preventing the connection from timing out
+ zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/x/y/z"));
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc); // read the watch message
+ CPPUNIT_ASSERT_EQUAL(0,zkServer.pingCount_); // not yet!
+
+ //Round 3.
+ // now is the time to send a ping; make sure it's actually sent
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
+ // verify a ping is sent
+ CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
+ // make sure only 1/3 of the timeout has passed
+ CPPUNIT_ASSERT_EQUAL((int32_t)TIMEOUT/3*1000,toMilliseconds(now-beginningOfTimes));
+ }
+
+#else
+ class TestGetDataJob: public TestJob{
+ public:
+ TestGetDataJob(ZookeeperServer* svr,zhandle_t* zh, int reps=500)
+ :svr_(svr),zh_(zh),rc_(ZAPIERROR),reps_(reps){}
+ virtual void run(){
+ int i;
+ for(i=0;i<reps_;i++){
+ char buf;
+ int size=sizeof(buf);
+
+ if (i % 10 == 0) {
+ // We need to pause every once in a while so we don't
+ // get too far ahead and finish before the disconnect
+ millisleep(1);
+ }
+ svr_->addOperationResponse(new ZooGetResponse("1",1));
+ rc_=zoo_get(zh_,"/x/y/z",0,&buf,&size,0);
+ if(rc_!=ZOK){
+ break;
+ }
+ }
+ }
+ ZookeeperServer* svr_;
+ zhandle_t* zh_;
+ int rc_;
+ int reps_;
+ };
+ class TestConcurrentOpJob: public TestGetDataJob{
+ public:
+ static const int REPS=500;
+ TestConcurrentOpJob(ZookeeperServer* svr,zhandle_t* zh):
+ TestGetDataJob(svr,zh,REPS){}
+ virtual TestJob* clone() const {
+ return new TestConcurrentOpJob(svr_,zh_);
+ }
+ virtual void validate(const char* file, int line) const{
+ CPPUNIT_ASSERT_EQUAL_MESSAGE_LOC("ZOK != rc",(int)ZOK,rc_,file,line);
+ }
+ };
+ void testConcurrentOperations1()
+ {
+ for(int counter=0; counter<50; counter++){
+ // frozen time -- no timeouts and no pings
+ Mock_gettimeofday timeMock;
+
+ ZookeeperServer zkServer;
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+ // must call zookeeper_close() while all the mocks are in the scope!
+ CloseFinally guard(&zh);
+
+ zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // make sure the client has connected
+ CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
+
+ TestJobManager jmgr(TestConcurrentOpJob(&zkServer,zh),10);
+ jmgr.startAllJobs();
+ jmgr.wait();
+ // validate test results
+ VALIDATE_JOBS(jmgr);
+ }
+ }
+ class ZKGetJob: public TestJob{
+ public:
+ static const int REPS=1000;
+ ZKGetJob(zhandle_t* zh)
+ :zh_(zh),rc_(ZAPIERROR){}
+ virtual TestJob* clone() const {
+ return new ZKGetJob(zh_);
+ }
+ virtual void run(){
+ int i;
+ for(i=0;i<REPS;i++){
+ char buf;
+ int size=sizeof(buf);
+ rc_=zoo_get(zh_,"/xyz",0,&buf,&size,0);
+ if(rc_!=ZOK){
+ break;
+ }
+ }
+ //TEST_TRACE(("Finished %d iterations",i));
+ }
+ virtual void validate(const char* file, int line) const{
+ CPPUNIT_ASSERT_EQUAL_MESSAGE_LOC("ZOK != rc",(int)ZOK,rc_,file,line);
+ }
+ zhandle_t* zh_;
+ int rc_;
+ };
+
+ // this test connects to a real ZK server and creates the /xyz node and sends
+ // lots of zoo_get requests.
+ // to run this test use the following command:
+ // zktest-mt Zookeeper_operations::testOperationsAndDisconnectConcurrently2 localhost:3181
+ // where the second parameter is the server host and port
+ void testOperationsAndDisconnectConcurrently2()
+ {
+ if(globalTestConfig.getTestName().find(__func__)==string::npos ||
+ globalTestConfig.getExtraOptCount()==0)
+ {
+ // only run this test when specifically asked so
+ return;
+ }
+ string host(*(globalTestConfig.getExtraOptBegin()));
+ zhandle_t* lzh=zookeeper_init(host.c_str(),watcher,10000,0,0,0);
+ CPPUNIT_ASSERT(lzh!=0);
+ // make sure the client has connected
+ CPPUNIT_ASSERT_MESSAGE("Unable to connect to the host",
+ ensureCondition(ClientConnected(zh),5000)<5000);
+
+ char realpath[1024];
+ int rc=zoo_create(lzh,"/xyz","1",1,&ZOO_OPEN_ACL_UNSAFE,0,realpath,sizeof(realpath)-1);
+ CPPUNIT_ASSERT(rc==ZOK || rc==ZNODEEXISTS);
+ zookeeper_close(lzh);
+
+ for(int counter=0; counter<200; counter++){
+ TEST_TRACE(("Loop count %d",counter));
+
+ CloseFinally guard(&zh);
+
+ zh=zookeeper_init(host.c_str(),watcher,10000,0,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // make sure the client has connected
+ CPPUNIT_ASSERT_MESSAGE("Unable to connect to the host",
+ ensureCondition(ClientConnected(zh),5000)<5000);
+
+ TestJobManager jmgr(ZKGetJob(zh),10);
+ jmgr.startJobsImmediately();
+ jmgr.wait();
+ VALIDATE_JOBS(jmgr);
+ TEST_TRACE(("run %d finished",counter));
+ }
+
+ }
+
+ class TestConcurrentOpWithDisconnectJob: public TestGetDataJob{
+ public:
+ static const int REPS=1000;
+ TestConcurrentOpWithDisconnectJob(ZookeeperServer* svr,zhandle_t* zh):
+ TestGetDataJob(svr,zh,REPS){}
+ virtual TestJob* clone() const {
+ return new TestConcurrentOpWithDisconnectJob(svr_,zh_);
+ }
+ virtual void validate(const char* file, int line) const{
+ CPPUNIT_ASSERT_EQUAL_MESSAGE_LOC("ZCONNECTIONLOSS != rc",(int)ZCONNECTIONLOSS,rc_,file,line);
+ }
+ };
+
+ // this test is not 100% accurate in a sense it may not detect all error cases.
+ // TODO: I can't think of a test that is 100% accurate and doesn't interfere
+ // with the code being tested (in terms of introducing additional
+ // implicit synchronization points)
+ void testOperationsAndDisconnectConcurrently1()
+ {
+ for(int counter=0; counter<50; counter++){
+ //TEST_TRACE(("Loop count %d",counter));
+ // frozen time -- no timeouts and no pings
+ Mock_gettimeofday timeMock;
+
+ ZookeeperServer zkServer;
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+ // must call zookeeper_close() while all the mocks are in the scope!
+ CloseFinally guard(&zh);
+
+ zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // make sure the client has connected
+ CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
+
+ TestJobManager jmgr(TestConcurrentOpWithDisconnectJob(&zkServer,zh),10);
+ jmgr.startJobsImmediately();
+ // let everything startup before we shutdown the server
+ millisleep(4);
+ // reconnect attempts will start failing immediately
+ zkServer.setServerDown(0);
+ // next recv call will return 0
+ zkServer.setConnectionLost();
+ jmgr.wait();
+ VALIDATE_JOBS(jmgr);
+ }
+
+ }
+ // call zoo_aget() in the multithreaded mode
+ void testAsyncGetOperation()
+ {
+ Mock_gettimeofday timeMock;
+
+ ZookeeperServer zkServer;
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+ // must call zookeeper_close() while all the mocks are in the scope!
+ CloseFinally guard(&zh);
+
+ zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // make sure the client has connected
+ CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
+
+ AsyncGetOperationCompletion res1;
+ zkServer.addOperationResponse(new ZooGetResponse("1",1));
+ int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ CPPUNIT_ASSERT(ensureCondition(res1,1000)<1000);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,res1.rc_);
+ CPPUNIT_ASSERT_EQUAL(string("1"),res1.value_);
+ }
+ class ChangeNodeWatcher: public WatcherAction{
+ public:
+ ChangeNodeWatcher():changed_(false){}
+ virtual void onNodeValueChanged(zhandle_t*,const char* path){
+ synchronized(mx_);
+ changed_=true;
+ if(path!=0) path_=path;
+ }
+ // this predicate checks if CHANGE_EVENT event type was triggered, unlike
+ // the isWatcherTriggered() that returns true whenever a watcher is triggered
+ // regardless of the event type
+ SyncedBoolCondition isNodeChangedTriggered() const{
+ return SyncedBoolCondition(changed_,mx_);
+ }
+ bool changed_;
+ string path_;
+ };
+
+ class AsyncWatcherCompletion: public AsyncCompletion{
+ public:
+ AsyncWatcherCompletion(ZookeeperServer& zkServer):zkServer_(zkServer){}
+ virtual void statCompl(int rc, const Stat *stat){
+ // we received a server response, now enqueue a watcher event
+ // to trigger the watcher
+ zkServer_.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/x/y/z"));
+ }
+ ZookeeperServer& zkServer_;
+ };
+ // verify that async watcher is called for znode events (CREATED, DELETED etc.)
+ void testAsyncWatcher1(){
+ Mock_gettimeofday timeMock;
+
+ ZookeeperServer zkServer;
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+ // must call zookeeper_close() while all the mocks are in the scope!
+ CloseFinally guard(&zh);
+
+ ChangeNodeWatcher action;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,
+ TEST_CLIENT_ID,&action,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // make sure the client has connected
+ CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
+
+ // set the watcher
+ AsyncWatcherCompletion completion(zkServer);
+ // prepare a response for the zoo_aexists() request
+ zkServer.addOperationResponse(new ZooStatResponse);
+ int rc=zoo_aexists(zh,"/x/y/z",1,asyncCompletion,&completion);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ CPPUNIT_ASSERT(ensureCondition(action.isNodeChangedTriggered(),1000)<1000);
+ CPPUNIT_ASSERT_EQUAL(string("/x/y/z"),action.path_);
+ }
+#endif
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_operations);
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/TestWatchers.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/TestWatchers.cc b/zookeeper-client/zookeeper-client-c/tests/TestWatchers.cc
new file mode 100644
index 0000000..0a26934
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/TestWatchers.cc
@@ -0,0 +1,773 @@
+/**
+ * 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 <cppunit/extensions/HelperMacros.h>
+#include "CppAssertHelper.h"
+
+#include "ZKMocks.h"
+#include "CollectionUtil.h"
+#include "Util.h"
+
+class Zookeeper_watchers : public CPPUNIT_NS::TestFixture
+{
+ CPPUNIT_TEST_SUITE(Zookeeper_watchers);
+ CPPUNIT_TEST(testDefaultSessionWatcher1);
+ CPPUNIT_TEST(testDefaultSessionWatcher2);
+ CPPUNIT_TEST(testObjectSessionWatcher1);
+ CPPUNIT_TEST(testObjectSessionWatcher2);
+ CPPUNIT_TEST(testNodeWatcher1);
+ CPPUNIT_TEST(testChildWatcher1);
+ CPPUNIT_TEST(testChildWatcher2);
+ CPPUNIT_TEST_SUITE_END();
+
+ static void watcher(zhandle_t *, int, int, const char *,void*){}
+ zhandle_t *zh;
+ FILE *logfile;
+
+public:
+
+ Zookeeper_watchers() {
+ logfile = openlogfile("Zookeeper_watchers");
+ }
+
+ ~Zookeeper_watchers() {
+ if (logfile) {
+ fflush(logfile);
+ fclose(logfile);
+ logfile = 0;
+ }
+ }
+
+ void setUp()
+ {
+ zoo_set_log_stream(logfile);
+
+ zoo_deterministic_conn_order(0);
+ zh=0;
+ }
+
+ void tearDown()
+ {
+ zookeeper_close(zh);
+ }
+
+ class ConnectionWatcher: public WatcherAction{
+ public:
+ ConnectionWatcher():connected_(false),counter_(0){}
+ virtual void onConnectionEstablished(zhandle_t*){
+ synchronized(mx_);
+ counter_++;
+ connected_=true;
+ }
+ SyncedBoolCondition isConnectionEstablished() const{
+ return SyncedBoolCondition(connected_,mx_);
+ }
+ bool connected_;
+ int counter_;
+ };
+
+ class DisconnectWatcher: public WatcherAction{
+ public:
+ DisconnectWatcher():disconnected_(false),counter_(0){}
+ virtual void onConnectionLost(zhandle_t*){
+ synchronized(mx_);
+ counter_++;
+ disconnected_=true;
+ }
+ SyncedBoolCondition isDisconnected() const{
+ return SyncedBoolCondition(disconnected_,mx_);
+ }
+ bool disconnected_;
+ int counter_;
+ };
+
+ class CountingDataWatcher: public WatcherAction{
+ public:
+ CountingDataWatcher():disconnected_(false),counter_(0){}
+ virtual void onNodeValueChanged(zhandle_t*,const char* path){
+ synchronized(mx_);
+ counter_++;
+ }
+ virtual void onConnectionLost(zhandle_t*){
+ synchronized(mx_);
+ counter_++;
+ disconnected_=true;
+ }
+ bool disconnected_;
+ int counter_;
+ };
+
+ class DeletionCountingDataWatcher: public WatcherAction{
+ public:
+ DeletionCountingDataWatcher():counter_(0){}
+ virtual void onNodeDeleted(zhandle_t*,const char* path){
+ synchronized(mx_);
+ counter_++;
+ }
+ int counter_;
+ };
+
+ class ChildEventCountingWatcher: public WatcherAction{
+ public:
+ ChildEventCountingWatcher():counter_(0){}
+ virtual void onChildChanged(zhandle_t*,const char* path){
+ synchronized(mx_);
+ counter_++;
+ }
+ int counter_;
+ };
+
+#ifndef THREADED
+
+ // verify: the default watcher is called once for a session event
+ void testDefaultSessionWatcher1(){
+ Mock_gettimeofday timeMock;
+ ZookeeperServer zkServer;
+ // must call zookeeper_close() while all the mocks are in scope
+ CloseFinally guard(&zh);
+
+ ConnectionWatcher watcher;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
+ &watcher,0);
+ CPPUNIT_ASSERT(zh!=0);
+
+ int fd=0;
+ int interest=0;
+ timeval tv;
+ // open the socket
+ int rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ CPPUNIT_ASSERT_EQUAL(ZOO_CONNECTING_STATE,zoo_state(zh));
+ // send the handshake packet to the server
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ CPPUNIT_ASSERT_EQUAL(ZOO_ASSOCIATING_STATE,zoo_state(zh));
+ // receive the server handshake response
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // verify connected
+ CPPUNIT_ASSERT_EQUAL(ZOO_CONNECTED_STATE,zoo_state(zh));
+ CPPUNIT_ASSERT(watcher.connected_);
+ CPPUNIT_ASSERT_EQUAL(1,watcher.counter_);
+ }
+
+ // test case: connect to server, set a default watcher, disconnect from the server
+ // verify: the default watcher is called once
+ void testDefaultSessionWatcher2(){
+ Mock_gettimeofday timeMock;
+ ZookeeperServer zkServer;
+ // must call zookeeper_close() while all the mocks are in scope
+ CloseFinally guard(&zh);
+
+ DisconnectWatcher watcher;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
+ &watcher,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // simulate connected state
+ forceConnected(zh);
+
+ // first operation
+ AsyncCompletion ignored;
+ zkServer.addOperationResponse(new ZooGetResponse("1",1));
+ int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // this will process the response and activate the watcher
+ rc=zookeeper_process(zh,ZOOKEEPER_READ);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ // now, disconnect
+ zkServer.setConnectionLost();
+ rc=zookeeper_process(zh,ZOOKEEPER_READ);
+ CPPUNIT_ASSERT_EQUAL((int)ZCONNECTIONLOSS,rc);
+ // verify disconnected
+ CPPUNIT_ASSERT(watcher.disconnected_);
+ CPPUNIT_ASSERT_EQUAL(1,watcher.counter_);
+ }
+
+ // testcase: connect to the server, set a watcher object on a node,
+ // disconnect from the server
+ // verify: the watcher object as well as the default watcher are called
+ void testObjectSessionWatcher1(){
+ Mock_gettimeofday timeMock;
+ ZookeeperServer zkServer;
+ // must call zookeeper_close() while all the mocks are in scope
+ CloseFinally guard(&zh);
+
+ DisconnectWatcher defWatcher;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
+ &defWatcher,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // simulate connected state
+ forceConnected(zh);
+
+ AsyncCompletion ignored;
+ CountingDataWatcher wobject;
+ zkServer.addOperationResponse(new ZooStatResponse);
+ int rc=zoo_awexists(zh,"/x/y/1",activeWatcher,&wobject,
+ asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // this will process the response and activate the watcher
+ rc=zookeeper_process(zh,ZOOKEEPER_READ);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ // now, disconnect
+ zkServer.setConnectionLost();
+ rc=zookeeper_process(zh,ZOOKEEPER_READ);
+ CPPUNIT_ASSERT_EQUAL((int)ZCONNECTIONLOSS,rc);
+
+ // verify the default watcher has been triggered
+ CPPUNIT_ASSERT(defWatcher.disconnected_);
+ // and triggered only once
+ CPPUNIT_ASSERT_EQUAL(1,defWatcher.counter_);
+
+ // the path-specific watcher has been triggered as well
+ CPPUNIT_ASSERT(wobject.disconnected_);
+ // only once!
+ CPPUNIT_ASSERT_EQUAL(1,wobject.counter_);
+ }
+
+ // testcase: connect to the server, set a watcher object on a node,
+ // set a def watcher on another node,disconnect from the server
+ // verify: the watcher object as well as the default watcher are called
+ void testObjectSessionWatcher2(){
+ Mock_gettimeofday timeMock;
+ ZookeeperServer zkServer;
+ // must call zookeeper_close() while all the mocks are in scope
+ CloseFinally guard(&zh);
+
+ DisconnectWatcher defWatcher;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
+ &defWatcher,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // simulate connected state
+ forceConnected(zh);
+
+ // set the default watcher
+ AsyncCompletion ignored;
+ zkServer.addOperationResponse(new ZooStatResponse);
+ int rc=zoo_aexists(zh,"/a/b/c",1,asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ CountingDataWatcher wobject;
+ zkServer.addOperationResponse(new ZooStatResponse);
+ rc=zoo_awexists(zh,"/x/y/z",activeWatcher,&wobject,
+ asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ // this will process the response and activate the watcher
+ while((rc=zookeeper_process(zh,ZOOKEEPER_READ))==ZOK) {
+ millisleep(100);
+ }
+ CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
+
+ // disconnect now
+ zkServer.setConnectionLost();
+ rc=zookeeper_process(zh,ZOOKEEPER_READ);
+ CPPUNIT_ASSERT_EQUAL((int)ZCONNECTIONLOSS,rc);
+
+ // verify the default watcher has been triggered
+ CPPUNIT_ASSERT(defWatcher.disconnected_);
+ // and triggered only once
+ CPPUNIT_ASSERT_EQUAL(1,defWatcher.counter_);
+
+ // the path-specific watcher has been triggered as well
+ CPPUNIT_ASSERT(wobject.disconnected_);
+ // only once!
+ CPPUNIT_ASSERT_EQUAL(1,wobject.counter_);
+ }
+
+ // testcase: register 2 node watches for different paths, trigger the watches
+ // verify: the data watchers are processed, the default watcher is not called
+ void testNodeWatcher1(){
+ Mock_gettimeofday timeMock;
+ ZookeeperServer zkServer;
+ // must call zookeeper_close() while all the mocks are in scope
+ CloseFinally guard(&zh);
+
+ DisconnectWatcher defWatcher;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
+ &defWatcher,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // simulate connected state
+ forceConnected(zh);
+
+ AsyncCompletion ignored;
+ CountingDataWatcher wobject1;
+ zkServer.addOperationResponse(new ZooStatResponse);
+ int rc=zoo_awexists(zh,"/a/b/c",activeWatcher,&wobject1,
+ asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ CountingDataWatcher wobject2;
+ zkServer.addOperationResponse(new ZooStatResponse);
+ rc=zoo_awexists(zh,"/x/y/z",activeWatcher,&wobject2,
+ asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ // this will process the response and activate the watcher
+ while((rc=zookeeper_process(zh,ZOOKEEPER_READ))==ZOK) {
+ millisleep(100);
+ }
+ CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
+
+ // we are all set now; let's trigger the watches
+ zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/a/b/c"));
+ zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/x/y/z"));
+ // make sure all watchers have been processed
+ while((rc=zookeeper_process(zh,ZOOKEEPER_READ))==ZOK) {
+ millisleep(100);
+ }
+ CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
+
+ CPPUNIT_ASSERT_EQUAL(1,wobject1.counter_);
+ CPPUNIT_ASSERT_EQUAL(1,wobject2.counter_);
+ CPPUNIT_ASSERT_EQUAL(0,defWatcher.counter_);
+ }
+
+ // testcase: set up both a children and a data watchers on the node /a, then
+ // delete the node by sending a DELETE_EVENT event
+ // verify: both watchers are triggered
+ void testChildWatcher1(){
+ Mock_gettimeofday timeMock;
+ ZookeeperServer zkServer;
+ // must call zookeeper_close() while all the mocks are in scope
+ CloseFinally guard(&zh);
+
+ DeletionCountingDataWatcher defWatcher;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
+ &defWatcher,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // simulate connected state
+ forceConnected(zh);
+
+ AsyncCompletion ignored;
+ DeletionCountingDataWatcher wobject1;
+ zkServer.addOperationResponse(new ZooStatResponse);
+ int rc=zoo_awexists(zh,"/a",activeWatcher,&wobject1,
+ asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ typedef ZooGetChildrenResponse::StringVector ZooVector;
+ zkServer.addOperationResponse(new ZooGetChildrenResponse(
+ Util::CollectionBuilder<ZooVector>()("/a/1")("/a/2")
+ ));
+ DeletionCountingDataWatcher wobject2;
+ rc=zoo_awget_children(zh,"/a",activeWatcher,
+ &wobject2,asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ // this will process the response and activate the watcher
+ while((rc=zookeeper_process(zh,ZOOKEEPER_READ))==ZOK) {
+ millisleep(100);
+ }
+ CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
+
+ // we are all set now; let's trigger the watches
+ zkServer.addRecvResponse(new ZNodeEvent(ZOO_DELETED_EVENT,"/a"));
+ // make sure the watchers have been processed
+ while((rc=zookeeper_process(zh,ZOOKEEPER_READ))==ZOK) {
+ millisleep(100);
+ }
+ CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
+
+ CPPUNIT_ASSERT_EQUAL(1,wobject1.counter_);
+ CPPUNIT_ASSERT_EQUAL(1,wobject2.counter_);
+ CPPUNIT_ASSERT_EQUAL(0,defWatcher.counter_);
+ }
+
+ // testcase: create both a child and data watch on the node /a, send a ZOO_CHILD_EVENT
+ // verify: only the child watch triggered
+ void testChildWatcher2(){
+ Mock_gettimeofday timeMock;
+ ZookeeperServer zkServer;
+ // must call zookeeper_close() while all the mocks are in scope
+ CloseFinally guard(&zh);
+
+ ChildEventCountingWatcher defWatcher;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
+ &defWatcher,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // simulate connected state
+ forceConnected(zh);
+
+ AsyncCompletion ignored;
+ ChildEventCountingWatcher wobject1;
+ zkServer.addOperationResponse(new ZooStatResponse);
+ int rc=zoo_awexists(zh,"/a",activeWatcher,&wobject1,
+ asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ typedef ZooGetChildrenResponse::StringVector ZooVector;
+ zkServer.addOperationResponse(new ZooGetChildrenResponse(
+ Util::CollectionBuilder<ZooVector>()("/a/1")("/a/2")
+ ));
+ ChildEventCountingWatcher wobject2;
+ rc=zoo_awget_children(zh,"/a",activeWatcher,
+ &wobject2,asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ // this will process the response and activate the watcher
+ while((rc=zookeeper_process(zh,ZOOKEEPER_READ))==ZOK) {
+ millisleep(100);
+ }
+ CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
+
+ // we are all set now; let's trigger the watches
+ zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHILD_EVENT,"/a"));
+ // make sure the watchers have been processed
+ while((rc=zookeeper_process(zh,ZOOKEEPER_READ))==ZOK) {
+ millisleep(100);
+ }
+ CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
+
+ CPPUNIT_ASSERT_EQUAL(0,wobject1.counter_);
+ CPPUNIT_ASSERT_EQUAL(1,wobject2.counter_);
+ CPPUNIT_ASSERT_EQUAL(0,defWatcher.counter_);
+ }
+
+#else
+ // verify: the default watcher is called once for a session event
+ void testDefaultSessionWatcher1(){
+ Mock_gettimeofday timeMock;
+ // zookeeper simulator
+ ZookeeperServer zkServer;
+ // detects when all watchers have been delivered
+ WatcherDeliveryTracker deliveryTracker(ZOO_SESSION_EVENT,ZOO_CONNECTED_STATE);
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+ // must call zookeeper_close() while all the mocks are in the scope!
+ CloseFinally guard(&zh);
+
+ ConnectionWatcher watcher;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
+ &watcher,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // wait till watcher proccessing has completed (the connection
+ // established event)
+ CPPUNIT_ASSERT(ensureCondition(
+ deliveryTracker.isWatcherProcessingCompleted(),1000)<1000);
+
+ // verify the watcher has been triggered
+ CPPUNIT_ASSERT(ensureCondition(watcher.isConnectionEstablished(),1000)<1000);
+ // triggered only once
+ CPPUNIT_ASSERT_EQUAL(1,watcher.counter_);
+ }
+
+ // test case: connect to server, set a default watcher, disconnect from the server
+ // verify: the default watcher is called once
+ void testDefaultSessionWatcher2(){
+ Mock_gettimeofday timeMock;
+ // zookeeper simulator
+ ZookeeperServer zkServer;
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+ // must call zookeeper_close() while all the mocks are in the scope!
+ CloseFinally guard(&zh);
+
+ // detects when all watchers have been delivered
+ WatcherDeliveryTracker deliveryTracker(ZOO_SESSION_EVENT,ZOO_CONNECTING_STATE);
+ DisconnectWatcher watcher;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
+ &watcher,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // make sure the client has connected
+ CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
+ // set a default watch
+ AsyncCompletion ignored;
+ // a successful server response will activate the watcher
+ zkServer.addOperationResponse(new ZooStatResponse);
+ int rc=zoo_aexists(zh,"/x/y/z",1,asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ // now, initiate a disconnect
+ zkServer.setConnectionLost();
+ CPPUNIT_ASSERT(ensureCondition(
+ deliveryTracker.isWatcherProcessingCompleted(),1000)<1000);
+
+ // verify the watcher has been triggered
+ CPPUNIT_ASSERT(watcher.disconnected_);
+ // triggered only once
+ CPPUNIT_ASSERT_EQUAL(1,watcher.counter_);
+ }
+
+ // testcase: connect to the server, set a watcher object on a node,
+ // disconnect from the server
+ // verify: the watcher object as well as the default watcher are called
+ void testObjectSessionWatcher1(){
+ Mock_gettimeofday timeMock;
+ // zookeeper simulator
+ ZookeeperServer zkServer;
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+ // must call zookeeper_close() while all the mocks are in the scope!
+ CloseFinally guard(&zh);
+
+ // detects when all watchers have been delivered
+ WatcherDeliveryTracker deliveryTracker(ZOO_SESSION_EVENT,ZOO_CONNECTING_STATE);
+ DisconnectWatcher defWatcher;
+ // use the tracker to find out when the watcher has been activated
+ WatcherActivationTracker activationTracker;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
+ &defWatcher,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // make sure the client has connected
+ CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
+
+ AsyncCompletion ignored;
+ // this successful server response will activate the watcher
+ zkServer.addOperationResponse(new ZooStatResponse);
+ CountingDataWatcher wobject;
+ activationTracker.track(&wobject);
+ // set a path-specific watcher
+ int rc=zoo_awexists(zh,"/x/y/z",activeWatcher,&wobject,
+ asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // make sure the watcher gets activated before we continue
+ CPPUNIT_ASSERT(ensureCondition(activationTracker.isWatcherActivated(),1000)<1000);
+
+ // now, initiate a disconnect
+ zkServer.setConnectionLost();
+ // make sure all watchers have been processed
+ CPPUNIT_ASSERT(ensureCondition(
+ deliveryTracker.isWatcherProcessingCompleted(),1000)<1000);
+
+ // verify the default watcher has been triggered
+ CPPUNIT_ASSERT(defWatcher.disconnected_);
+ // and triggered only once
+ CPPUNIT_ASSERT_EQUAL(1,defWatcher.counter_);
+
+ // the path-specific watcher has been triggered as well
+ CPPUNIT_ASSERT(wobject.disconnected_);
+ // only once!
+ CPPUNIT_ASSERT_EQUAL(1,wobject.counter_);
+ }
+
+ // testcase: connect to the server, set a watcher object on a node,
+ // set a def watcher on another node,disconnect from the server
+ // verify: the watcher object as well as the default watcher are called
+ void testObjectSessionWatcher2(){
+ Mock_gettimeofday timeMock;
+ // zookeeper simulator
+ ZookeeperServer zkServer;
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+ // must call zookeeper_close() while all the mocks are in the scope!
+ CloseFinally guard(&zh);
+
+ // detects when all watchers have been delivered
+ WatcherDeliveryTracker deliveryTracker(ZOO_SESSION_EVENT,ZOO_CONNECTING_STATE);
+ DisconnectWatcher defWatcher;
+ // use the tracker to find out when the watcher has been activated
+ WatcherActivationTracker activationTracker;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
+ &defWatcher,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // make sure the client has connected
+ CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
+
+ // set a default watch
+ AsyncCompletion ignored;
+ // a successful server response will activate the watcher
+ zkServer.addOperationResponse(new ZooStatResponse);
+ activationTracker.track(&defWatcher);
+ int rc=zoo_aexists(zh,"/a/b/c",1,asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // make sure the watcher gets activated before we continue
+ CPPUNIT_ASSERT(ensureCondition(activationTracker.isWatcherActivated(),1000)<1000);
+
+ // this successful server response will activate the watcher
+ zkServer.addOperationResponse(new ZooStatResponse);
+ CountingDataWatcher wobject;
+ activationTracker.track(&wobject);
+ // set a path-specific watcher
+ rc=zoo_awexists(zh,"/x/y/z",activeWatcher,&wobject,
+ asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // make sure the watcher gets activated before we continue
+ CPPUNIT_ASSERT(ensureCondition(activationTracker.isWatcherActivated(),1000)<1000);
+
+ // now, initiate a disconnect
+ zkServer.setConnectionLost();
+ // make sure all watchers have been processed
+ CPPUNIT_ASSERT(ensureCondition(
+ deliveryTracker.isWatcherProcessingCompleted(),1000)<1000);
+
+ // verify the default watcher has been triggered
+ CPPUNIT_ASSERT(defWatcher.disconnected_);
+ // and triggered only once
+ CPPUNIT_ASSERT_EQUAL(1,defWatcher.counter_);
+
+ // the path-specific watcher has been triggered as well
+ CPPUNIT_ASSERT(wobject.disconnected_);
+ // only once!
+ CPPUNIT_ASSERT_EQUAL(1,wobject.counter_);
+ }
+
+ // testcase: register 2 node watches for different paths, trigger the watches
+ // verify: the data watchers are processed, the default watcher is not called
+ void testNodeWatcher1(){
+ Mock_gettimeofday timeMock;
+ // zookeeper simulator
+ ZookeeperServer zkServer;
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+ // must call zookeeper_close() while all the mocks are in the scope!
+ CloseFinally guard(&zh);
+
+ // detects when all watchers have been delivered
+ WatcherDeliveryTracker deliveryTracker(ZOO_CHANGED_EVENT,0,false);
+ CountingDataWatcher defWatcher;
+ // use the tracker to find out when the watcher has been activated
+ WatcherActivationTracker activationTracker;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
+ &defWatcher,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // make sure the client has connected
+ CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
+
+ // don't care about completions
+ AsyncCompletion ignored;
+ // set a one-shot watch
+ // a successful server response will activate the watcher
+ zkServer.addOperationResponse(new ZooStatResponse);
+ CountingDataWatcher wobject1;
+ activationTracker.track(&wobject1);
+ int rc=zoo_awexists(zh,"/a/b/c",activeWatcher,&wobject1,
+ asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // make sure the watcher gets activated before we continue
+ CPPUNIT_ASSERT(ensureCondition(activationTracker.isWatcherActivated(),1000)<1000);
+
+ // this successful server response will activate the watcher
+ zkServer.addOperationResponse(new ZooStatResponse);
+ CountingDataWatcher wobject2;
+ activationTracker.track(&wobject2);
+ // set a path-specific watcher
+ rc=zoo_awexists(zh,"/x/y/z",activeWatcher,&wobject2,
+ asyncCompletion,&ignored);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // make sure the watcher gets activated before we continue
+ CPPUNIT_ASSERT(ensureCondition(activationTracker.isWatcherActivated(),1000)<1000);
+
+ // we are all set now; let's trigger the watches
+ zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/a/b/c"));
+ zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/x/y/z"));
+ // make sure all watchers have been processed
+ CPPUNIT_ASSERT(ensureCondition(
+ deliveryTracker.deliveryCounterEquals(2),1000)<1000);
+
+ CPPUNIT_ASSERT_EQUAL(1,wobject1.counter_);
+ CPPUNIT_ASSERT_EQUAL(1,wobject2.counter_);
+ CPPUNIT_ASSERT_EQUAL(0,defWatcher.counter_);
+ }
+
+ // testcase: set up both a children and a data watchers on the node /a, then
+ // delete the node (that is, send a DELETE_EVENT)
+ // verify: both watchers are triggered
+ void testChildWatcher1(){
+ Mock_gettimeofday timeMock;
+ // zookeeper simulator
+ ZookeeperServer zkServer;
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+ // must call zookeeper_close() while all the mocks are in the scope!
+ CloseFinally guard(&zh);
+
+ // detects when all watchers have been delivered
+ WatcherDeliveryTracker deliveryTracker(ZOO_DELETED_EVENT,0);
+ DeletionCountingDataWatcher defWatcher;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
+ &defWatcher,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // make sure the client has connected
+ CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
+
+ // a successful server response will activate the watcher
+ zkServer.addOperationResponse(new ZooStatResponse);
+ DeletionCountingDataWatcher wobject1;
+ Stat stat;
+ // add a node watch
+ int rc=zoo_wexists(zh,"/a",activeWatcher,&wobject1,&stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ typedef ZooGetChildrenResponse::StringVector ZooVector;
+ zkServer.addOperationResponse(new ZooGetChildrenResponse(
+ Util::CollectionBuilder<ZooVector>()("/a/1")("/a/2")
+ ));
+ DeletionCountingDataWatcher wobject2;
+ String_vector children;
+ rc=zoo_wget_children(zh,"/a",activeWatcher,&wobject2,&children);
+ deallocate_String_vector(&children);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ // we are all set now; let's trigger the watches
+ zkServer.addRecvResponse(new ZNodeEvent(ZOO_DELETED_EVENT,"/a"));
+ // make sure the watchers have been processed
+ CPPUNIT_ASSERT(ensureCondition(
+ deliveryTracker.isWatcherProcessingCompleted(),1000)<1000);
+
+ CPPUNIT_ASSERT_EQUAL(1,wobject1.counter_);
+ CPPUNIT_ASSERT_EQUAL(1,wobject2.counter_);
+ CPPUNIT_ASSERT_EQUAL(0,defWatcher.counter_);
+ }
+
+ // testcase: create both a child and data watch on the node /a, send a ZOO_CHILD_EVENT
+ // verify: only the child watch triggered
+ void testChildWatcher2(){
+ Mock_gettimeofday timeMock;
+ // zookeeper simulator
+ ZookeeperServer zkServer;
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+ // must call zookeeper_close() while all the mocks are in the scope!
+ CloseFinally guard(&zh);
+
+ // detects when all watchers have been delivered
+ WatcherDeliveryTracker deliveryTracker(ZOO_CHILD_EVENT,0);
+ ChildEventCountingWatcher defWatcher;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
+ &defWatcher,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // make sure the client has connected
+ CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
+ // a successful server response will activate the watcher
+ zkServer.addOperationResponse(new ZooStatResponse);
+ ChildEventCountingWatcher wobject1;
+ Stat stat;
+ // add a node watch
+ int rc=zoo_wexists(zh,"/a",activeWatcher,&wobject1,&stat);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ typedef ZooGetChildrenResponse::StringVector ZooVector;
+ zkServer.addOperationResponse(new ZooGetChildrenResponse(
+ Util::CollectionBuilder<ZooVector>()("/a/1")("/a/2")
+ ));
+ ChildEventCountingWatcher wobject2;
+ String_vector children;
+ rc=zoo_wget_children(zh,"/a",activeWatcher,&wobject2,&children);
+ deallocate_String_vector(&children);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ // we are all set now; let's trigger the watches
+ zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHILD_EVENT,"/a"));
+ // make sure the watchers have been processed
+ CPPUNIT_ASSERT(ensureCondition(
+ deliveryTracker.isWatcherProcessingCompleted(),1000)<1000);
+
+ CPPUNIT_ASSERT_EQUAL(0,wobject1.counter_);
+ CPPUNIT_ASSERT_EQUAL(1,wobject2.counter_);
+ CPPUNIT_ASSERT_EQUAL(0,defWatcher.counter_);
+ }
+
+#endif //THREADED
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_watchers);
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/tests/TestZookeeperClose.cc
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/tests/TestZookeeperClose.cc b/zookeeper-client/zookeeper-client-c/tests/TestZookeeperClose.cc
new file mode 100644
index 0000000..edefa66
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/tests/TestZookeeperClose.cc
@@ -0,0 +1,472 @@
+/**
+ * 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 <cppunit/extensions/HelperMacros.h>
+
+#include "ZKMocks.h"
+
+#ifdef THREADED
+#include "PthreadMocks.h"
+#endif
+
+using namespace std;
+
+class Zookeeper_close : public CPPUNIT_NS::TestFixture
+{
+ CPPUNIT_TEST_SUITE(Zookeeper_close);
+#ifdef THREADED
+ CPPUNIT_TEST(testIOThreadStoppedOnExpire);
+#endif
+ CPPUNIT_TEST(testCloseUnconnected);
+ CPPUNIT_TEST(testCloseUnconnected1);
+ CPPUNIT_TEST(testCloseConnected1);
+ CPPUNIT_TEST(testCloseFromWatcher1);
+ CPPUNIT_TEST_SUITE_END();
+ zhandle_t *zh;
+ static void watcher(zhandle_t *, int, int, const char *,void*){}
+ FILE *logfile;
+public:
+
+ Zookeeper_close() {
+ logfile = openlogfile("Zookeeper_close");
+ }
+
+ ~Zookeeper_close() {
+ if (logfile) {
+ fflush(logfile);
+ fclose(logfile);
+ logfile = 0;
+ }
+ }
+
+ void setUp()
+ {
+ zoo_set_log_stream(logfile);
+
+ zoo_deterministic_conn_order(0);
+ zh=0;
+ }
+
+ void tearDown()
+ {
+ zookeeper_close(zh);
+ }
+
+ class CloseOnSessionExpired: public WatcherAction{
+ public:
+ CloseOnSessionExpired(bool callClose=true):
+ callClose_(callClose),rc(ZOK){}
+ virtual void onSessionExpired(zhandle_t* zh){
+ memcpy(&lzh,zh,sizeof(lzh));
+ if(callClose_)
+ rc=zookeeper_close(zh);
+ }
+ zhandle_t lzh;
+ bool callClose_;
+ int rc;
+ };
+
+#ifndef THREADED
+ void testCloseUnconnected()
+ {
+ zh=zookeeper_init("localhost:2121",watcher,10000,0,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+
+ // do not actually free the memory while in zookeeper_close()
+ Mock_free_noop freeMock;
+ // make a copy of zhandle before close() overwrites some of
+ // it members with NULLs
+ zhandle_t lzh;
+ memcpy(&lzh,zh,sizeof(lzh));
+ int rc=zookeeper_close(zh);
+ zhandle_t* savezh=zh; zh=0;
+ freeMock.disable(); // disable mock's fake free()- use libc's free() instead
+
+ // verify that zookeeper_close has done its job
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // memory
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.hostname));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.addrs));
+ // This cannot be maintained properly CPPUNIT_ASSERT_EQUAL(9,freeMock.callCounter);
+ }
+ void testCloseUnconnected1()
+ {
+ zh=zookeeper_init("localhost:2121",watcher,10000,0,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // simulate connected state
+ zh->fd=ZookeeperServer::FD;
+ zh->state=ZOO_CONNECTED_STATE;
+ Mock_flush_send_queue zkMock;
+ // do not actually free the memory while in zookeeper_close()
+ Mock_free_noop freeMock;
+ // make a copy of zhandle before close() overwrites some of
+ // it members with NULLs
+ zhandle_t lzh;
+ memcpy(&lzh,zh,sizeof(lzh));
+ int rc=zookeeper_close(zh);
+ zhandle_t* savezh=zh; zh=0;
+ freeMock.disable(); // disable mock's fake free()- use libc's free() instead
+
+ // verify that zookeeper_close has done its job
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // memory
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.hostname));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.addrs));
+ // the close request sent?
+ CPPUNIT_ASSERT_EQUAL(1,zkMock.counter);
+ }
+ void testCloseConnected1()
+ {
+ ZookeeperServer zkServer;
+ // poll() will called from zookeeper_close()
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+
+ zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+
+ Mock_gettimeofday timeMock;
+
+ int fd=0;
+ int interest=0;
+ timeval tv;
+ int rc=zookeeper_interest(zh,&fd,&interest,&tv);
+
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ CPPUNIT_ASSERT_EQUAL(ZOO_CONNECTING_STATE,zoo_state(zh));
+ CPPUNIT_ASSERT_EQUAL(ZOOKEEPER_READ|ZOOKEEPER_WRITE,interest);
+
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ CPPUNIT_ASSERT_EQUAL(ZOO_ASSOCIATING_STATE,zoo_state(zh));
+
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ rc=zookeeper_process(zh,interest);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ CPPUNIT_ASSERT_EQUAL(ZOO_CONNECTED_STATE,zoo_state(zh));
+ // do not actually free the memory while in zookeeper_close()
+ Mock_free_noop freeMock;
+ // make a copy of zhandle before close() overwrites some of
+ // it members with NULLs
+ zhandle_t lzh;
+ memcpy(&lzh,zh,sizeof(lzh));
+ zookeeper_close(zh);
+ zhandle_t* savezh=zh; zh=0;
+ freeMock.disable(); // disable mock's fake free()- use libc's free() instead
+ // memory
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.hostname));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.addrs));
+ // the close request sent?
+ CPPUNIT_ASSERT_EQUAL(1,(int)zkServer.closeSent);
+ }
+ void testCloseFromWatcher1()
+ {
+ Mock_gettimeofday timeMock;
+
+ ZookeeperServer zkServer;
+ // make the server return a non-matching session id
+ zkServer.returnSessionExpired();
+ // poll() will called from zookeeper_close()
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+
+ CloseOnSessionExpired closeAction;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,
+ TEST_CLIENT_ID,&closeAction,0);
+ CPPUNIT_ASSERT(zh!=0);
+
+ int fd=0;
+ int interest=0;
+ timeval tv;
+ // initiate connection
+ int rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ CPPUNIT_ASSERT_EQUAL(ZOO_CONNECTING_STATE,zoo_state(zh));
+ CPPUNIT_ASSERT_EQUAL(ZOOKEEPER_READ|ZOOKEEPER_WRITE,interest);
+ rc=zookeeper_process(zh,interest);
+ // make sure the handshake in progress
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ CPPUNIT_ASSERT_EQUAL(ZOO_ASSOCIATING_STATE,zoo_state(zh));
+ rc=zookeeper_interest(zh,&fd,&interest,&tv);
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+
+ // do not actually free the memory while in zookeeper_close()
+ Mock_free_noop freeMock;
+ // should call the watcher with ZOO_EXPIRED_SESSION_STATE state
+ rc=zookeeper_process(zh,interest);
+ zhandle_t* savezh=zh; zh=0;
+ freeMock.disable(); // disable mock's fake free()- use libc's free() instead
+
+ CPPUNIT_ASSERT_EQUAL(ZOO_EXPIRED_SESSION_STATE,zoo_state(savezh));
+ // memory
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(closeAction.lzh.hostname));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(closeAction.lzh.addrs));
+ // make sure the close request NOT sent
+ CPPUNIT_ASSERT_EQUAL(0,(int)zkServer.closeSent);
+ }
+#else
+ void testCloseUnconnected()
+ {
+ // disable threading
+ MockPthreadZKNull pthreadMock;
+ zh=zookeeper_init("localhost:2121",watcher,10000,0,0,0);
+
+ CPPUNIT_ASSERT(zh!=0);
+ adaptor_threads* adaptor=(adaptor_threads*)zh->adaptor_priv;
+ CPPUNIT_ASSERT(adaptor!=0);
+
+ // do not actually free the memory while in zookeeper_close()
+ Mock_free_noop freeMock;
+ // make a copy of zhandle before close() overwrites some of
+ // it members with NULLs
+ zhandle_t lzh;
+ memcpy(&lzh,zh,sizeof(lzh));
+ int rc=zookeeper_close(zh);
+ zhandle_t* savezh=zh; zh=0;
+ // we're done, disable mock's fake free(), use libc's free() instead
+ freeMock.disable();
+
+ // verify that zookeeper_close has done its job
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ // memory
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.hostname));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.addrs));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(adaptor));
+ // Cannot be maintained accurately: CPPUNIT_ASSERT_EQUAL(10,freeMock.callCounter);
+ // threads
+ CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(adaptor->io));
+ CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(adaptor->completion));
+ // mutexes
+ CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(&savezh->to_process.lock));
+ CPPUNIT_ASSERT_EQUAL(0,MockPthreadsNull::getInvalidAccessCounter(&savezh->to_process.lock));
+ CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(&savezh->to_send.lock));
+ CPPUNIT_ASSERT_EQUAL(0,MockPthreadsNull::getInvalidAccessCounter(&savezh->to_send.lock));
+ CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(&savezh->sent_requests.lock));
+ CPPUNIT_ASSERT_EQUAL(0,MockPthreadsNull::getInvalidAccessCounter(&savezh->sent_requests.lock));
+ CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(&savezh->completions_to_process.lock));
+ CPPUNIT_ASSERT_EQUAL(0,MockPthreadsNull::getInvalidAccessCounter(&savezh->completions_to_process.lock));
+ // conditionals
+ CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(&savezh->sent_requests.cond));
+ CPPUNIT_ASSERT_EQUAL(0,MockPthreadsNull::getInvalidAccessCounter(&savezh->sent_requests.cond));
+ CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(&savezh->completions_to_process.cond));
+ CPPUNIT_ASSERT_EQUAL(0,MockPthreadsNull::getInvalidAccessCounter(&savezh->completions_to_process.cond));
+ }
+ void testCloseUnconnected1()
+ {
+ for(int i=0; i<100;i++){
+ zh=zookeeper_init("localhost:2121",watcher,10000,0,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+ adaptor_threads* adaptor=(adaptor_threads*)zh->adaptor_priv;
+ CPPUNIT_ASSERT(adaptor!=0);
+ int rc=zookeeper_close(zh);
+ zh=0;
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ }
+ }
+ void testCloseConnected1()
+ {
+ // frozen time -- no timeouts and no pings
+ Mock_gettimeofday timeMock;
+
+ for(int i=0;i<100;i++){
+ ZookeeperServer zkServer;
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+ // use a checked version of pthread calls
+ CheckedPthread threadMock;
+ // do not actually free the memory while in zookeeper_close()
+ Mock_free_noop freeMock;
+
+ zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
+ CPPUNIT_ASSERT(zh!=0);
+ // make sure the client has connected
+ CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
+ // make a copy of zhandle before close() overwrites some of
+ // its members with NULLs
+ zhandle_t lzh;
+ memcpy(&lzh,zh,sizeof(lzh));
+ int rc=zookeeper_close(zh);
+ zhandle_t* savezh=zh; zh=0;
+ // we're done, disable mock's fake free(), use libc's free() instead
+ freeMock.disable();
+
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
+ adaptor_threads* adaptor=(adaptor_threads*)lzh.adaptor_priv;
+ // memory
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.hostname));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.addrs));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(adaptor));
+ // threads
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(adaptor->io));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(adaptor->completion));
+ // mutexes
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&savezh->to_process.lock));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&savezh->to_process.lock));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&savezh->to_send.lock));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&savezh->to_send.lock));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&savezh->sent_requests.lock));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&savezh->sent_requests.lock));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&savezh->completions_to_process.lock));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&savezh->completions_to_process.lock));
+ // conditionals
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&savezh->sent_requests.cond));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&savezh->sent_requests.cond));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&savezh->completions_to_process.cond));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&savezh->completions_to_process.cond));
+ }
+ }
+
+ struct PointerFreed{
+ PointerFreed(Mock_free_noop& freeMock,void* ptr):
+ freeMock_(freeMock),ptr_(ptr){}
+ bool operator()() const{return freeMock_.isFreed(ptr_); }
+ Mock_free_noop& freeMock_;
+ void* ptr_;
+ };
+ // test if zookeeper_close may be called from a watcher callback on
+ // SESSION_EXPIRED event
+ void testCloseFromWatcher1()
+ {
+ // frozen time -- no timeouts and no pings
+ Mock_gettimeofday timeMock;
+
+ for(int i=0;i<100;i++){
+ ZookeeperServer zkServer;
+ // make the server return a non-matching session id
+ zkServer.returnSessionExpired();
+
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+ // use a checked version of pthread calls
+ CheckedPthread threadMock;
+ // do not actually free the memory while in zookeeper_close()
+ Mock_free_noop freeMock;
+
+ CloseOnSessionExpired closeAction;
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,
+ TEST_CLIENT_ID,&closeAction,0);
+
+ CPPUNIT_ASSERT(zh!=0);
+ // we rely on the fact that zh is freed the last right before
+ // zookeeper_close() returns...
+ CPPUNIT_ASSERT(ensureCondition(PointerFreed(freeMock,zh),1000)<1000);
+ zhandle_t* lzh=zh;
+ zh=0;
+ // we're done, disable mock's fake free(), use libc's free() instead
+ freeMock.disable();
+
+ CPPUNIT_ASSERT_EQUAL((int)ZOK,closeAction.rc);
+ adaptor_threads* adaptor=(adaptor_threads*)closeAction.lzh.adaptor_priv;
+ // memory
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(closeAction.lzh.hostname));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(closeAction.lzh.addrs));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(adaptor));
+ // threads
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(adaptor->io));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(adaptor->completion));
+ // mutexes
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->to_process.lock));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->to_process.lock));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->to_send.lock));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->to_send.lock));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->sent_requests.lock));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->sent_requests.lock));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->completions_to_process.lock));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->completions_to_process.lock));
+ // conditionals
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->sent_requests.cond));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->sent_requests.cond));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->completions_to_process.cond));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->completions_to_process.cond));
+ }
+ }
+
+ void testIOThreadStoppedOnExpire()
+ {
+ // frozen time -- no timeouts and no pings
+ Mock_gettimeofday timeMock;
+
+ for(int i=0;i<100;i++){
+ ZookeeperServer zkServer;
+ // make the server return a non-matching session id
+ zkServer.returnSessionExpired();
+
+ Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
+ // use a checked version of pthread calls
+ CheckedPthread threadMock;
+ // do not call zookeeper_close() from the watcher
+ CloseOnSessionExpired closeAction(false);
+ zh=zookeeper_init("localhost:2121",activeWatcher,10000,
+ &testClientId,&closeAction,0);
+
+ // this is to ensure that if any assert fires, zookeeper_close()
+ // will still be called while all the mocks are in the scope!
+ CloseFinally guard(&zh);
+
+ CPPUNIT_ASSERT(zh!=0);
+ CPPUNIT_ASSERT(ensureCondition(SessionExpired(zh),1000)<1000);
+ CPPUNIT_ASSERT(ensureCondition(IOThreadStopped(zh),1000)<1000);
+ // make sure the watcher has been processed
+ CPPUNIT_ASSERT(ensureCondition(closeAction.isWatcherTriggered(),1000)<1000);
+ // make sure the threads have not been destroyed yet
+ adaptor_threads* adaptor=(adaptor_threads*)zh->adaptor_priv;
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getDestroyCounter(adaptor->io));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getDestroyCounter(adaptor->completion));
+ // about to call zookeeper_close() -- no longer need the guard
+ guard.disarm();
+
+ // do not actually free the memory while in zookeeper_close()
+ Mock_free_noop freeMock;
+ zookeeper_close(zh);
+ zhandle_t* lzh=zh; zh=0;
+ // we're done, disable mock's fake free(), use libc's free() instead
+ freeMock.disable();
+
+ // memory
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(closeAction.lzh.hostname));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(closeAction.lzh.addrs));
+ CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(adaptor));
+ // threads
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(adaptor->io));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(adaptor->completion));
+ // mutexes
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->to_process.lock));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->to_process.lock));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->to_send.lock));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->to_send.lock));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->sent_requests.lock));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->sent_requests.lock));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->completions_to_process.lock));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->completions_to_process.lock));
+ // conditionals
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->sent_requests.cond));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->sent_requests.cond));
+ CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->completions_to_process.cond));
+ CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->completions_to_process.cond));
+ }
+ }
+
+#endif
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_close);
[10/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/INSTALL
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/INSTALL b/zookeeper-client/zookeeper-client-c/INSTALL
new file mode 100644
index 0000000..5458714
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/INSTALL
@@ -0,0 +1,234 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006 Free Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about. Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/LICENSE
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/LICENSE b/zookeeper-client/zookeeper-client-c/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed 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.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/Makefile.am
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/Makefile.am b/zookeeper-client/zookeeper-client-c/Makefile.am
new file mode 100644
index 0000000..5993098
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/Makefile.am
@@ -0,0 +1,128 @@
+# need this for Doxygen integration
+include $(top_srcdir)/aminclude.am
+
+if SOLARIS
+ SOLARIS_CPPFLAGS = -D_POSIX_PTHREAD_SEMANTICS
+ SOLARIS_LIB_LDFLAGS = -lnsl -lsocket
+endif
+AM_CPPFLAGS = -I${srcdir}/include -I${srcdir}/tests -I${srcdir}/generated $(SOLARIS_CPPFLAGS)
+AM_CFLAGS = -Wall -Werror
+AM_CXXFLAGS = -Wall $(USEIPV6)
+
+# Additional flags for coverage testing (if enabled)
+if ENABLEGCOV
+ AM_CFLAGS += -fprofile-arcs -ftest-coverage
+ AM_LDFLAGS = -lgcov
+endif
+
+LIB_LDFLAGS = -no-undefined -version-info 2 $(SOLARIS_LIB_LDFLAGS)
+
+pkginclude_HEADERS = include/zookeeper.h include/zookeeper_version.h include/zookeeper_log.h include/proto.h include/recordio.h generated/zookeeper.jute.h
+EXTRA_DIST=LICENSE
+
+HASHTABLE_SRC = src/hashtable/hashtable_itr.h src/hashtable/hashtable_itr.c \
+ src/hashtable/hashtable_private.h src/hashtable/hashtable.h src/hashtable/hashtable.c
+
+noinst_LTLIBRARIES = libhashtable.la
+libhashtable_la_SOURCES = $(HASHTABLE_SRC)
+
+COMMON_SRC = src/zookeeper.c include/zookeeper.h include/zookeeper_version.h include/zookeeper_log.h\
+ src/recordio.c include/recordio.h include/proto.h \
+ src/zk_adaptor.h generated/zookeeper.jute.c \
+ src/zookeeper_log.h src/zk_log.c src/zk_hashtable.h src/zk_hashtable.c
+
+# These are the symbols (classes, mostly) we want to export from our library.
+EXPORT_SYMBOLS = '(zoo_|zookeeper_|zhandle|Z|format_log_message|log_message|logLevel|deallocate_|allocate_|zerror|is_unrecoverable)'
+noinst_LTLIBRARIES += libzkst.la
+libzkst_la_SOURCES =$(COMMON_SRC) src/st_adaptor.c
+libzkst_la_LIBADD = -lm
+
+lib_LTLIBRARIES = libzookeeper_st.la
+libzookeeper_st_la_SOURCES =
+libzookeeper_st_la_LIBADD=libzkst.la libhashtable.la
+libzookeeper_st_la_DEPENDENCIES=libzkst.la libhashtable.la
+libzookeeper_st_la_LDFLAGS = $(LIB_LDFLAGS) -export-symbols-regex $(EXPORT_SYMBOLS)
+
+if WANT_SYNCAPI
+noinst_LTLIBRARIES += libzkmt.la
+libzkmt_la_SOURCES =$(COMMON_SRC) src/mt_adaptor.c
+libzkmt_la_CFLAGS = -DTHREADED
+libzkmt_la_LIBADD = -lm
+
+lib_LTLIBRARIES += libzookeeper_mt.la
+libzookeeper_mt_la_SOURCES =
+libzookeeper_mt_la_LIBADD=libzkmt.la libhashtable.la -lpthread
+libzookeeper_mt_la_DEPENDENCIES=libzkmt.la libhashtable.la
+libzookeeper_mt_la_LDFLAGS = $(LIB_LDFLAGS) -export-symbols-regex $(EXPORT_SYMBOLS)
+endif
+
+bin_PROGRAMS = cli_st
+
+cli_st_SOURCES = src/cli.c
+cli_st_LDADD = libzookeeper_st.la
+
+if WANT_SYNCAPI
+bin_PROGRAMS += cli_mt load_gen
+
+cli_mt_SOURCES = src/cli.c
+cli_mt_LDADD = libzookeeper_mt.la
+cli_mt_CFLAGS = -DTHREADED
+
+load_gen_SOURCES = src/load_gen.c
+load_gen_LDADD = libzookeeper_mt.la
+load_gen_CFLAGS = -DTHREADED
+
+endif
+
+#########################################################################
+# build and run unit tests
+
+EXTRA_DIST+=$(wildcard ${srcdir}/tests/*.cc) $(wildcard ${srcdir}/tests/*.h) \
+ ${srcdir}/tests/wrappers.opt ${srcdir}/tests/wrappers-mt.opt
+
+TEST_SOURCES = tests/TestDriver.cc tests/LibCMocks.cc tests/LibCSymTable.cc \
+ tests/MocksBase.cc tests/ZKMocks.cc tests/Util.cc tests/ThreadingUtil.cc \
+ tests/TestClientRetry.cc \
+ tests/TestOperations.cc tests/TestZookeeperInit.cc \
+ tests/TestZookeeperClose.cc tests/TestClient.cc \
+ tests/TestMulti.cc tests/TestWatchers.cc
+
+
+if SOLARIS
+ SHELL_SYMBOL_WRAPPERS = cat ${srcdir}/tests/wrappers.opt
+ SYMBOL_WRAPPERS=$(SHELL_SYMBOL_WRAPPERS:sh)
+else
+ SYMBOL_WRAPPERS=$(shell cat ${srcdir}/tests/wrappers.opt)
+endif
+
+check_PROGRAMS = zktest-st
+nodist_zktest_st_SOURCES = $(TEST_SOURCES)
+zktest_st_LDADD = libzkst.la libhashtable.la $(CPPUNIT_LIBS)
+zktest_st_CXXFLAGS = -DUSE_STATIC_LIB $(CPPUNIT_CFLAGS) $(USEIPV6) $(SOLARIS_CPPFLAGS)
+zktest_st_LDFLAGS = -static-libtool-libs $(SYMBOL_WRAPPERS) $(SOLARIS_LIB_LDFLAGS)
+
+if WANT_SYNCAPI
+ check_PROGRAMS += zktest-mt
+ nodist_zktest_mt_SOURCES = $(TEST_SOURCES) tests/PthreadMocks.cc
+ zktest_mt_LDADD = libzkmt.la libhashtable.la -lpthread $(CPPUNIT_LIBS)
+ zktest_mt_CXXFLAGS = -DUSE_STATIC_LIB -DTHREADED $(CPPUNIT_CFLAGS) $(USEIPV6)
+if SOLARIS
+ SHELL_SYMBOL_WRAPPERS_MT = cat ${srcdir}/tests/wrappers-mt.opt
+ SYMBOL_WRAPPERS_MT=$(SYMBOL_WRAPPERS) $(SHELL_SYMBOL_WRAPPERS_MT:sh)
+else
+ SYMBOL_WRAPPERS_MT=$(SYMBOL_WRAPPERS) $(shell cat ${srcdir}/tests/wrappers-mt.opt)
+endif
+ zktest_mt_LDFLAGS = -static-libtool-libs $(SYMBOL_WRAPPERS_MT) $(SOLARIS_LIB_LDFLAGS)
+endif
+
+run-check: check
+ ./zktest-st $(TEST_OPTIONS)
+if WANT_SYNCAPI
+ ./zktest-mt $(TEST_OPTIONS)
+endif
+
+clean-local: clean-check
+ $(RM) $(DX_CLEANFILES)
+
+clean-check:
+ $(RM) $(nodist_zktest_st_OBJECTS) $(nodist_zktest_mt_OBJECTS)
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/NOTICE.txt
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/NOTICE.txt b/zookeeper-client/zookeeper-client-c/NOTICE.txt
new file mode 100644
index 0000000..dcd9d53
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/NOTICE.txt
@@ -0,0 +1,41 @@
+Apache ZooKeeper
+Copyright 2009-2018 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+----------
+include/winstdint.h is included only for Windows Client support, as follows:
+
+// ISO C9x compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+// Copyright (c) 2006-2008 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 3. The name of the author may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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/5694559d/zookeeper-client/zookeeper-client-c/README
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/README b/zookeeper-client/zookeeper-client-c/README
new file mode 100644
index 0000000..1ef2cfd
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/README
@@ -0,0 +1,157 @@
+ Zookeeper C client library
+
+
+This package provides a C client interface to Zookeeper server.
+
+For the latest information about ZooKeeper, please visit our website at:
+ http://zookeeper.apache.org/
+and our wiki, at:
+ https://cwiki.apache.org/confluence/display/ZOOKEEPER
+
+Full documentation for this release can also be found in ../../docs/index.html
+
+
+OVERVIEW
+
+The client supports two types of APIs -- synchronous and asynchronous.
+
+Asynchronous API provides non-blocking operations with completion callbacks and
+relies on the application to implement event multiplexing on its behalf.
+
+On the other hand, Synchronous API provides a blocking flavor of
+zookeeper operations and runs its own event loop in a separate thread.
+
+Sync and Async APIs can be mixed and matched within the same application.
+
+The package includes two shared libraries: zookeeper_st and
+zookeeper_mt. The former only provides the Async API and is not
+thread-safe. The only reason this library exists is to support the
+platforms were pthread library is not available or unstable
+(i.e. FreeBSD 4.x). In all other cases the application developers are
+advised to link against zookeeper_mt as it includes support for both
+Sync and Async API.
+
+
+INSTALLATION
+
+If you're building the client from a source checkout you need to
+follow the steps outlined below. If you're building from a release
+tar downloaded from Apache please skip to step 2.
+
+1) do a "ant compile_jute" from the zookeeper top level directory (.../trunk).
+ This will create a directory named "generated" under zookeeper-client/zookeeper-client-c.
+ Skip to step 3.
+2) unzip/untar the source tarball and cd to the zookeeper-x.x.x/zookeeper-client/zookeeper-client-c directory
+3) change directory to zookeeper-client/zookeeper-client-c and do a "autoreconf -if" to bootstrap
+ autoconf, automake and libtool. Please make sure you have autoconf
+ version 2.59 or greater installed. If cppunit is installed in a non-standard
+ directory, you need to specify where to find cppunit.m4. For example, if
+ cppunit is installed under /usr/local, run:
+
+ ACLOCAL="aclocal -I /usr/local/share/aclocal" autoreconf -if
+
+4) do a "./configure [OPTIONS]" to generate the makefile. See INSTALL
+ for general information about running configure. Additionally, the
+ configure supports the following options:
+ --enable-debug enables optimization and enables debug info compiler
+ options, disabled by default
+ --without-syncapi disables Sync API support; zookeeper_mt library won't
+ be built, enabled by default
+ --disable-static do not build static libraries, enabled by default
+ --disable-shared do not build shared libraries, enabled by default
+ --without-cppunit do not build the test library, enabled by default.
+
+5) do a "make" or "make install" to build the libraries and install them.
+ Alternatively, you can also build and run a unit test suite (and
+ you probably should). Please make sure you have cppunit-1.10.x or
+ higher installed before you execute step 4. Once ./configure has
+ finished, do a "make run-check". It will build the libraries, build
+ the tests and run them.
+6) to generate doxygen documentation do a "make doxygen-doc". All
+ documentations will be placed to a new subfolder named docs. By
+ default only HTML documentation is generated. For information on
+ other document formats please use "./configure --help"
+
+Alternatively you can use the CMake build system. On Windows, this is required.
+Follow steps 1 and 2 above, and then continue here.
+
+1) do a "cmake [OPTIONS]" to generate the makefile or msbuild files (the correct
+ build system will be generated based on your platform). Some options from above
+ are supported:
+ -DCMAKE_BUILD_TYPE Debug by default, Release enables optimzation etc.
+ -DWANT_SYNCAPI ON by default, OFF disables the Sync API support
+ -DWANT_CPPUNIT ON except on Windows, OFF disables the tests
+ -DBUILD_SHARED_LIBS not yet supported, only static libraries are built
+ other CMake options see "cmake --help" for generic options, such as generator
+
+2) do a "cmake --build ." to build the default targets. Alternatively you can
+ invoke "make" or "msbuild" manually. If the tests were enabled, use "ctest -V"
+ to run them.
+
+Current limitations of the CMake build system include lack of Solaris support,
+no shared library option, no explicitly exported symbols (all are exported by
+default), no versions on the libraries, and no documentation generation.
+Features of CMake include a single, easily consumed cross-platform build system
+to generate the ZooKeeper C Client libraries for any project, with little to no
+configuration.
+
+EXAMPLE/SAMPLE C CLIENT SHELL
+
+NOTE: the ZooKeeper C client shell (cli_st and cli_mt) is meant as a
+example/sample of ZooKeeper C client API usage. It is not a full
+fledged client and not meant for production usage - see the Java
+client shell for a fully featured shell.
+
+You can test your client by running a zookeeper server (see
+instructions on the project wiki page on how to run it) and connecting
+to it using the zookeeper shell application cli that is built as part
+of the installation procedure.
+
+cli_mt (multithreaded, built against zookeeper_mt library) is shown in
+this example, but you could also use cli_st (singlethreaded, built
+against zookeeper_st library):
+
+$ cli_mt zookeeper_host:9876
+
+This is a client application that gives you a shell for executing
+simple zookeeper commands. Once successfully started and connected to
+the server it displays a shell prompt.
+
+You can now enter zookeeper commands. For example, to create a node:
+
+> create /my_new_node
+
+To verify that the node's been created:
+
+> ls /
+
+You should see a list of nodes who are the children of the root node "/".
+
+Here's a list of command supported by the cli shell:
+
+ls <path> -- list children of a znode identified by <path>. The
+ command set a children watch on the znode.
+get <path> -- get the value of a znode at <path>
+set <path> <value> -- set the value of a znode at <path> to <value>
+create [+e|+s] <path> -- create a znode as a child of znode <path>;
+ use +e option to create an ephemeral znode,
+ use +s option to create a znode with a sequence number
+ appended to the name. The operation will fail if
+ the parent znode (the one identified by <path>) doesn't
+ exist.
+delete <path> -- delete the znode at <path>. The command will fail if the znode
+ has children.
+sync <path> -- make sure all pending updates have been applied to znode at <path>
+exists <path> -- returns a result code indicating whether the znode at <path>
+ exists. The command also sets a znode watch.
+myid -- prints out the current zookeeper session id.
+quit -- exit the shell.
+
+In order to be able to use the zookeeper API in your application you have to
+1) remember to include the zookeeper header
+ #include <zookeeper/zookeeper.h>
+2) use -DTHREADED compiler option to enable Sync API; in this case you should
+ be linking your code against zookeeper_mt library
+
+Please take a look at cli.c to understand how to use the two API types.
+(TODO: some kind of short tutorial would be helpful, I guess)
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/acinclude.m4
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/acinclude.m4 b/zookeeper-client/zookeeper-client-c/acinclude.m4
new file mode 100644
index 0000000..d0041d8
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/acinclude.m4
@@ -0,0 +1,312 @@
+# This file is part of Autoconf. -*- Autoconf -*-
+
+# Copyright (C) 2004 Oren Ben-Kiki
+# This file is distributed under the same terms as the Autoconf macro files.
+
+# Generate automatic documentation using Doxygen. Works in concert with the
+# aminclude.m4 file and a compatible doxygen configuration file. Defines the
+# following public macros:
+#
+# DX_???_FEATURE(ON|OFF) - control the default setting fo a Doxygen feature.
+# Supported features are 'DOXYGEN' itself, 'DOT' for generating graphics,
+# 'HTML' for plain HTML, 'CHM' for compressed HTML help (for MS users), 'CHI'
+# for generating a seperate .chi file by the .chm file, and 'MAN', 'RTF',
+# 'XML', 'PDF' and 'PS' for the appropriate output formats. The environment
+# variable DOXYGEN_PAPER_SIZE may be specified to override the default 'a4wide'
+# paper size.
+#
+# By default, HTML, PDF and PS documentation is generated as this seems to be
+# the most popular and portable combination. MAN pages created by Doxygen are
+# usually problematic, though by picking an appropriate subset and doing some
+# massaging they might be better than nothing. CHM and RTF are specific for MS
+# (note that you can't generate both HTML and CHM at the same time). The XML is
+# rather useless unless you apply specialized post-processing to it.
+#
+# The macro mainly controls the default state of the feature. The use can
+# override the default by specifying --enable or --disable. The macros ensure
+# that contradictory flags are not given (e.g., --enable-doxygen-html and
+# --enable-doxygen-chm, --enable-doxygen-anything with --disable-doxygen, etc.)
+# Finally, each feature will be automatically disabled (with a warning) if the
+# required programs are missing.
+#
+# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN with
+# the following parameters: a one-word name for the project for use as a
+# filename base etc., an optional configuration file name (the default is
+# 'Doxyfile', the same as Doxygen's default), and an optional output directory
+# name (the default is 'doxygen-doc').
+
+## ----------##
+## Defaults. ##
+## ----------##
+
+DX_ENV=""
+AC_DEFUN([DX_FEATURE_doc], ON)
+AC_DEFUN([DX_FEATURE_dot], ON)
+AC_DEFUN([DX_FEATURE_man], OFF)
+AC_DEFUN([DX_FEATURE_html], ON)
+AC_DEFUN([DX_FEATURE_chm], OFF)
+AC_DEFUN([DX_FEATURE_chi], OFF)
+AC_DEFUN([DX_FEATURE_rtf], OFF)
+AC_DEFUN([DX_FEATURE_xml], OFF)
+AC_DEFUN([DX_FEATURE_pdf], ON)
+AC_DEFUN([DX_FEATURE_ps], ON)
+
+## --------------- ##
+## Private macros. ##
+## --------------- ##
+
+# DX_ENV_APPEND(VARIABLE, VALUE)
+# ------------------------------
+# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen.
+AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])])
+
+# DX_DIRNAME_EXPR
+# ---------------
+# Expand into a shell expression prints the directory part of a path.
+AC_DEFUN([DX_DIRNAME_EXPR],
+ [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
+
+# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
+# -------------------------------------
+# Expands according to the M4 (static) status of the feature.
+AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
+
+# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
+# ----------------------------------
+# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
+AC_DEFUN([DX_REQUIRE_PROG], [
+AC_PATH_TOOL([$1], [$2])
+if test "$DX_FLAG_$[DX_CURRENT_FEATURE$$1]" = 1; then
+ AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
+ AC_SUBST([DX_FLAG_]DX_CURRENT_FEATURE, 0)
+fi
+])
+
+# DX_TEST_FEATURE(FEATURE)
+# ------------------------
+# Expand to a shell expression testing whether the feature is active.
+AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
+
+# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
+# -------------------------------------------------
+# Verify that a required features has the right state before trying to turn on
+# the DX_CURRENT_FEATURE.
+AC_DEFUN([DX_CHECK_DEPEND], [
+test "$DX_FLAG_$1" = "$2" \
+|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
+ requires, contradicts) doxygen-DX_CURRENT_FEATURE])
+])
+
+# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
+# ----------------------------------------------------------
+# Turn off the DX_CURRENT_FEATURE if the required feature is off.
+AC_DEFUN([DX_CLEAR_DEPEND], [
+test "$DX_FLAG_$1" = "$2" || AC_SUBST([DX_FLAG_]DX_CURRENT_FEATURE, 0)
+])
+
+# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
+# CHECK_DEPEND, CLEAR_DEPEND,
+# REQUIRE, DO-IF-ON, DO-IF-OFF)
+# --------------------------------------------
+# Parse the command-line option controlling a feature. CHECK_DEPEND is called
+# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
+# otherwise CLEAR_DEPEND is called to turn off the default state if a required
+# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
+# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
+# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
+AC_DEFUN([DX_ARG_ABLE], [
+ AC_DEFUN([DX_CURRENT_FEATURE], [$1])
+ AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
+ AC_ARG_ENABLE(doxygen-$1,
+ [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
+ [--enable-doxygen-$1]),
+ DX_IF_FEATURE([$1], [don't $2], [$2]))],
+ [
+case "$enableval" in
+#(
+y|Y|yes|Yes|YES)
+ AC_SUBST([DX_FLAG_$1], 1)
+ $3
+;; #(
+n|N|no|No|NO)
+ AC_SUBST([DX_FLAG_$1], 0)
+;; #(
+*)
+ AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
+;;
+esac
+], [
+AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
+$4
+])
+if DX_TEST_FEATURE([$1]); then
+ $5
+ :
+fi
+if DX_TEST_FEATURE([$1]); then
+ AM_CONDITIONAL(DX_COND_$1, :)
+ $6
+ :
+else
+ AM_CONDITIONAL(DX_COND_$1, false)
+ $7
+ :
+fi
+])
+
+## -------------- ##
+## Public macros. ##
+## -------------- ##
+
+# DX_XXX_FEATURE(DEFAULT_STATE)
+# -----------------------------
+AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])])
+AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])])
+AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])])
+AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])])
+AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])])
+AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])])
+AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
+AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
+AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])])
+AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])])
+
+# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR])
+# ---------------------------------------------------------
+# PROJECT also serves as the base name for the documentation files.
+# The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc".
+AC_DEFUN([DX_INIT_DOXYGEN], [
+
+# Files:
+AC_SUBST([DX_PROJECT], [$1])
+AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])])
+AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])])
+
+# Environment variables used inside doxygen.cfg:
+DX_ENV_APPEND(SRCDIR, $srcdir)
+DX_ENV_APPEND(PROJECT, $DX_PROJECT)
+DX_ENV_APPEND(DOCDIR, $DX_DOCDIR)
+DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
+
+# Doxygen itself:
+DX_ARG_ABLE(doc, [generate any doxygen documentation],
+ [],
+ [],
+ [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
+ DX_REQUIRE_PROG([DX_PERL], perl)],
+ [DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
+
+# Dot for graphics:
+DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_DOT], dot)],
+ [DX_ENV_APPEND(HAVE_DOT, YES)
+ DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
+ [DX_ENV_APPEND(HAVE_DOT, NO)])
+
+# Man pages generation:
+DX_ARG_ABLE(man, [generate doxygen manual pages],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_MAN, YES)],
+ [DX_ENV_APPEND(GENERATE_MAN, NO)])
+
+# RTF file generation:
+DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_RTF, YES)],
+ [DX_ENV_APPEND(GENERATE_RTF, NO)])
+
+# XML file generation:
+DX_ARG_ABLE(xml, [generate doxygen XML documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_XML, YES)],
+ [DX_ENV_APPEND(GENERATE_XML, NO)])
+
+# (Compressed) HTML help generation:
+DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_HHC], hhc)],
+ [DX_ENV_APPEND(HHC_PATH, $DX_HHC)
+ DX_ENV_APPEND(GENERATE_HTML, YES)
+ DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
+ [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
+
+# Seperate CHI file generation.
+DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file],
+ [DX_CHECK_DEPEND(chm, 1)],
+ [DX_CLEAR_DEPEND(chm, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_CHI, YES)],
+ [DX_ENV_APPEND(GENERATE_CHI, NO)])
+
+# Plain HTML pages generation:
+DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
+ [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
+ [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
+ [],
+ [DX_ENV_APPEND(GENERATE_HTML, YES)],
+ [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
+
+# PostScript file generation:
+DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_LATEX], latex)
+ DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+ DX_REQUIRE_PROG([DX_DVIPS], dvips)
+ DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# PDF file generation:
+DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
+ DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+ DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# LaTeX generation for PS and/or PDF:
+if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
+ AM_CONDITIONAL(DX_COND_latex, :)
+ DX_ENV_APPEND(GENERATE_LATEX, YES)
+else
+ AM_CONDITIONAL(DX_COND_latex, false)
+ DX_ENV_APPEND(GENERATE_LATEX, NO)
+fi
+
+# Paper size for PS and/or PDF:
+AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
+ [a4wide (default), a4, letter, legal or executive])
+case "$DOXYGEN_PAPER_SIZE" in
+#(
+"")
+ AC_SUBST(DOXYGEN_PAPER_SIZE, "")
+;; #(
+a4wide|a4|letter|legal|executive)
+ DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
+;; #(
+*)
+ AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
+;;
+esac
+
+#For debugging:
+#echo DX_FLAG_doc=$DX_FLAG_doc
+#echo DX_FLAG_dot=$DX_FLAG_dot
+#echo DX_FLAG_man=$DX_FLAG_man
+#echo DX_FLAG_html=$DX_FLAG_html
+#echo DX_FLAG_chm=$DX_FLAG_chm
+#echo DX_FLAG_chi=$DX_FLAG_chi
+#echo DX_FLAG_rtf=$DX_FLAG_rtf
+#echo DX_FLAG_xml=$DX_FLAG_xml
+#echo DX_FLAG_pdf=$DX_FLAG_pdf
+#echo DX_FLAG_ps=$DX_FLAG_ps
+#echo DX_ENV=$DX_ENV
+])
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/aminclude.am
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/aminclude.am b/zookeeper-client/zookeeper-client-c/aminclude.am
new file mode 100644
index 0000000..420049e
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/aminclude.am
@@ -0,0 +1,186 @@
+# Copyright (C) 2004 Oren Ben-Kiki
+# This file is distributed under the same terms as the Automake macro files.
+
+# Generate automatic documentation using Doxygen. Goals and variables values
+# are controlled by the various DX_COND_??? conditionals set by autoconf.
+#
+# The provided goals are:
+# doxygen-doc: Generate all doxygen documentation.
+# doxygen-run: Run doxygen, which will generate some of the documentation
+# (HTML, CHM, CHI, MAN, RTF, XML) but will not do the post
+# processing required for the rest of it (PS, PDF, and some MAN).
+# doxygen-man: Rename some doxygen generated man pages.
+# doxygen-ps: Generate doxygen PostScript documentation.
+# doxygen-pdf: Generate doxygen PDF documentation.
+#
+# Note that by default these are not integrated into the automake goals. If
+# doxygen is used to generate man pages, you can achieve this integration by
+# setting man3_MANS to the list of man pages generated and then adding the
+# dependency:
+#
+# $(man3_MANS): doxygen-doc
+#
+# This will cause make to run doxygen and generate all the documentation.
+#
+# The following variable is intended for use in Makefile.am:
+#
+# DX_CLEANFILES = everything to clean.
+#
+# This is usually added to MOSTLYCLEANFILES.
+
+## --------------------------------- ##
+## Format-independent Doxygen rules. ##
+## --------------------------------- ##
+
+if DX_COND_doc
+
+## ------------------------------- ##
+## Rules specific for HTML output. ##
+## ------------------------------- ##
+
+if DX_COND_html
+
+DX_CLEAN_HTML = @DX_DOCDIR@/html
+
+endif DX_COND_html
+
+## ------------------------------ ##
+## Rules specific for CHM output. ##
+## ------------------------------ ##
+
+if DX_COND_chm
+
+DX_CLEAN_CHM = @DX_DOCDIR@/chm
+
+if DX_COND_chi
+
+DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi
+
+endif DX_COND_chi
+
+endif DX_COND_chm
+
+## ------------------------------ ##
+## Rules specific for MAN output. ##
+## ------------------------------ ##
+
+if DX_COND_man
+
+DX_CLEAN_MAN = @DX_DOCDIR@/man
+
+endif DX_COND_man
+
+## ------------------------------ ##
+## Rules specific for RTF output. ##
+## ------------------------------ ##
+
+if DX_COND_rtf
+
+DX_CLEAN_RTF = @DX_DOCDIR@/rtf
+
+endif DX_COND_rtf
+
+## ------------------------------ ##
+## Rules specific for XML output. ##
+## ------------------------------ ##
+
+if DX_COND_xml
+
+DX_CLEAN_XML = @DX_DOCDIR@/xml
+
+endif DX_COND_xml
+
+## ----------------------------- ##
+## Rules specific for PS output. ##
+## ----------------------------- ##
+
+if DX_COND_ps
+
+DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps
+
+DX_PS_GOAL = doxygen-ps
+
+doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps
+
+@DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag
+ cd @DX_DOCDIR@/latex; \
+ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
+ $(DX_LATEX) refman.tex; \
+ $(MAKEINDEX_PATH) refman.idx; \
+ $(DX_LATEX) refman.tex; \
+ countdown=5; \
+ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
+ refman.log > /dev/null 2>&1 \
+ && test $$countdown -gt 0; do \
+ $(DX_LATEX) refman.tex; \
+ countdown=`expr $$countdown - 1`; \
+ done; \
+ $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi
+
+endif DX_COND_ps
+
+## ------------------------------ ##
+## Rules specific for PDF output. ##
+## ------------------------------ ##
+
+if DX_COND_pdf
+
+DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf
+
+DX_PDF_GOAL = doxygen-pdf
+
+doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf
+
+@DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag
+ cd @DX_DOCDIR@/latex; \
+ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
+ $(DX_PDFLATEX) refman.tex; \
+ $(DX_MAKEINDEX) refman.idx; \
+ $(DX_PDFLATEX) refman.tex; \
+ countdown=5; \
+ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
+ refman.log > /dev/null 2>&1 \
+ && test $$countdown -gt 0; do \
+ $(DX_PDFLATEX) refman.tex; \
+ countdown=`expr $$countdown - 1`; \
+ done; \
+ mv refman.pdf ../@PACKAGE@.pdf
+
+endif DX_COND_pdf
+
+## ------------------------------------------------- ##
+## Rules specific for LaTeX (shared for PS and PDF). ##
+## ------------------------------------------------- ##
+
+if DX_COND_latex
+
+DX_CLEAN_LATEX = @DX_DOCDIR@/latex
+
+endif DX_COND_latex
+
+.PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL)
+
+.INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
+
+doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag
+
+doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
+
+@DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS)
+ rm -rf @DX_DOCDIR@
+ $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
+
+DX_CLEANFILES = \
+ @DX_DOCDIR@/@PACKAGE@.tag \
+ -r \
+ $(DX_CLEAN_HTML) \
+ $(DX_CLEAN_CHM) \
+ $(DX_CLEAN_CHI) \
+ $(DX_CLEAN_MAN) \
+ $(DX_CLEAN_RTF) \
+ $(DX_CLEAN_XML) \
+ $(DX_CLEAN_PS) \
+ $(DX_CLEAN_PDF) \
+ $(DX_CLEAN_LATEX)
+
+endif DX_COND_doc
[19/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/c-doc.Doxyfile
----------------------------------------------------------------------
diff --git a/src/c/c-doc.Doxyfile b/src/c/c-doc.Doxyfile
deleted file mode 100644
index e9029cb..0000000
--- a/src/c/c-doc.Doxyfile
+++ /dev/null
@@ -1,1252 +0,0 @@
-# Doxyfile 1.4.7
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
-#
-# All text after a hash (#) is considered a comment and will be ignored
-# The format is:
-# TAG = value [value, ...]
-# For lists items can also be appended using:
-# TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
-# by quotes) that should identify the project.
-
-PROJECT_NAME = $(PROJECT)-$(VERSION)
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
-# if some version control system is used.
-
-PROJECT_NUMBER =
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
-# where doxygen was started. If left blank the current directory will be used.
-
-OUTPUT_DIRECTORY = $(DOCDIR)
-
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
-# otherwise cause performance problems for the file system.
-
-CREATE_SUBDIRS = NO
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all
-# documentation generated by doxygen is written. Doxygen will use this
-# information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
-# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
-# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
-# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
-# Swedish, and Ukrainian.
-
-OUTPUT_LANGUAGE = English
-
-# This tag can be used to specify the encoding used in the generated output.
-# The encoding is not always determined by the language that is chosen,
-# but also whether or not the output is meant for Windows or non-Windows users.
-# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
-# forces the Windows encoding (this is the default for the Windows binary),
-# whereas setting the tag to NO uses a Unix-style encoding (the default for
-# all platforms other than Windows).
-
-USE_WINDOWS_ENCODING = NO
-
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
-# brief descriptions will be completely suppressed.
-
-REPEAT_BRIEF = YES
-
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
-# "represents" "a" "an" "the"
-
-ABBREVIATE_BRIEF =
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
-# description.
-
-ALWAYS_DETAILED_SEC = NO
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
-# inherited members of a class in the documentation of that class as if those
-# members were ordinary class members. Constructors, destructors and assignment
-# operators of the base classes will not be shown.
-
-INLINE_INHERITED_MEMB = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES = YES
-
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
-# path to strip.
-
-STRIP_FROM_PATH =
-
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
-# are normally passed to the compiler using the -I flag.
-
-STRIP_FROM_INC_PATH =
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful is your file systems
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES = NO
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like the Qt-style comments (thus requiring an
-# explicit @brief command for a brief description.
-
-JAVADOC_AUTOBRIEF = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member
-# documentation.
-
-DETAILS_AT_TOP = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# re-implements.
-
-INHERIT_DOCS = YES
-
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
-# be part of the file/class/namespace that contains it.
-
-SEPARATE_MEMBER_PAGES = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
-
-TAB_SIZE = 8
-
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES =
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
-# of all members will be omitted, etc.
-
-OPTIMIZE_OUTPUT_FOR_C = YES
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for Java.
-# For instance, namespaces will be presented as packages, qualified scopes
-# will look different, etc.
-
-OPTIMIZE_OUTPUT_JAVA = NO
-
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
-# include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also make the inheritance and collaboration
-# diagrams that involve STL classes more complete and accurate.
-
-BUILTIN_STL_SUPPORT = NO
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC = NO
-
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
-# the \nosubgrouping command.
-
-SUBGROUPING = YES
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-
-EXTRACT_ALL = NO
-
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
-# will be included in the documentation.
-
-EXTRACT_PRIVATE = NO
-
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
-# will be included in the documentation.
-
-EXTRACT_STATIC = YES
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
-# If set to NO only classes defined in header files are included.
-
-EXTRACT_LOCAL_CLASSES = YES
-
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
-# If set to NO (the default) only methods in the interface are included.
-
-EXTRACT_LOCAL_METHODS = NO
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
-# This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_MEMBERS = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_CLASSES = NO
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
-# documentation.
-
-HIDE_FRIEND_COMPOUNDS = NO
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
-# function's detailed documentation block.
-
-HIDE_IN_BODY_DOCS = NO
-
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
-# Set it to YES to include the internal documentation.
-
-INTERNAL_DOCS = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-
-CASE_SENSE_NAMES = YES
-
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
-# documentation. If set to YES the scope will be hidden.
-
-HIDE_SCOPE_NAMES = NO
-
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
-# of that file.
-
-SHOW_INCLUDE_FILES = NO
-
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
-# is inserted in the documentation for inline members.
-
-INLINE_INFO = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
-# declaration order.
-
-SORT_MEMBER_DOCS = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
-# declaration order.
-
-SORT_BRIEF_DOCS = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
-# alphabetical list.
-
-SORT_BY_SCOPE_NAME = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
-# commands in the documentation.
-
-GENERATE_TODOLIST = YES
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
-# commands in the documentation.
-
-GENERATE_TESTLIST = YES
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
-# commands in the documentation.
-
-GENERATE_BUGLIST = YES
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
-# \deprecated commands in the documentation.
-
-GENERATE_DEPRECATEDLIST = YES
-
-# The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if sectionname ... \endif.
-
-ENABLED_SECTIONS =
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or define consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and defines in the
-# documentation can be controlled using \showinitializer or \hideinitializer
-# command in the documentation regardless of this setting.
-
-MAX_INITIALIZER_LINES = 30
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
-# list will mention the files that were used to generate the documentation.
-
-SHOW_USED_FILES = YES
-
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = NO
-
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that
-# doxygen should invoke to get the current version for each file (typically from the
-# version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
-# is used as the file version. See the manual for examples.
-
-FILE_VERSION_FILTER =
-
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
-
-QUIET = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
-# NO is used.
-
-WARNINGS = YES
-
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
-# automatically be disabled.
-
-WARN_IF_UNDOCUMENTED = YES
-
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
-# don't exist or using markup commands wrongly.
-
-WARN_IF_DOC_ERROR = YES
-
-# This WARN_NO_PARAMDOC option can be abled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
-# documentation.
-
-WARN_NO_PARAMDOC = NO
-
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
-# be obtained via FILE_VERSION_FILTER)
-
-WARN_FORMAT = "$file:$line: $text"
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
-# to stderr.
-
-WARN_LOGFILE =
-
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
-# with spaces.
-
-INPUT = include/zookeeper.h
-
-# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
-# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
-
-FILE_PATTERNS =
-
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
-# If left blank NO is used.
-
-RECURSIVE = NO
-
-# The EXCLUDE tag can be used to specify files and/or directories that should
-# excluded from the INPUT source files. This way you can easily exclude a
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-
-EXCLUDE =
-
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
-# directories that are symbolic links (a Unix filesystem feature) are excluded
-# from the input.
-
-EXCLUDE_SYMLINKS = NO
-
-# If the value of the INPUT tag contains directories, you can use the
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
-# for example use the pattern */test/*
-
-EXCLUDE_PATTERNS =
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
-# the \include command).
-
-EXAMPLE_PATH =
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank all files are included.
-
-EXAMPLE_PATTERNS =
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
-# Possible values are YES and NO. If left blank NO is used.
-
-EXAMPLE_RECURSIVE = NO
-
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
-# the \image command).
-
-IMAGE_PATH =
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output. If FILTER_PATTERNS is specified, this tag will be
-# ignored.
-
-INPUT_FILTER =
-
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis. Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match. The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
-# is applied to all files.
-
-FILTER_PATTERNS =
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
-
-FILTER_SOURCE_FILES = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
-# VERBATIM_HEADERS is set to NO.
-
-SOURCE_BROWSER = NO
-
-# Setting the INLINE_SOURCES tag to YES will include the body
-# of functions and classes directly in the documentation.
-
-INLINE_SOURCES = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C and C++ comments will always remain visible.
-
-STRIP_CODE_COMMENTS = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES (the default)
-# then for each documented function all documented
-# functions referencing it will be listed.
-
-REFERENCED_BY_RELATION = YES
-
-# If the REFERENCES_RELATION tag is set to YES (the default)
-# then for each documented function all documented entities
-# called/used by that function will be listed.
-
-REFERENCES_RELATION = YES
-
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code. Otherwise they will link to the documentstion.
-
-REFERENCES_LINK_SOURCE = YES
-
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
-# will need version 4.8.6 or higher.
-
-USE_HTAGS = NO
-
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
-# contains a lot of classes, structs, unions or interfaces.
-
-ALPHABETICAL_INDEX = NO
-
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
-# in which this list will be split (can be a number in the range [1..20])
-
-COLS_IN_ALPHA_INDEX = 5
-
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
-# should be ignored while generating the index headers.
-
-IGNORE_PREFIX =
-
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
-# generate HTML output.
-
-GENERATE_HTML = $(GENERATE_HTML)
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `html' will be used as the default path.
-
-HTML_OUTPUT = html
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
-# doxygen will generate files with .html extension.
-
-HTML_FILE_EXTENSION = .html
-
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard header.
-
-HTML_HEADER =
-
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard footer.
-
-HTML_FOOTER =
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
-# stylesheet in the HTML output directory as well, or it will be erased!
-
-HTML_STYLESHEET =
-
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS = YES
-
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
-# of the generated HTML documentation.
-
-GENERATE_HTMLHELP = $(GENERATE_HTMLHELP)
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
-# written to the html output directory.
-
-CHM_FILE = ../$(PROJECT).chm
-
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
-# the HTML help compiler on the generated index.hhp.
-
-HHC_LOCATION = $(HHC_PATH)
-
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
-# it should be included in the master .chm file (NO).
-
-GENERATE_CHI = $(GENERATE_CHI)
-
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
-# normal table of contents (NO) in the .chm file.
-
-BINARY_TOC = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
-# to the contents of the HTML help documentation and to the tree view.
-
-TOC_EXPAND = NO
-
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
-# top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it.
-
-DISABLE_INDEX = NO
-
-# This tag can be used to set the number of enum values (range [1..20])
-# that doxygen will group on one line in the generated HTML documentation.
-
-ENUM_VALUES_PER_LINE = 4
-
-# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
-# generated containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
-# probably better off using the HTML help feature.
-
-GENERATE_TREEVIEW = NO
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
-# is shown.
-
-TREEVIEW_WIDTH = 250
-
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
-# generate Latex output.
-
-GENERATE_LATEX = $(GENERATE_LATEX)
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `latex' will be used as the default path.
-
-LATEX_OUTPUT = latex
-
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
-# invoked. If left blank `latex' will be used as the default command name.
-
-LATEX_CMD_NAME = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
-# default command name.
-
-MAKEINDEX_CMD_NAME = makeindex
-
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
-# save some trees in general.
-
-COMPACT_LATEX = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, a4wide, letter, legal and
-# executive. If left blank a4wide will be used.
-
-PAPER_TYPE = $(PAPER_SIZE)
-
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
-# packages that should be included in the LaTeX output.
-
-EXTRA_PACKAGES =
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
-# standard header. Notice: only use this tag if you know what you are doing!
-
-LATEX_HEADER =
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
-# This makes the output suitable for online browsing using a pdf viewer.
-
-PDF_HYPERLINKS = NO
-
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
-# higher quality PDF documentation.
-
-USE_PDFLATEX = $(GENERATE_PDF)
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
-# This option is also used when generating formulas in HTML.
-
-LATEX_BATCHMODE = NO
-
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
-# in the output.
-
-LATEX_HIDE_INDICES = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
-# other RTF readers or editors.
-
-GENERATE_RTF = $(GENERATE_RTF)
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `rtf' will be used as the default path.
-
-RTF_OUTPUT = rtf
-
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
-# save some trees in general.
-
-COMPACT_RTF = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
-# Note: wordpad (write) and others do not support links.
-
-RTF_HYPERLINKS = NO
-
-# Load stylesheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
-# replacements, missing definitions are set to their default value.
-
-RTF_STYLESHEET_FILE =
-
-# Set optional variables used in the generation of an rtf document.
-# Syntax is similar to doxygen's config file.
-
-RTF_EXTENSIONS_FILE =
-
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
-# generate man pages
-
-GENERATE_MAN = $(GENERATE_MAN)
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `man' will be used as the default path.
-
-MAN_OUTPUT = man
-
-# The MAN_EXTENSION tag determines the extension that is added to
-# the generated man pages (default is the subroutine's section .3)
-
-MAN_EXTENSION = .3
-
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
-# would be unable to find the correct page. The default is NO.
-
-MAN_LINKS = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
-# the code including all documentation.
-
-GENERATE_XML = $(GENERATE_XML)
-
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `xml' will be used as the default path.
-
-XML_OUTPUT = xml
-
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_SCHEMA =
-
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_DTD =
-
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
-# enabling this will significantly increase the size of the XML output.
-
-XML_PROGRAMLISTING = YES
-
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
-# and incomplete at the moment.
-
-GENERATE_AUTOGEN_DEF = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
-
-GENERATE_PERLMOD = NO
-
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
-# to generate PDF and DVI output from the Perl module output.
-
-PERLMOD_LATEX = NO
-
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader. This is useful
-# if you want to understand what is going on. On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
-# and Perl will parse it just the same.
-
-PERLMOD_PRETTY = YES
-
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
-# Makefile don't overwrite each other's variables.
-
-PERLMOD_MAKEVAR_PREFIX =
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
-# files.
-
-ENABLE_PREPROCESSING = YES
-
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
-# way by setting EXPAND_ONLY_PREDEF to YES.
-
-MACRO_EXPANSION = NO
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
-# PREDEFINED and EXPAND_AS_DEFINED tags.
-
-EXPAND_ONLY_PREDEF = NO
-
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
-
-SEARCH_INCLUDES = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
-# the preprocessor.
-
-INCLUDE_PATH =
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
-# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
-# be used.
-
-INCLUDE_FILE_PATTERNS =
-
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
-# instead of the = operator.
-
-PREDEFINED =
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition.
-
-EXPAND_AS_DEFINED =
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all function-like macros that are alone
-# on a line, have an all uppercase name, and do not end with a semicolon. Such
-# function macros are typically used for boiler-plate code, and will confuse
-# the parser if not removed.
-
-SKIP_FUNCTION_MACROS = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references
-#---------------------------------------------------------------------------
-
-# The TAGFILES option can be used to specify one or more tagfiles.
-# Optionally an initial location of the external documentation
-# can be added for each tagfile. The format of a tag file without
-# this location is as follows:
-# TAGFILES = file1 file2 ...
-# Adding location for the tag files is done as follows:
-# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths or
-# URLs. If a location is present for each tag, the installdox tool
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen
-# is run, you must also specify the path to the tagfile here.
-
-TAGFILES =
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
-# a tag file that is based on the input files it reads.
-
-GENERATE_TAGFILE = $(DOCDIR)/$(PROJECT).tag
-
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
-# will be listed.
-
-ALLEXTERNALS = NO
-
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
-# be listed.
-
-EXTERNAL_GROUPS = YES
-
-# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of `which perl').
-
-PERL_PATH = /usr/bin/perl
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
-#---------------------------------------------------------------------------
-
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option is superseded by the HAVE_DOT option below. This is only a
-# fallback. It is recommended to install and use dot, since it yields more
-# powerful graphs.
-
-CLASS_DIAGRAMS = YES
-
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
-# or is not a class.
-
-HIDE_UNDOC_RELATIONS = YES
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
-# have no effect if this option is set to NO (the default)
-
-HAVE_DOT = $(HAVE_DOT)
-
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
-# the CLASS_DIAGRAMS tag to NO.
-
-CLASS_GRAPH = YES
-
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
-# class references variables) of the class with other documented classes.
-
-COLLABORATION_GRAPH = YES
-
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for groups, showing the direct groups dependencies
-
-GROUP_GRAPHS = YES
-
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
-# collaboration diagrams in a style similar to the OMG's Unified Modeling
-# Language.
-
-UML_LOOK = NO
-
-# If set to YES, the inheritance and collaboration graphs will show the
-# relations between templates and their instances.
-
-TEMPLATE_RELATIONS = NO
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
-# other documented files.
-
-INCLUDE_GRAPH = YES
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
-# indirectly include this file.
-
-INCLUDED_BY_GRAPH = YES
-
-# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
-# generate a call dependency graph for every global function or class method.
-# Note that enabling this option will significantly increase the time of a run.
-# So in most cases it will be better to enable call graphs for selected
-# functions only using the \callgraph command.
-
-CALL_GRAPH = NO
-
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
-# generate a caller dependency graph for every global function or class method.
-# Note that enabling this option will significantly increase the time of a run.
-# So in most cases it will be better to enable caller graphs for selected
-# functions only using the \callergraph command.
-
-CALLER_GRAPH = NO
-
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will graphical hierarchy of all classes instead of a textual one.
-
-GRAPHICAL_HIERARCHY = YES
-
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
-# in a graphical way. The dependency relations are determined by the #include
-# relations between the files in the directories.
-
-DIRECTORY_GRAPH = YES
-
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are png, jpg, or gif
-# If left blank png will be used.
-
-DOT_IMAGE_FORMAT = png
-
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
-# found. If left blank, it is assumed the dot tool can be found in the path.
-
-DOT_PATH = $(DOT_PATH)
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
-# \dotfile command).
-
-DOTFILE_DIRS =
-
-# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than
-# this value, doxygen will try to truncate the graph, so that it fits within
-# the specified constraint. Beware that most browsers cannot cope with very
-# large images.
-
-MAX_DOT_GRAPH_WIDTH = 1024
-
-# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than
-# this value, doxygen will try to truncate the graph, so that it fits within
-# the specified constraint. Beware that most browsers cannot cope with very
-# large images.
-
-MAX_DOT_GRAPH_HEIGHT = 1024
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
-# graphs generated by dot. A depth value of 3 means that only nodes reachable
-# from the root by following a path via at most 3 edges will be shown. Nodes
-# that lay further from the root node will be omitted. Note that setting this
-# option to 1 or 2 may greatly reduce the computation time needed for large
-# code bases. Also note that a graph may be further truncated if the graph's
-# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
-# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
-# the graph is not depth-constrained.
-
-MAX_DOT_GRAPH_DEPTH = 0
-
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, which results in a white background.
-# Warning: Depending on the platform used, enabling this option may lead to
-# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
-# read).
-
-DOT_TRANSPARENT = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
-# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
-# support this, this feature is disabled by default.
-
-DOT_MULTI_TARGETS = NO
-
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
-# arrows in the dot generated graphs.
-
-GENERATE_LEGEND = YES
-
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
-# the various graphs.
-
-DOT_CLEANUP = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine
-#---------------------------------------------------------------------------
-
-# The SEARCHENGINE tag specifies whether or not a search engine should be
-# used. If set to NO the values of all tags below this one will be ignored.
-
-SEARCHENGINE = NO
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/cmake_config.h.in
----------------------------------------------------------------------
diff --git a/src/c/cmake_config.h.in b/src/c/cmake_config.h.in
deleted file mode 100644
index 55efd8a..0000000
--- a/src/c/cmake_config.h.in
+++ /dev/null
@@ -1,154 +0,0 @@
-/**
- * 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 CONFIG_H_
-#define CONFIG_H_
-
-/* Define to 1 if you have the <arpa/inet.h> header file. */
-#cmakedefine HAVE_ARPA_INET_H 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#cmakedefine HAVE_DLFCN_H 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#cmakedefine HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the file `generated/zookeeper.jute.c'. */
-#cmakedefine HAVE_GENERATED_ZOOKEEPER_JUTE_C 1
-
-/* Define to 1 if you have the file `generated/zookeeper.jute.h'. */
-#cmakedefine HAVE_GENERATED_ZOOKEEPER_JUTE_H 1
-
-/* Define to 1 if you have the `getcwd' function. */
-#cmakedefine HAVE_GETCWD 1
-
-/* Define to 1 if you have the `gethostbyname' function. */
-#cmakedefine HAVE_GETHOSTBYNAME 1
-
-/* Define to 1 if you have the `gethostname' function. */
-#cmakedefine HAVE_GETHOSTNAME 1
-
-/* Define to 1 if you have the `getlogin' function. */
-#cmakedefine HAVE_GETLOGIN 1
-
-/* Define to 1 if you have the `getpwuid_r' function. */
-#cmakedefine HAVE_GETPWUID_R 1
-
-/* Define to 1 if you have the `gettimeofday' function. */
-#cmakedefine HAVE_GETTIMEOFDAY 1
-
-/* Define to 1 if you have the `getuid' function. */
-#cmakedefine HAVE_GETUID 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#cmakedefine HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `rt' library (-lrt). */
-#cmakedefine HAVE_LIBRT 1
-
-/* Define to 1 if you have the `memmove' function. */
-#cmakedefine HAVE_MEMMOVE 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#cmakedefine HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `memset' function. */
-#cmakedefine HAVE_MEMSET 1
-
-/* Define to 1 if you have the <netdb.h> header file. */
-#cmakedefine HAVE_NETDB_H 1
-
-/* Define to 1 if you have the <netinet/in.h> header file. */
-#cmakedefine HAVE_NETINET_IN_H 1
-
-/* Define to 1 if you have the `poll' function. */
-#cmakedefine HAVE_POLL 1
-
-/* Define to 1 if you have the `socket' function. */
-#cmakedefine HAVE_SOCKET 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#cmakedefine HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#cmakedefine HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strchr' function. */
-#cmakedefine HAVE_STRCHR 1
-
-/* Define to 1 if you have the `strdup' function. */
-#cmakedefine HAVE_STRDUP 1
-
-/* Define to 1 if you have the `strerror' function. */
-#cmakedefine HAVE_STRERROR 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#cmakedefine HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#cmakedefine HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strtol' function. */
-#cmakedefine HAVE_STRTOL 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#cmakedefine HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#cmakedefine HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#cmakedefine HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#cmakedefine HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/utsname.h> header file. */
-#cmakedefine HAVE_SYS_UTSNAME_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#cmakedefine HAVE_UNISTD_H 1
-
-/* Define to 1 if IPv6 support is available. */
-#cmakedefine ZOO_IPV6_ENABLED 1
-
-/* poll() second argument type */
-#define POLL_NFDS_TYPE nfds_t
-
-/* Name of package */
-#define PACKAGE "${PROJECT_NAME}"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "${email}"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "${description}"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "${description} ${PROJECT_VERSION}"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "${PROJECT_NAME}"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "${PROJECT_VERSION}"
-
-/* Version number of package */
-#define VERSION "${PROJECT_VERSION}"
-
-#endif
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/configure.ac
----------------------------------------------------------------------
diff --git a/src/c/configure.ac b/src/c/configure.ac
deleted file mode 100644
index aa1c30b..0000000
--- a/src/c/configure.ac
+++ /dev/null
@@ -1,165 +0,0 @@
-# -*- Autoconf -*-
-# Process this file with autoconf to produce a configure script.
-
-AC_PREREQ(2.59)
-
-AC_INIT([zookeeper C client],3.4.13,[user@zookeeper.apache.org],[zookeeper])
-AC_CONFIG_SRCDIR([src/zookeeper.c])
-
-# Save initial CFLAGS and CXXFLAGS values before AC_PROG_CC and AC_PROG_CXX
-init_cflags="$CFLAGS"
-init_cxxflags="$CXXFLAGS"
-
-# initialize Doxygen support
-DX_HTML_FEATURE(ON)
-DX_CHM_FEATURE(OFF)
-DX_CHI_FEATURE(OFF)
-DX_MAN_FEATURE(OFF)
-DX_RTF_FEATURE(OFF)
-DX_XML_FEATURE(OFF)
-DX_PDF_FEATURE(OFF)
-DX_PS_FEATURE(OFF)
-DX_INIT_DOXYGEN([zookeeper],[c-doc.Doxyfile],[docs])
-
-# initialize automake
-AM_INIT_AUTOMAKE([-Wall foreign])
-AC_CONFIG_HEADER([config.h])
-
-# Checks for programs.
-AC_ARG_WITH(cppunit,
- [ --without-cppunit do not use CPPUNIT])
-
-if test "$with_cppunit" = "no" ; then
- CPPUNIT_PATH="No_CPPUNIT"
- CPPUNIT_INCLUDE=
- CPPUNIT_LIBS=
-else
- AM_PATH_CPPUNIT(1.10.2)
-fi
-
-if test "$CALLER" = "ANT" ; then
-CPPUNIT_CFLAGS="$CPPUNIT_CFLAGS -DZKSERVER_CMD=\"\\\"${base_dir}/src/c/tests/zkServer.sh\\\"\""
-else
-CPPUNIT_CFLAGS="$CPPUNIT_CFLAGS -DZKSERVER_CMD=\"\\\"./tests/zkServer.sh\\\"\""
-AC_CHECK_FILES([$srcdir/generated/zookeeper.jute.c $srcdir/generated/zookeeper.jute.h],[],
- [AC_MSG_ERROR([jute files are missing! Please run "ant compile_jute" while in the zookeeper top level directory.])
-])
-fi
-AC_SUBST(CPPUNIT_CFLAGS)
-
-AC_PROG_CC
-AM_PROG_CC_C_O
-AC_PROG_CXX
-AC_PROG_INSTALL
-AC_PROG_LN_S
-
-# AC_DISABLE_SHARED
-AC_PROG_LIBTOOL
-
-#enable -D_GNU_SOURCE since the return code value of getaddrinfo
-#ifdefed with __USE_GNU
-#features.h header undef's __USE_GNU and defines it only if _GNU_SOURCE is defined
-#hence this define for gcc
-AC_ARG_ENABLE([debug],
- [AS_HELP_STRING([--enable-debug],[enable debug build [default=no]])],
- [],[enable_debug=no])
-
-if test "x$enable_debug" = xyes; then
- if test "x$init_cflags" = x; then
- CFLAGS=""
- fi
- CFLAGS="$CFLAGS -g -O0 -D_GNU_SOURCE"
-else
- if test "x$init_cflags" = x; then
- CFLAGS="-g -O2 -D_GNU_SOURCE"
- fi
-fi
-
-if test "x$enable_debug" = xyes; then
- if test "x$init_cxxflags" = x; then
- CXXFLAGS=""
- fi
- CXXFLAGS="$CXXFLAGS -g -O0"
-else
- if test "x$init_cxxflags" = x; then
- CXXFLAGS="-g -O2"
- fi
-fi
-
-# Check whether to enable gcov (coverage test)
-AC_ARG_ENABLE(gcov, [AS_HELP_STRING([--enable-gcov],[enable coverage test])])
-AC_MSG_CHECKING([whether to enable gcov])
-AS_IF([test "x${enable_gcov}" = "xyes"],AC_MSG_RESULT([yes]),AC_MSG_RESULT([no]))
-AM_CONDITIONAL([ENABLEGCOV],[test "x${enable_gcov}" = "xyes"])
-
-AC_ARG_WITH([syncapi],
- [AS_HELP_STRING([--with-syncapi],[build with support for SyncAPI [default=yes]])],
- [],[with_syncapi=yes])
-
-# Checks for libraries.
-AC_CHECK_LIB([pthread], [pthread_mutex_lock],[have_pthread=yes],[have_pthread=no])
-
-if test "x$with_syncapi" != xno && test "x$have_pthread" = xno; then
- AC_MSG_WARN([cannot build SyncAPI -- pthread not found])
- with_syncapi=no
-fi
-if test "x$with_syncapi" != xno; then
- AC_MSG_NOTICE([building with SyncAPI support])
-else
- AC_MSG_NOTICE([building without SyncAPI support])
-fi
-
-AM_CONDITIONAL([WANT_SYNCAPI],[test "x$with_syncapi" != xno])
-
-# Checks for header files.
-AC_HEADER_STDC
-AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h sys/utsname.h])
-
-# Checks for typedefs, structures, and compiler characteristics.
-AC_C_CONST
-AC_C_INLINE
-AC_HEADER_TIME
-AC_CHECK_TYPE([nfds_t],
- [AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[poll() second argument type])],
- [AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[poll() second argument type])],
- [#include <poll.h>])
-
-AC_MSG_CHECKING([whether to enable ipv6])
-
-AC_TRY_RUN([ /* is AF_INET6 available? */
-#include <sys/types.h>
-#include <sys/socket.h>
-main()
-{
- if (socket(AF_INET6, SOCK_STREAM, 0) < 0)
- exit(1);
- else
- exit(0);
-}
-], AC_MSG_RESULT(yes)
- ipv6=yes,
- AC_MSG_RESULT(no)
- ipv6=no,
- AC_MSG_RESULT(no)
- ipv6=no)
-
-if test x"$ipv6" = xyes; then
- USEIPV6="-DZOO_IPV6_ENABLED"
- AC_SUBST(USEIPV6)
-fi
-
-# Checks for library functions.
-AC_CHECK_FUNCS([getcwd gethostbyname gethostname getlogin getpwuid_r gettimeofday getuid memmove memset poll socket strchr strdup strerror strtol])
-
-AC_CONFIG_FILES([Makefile])
-AC_CANONICAL_HOST
-AM_CONDITIONAL([SOLARIS],[
- case "$host_os" in
- *solaris*)
- true
- ;;
- *)
- false
- ;;
- esac ])
-AC_OUTPUT
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/include/proto.h
----------------------------------------------------------------------
diff --git a/src/c/include/proto.h b/src/c/include/proto.h
deleted file mode 100644
index bce408e..0000000
--- a/src/c/include/proto.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * 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 PROTO_H_
-#define PROTO_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define ZOO_NOTIFY_OP 0
-#define ZOO_CREATE_OP 1
-#define ZOO_DELETE_OP 2
-#define ZOO_EXISTS_OP 3
-#define ZOO_GETDATA_OP 4
-#define ZOO_SETDATA_OP 5
-#define ZOO_GETACL_OP 6
-#define ZOO_SETACL_OP 7
-#define ZOO_GETCHILDREN_OP 8
-#define ZOO_SYNC_OP 9
-#define ZOO_PING_OP 11
-#define ZOO_GETCHILDREN2_OP 12
-#define ZOO_CHECK_OP 13
-#define ZOO_MULTI_OP 14
-#define ZOO_CLOSE_OP -11
-#define ZOO_SETAUTH_OP 100
-#define ZOO_SETWATCHES_OP 101
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*PROTO_H_*/
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/include/recordio.h
----------------------------------------------------------------------
diff --git a/src/c/include/recordio.h b/src/c/include/recordio.h
deleted file mode 100644
index eed5f99..0000000
--- a/src/c/include/recordio.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * 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 __RECORDIO_H__
-#define __RECORDIO_H__
-
-#include <sys/types.h>
-#include <stdint.h> /* for int64_t */
-#ifdef WIN32
-#include "winconfig.h"
-#define STRUCT_INITIALIZER(l,r) r
-#else
-#define STRUCT_INITIALIZER(l,r) .l = r
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct buffer {
- int32_t len;
- char *buff;
-};
-
-void deallocate_String(char **s);
-void deallocate_Buffer(struct buffer *b);
-void deallocate_vector(void *d);
-struct iarchive {
- int (*start_record)(struct iarchive *ia, const char *tag);
- int (*end_record)(struct iarchive *ia, const char *tag);
- int (*start_vector)(struct iarchive *ia, const char *tag, int32_t *count);
- int (*end_vector)(struct iarchive *ia, const char *tag);
- int (*deserialize_Bool)(struct iarchive *ia, const char *name, int32_t *);
- int (*deserialize_Int)(struct iarchive *ia, const char *name, int32_t *);
- int (*deserialize_Long)(struct iarchive *ia, const char *name, int64_t *);
- int (*deserialize_Buffer)(struct iarchive *ia, const char *name,
- struct buffer *);
- int (*deserialize_String)(struct iarchive *ia, const char *name, char **);
- void *priv;
-};
-struct oarchive {
- int (*start_record)(struct oarchive *oa, const char *tag);
- int (*end_record)(struct oarchive *oa, const char *tag);
- int (*start_vector)(struct oarchive *oa, const char *tag, const int32_t *count);
- int (*end_vector)(struct oarchive *oa, const char *tag);
- int (*serialize_Bool)(struct oarchive *oa, const char *name, const int32_t *);
- int (*serialize_Int)(struct oarchive *oa, const char *name, const int32_t *);
- int (*serialize_Long)(struct oarchive *oa, const char *name,
- const int64_t *);
- int (*serialize_Buffer)(struct oarchive *oa, const char *name,
- const struct buffer *);
- int (*serialize_String)(struct oarchive *oa, const char *name, char **);
- void *priv;
-};
-
-struct oarchive *create_buffer_oarchive(void);
-void close_buffer_oarchive(struct oarchive **oa, int free_buffer);
-struct iarchive *create_buffer_iarchive(char *buffer, int len);
-void close_buffer_iarchive(struct iarchive **ia);
-char *get_buffer(struct oarchive *);
-int get_buffer_len(struct oarchive *);
-
-int64_t zoo_htonll(int64_t v);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/include/winconfig.h
----------------------------------------------------------------------
diff --git a/src/c/include/winconfig.h b/src/c/include/winconfig.h
deleted file mode 100644
index c273a93..0000000
--- a/src/c/include/winconfig.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef WINCONFIG_H_
-#define WINCONFIG_H_
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-#define inline __inline
-#endif
-
-#define __attribute__(x)
-#define __func__ __FUNCTION__
-
-#define ACL ZKACL /* Conflict with windows API */
-
-#endif
[12/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/TestOperations.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/TestOperations.cc b/src/c/tests/TestOperations.cc
deleted file mode 100644
index 27d9270..0000000
--- a/src/c/tests/TestOperations.cc
+++ /dev/null
@@ -1,710 +0,0 @@
-/**
- * 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 <cppunit/extensions/HelperMacros.h>
-#include "CppAssertHelper.h"
-
-#include "ZKMocks.h"
-#include <proto.h>
-
-using namespace std;
-
-class Zookeeper_operations : public CPPUNIT_NS::TestFixture
-{
- CPPUNIT_TEST_SUITE(Zookeeper_operations);
-#ifndef THREADED
- CPPUNIT_TEST(testPing);
- CPPUNIT_TEST(testUnsolicitedPing);
- CPPUNIT_TEST(testTimeoutCausedByWatches1);
- CPPUNIT_TEST(testTimeoutCausedByWatches2);
-#else
- CPPUNIT_TEST(testAsyncWatcher1);
- CPPUNIT_TEST(testAsyncGetOperation);
-#endif
- CPPUNIT_TEST(testOperationsAndDisconnectConcurrently1);
- CPPUNIT_TEST(testOperationsAndDisconnectConcurrently2);
- CPPUNIT_TEST(testConcurrentOperations1);
- CPPUNIT_TEST_SUITE_END();
- zhandle_t *zh;
- FILE *logfile;
-
- static void watcher(zhandle_t *, int, int, const char *,void*){}
-public:
- Zookeeper_operations() {
- logfile = openlogfile("Zookeeper_operations");
- }
-
- ~Zookeeper_operations() {
- if (logfile) {
- fflush(logfile);
- fclose(logfile);
- logfile = 0;
- }
- }
-
- void setUp()
- {
- zoo_set_log_stream(logfile);
-
- zoo_deterministic_conn_order(0);
- zh=0;
- }
-
- void tearDown()
- {
- zookeeper_close(zh);
- }
-
- class AsyncGetOperationCompletion: public AsyncCompletion{
- public:
- AsyncGetOperationCompletion():called_(false),rc_(ZAPIERROR){}
- virtual void dataCompl(int rc, const char *value, int len, const Stat *stat){
- synchronized(mx_);
- called_=true;
- rc_=rc;
- value_.erase();
- if(rc!=ZOK) return;
- value_.assign(value,len);
- if(stat)
- stat_=*stat;
- }
- bool operator()()const{
- synchronized(mx_);
- return called_;
- }
- mutable Mutex mx_;
- bool called_;
- int rc_;
- string value_;
- NodeStat stat_;
- };
-#ifndef THREADED
- // send two get data requests; verify that the corresponding completions called
- void testConcurrentOperations1()
- {
- Mock_gettimeofday timeMock;
- ZookeeperServer zkServer;
- // must call zookeeper_close() while all the mocks are in scope
- CloseFinally guard(&zh);
-
- zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
- CPPUNIT_ASSERT(zh!=0);
- // simulate connected state
- forceConnected(zh);
-
- int fd=0;
- int interest=0;
- timeval tv;
- // first operation
- AsyncGetOperationCompletion res1;
- zkServer.addOperationResponse(new ZooGetResponse("1",1));
- int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // second operation
- AsyncGetOperationCompletion res2;
- zkServer.addOperationResponse(new ZooGetResponse("2",1));
- rc=zoo_aget(zh,"/x/y/2",0,asyncCompletion,&res2);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // process the send queue
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- while((rc=zookeeper_process(zh,interest))==ZOK) {
- millisleep(100);
- //printf("%d\n", rc);
- }
- //printf("RC = %d", rc);
- CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
-
- CPPUNIT_ASSERT_EQUAL((int)ZOK,res1.rc_);
- CPPUNIT_ASSERT_EQUAL(string("1"),res1.value_);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,res2.rc_);
- CPPUNIT_ASSERT_EQUAL(string("2"),res2.value_);
- }
- // send two getData requests and disconnect while the second request is
- // outstanding;
- // verify the completions are called
- void testOperationsAndDisconnectConcurrently1()
- {
- Mock_gettimeofday timeMock;
- ZookeeperServer zkServer;
- // must call zookeeper_close() while all the mocks are in scope
- CloseFinally guard(&zh);
-
- zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
- CPPUNIT_ASSERT(zh!=0);
- // simulate connected state
- forceConnected(zh);
-
- int fd=0;
- int interest=0;
- timeval tv;
- // first operation
- AsyncGetOperationCompletion res1;
- zkServer.addOperationResponse(new ZooGetResponse("1",1));
- int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // second operation
- AsyncGetOperationCompletion res2;
- zkServer.addOperationResponse(new ZooGetResponse("2",1));
- rc=zoo_aget(zh,"/x/y/2",0,asyncCompletion,&res2);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // process the send queue
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // simulate a disconnect
- zkServer.setConnectionLost();
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZCONNECTIONLOSS,rc);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,res1.rc_);
- CPPUNIT_ASSERT_EQUAL(string("1"),res1.value_);
- CPPUNIT_ASSERT_EQUAL((int)ZCONNECTIONLOSS,res2.rc_);
- CPPUNIT_ASSERT_EQUAL(string(""),res2.value_);
- }
- // send two getData requests and simulate timeout while the both request
- // are pending;
- // verify the completions are called
- void testOperationsAndDisconnectConcurrently2()
- {
- Mock_gettimeofday timeMock;
- ZookeeperServer zkServer;
- // must call zookeeper_close() while all the mocks are in scope
- CloseFinally guard(&zh);
-
- zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
- CPPUNIT_ASSERT(zh!=0);
- // simulate connected state
- forceConnected(zh);
-
- int fd=0;
- int interest=0;
- timeval tv;
- // first operation
- AsyncGetOperationCompletion res1;
- zkServer.addOperationResponse(new ZooGetResponse("1",1));
- int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // second operation
- AsyncGetOperationCompletion res2;
- zkServer.addOperationResponse(new ZooGetResponse("2",1));
- rc=zoo_aget(zh,"/x/y/2",0,asyncCompletion,&res2);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // simulate timeout
- timeMock.tick(+10); // advance system time by 10 secs
- // the next call to zookeeper_interest should return ZOPERATIONTIMEOUT
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOPERATIONTIMEOUT,rc);
- // make sure the completions have been called
- CPPUNIT_ASSERT_EQUAL((int)ZOPERATIONTIMEOUT,res1.rc_);
- CPPUNIT_ASSERT_EQUAL((int)ZOPERATIONTIMEOUT,res2.rc_);
- }
-
- class PingCountingServer: public ZookeeperServer{
- public:
- PingCountingServer():pingCount_(0){}
- // called when a client request is received
- virtual void onMessageReceived(const RequestHeader& rh, iarchive* ia){
- if(rh.type==ZOO_PING_OP){
- pingCount_++;
- }
- }
- int pingCount_;
- };
-
- // establish a connection; idle for a while
- // verify ping was sent at least once
- void testPing()
- {
- const int TIMEOUT=9; // timeout in secs
- Mock_gettimeofday timeMock;
- PingCountingServer zkServer;
- // must call zookeeper_close() while all the mocks are in scope
- CloseFinally guard(&zh);
-
- // receive timeout is in milliseconds
- zh=zookeeper_init("localhost:1234",watcher,TIMEOUT*1000,TEST_CLIENT_ID,0,0);
- CPPUNIT_ASSERT(zh!=0);
- // simulate connected state
- forceConnected(zh);
-
- int fd=0;
- int interest=0;
- timeval tv;
- // Round 1.
- int rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // simulate waiting for the select() call to timeout;
- // advance the system clock accordingly
- timeMock.tick(tv);
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
- // verify no ping sent
- CPPUNIT_ASSERT(zkServer.pingCount_==0);
-
- // Round 2.
- // the client should have the idle threshold exceeded, by now
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // assume the socket is writable, so no idling here; move on to
- // zookeeper_process immediately
- rc=zookeeper_process(zh,interest);
- // ZNOTHING means the client hasn't received a ping response yet
- CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
- // verify a ping is sent
- CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
-
- // Round 3.
- // we're going to receive a server PING response and make sure
- // that the client has updated its last_recv timestamp
- zkServer.addRecvResponse(new PingResponse);
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // pseudo-sleep for a short while (10 ms)
- timeMock.millitick(10);
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // only one ping so far?
- CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
- CPPUNIT_ASSERT(timeMock==zh->last_recv);
-
- // Round 4
- // make sure that a ping is not sent if something is outstanding
- AsyncGetOperationCompletion res1;
- rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- timeMock.tick(tv);
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // pseudo-sleep for a short while (10 ms)
- timeMock.millitick(10);
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
- // only one ping so far?
- CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
- }
-
- // ZOOKEEPER-2253: Permit unsolicited pings
- void testUnsolicitedPing()
- {
- const int TIMEOUT=9; // timeout in secs
- Mock_gettimeofday timeMock;
- PingCountingServer zkServer;
- // must call zookeeper_close() while all the mocks are in scope
- CloseFinally guard(&zh);
-
- // receive timeout is in milliseconds
- zh=zookeeper_init("localhost:1234",watcher,TIMEOUT*1000,TEST_CLIENT_ID,0,0);
- CPPUNIT_ASSERT(zh!=0);
- // simulate connected state
- forceConnected(zh);
-
- int fd=0;
- int interest=0;
- timeval tv;
-
- int rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- // verify no ping sent
- CPPUNIT_ASSERT(zkServer.pingCount_==0);
-
- // we're going to receive a unsolicited PING response; ensure
- // that the client has updated its last_recv timestamp
- timeMock.tick(tv);
- zkServer.addRecvResponse(new PingResponse);
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- CPPUNIT_ASSERT(timeMock==zh->last_recv);
- }
-
- // simulate a watch arriving right before a ping is due
- // assert the ping is sent nevertheless
- void testTimeoutCausedByWatches1()
- {
- const int TIMEOUT=9; // timeout in secs
- Mock_gettimeofday timeMock;
- PingCountingServer zkServer;
- // must call zookeeper_close() while all the mocks are in scope
- CloseFinally guard(&zh);
-
- // receive timeout is in milliseconds
- zh=zookeeper_init("localhost:1234",watcher,TIMEOUT*1000,TEST_CLIENT_ID,0,0);
- CPPUNIT_ASSERT(zh!=0);
- // simulate connected state
- forceConnected(zh);
-
- int fd=0;
- int interest=0;
- timeval tv;
- // Round 1.
- int rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // simulate waiting for the select() call to timeout;
- // advance the system clock accordingly
- timeMock.tick(tv);
- timeMock.tick(-1); // set the clock to a millisecond before a ping is due
- // trigger a watch now
- zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/x/y/z"));
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // arrival of a watch sets the last_recv to the current time
- CPPUNIT_ASSERT(timeMock==zh->last_recv);
- // spend 1 millisecond by processing the watch
- timeMock.tick(1);
-
- // Round 2.
- // a ping is due; zookeeper_interest() must send it now
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // no delay here -- as if the socket is immediately writable
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
- // verify a ping is sent
- CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
- }
-
- // similar to testTimeoutCausedByWatches1, but this time the watch is
- // triggered while the client has an outstanding request
- // assert the ping is sent on time
- void testTimeoutCausedByWatches2()
- {
- const int TIMEOUT=9; // timeout in secs
- Mock_gettimeofday now;
- PingCountingServer zkServer;
- // must call zookeeper_close() while all the mocks are in scope
- CloseFinally guard(&zh);
-
- // receive timeout is in milliseconds
- zh=zookeeper_init("localhost:1234",watcher,TIMEOUT*1000,TEST_CLIENT_ID,0,0);
- CPPUNIT_ASSERT(zh!=0);
- // simulate connected state
- forceConnected(zh);
-
- // queue up a request; keep it pending (as if the server is busy or has died)
- AsyncGetOperationCompletion res1;
- zkServer.addOperationResponse(new ZooGetResponse("2",1));
- int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
-
- int fd=0;
- int interest=0;
- timeval tv;
- // Round 1.
- // send the queued up zoo_aget() request
- Mock_gettimeofday beginningOfTimes(now); // remember when we started
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // no delay -- the socket is writable
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- // Round 2.
- // what's next?
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // no response from the server yet -- waiting in the select() call
- now.tick(tv);
- // a watch has arrived, thus preventing the connection from timing out
- zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/x/y/z"));
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc); // read the watch message
- CPPUNIT_ASSERT_EQUAL(0,zkServer.pingCount_); // not yet!
-
- //Round 3.
- // now is the time to send a ping; make sure it's actually sent
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
- // verify a ping is sent
- CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
- // make sure only 1/3 of the timeout has passed
- CPPUNIT_ASSERT_EQUAL((int32_t)TIMEOUT/3*1000,toMilliseconds(now-beginningOfTimes));
- }
-
-#else
- class TestGetDataJob: public TestJob{
- public:
- TestGetDataJob(ZookeeperServer* svr,zhandle_t* zh, int reps=500)
- :svr_(svr),zh_(zh),rc_(ZAPIERROR),reps_(reps){}
- virtual void run(){
- int i;
- for(i=0;i<reps_;i++){
- char buf;
- int size=sizeof(buf);
-
- if (i % 10 == 0) {
- // We need to pause every once in a while so we don't
- // get too far ahead and finish before the disconnect
- millisleep(1);
- }
- svr_->addOperationResponse(new ZooGetResponse("1",1));
- rc_=zoo_get(zh_,"/x/y/z",0,&buf,&size,0);
- if(rc_!=ZOK){
- break;
- }
- }
- }
- ZookeeperServer* svr_;
- zhandle_t* zh_;
- int rc_;
- int reps_;
- };
- class TestConcurrentOpJob: public TestGetDataJob{
- public:
- static const int REPS=500;
- TestConcurrentOpJob(ZookeeperServer* svr,zhandle_t* zh):
- TestGetDataJob(svr,zh,REPS){}
- virtual TestJob* clone() const {
- return new TestConcurrentOpJob(svr_,zh_);
- }
- virtual void validate(const char* file, int line) const{
- CPPUNIT_ASSERT_EQUAL_MESSAGE_LOC("ZOK != rc",(int)ZOK,rc_,file,line);
- }
- };
- void testConcurrentOperations1()
- {
- for(int counter=0; counter<50; counter++){
- // frozen time -- no timeouts and no pings
- Mock_gettimeofday timeMock;
-
- ZookeeperServer zkServer;
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
- // must call zookeeper_close() while all the mocks are in the scope!
- CloseFinally guard(&zh);
-
- zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
- CPPUNIT_ASSERT(zh!=0);
- // make sure the client has connected
- CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
-
- TestJobManager jmgr(TestConcurrentOpJob(&zkServer,zh),10);
- jmgr.startAllJobs();
- jmgr.wait();
- // validate test results
- VALIDATE_JOBS(jmgr);
- }
- }
- class ZKGetJob: public TestJob{
- public:
- static const int REPS=1000;
- ZKGetJob(zhandle_t* zh)
- :zh_(zh),rc_(ZAPIERROR){}
- virtual TestJob* clone() const {
- return new ZKGetJob(zh_);
- }
- virtual void run(){
- int i;
- for(i=0;i<REPS;i++){
- char buf;
- int size=sizeof(buf);
- rc_=zoo_get(zh_,"/xyz",0,&buf,&size,0);
- if(rc_!=ZOK){
- break;
- }
- }
- //TEST_TRACE(("Finished %d iterations",i));
- }
- virtual void validate(const char* file, int line) const{
- CPPUNIT_ASSERT_EQUAL_MESSAGE_LOC("ZOK != rc",(int)ZOK,rc_,file,line);
- }
- zhandle_t* zh_;
- int rc_;
- };
-
- // this test connects to a real ZK server and creates the /xyz node and sends
- // lots of zoo_get requests.
- // to run this test use the following command:
- // zktest-mt Zookeeper_operations::testOperationsAndDisconnectConcurrently2 localhost:3181
- // where the second parameter is the server host and port
- void testOperationsAndDisconnectConcurrently2()
- {
- if(globalTestConfig.getTestName().find(__func__)==string::npos ||
- globalTestConfig.getExtraOptCount()==0)
- {
- // only run this test when specifically asked so
- return;
- }
- string host(*(globalTestConfig.getExtraOptBegin()));
- zhandle_t* lzh=zookeeper_init(host.c_str(),watcher,10000,0,0,0);
- CPPUNIT_ASSERT(lzh!=0);
- // make sure the client has connected
- CPPUNIT_ASSERT_MESSAGE("Unable to connect to the host",
- ensureCondition(ClientConnected(zh),5000)<5000);
-
- char realpath[1024];
- int rc=zoo_create(lzh,"/xyz","1",1,&ZOO_OPEN_ACL_UNSAFE,0,realpath,sizeof(realpath)-1);
- CPPUNIT_ASSERT(rc==ZOK || rc==ZNODEEXISTS);
- zookeeper_close(lzh);
-
- for(int counter=0; counter<200; counter++){
- TEST_TRACE(("Loop count %d",counter));
-
- CloseFinally guard(&zh);
-
- zh=zookeeper_init(host.c_str(),watcher,10000,0,0,0);
- CPPUNIT_ASSERT(zh!=0);
- // make sure the client has connected
- CPPUNIT_ASSERT_MESSAGE("Unable to connect to the host",
- ensureCondition(ClientConnected(zh),5000)<5000);
-
- TestJobManager jmgr(ZKGetJob(zh),10);
- jmgr.startJobsImmediately();
- jmgr.wait();
- VALIDATE_JOBS(jmgr);
- TEST_TRACE(("run %d finished",counter));
- }
-
- }
-
- class TestConcurrentOpWithDisconnectJob: public TestGetDataJob{
- public:
- static const int REPS=1000;
- TestConcurrentOpWithDisconnectJob(ZookeeperServer* svr,zhandle_t* zh):
- TestGetDataJob(svr,zh,REPS){}
- virtual TestJob* clone() const {
- return new TestConcurrentOpWithDisconnectJob(svr_,zh_);
- }
- virtual void validate(const char* file, int line) const{
- CPPUNIT_ASSERT_EQUAL_MESSAGE_LOC("ZCONNECTIONLOSS != rc",(int)ZCONNECTIONLOSS,rc_,file,line);
- }
- };
-
- // this test is not 100% accurate in a sense it may not detect all error cases.
- // TODO: I can't think of a test that is 100% accurate and doesn't interfere
- // with the code being tested (in terms of introducing additional
- // implicit synchronization points)
- void testOperationsAndDisconnectConcurrently1()
- {
- for(int counter=0; counter<50; counter++){
- //TEST_TRACE(("Loop count %d",counter));
- // frozen time -- no timeouts and no pings
- Mock_gettimeofday timeMock;
-
- ZookeeperServer zkServer;
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
- // must call zookeeper_close() while all the mocks are in the scope!
- CloseFinally guard(&zh);
-
- zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
- CPPUNIT_ASSERT(zh!=0);
- // make sure the client has connected
- CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
-
- TestJobManager jmgr(TestConcurrentOpWithDisconnectJob(&zkServer,zh),10);
- jmgr.startJobsImmediately();
- // let everything startup before we shutdown the server
- millisleep(4);
- // reconnect attempts will start failing immediately
- zkServer.setServerDown(0);
- // next recv call will return 0
- zkServer.setConnectionLost();
- jmgr.wait();
- VALIDATE_JOBS(jmgr);
- }
-
- }
- // call zoo_aget() in the multithreaded mode
- void testAsyncGetOperation()
- {
- Mock_gettimeofday timeMock;
-
- ZookeeperServer zkServer;
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
- // must call zookeeper_close() while all the mocks are in the scope!
- CloseFinally guard(&zh);
-
- zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
- CPPUNIT_ASSERT(zh!=0);
- // make sure the client has connected
- CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
-
- AsyncGetOperationCompletion res1;
- zkServer.addOperationResponse(new ZooGetResponse("1",1));
- int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- CPPUNIT_ASSERT(ensureCondition(res1,1000)<1000);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,res1.rc_);
- CPPUNIT_ASSERT_EQUAL(string("1"),res1.value_);
- }
- class ChangeNodeWatcher: public WatcherAction{
- public:
- ChangeNodeWatcher():changed_(false){}
- virtual void onNodeValueChanged(zhandle_t*,const char* path){
- synchronized(mx_);
- changed_=true;
- if(path!=0) path_=path;
- }
- // this predicate checks if CHANGE_EVENT event type was triggered, unlike
- // the isWatcherTriggered() that returns true whenever a watcher is triggered
- // regardless of the event type
- SyncedBoolCondition isNodeChangedTriggered() const{
- return SyncedBoolCondition(changed_,mx_);
- }
- bool changed_;
- string path_;
- };
-
- class AsyncWatcherCompletion: public AsyncCompletion{
- public:
- AsyncWatcherCompletion(ZookeeperServer& zkServer):zkServer_(zkServer){}
- virtual void statCompl(int rc, const Stat *stat){
- // we received a server response, now enqueue a watcher event
- // to trigger the watcher
- zkServer_.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/x/y/z"));
- }
- ZookeeperServer& zkServer_;
- };
- // verify that async watcher is called for znode events (CREATED, DELETED etc.)
- void testAsyncWatcher1(){
- Mock_gettimeofday timeMock;
-
- ZookeeperServer zkServer;
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
- // must call zookeeper_close() while all the mocks are in the scope!
- CloseFinally guard(&zh);
-
- ChangeNodeWatcher action;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,
- TEST_CLIENT_ID,&action,0);
- CPPUNIT_ASSERT(zh!=0);
- // make sure the client has connected
- CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
-
- // set the watcher
- AsyncWatcherCompletion completion(zkServer);
- // prepare a response for the zoo_aexists() request
- zkServer.addOperationResponse(new ZooStatResponse);
- int rc=zoo_aexists(zh,"/x/y/z",1,asyncCompletion,&completion);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- CPPUNIT_ASSERT(ensureCondition(action.isNodeChangedTriggered(),1000)<1000);
- CPPUNIT_ASSERT_EQUAL(string("/x/y/z"),action.path_);
- }
-#endif
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_operations);
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/TestWatchers.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/TestWatchers.cc b/src/c/tests/TestWatchers.cc
deleted file mode 100644
index 0a26934..0000000
--- a/src/c/tests/TestWatchers.cc
+++ /dev/null
@@ -1,773 +0,0 @@
-/**
- * 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 <cppunit/extensions/HelperMacros.h>
-#include "CppAssertHelper.h"
-
-#include "ZKMocks.h"
-#include "CollectionUtil.h"
-#include "Util.h"
-
-class Zookeeper_watchers : public CPPUNIT_NS::TestFixture
-{
- CPPUNIT_TEST_SUITE(Zookeeper_watchers);
- CPPUNIT_TEST(testDefaultSessionWatcher1);
- CPPUNIT_TEST(testDefaultSessionWatcher2);
- CPPUNIT_TEST(testObjectSessionWatcher1);
- CPPUNIT_TEST(testObjectSessionWatcher2);
- CPPUNIT_TEST(testNodeWatcher1);
- CPPUNIT_TEST(testChildWatcher1);
- CPPUNIT_TEST(testChildWatcher2);
- CPPUNIT_TEST_SUITE_END();
-
- static void watcher(zhandle_t *, int, int, const char *,void*){}
- zhandle_t *zh;
- FILE *logfile;
-
-public:
-
- Zookeeper_watchers() {
- logfile = openlogfile("Zookeeper_watchers");
- }
-
- ~Zookeeper_watchers() {
- if (logfile) {
- fflush(logfile);
- fclose(logfile);
- logfile = 0;
- }
- }
-
- void setUp()
- {
- zoo_set_log_stream(logfile);
-
- zoo_deterministic_conn_order(0);
- zh=0;
- }
-
- void tearDown()
- {
- zookeeper_close(zh);
- }
-
- class ConnectionWatcher: public WatcherAction{
- public:
- ConnectionWatcher():connected_(false),counter_(0){}
- virtual void onConnectionEstablished(zhandle_t*){
- synchronized(mx_);
- counter_++;
- connected_=true;
- }
- SyncedBoolCondition isConnectionEstablished() const{
- return SyncedBoolCondition(connected_,mx_);
- }
- bool connected_;
- int counter_;
- };
-
- class DisconnectWatcher: public WatcherAction{
- public:
- DisconnectWatcher():disconnected_(false),counter_(0){}
- virtual void onConnectionLost(zhandle_t*){
- synchronized(mx_);
- counter_++;
- disconnected_=true;
- }
- SyncedBoolCondition isDisconnected() const{
- return SyncedBoolCondition(disconnected_,mx_);
- }
- bool disconnected_;
- int counter_;
- };
-
- class CountingDataWatcher: public WatcherAction{
- public:
- CountingDataWatcher():disconnected_(false),counter_(0){}
- virtual void onNodeValueChanged(zhandle_t*,const char* path){
- synchronized(mx_);
- counter_++;
- }
- virtual void onConnectionLost(zhandle_t*){
- synchronized(mx_);
- counter_++;
- disconnected_=true;
- }
- bool disconnected_;
- int counter_;
- };
-
- class DeletionCountingDataWatcher: public WatcherAction{
- public:
- DeletionCountingDataWatcher():counter_(0){}
- virtual void onNodeDeleted(zhandle_t*,const char* path){
- synchronized(mx_);
- counter_++;
- }
- int counter_;
- };
-
- class ChildEventCountingWatcher: public WatcherAction{
- public:
- ChildEventCountingWatcher():counter_(0){}
- virtual void onChildChanged(zhandle_t*,const char* path){
- synchronized(mx_);
- counter_++;
- }
- int counter_;
- };
-
-#ifndef THREADED
-
- // verify: the default watcher is called once for a session event
- void testDefaultSessionWatcher1(){
- Mock_gettimeofday timeMock;
- ZookeeperServer zkServer;
- // must call zookeeper_close() while all the mocks are in scope
- CloseFinally guard(&zh);
-
- ConnectionWatcher watcher;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
- &watcher,0);
- CPPUNIT_ASSERT(zh!=0);
-
- int fd=0;
- int interest=0;
- timeval tv;
- // open the socket
- int rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- CPPUNIT_ASSERT_EQUAL(ZOO_CONNECTING_STATE,zoo_state(zh));
- // send the handshake packet to the server
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- CPPUNIT_ASSERT_EQUAL(ZOO_ASSOCIATING_STATE,zoo_state(zh));
- // receive the server handshake response
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // verify connected
- CPPUNIT_ASSERT_EQUAL(ZOO_CONNECTED_STATE,zoo_state(zh));
- CPPUNIT_ASSERT(watcher.connected_);
- CPPUNIT_ASSERT_EQUAL(1,watcher.counter_);
- }
-
- // test case: connect to server, set a default watcher, disconnect from the server
- // verify: the default watcher is called once
- void testDefaultSessionWatcher2(){
- Mock_gettimeofday timeMock;
- ZookeeperServer zkServer;
- // must call zookeeper_close() while all the mocks are in scope
- CloseFinally guard(&zh);
-
- DisconnectWatcher watcher;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
- &watcher,0);
- CPPUNIT_ASSERT(zh!=0);
- // simulate connected state
- forceConnected(zh);
-
- // first operation
- AsyncCompletion ignored;
- zkServer.addOperationResponse(new ZooGetResponse("1",1));
- int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // this will process the response and activate the watcher
- rc=zookeeper_process(zh,ZOOKEEPER_READ);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- // now, disconnect
- zkServer.setConnectionLost();
- rc=zookeeper_process(zh,ZOOKEEPER_READ);
- CPPUNIT_ASSERT_EQUAL((int)ZCONNECTIONLOSS,rc);
- // verify disconnected
- CPPUNIT_ASSERT(watcher.disconnected_);
- CPPUNIT_ASSERT_EQUAL(1,watcher.counter_);
- }
-
- // testcase: connect to the server, set a watcher object on a node,
- // disconnect from the server
- // verify: the watcher object as well as the default watcher are called
- void testObjectSessionWatcher1(){
- Mock_gettimeofday timeMock;
- ZookeeperServer zkServer;
- // must call zookeeper_close() while all the mocks are in scope
- CloseFinally guard(&zh);
-
- DisconnectWatcher defWatcher;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
- &defWatcher,0);
- CPPUNIT_ASSERT(zh!=0);
- // simulate connected state
- forceConnected(zh);
-
- AsyncCompletion ignored;
- CountingDataWatcher wobject;
- zkServer.addOperationResponse(new ZooStatResponse);
- int rc=zoo_awexists(zh,"/x/y/1",activeWatcher,&wobject,
- asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // this will process the response and activate the watcher
- rc=zookeeper_process(zh,ZOOKEEPER_READ);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- // now, disconnect
- zkServer.setConnectionLost();
- rc=zookeeper_process(zh,ZOOKEEPER_READ);
- CPPUNIT_ASSERT_EQUAL((int)ZCONNECTIONLOSS,rc);
-
- // verify the default watcher has been triggered
- CPPUNIT_ASSERT(defWatcher.disconnected_);
- // and triggered only once
- CPPUNIT_ASSERT_EQUAL(1,defWatcher.counter_);
-
- // the path-specific watcher has been triggered as well
- CPPUNIT_ASSERT(wobject.disconnected_);
- // only once!
- CPPUNIT_ASSERT_EQUAL(1,wobject.counter_);
- }
-
- // testcase: connect to the server, set a watcher object on a node,
- // set a def watcher on another node,disconnect from the server
- // verify: the watcher object as well as the default watcher are called
- void testObjectSessionWatcher2(){
- Mock_gettimeofday timeMock;
- ZookeeperServer zkServer;
- // must call zookeeper_close() while all the mocks are in scope
- CloseFinally guard(&zh);
-
- DisconnectWatcher defWatcher;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
- &defWatcher,0);
- CPPUNIT_ASSERT(zh!=0);
- // simulate connected state
- forceConnected(zh);
-
- // set the default watcher
- AsyncCompletion ignored;
- zkServer.addOperationResponse(new ZooStatResponse);
- int rc=zoo_aexists(zh,"/a/b/c",1,asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- CountingDataWatcher wobject;
- zkServer.addOperationResponse(new ZooStatResponse);
- rc=zoo_awexists(zh,"/x/y/z",activeWatcher,&wobject,
- asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- // this will process the response and activate the watcher
- while((rc=zookeeper_process(zh,ZOOKEEPER_READ))==ZOK) {
- millisleep(100);
- }
- CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
-
- // disconnect now
- zkServer.setConnectionLost();
- rc=zookeeper_process(zh,ZOOKEEPER_READ);
- CPPUNIT_ASSERT_EQUAL((int)ZCONNECTIONLOSS,rc);
-
- // verify the default watcher has been triggered
- CPPUNIT_ASSERT(defWatcher.disconnected_);
- // and triggered only once
- CPPUNIT_ASSERT_EQUAL(1,defWatcher.counter_);
-
- // the path-specific watcher has been triggered as well
- CPPUNIT_ASSERT(wobject.disconnected_);
- // only once!
- CPPUNIT_ASSERT_EQUAL(1,wobject.counter_);
- }
-
- // testcase: register 2 node watches for different paths, trigger the watches
- // verify: the data watchers are processed, the default watcher is not called
- void testNodeWatcher1(){
- Mock_gettimeofday timeMock;
- ZookeeperServer zkServer;
- // must call zookeeper_close() while all the mocks are in scope
- CloseFinally guard(&zh);
-
- DisconnectWatcher defWatcher;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
- &defWatcher,0);
- CPPUNIT_ASSERT(zh!=0);
- // simulate connected state
- forceConnected(zh);
-
- AsyncCompletion ignored;
- CountingDataWatcher wobject1;
- zkServer.addOperationResponse(new ZooStatResponse);
- int rc=zoo_awexists(zh,"/a/b/c",activeWatcher,&wobject1,
- asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- CountingDataWatcher wobject2;
- zkServer.addOperationResponse(new ZooStatResponse);
- rc=zoo_awexists(zh,"/x/y/z",activeWatcher,&wobject2,
- asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- // this will process the response and activate the watcher
- while((rc=zookeeper_process(zh,ZOOKEEPER_READ))==ZOK) {
- millisleep(100);
- }
- CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
-
- // we are all set now; let's trigger the watches
- zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/a/b/c"));
- zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/x/y/z"));
- // make sure all watchers have been processed
- while((rc=zookeeper_process(zh,ZOOKEEPER_READ))==ZOK) {
- millisleep(100);
- }
- CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
-
- CPPUNIT_ASSERT_EQUAL(1,wobject1.counter_);
- CPPUNIT_ASSERT_EQUAL(1,wobject2.counter_);
- CPPUNIT_ASSERT_EQUAL(0,defWatcher.counter_);
- }
-
- // testcase: set up both a children and a data watchers on the node /a, then
- // delete the node by sending a DELETE_EVENT event
- // verify: both watchers are triggered
- void testChildWatcher1(){
- Mock_gettimeofday timeMock;
- ZookeeperServer zkServer;
- // must call zookeeper_close() while all the mocks are in scope
- CloseFinally guard(&zh);
-
- DeletionCountingDataWatcher defWatcher;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
- &defWatcher,0);
- CPPUNIT_ASSERT(zh!=0);
- // simulate connected state
- forceConnected(zh);
-
- AsyncCompletion ignored;
- DeletionCountingDataWatcher wobject1;
- zkServer.addOperationResponse(new ZooStatResponse);
- int rc=zoo_awexists(zh,"/a",activeWatcher,&wobject1,
- asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- typedef ZooGetChildrenResponse::StringVector ZooVector;
- zkServer.addOperationResponse(new ZooGetChildrenResponse(
- Util::CollectionBuilder<ZooVector>()("/a/1")("/a/2")
- ));
- DeletionCountingDataWatcher wobject2;
- rc=zoo_awget_children(zh,"/a",activeWatcher,
- &wobject2,asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- // this will process the response and activate the watcher
- while((rc=zookeeper_process(zh,ZOOKEEPER_READ))==ZOK) {
- millisleep(100);
- }
- CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
-
- // we are all set now; let's trigger the watches
- zkServer.addRecvResponse(new ZNodeEvent(ZOO_DELETED_EVENT,"/a"));
- // make sure the watchers have been processed
- while((rc=zookeeper_process(zh,ZOOKEEPER_READ))==ZOK) {
- millisleep(100);
- }
- CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
-
- CPPUNIT_ASSERT_EQUAL(1,wobject1.counter_);
- CPPUNIT_ASSERT_EQUAL(1,wobject2.counter_);
- CPPUNIT_ASSERT_EQUAL(0,defWatcher.counter_);
- }
-
- // testcase: create both a child and data watch on the node /a, send a ZOO_CHILD_EVENT
- // verify: only the child watch triggered
- void testChildWatcher2(){
- Mock_gettimeofday timeMock;
- ZookeeperServer zkServer;
- // must call zookeeper_close() while all the mocks are in scope
- CloseFinally guard(&zh);
-
- ChildEventCountingWatcher defWatcher;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
- &defWatcher,0);
- CPPUNIT_ASSERT(zh!=0);
- // simulate connected state
- forceConnected(zh);
-
- AsyncCompletion ignored;
- ChildEventCountingWatcher wobject1;
- zkServer.addOperationResponse(new ZooStatResponse);
- int rc=zoo_awexists(zh,"/a",activeWatcher,&wobject1,
- asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- typedef ZooGetChildrenResponse::StringVector ZooVector;
- zkServer.addOperationResponse(new ZooGetChildrenResponse(
- Util::CollectionBuilder<ZooVector>()("/a/1")("/a/2")
- ));
- ChildEventCountingWatcher wobject2;
- rc=zoo_awget_children(zh,"/a",activeWatcher,
- &wobject2,asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- // this will process the response and activate the watcher
- while((rc=zookeeper_process(zh,ZOOKEEPER_READ))==ZOK) {
- millisleep(100);
- }
- CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
-
- // we are all set now; let's trigger the watches
- zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHILD_EVENT,"/a"));
- // make sure the watchers have been processed
- while((rc=zookeeper_process(zh,ZOOKEEPER_READ))==ZOK) {
- millisleep(100);
- }
- CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
-
- CPPUNIT_ASSERT_EQUAL(0,wobject1.counter_);
- CPPUNIT_ASSERT_EQUAL(1,wobject2.counter_);
- CPPUNIT_ASSERT_EQUAL(0,defWatcher.counter_);
- }
-
-#else
- // verify: the default watcher is called once for a session event
- void testDefaultSessionWatcher1(){
- Mock_gettimeofday timeMock;
- // zookeeper simulator
- ZookeeperServer zkServer;
- // detects when all watchers have been delivered
- WatcherDeliveryTracker deliveryTracker(ZOO_SESSION_EVENT,ZOO_CONNECTED_STATE);
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
- // must call zookeeper_close() while all the mocks are in the scope!
- CloseFinally guard(&zh);
-
- ConnectionWatcher watcher;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
- &watcher,0);
- CPPUNIT_ASSERT(zh!=0);
- // wait till watcher proccessing has completed (the connection
- // established event)
- CPPUNIT_ASSERT(ensureCondition(
- deliveryTracker.isWatcherProcessingCompleted(),1000)<1000);
-
- // verify the watcher has been triggered
- CPPUNIT_ASSERT(ensureCondition(watcher.isConnectionEstablished(),1000)<1000);
- // triggered only once
- CPPUNIT_ASSERT_EQUAL(1,watcher.counter_);
- }
-
- // test case: connect to server, set a default watcher, disconnect from the server
- // verify: the default watcher is called once
- void testDefaultSessionWatcher2(){
- Mock_gettimeofday timeMock;
- // zookeeper simulator
- ZookeeperServer zkServer;
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
- // must call zookeeper_close() while all the mocks are in the scope!
- CloseFinally guard(&zh);
-
- // detects when all watchers have been delivered
- WatcherDeliveryTracker deliveryTracker(ZOO_SESSION_EVENT,ZOO_CONNECTING_STATE);
- DisconnectWatcher watcher;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
- &watcher,0);
- CPPUNIT_ASSERT(zh!=0);
- // make sure the client has connected
- CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
- // set a default watch
- AsyncCompletion ignored;
- // a successful server response will activate the watcher
- zkServer.addOperationResponse(new ZooStatResponse);
- int rc=zoo_aexists(zh,"/x/y/z",1,asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- // now, initiate a disconnect
- zkServer.setConnectionLost();
- CPPUNIT_ASSERT(ensureCondition(
- deliveryTracker.isWatcherProcessingCompleted(),1000)<1000);
-
- // verify the watcher has been triggered
- CPPUNIT_ASSERT(watcher.disconnected_);
- // triggered only once
- CPPUNIT_ASSERT_EQUAL(1,watcher.counter_);
- }
-
- // testcase: connect to the server, set a watcher object on a node,
- // disconnect from the server
- // verify: the watcher object as well as the default watcher are called
- void testObjectSessionWatcher1(){
- Mock_gettimeofday timeMock;
- // zookeeper simulator
- ZookeeperServer zkServer;
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
- // must call zookeeper_close() while all the mocks are in the scope!
- CloseFinally guard(&zh);
-
- // detects when all watchers have been delivered
- WatcherDeliveryTracker deliveryTracker(ZOO_SESSION_EVENT,ZOO_CONNECTING_STATE);
- DisconnectWatcher defWatcher;
- // use the tracker to find out when the watcher has been activated
- WatcherActivationTracker activationTracker;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
- &defWatcher,0);
- CPPUNIT_ASSERT(zh!=0);
- // make sure the client has connected
- CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
-
- AsyncCompletion ignored;
- // this successful server response will activate the watcher
- zkServer.addOperationResponse(new ZooStatResponse);
- CountingDataWatcher wobject;
- activationTracker.track(&wobject);
- // set a path-specific watcher
- int rc=zoo_awexists(zh,"/x/y/z",activeWatcher,&wobject,
- asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // make sure the watcher gets activated before we continue
- CPPUNIT_ASSERT(ensureCondition(activationTracker.isWatcherActivated(),1000)<1000);
-
- // now, initiate a disconnect
- zkServer.setConnectionLost();
- // make sure all watchers have been processed
- CPPUNIT_ASSERT(ensureCondition(
- deliveryTracker.isWatcherProcessingCompleted(),1000)<1000);
-
- // verify the default watcher has been triggered
- CPPUNIT_ASSERT(defWatcher.disconnected_);
- // and triggered only once
- CPPUNIT_ASSERT_EQUAL(1,defWatcher.counter_);
-
- // the path-specific watcher has been triggered as well
- CPPUNIT_ASSERT(wobject.disconnected_);
- // only once!
- CPPUNIT_ASSERT_EQUAL(1,wobject.counter_);
- }
-
- // testcase: connect to the server, set a watcher object on a node,
- // set a def watcher on another node,disconnect from the server
- // verify: the watcher object as well as the default watcher are called
- void testObjectSessionWatcher2(){
- Mock_gettimeofday timeMock;
- // zookeeper simulator
- ZookeeperServer zkServer;
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
- // must call zookeeper_close() while all the mocks are in the scope!
- CloseFinally guard(&zh);
-
- // detects when all watchers have been delivered
- WatcherDeliveryTracker deliveryTracker(ZOO_SESSION_EVENT,ZOO_CONNECTING_STATE);
- DisconnectWatcher defWatcher;
- // use the tracker to find out when the watcher has been activated
- WatcherActivationTracker activationTracker;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
- &defWatcher,0);
- CPPUNIT_ASSERT(zh!=0);
- // make sure the client has connected
- CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
-
- // set a default watch
- AsyncCompletion ignored;
- // a successful server response will activate the watcher
- zkServer.addOperationResponse(new ZooStatResponse);
- activationTracker.track(&defWatcher);
- int rc=zoo_aexists(zh,"/a/b/c",1,asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // make sure the watcher gets activated before we continue
- CPPUNIT_ASSERT(ensureCondition(activationTracker.isWatcherActivated(),1000)<1000);
-
- // this successful server response will activate the watcher
- zkServer.addOperationResponse(new ZooStatResponse);
- CountingDataWatcher wobject;
- activationTracker.track(&wobject);
- // set a path-specific watcher
- rc=zoo_awexists(zh,"/x/y/z",activeWatcher,&wobject,
- asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // make sure the watcher gets activated before we continue
- CPPUNIT_ASSERT(ensureCondition(activationTracker.isWatcherActivated(),1000)<1000);
-
- // now, initiate a disconnect
- zkServer.setConnectionLost();
- // make sure all watchers have been processed
- CPPUNIT_ASSERT(ensureCondition(
- deliveryTracker.isWatcherProcessingCompleted(),1000)<1000);
-
- // verify the default watcher has been triggered
- CPPUNIT_ASSERT(defWatcher.disconnected_);
- // and triggered only once
- CPPUNIT_ASSERT_EQUAL(1,defWatcher.counter_);
-
- // the path-specific watcher has been triggered as well
- CPPUNIT_ASSERT(wobject.disconnected_);
- // only once!
- CPPUNIT_ASSERT_EQUAL(1,wobject.counter_);
- }
-
- // testcase: register 2 node watches for different paths, trigger the watches
- // verify: the data watchers are processed, the default watcher is not called
- void testNodeWatcher1(){
- Mock_gettimeofday timeMock;
- // zookeeper simulator
- ZookeeperServer zkServer;
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
- // must call zookeeper_close() while all the mocks are in the scope!
- CloseFinally guard(&zh);
-
- // detects when all watchers have been delivered
- WatcherDeliveryTracker deliveryTracker(ZOO_CHANGED_EVENT,0,false);
- CountingDataWatcher defWatcher;
- // use the tracker to find out when the watcher has been activated
- WatcherActivationTracker activationTracker;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
- &defWatcher,0);
- CPPUNIT_ASSERT(zh!=0);
- // make sure the client has connected
- CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
-
- // don't care about completions
- AsyncCompletion ignored;
- // set a one-shot watch
- // a successful server response will activate the watcher
- zkServer.addOperationResponse(new ZooStatResponse);
- CountingDataWatcher wobject1;
- activationTracker.track(&wobject1);
- int rc=zoo_awexists(zh,"/a/b/c",activeWatcher,&wobject1,
- asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // make sure the watcher gets activated before we continue
- CPPUNIT_ASSERT(ensureCondition(activationTracker.isWatcherActivated(),1000)<1000);
-
- // this successful server response will activate the watcher
- zkServer.addOperationResponse(new ZooStatResponse);
- CountingDataWatcher wobject2;
- activationTracker.track(&wobject2);
- // set a path-specific watcher
- rc=zoo_awexists(zh,"/x/y/z",activeWatcher,&wobject2,
- asyncCompletion,&ignored);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // make sure the watcher gets activated before we continue
- CPPUNIT_ASSERT(ensureCondition(activationTracker.isWatcherActivated(),1000)<1000);
-
- // we are all set now; let's trigger the watches
- zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/a/b/c"));
- zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/x/y/z"));
- // make sure all watchers have been processed
- CPPUNIT_ASSERT(ensureCondition(
- deliveryTracker.deliveryCounterEquals(2),1000)<1000);
-
- CPPUNIT_ASSERT_EQUAL(1,wobject1.counter_);
- CPPUNIT_ASSERT_EQUAL(1,wobject2.counter_);
- CPPUNIT_ASSERT_EQUAL(0,defWatcher.counter_);
- }
-
- // testcase: set up both a children and a data watchers on the node /a, then
- // delete the node (that is, send a DELETE_EVENT)
- // verify: both watchers are triggered
- void testChildWatcher1(){
- Mock_gettimeofday timeMock;
- // zookeeper simulator
- ZookeeperServer zkServer;
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
- // must call zookeeper_close() while all the mocks are in the scope!
- CloseFinally guard(&zh);
-
- // detects when all watchers have been delivered
- WatcherDeliveryTracker deliveryTracker(ZOO_DELETED_EVENT,0);
- DeletionCountingDataWatcher defWatcher;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
- &defWatcher,0);
- CPPUNIT_ASSERT(zh!=0);
- // make sure the client has connected
- CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
-
- // a successful server response will activate the watcher
- zkServer.addOperationResponse(new ZooStatResponse);
- DeletionCountingDataWatcher wobject1;
- Stat stat;
- // add a node watch
- int rc=zoo_wexists(zh,"/a",activeWatcher,&wobject1,&stat);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- typedef ZooGetChildrenResponse::StringVector ZooVector;
- zkServer.addOperationResponse(new ZooGetChildrenResponse(
- Util::CollectionBuilder<ZooVector>()("/a/1")("/a/2")
- ));
- DeletionCountingDataWatcher wobject2;
- String_vector children;
- rc=zoo_wget_children(zh,"/a",activeWatcher,&wobject2,&children);
- deallocate_String_vector(&children);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- // we are all set now; let's trigger the watches
- zkServer.addRecvResponse(new ZNodeEvent(ZOO_DELETED_EVENT,"/a"));
- // make sure the watchers have been processed
- CPPUNIT_ASSERT(ensureCondition(
- deliveryTracker.isWatcherProcessingCompleted(),1000)<1000);
-
- CPPUNIT_ASSERT_EQUAL(1,wobject1.counter_);
- CPPUNIT_ASSERT_EQUAL(1,wobject2.counter_);
- CPPUNIT_ASSERT_EQUAL(0,defWatcher.counter_);
- }
-
- // testcase: create both a child and data watch on the node /a, send a ZOO_CHILD_EVENT
- // verify: only the child watch triggered
- void testChildWatcher2(){
- Mock_gettimeofday timeMock;
- // zookeeper simulator
- ZookeeperServer zkServer;
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
- // must call zookeeper_close() while all the mocks are in the scope!
- CloseFinally guard(&zh);
-
- // detects when all watchers have been delivered
- WatcherDeliveryTracker deliveryTracker(ZOO_CHILD_EVENT,0);
- ChildEventCountingWatcher defWatcher;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,TEST_CLIENT_ID,
- &defWatcher,0);
- CPPUNIT_ASSERT(zh!=0);
- // make sure the client has connected
- CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
- // a successful server response will activate the watcher
- zkServer.addOperationResponse(new ZooStatResponse);
- ChildEventCountingWatcher wobject1;
- Stat stat;
- // add a node watch
- int rc=zoo_wexists(zh,"/a",activeWatcher,&wobject1,&stat);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- typedef ZooGetChildrenResponse::StringVector ZooVector;
- zkServer.addOperationResponse(new ZooGetChildrenResponse(
- Util::CollectionBuilder<ZooVector>()("/a/1")("/a/2")
- ));
- ChildEventCountingWatcher wobject2;
- String_vector children;
- rc=zoo_wget_children(zh,"/a",activeWatcher,&wobject2,&children);
- deallocate_String_vector(&children);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- // we are all set now; let's trigger the watches
- zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHILD_EVENT,"/a"));
- // make sure the watchers have been processed
- CPPUNIT_ASSERT(ensureCondition(
- deliveryTracker.isWatcherProcessingCompleted(),1000)<1000);
-
- CPPUNIT_ASSERT_EQUAL(0,wobject1.counter_);
- CPPUNIT_ASSERT_EQUAL(1,wobject2.counter_);
- CPPUNIT_ASSERT_EQUAL(0,defWatcher.counter_);
- }
-
-#endif //THREADED
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_watchers);
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/src/c/tests/TestZookeeperClose.cc
----------------------------------------------------------------------
diff --git a/src/c/tests/TestZookeeperClose.cc b/src/c/tests/TestZookeeperClose.cc
deleted file mode 100644
index edefa66..0000000
--- a/src/c/tests/TestZookeeperClose.cc
+++ /dev/null
@@ -1,472 +0,0 @@
-/**
- * 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 <cppunit/extensions/HelperMacros.h>
-
-#include "ZKMocks.h"
-
-#ifdef THREADED
-#include "PthreadMocks.h"
-#endif
-
-using namespace std;
-
-class Zookeeper_close : public CPPUNIT_NS::TestFixture
-{
- CPPUNIT_TEST_SUITE(Zookeeper_close);
-#ifdef THREADED
- CPPUNIT_TEST(testIOThreadStoppedOnExpire);
-#endif
- CPPUNIT_TEST(testCloseUnconnected);
- CPPUNIT_TEST(testCloseUnconnected1);
- CPPUNIT_TEST(testCloseConnected1);
- CPPUNIT_TEST(testCloseFromWatcher1);
- CPPUNIT_TEST_SUITE_END();
- zhandle_t *zh;
- static void watcher(zhandle_t *, int, int, const char *,void*){}
- FILE *logfile;
-public:
-
- Zookeeper_close() {
- logfile = openlogfile("Zookeeper_close");
- }
-
- ~Zookeeper_close() {
- if (logfile) {
- fflush(logfile);
- fclose(logfile);
- logfile = 0;
- }
- }
-
- void setUp()
- {
- zoo_set_log_stream(logfile);
-
- zoo_deterministic_conn_order(0);
- zh=0;
- }
-
- void tearDown()
- {
- zookeeper_close(zh);
- }
-
- class CloseOnSessionExpired: public WatcherAction{
- public:
- CloseOnSessionExpired(bool callClose=true):
- callClose_(callClose),rc(ZOK){}
- virtual void onSessionExpired(zhandle_t* zh){
- memcpy(&lzh,zh,sizeof(lzh));
- if(callClose_)
- rc=zookeeper_close(zh);
- }
- zhandle_t lzh;
- bool callClose_;
- int rc;
- };
-
-#ifndef THREADED
- void testCloseUnconnected()
- {
- zh=zookeeper_init("localhost:2121",watcher,10000,0,0,0);
- CPPUNIT_ASSERT(zh!=0);
-
- // do not actually free the memory while in zookeeper_close()
- Mock_free_noop freeMock;
- // make a copy of zhandle before close() overwrites some of
- // it members with NULLs
- zhandle_t lzh;
- memcpy(&lzh,zh,sizeof(lzh));
- int rc=zookeeper_close(zh);
- zhandle_t* savezh=zh; zh=0;
- freeMock.disable(); // disable mock's fake free()- use libc's free() instead
-
- // verify that zookeeper_close has done its job
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // memory
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.hostname));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.addrs));
- // This cannot be maintained properly CPPUNIT_ASSERT_EQUAL(9,freeMock.callCounter);
- }
- void testCloseUnconnected1()
- {
- zh=zookeeper_init("localhost:2121",watcher,10000,0,0,0);
- CPPUNIT_ASSERT(zh!=0);
- // simulate connected state
- zh->fd=ZookeeperServer::FD;
- zh->state=ZOO_CONNECTED_STATE;
- Mock_flush_send_queue zkMock;
- // do not actually free the memory while in zookeeper_close()
- Mock_free_noop freeMock;
- // make a copy of zhandle before close() overwrites some of
- // it members with NULLs
- zhandle_t lzh;
- memcpy(&lzh,zh,sizeof(lzh));
- int rc=zookeeper_close(zh);
- zhandle_t* savezh=zh; zh=0;
- freeMock.disable(); // disable mock's fake free()- use libc's free() instead
-
- // verify that zookeeper_close has done its job
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // memory
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.hostname));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.addrs));
- // the close request sent?
- CPPUNIT_ASSERT_EQUAL(1,zkMock.counter);
- }
- void testCloseConnected1()
- {
- ZookeeperServer zkServer;
- // poll() will called from zookeeper_close()
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
-
- zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
- CPPUNIT_ASSERT(zh!=0);
-
- Mock_gettimeofday timeMock;
-
- int fd=0;
- int interest=0;
- timeval tv;
- int rc=zookeeper_interest(zh,&fd,&interest,&tv);
-
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- CPPUNIT_ASSERT_EQUAL(ZOO_CONNECTING_STATE,zoo_state(zh));
- CPPUNIT_ASSERT_EQUAL(ZOOKEEPER_READ|ZOOKEEPER_WRITE,interest);
-
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- CPPUNIT_ASSERT_EQUAL(ZOO_ASSOCIATING_STATE,zoo_state(zh));
-
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- rc=zookeeper_process(zh,interest);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- CPPUNIT_ASSERT_EQUAL(ZOO_CONNECTED_STATE,zoo_state(zh));
- // do not actually free the memory while in zookeeper_close()
- Mock_free_noop freeMock;
- // make a copy of zhandle before close() overwrites some of
- // it members with NULLs
- zhandle_t lzh;
- memcpy(&lzh,zh,sizeof(lzh));
- zookeeper_close(zh);
- zhandle_t* savezh=zh; zh=0;
- freeMock.disable(); // disable mock's fake free()- use libc's free() instead
- // memory
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.hostname));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.addrs));
- // the close request sent?
- CPPUNIT_ASSERT_EQUAL(1,(int)zkServer.closeSent);
- }
- void testCloseFromWatcher1()
- {
- Mock_gettimeofday timeMock;
-
- ZookeeperServer zkServer;
- // make the server return a non-matching session id
- zkServer.returnSessionExpired();
- // poll() will called from zookeeper_close()
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
-
- CloseOnSessionExpired closeAction;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,
- TEST_CLIENT_ID,&closeAction,0);
- CPPUNIT_ASSERT(zh!=0);
-
- int fd=0;
- int interest=0;
- timeval tv;
- // initiate connection
- int rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- CPPUNIT_ASSERT_EQUAL(ZOO_CONNECTING_STATE,zoo_state(zh));
- CPPUNIT_ASSERT_EQUAL(ZOOKEEPER_READ|ZOOKEEPER_WRITE,interest);
- rc=zookeeper_process(zh,interest);
- // make sure the handshake in progress
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- CPPUNIT_ASSERT_EQUAL(ZOO_ASSOCIATING_STATE,zoo_state(zh));
- rc=zookeeper_interest(zh,&fd,&interest,&tv);
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
-
- // do not actually free the memory while in zookeeper_close()
- Mock_free_noop freeMock;
- // should call the watcher with ZOO_EXPIRED_SESSION_STATE state
- rc=zookeeper_process(zh,interest);
- zhandle_t* savezh=zh; zh=0;
- freeMock.disable(); // disable mock's fake free()- use libc's free() instead
-
- CPPUNIT_ASSERT_EQUAL(ZOO_EXPIRED_SESSION_STATE,zoo_state(savezh));
- // memory
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(closeAction.lzh.hostname));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(closeAction.lzh.addrs));
- // make sure the close request NOT sent
- CPPUNIT_ASSERT_EQUAL(0,(int)zkServer.closeSent);
- }
-#else
- void testCloseUnconnected()
- {
- // disable threading
- MockPthreadZKNull pthreadMock;
- zh=zookeeper_init("localhost:2121",watcher,10000,0,0,0);
-
- CPPUNIT_ASSERT(zh!=0);
- adaptor_threads* adaptor=(adaptor_threads*)zh->adaptor_priv;
- CPPUNIT_ASSERT(adaptor!=0);
-
- // do not actually free the memory while in zookeeper_close()
- Mock_free_noop freeMock;
- // make a copy of zhandle before close() overwrites some of
- // it members with NULLs
- zhandle_t lzh;
- memcpy(&lzh,zh,sizeof(lzh));
- int rc=zookeeper_close(zh);
- zhandle_t* savezh=zh; zh=0;
- // we're done, disable mock's fake free(), use libc's free() instead
- freeMock.disable();
-
- // verify that zookeeper_close has done its job
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- // memory
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.hostname));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.addrs));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(adaptor));
- // Cannot be maintained accurately: CPPUNIT_ASSERT_EQUAL(10,freeMock.callCounter);
- // threads
- CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(adaptor->io));
- CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(adaptor->completion));
- // mutexes
- CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(&savezh->to_process.lock));
- CPPUNIT_ASSERT_EQUAL(0,MockPthreadsNull::getInvalidAccessCounter(&savezh->to_process.lock));
- CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(&savezh->to_send.lock));
- CPPUNIT_ASSERT_EQUAL(0,MockPthreadsNull::getInvalidAccessCounter(&savezh->to_send.lock));
- CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(&savezh->sent_requests.lock));
- CPPUNIT_ASSERT_EQUAL(0,MockPthreadsNull::getInvalidAccessCounter(&savezh->sent_requests.lock));
- CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(&savezh->completions_to_process.lock));
- CPPUNIT_ASSERT_EQUAL(0,MockPthreadsNull::getInvalidAccessCounter(&savezh->completions_to_process.lock));
- // conditionals
- CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(&savezh->sent_requests.cond));
- CPPUNIT_ASSERT_EQUAL(0,MockPthreadsNull::getInvalidAccessCounter(&savezh->sent_requests.cond));
- CPPUNIT_ASSERT_EQUAL(1,MockPthreadsNull::getDestroyCounter(&savezh->completions_to_process.cond));
- CPPUNIT_ASSERT_EQUAL(0,MockPthreadsNull::getInvalidAccessCounter(&savezh->completions_to_process.cond));
- }
- void testCloseUnconnected1()
- {
- for(int i=0; i<100;i++){
- zh=zookeeper_init("localhost:2121",watcher,10000,0,0,0);
- CPPUNIT_ASSERT(zh!=0);
- adaptor_threads* adaptor=(adaptor_threads*)zh->adaptor_priv;
- CPPUNIT_ASSERT(adaptor!=0);
- int rc=zookeeper_close(zh);
- zh=0;
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- }
- }
- void testCloseConnected1()
- {
- // frozen time -- no timeouts and no pings
- Mock_gettimeofday timeMock;
-
- for(int i=0;i<100;i++){
- ZookeeperServer zkServer;
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
- // use a checked version of pthread calls
- CheckedPthread threadMock;
- // do not actually free the memory while in zookeeper_close()
- Mock_free_noop freeMock;
-
- zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
- CPPUNIT_ASSERT(zh!=0);
- // make sure the client has connected
- CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
- // make a copy of zhandle before close() overwrites some of
- // its members with NULLs
- zhandle_t lzh;
- memcpy(&lzh,zh,sizeof(lzh));
- int rc=zookeeper_close(zh);
- zhandle_t* savezh=zh; zh=0;
- // we're done, disable mock's fake free(), use libc's free() instead
- freeMock.disable();
-
- CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
- adaptor_threads* adaptor=(adaptor_threads*)lzh.adaptor_priv;
- // memory
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.hostname));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh.addrs));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(adaptor));
- // threads
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(adaptor->io));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(adaptor->completion));
- // mutexes
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&savezh->to_process.lock));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&savezh->to_process.lock));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&savezh->to_send.lock));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&savezh->to_send.lock));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&savezh->sent_requests.lock));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&savezh->sent_requests.lock));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&savezh->completions_to_process.lock));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&savezh->completions_to_process.lock));
- // conditionals
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&savezh->sent_requests.cond));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&savezh->sent_requests.cond));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&savezh->completions_to_process.cond));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&savezh->completions_to_process.cond));
- }
- }
-
- struct PointerFreed{
- PointerFreed(Mock_free_noop& freeMock,void* ptr):
- freeMock_(freeMock),ptr_(ptr){}
- bool operator()() const{return freeMock_.isFreed(ptr_); }
- Mock_free_noop& freeMock_;
- void* ptr_;
- };
- // test if zookeeper_close may be called from a watcher callback on
- // SESSION_EXPIRED event
- void testCloseFromWatcher1()
- {
- // frozen time -- no timeouts and no pings
- Mock_gettimeofday timeMock;
-
- for(int i=0;i<100;i++){
- ZookeeperServer zkServer;
- // make the server return a non-matching session id
- zkServer.returnSessionExpired();
-
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
- // use a checked version of pthread calls
- CheckedPthread threadMock;
- // do not actually free the memory while in zookeeper_close()
- Mock_free_noop freeMock;
-
- CloseOnSessionExpired closeAction;
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,
- TEST_CLIENT_ID,&closeAction,0);
-
- CPPUNIT_ASSERT(zh!=0);
- // we rely on the fact that zh is freed the last right before
- // zookeeper_close() returns...
- CPPUNIT_ASSERT(ensureCondition(PointerFreed(freeMock,zh),1000)<1000);
- zhandle_t* lzh=zh;
- zh=0;
- // we're done, disable mock's fake free(), use libc's free() instead
- freeMock.disable();
-
- CPPUNIT_ASSERT_EQUAL((int)ZOK,closeAction.rc);
- adaptor_threads* adaptor=(adaptor_threads*)closeAction.lzh.adaptor_priv;
- // memory
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(closeAction.lzh.hostname));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(closeAction.lzh.addrs));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(adaptor));
- // threads
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(adaptor->io));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(adaptor->completion));
- // mutexes
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->to_process.lock));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->to_process.lock));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->to_send.lock));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->to_send.lock));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->sent_requests.lock));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->sent_requests.lock));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->completions_to_process.lock));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->completions_to_process.lock));
- // conditionals
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->sent_requests.cond));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->sent_requests.cond));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->completions_to_process.cond));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->completions_to_process.cond));
- }
- }
-
- void testIOThreadStoppedOnExpire()
- {
- // frozen time -- no timeouts and no pings
- Mock_gettimeofday timeMock;
-
- for(int i=0;i<100;i++){
- ZookeeperServer zkServer;
- // make the server return a non-matching session id
- zkServer.returnSessionExpired();
-
- Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
- // use a checked version of pthread calls
- CheckedPthread threadMock;
- // do not call zookeeper_close() from the watcher
- CloseOnSessionExpired closeAction(false);
- zh=zookeeper_init("localhost:2121",activeWatcher,10000,
- &testClientId,&closeAction,0);
-
- // this is to ensure that if any assert fires, zookeeper_close()
- // will still be called while all the mocks are in the scope!
- CloseFinally guard(&zh);
-
- CPPUNIT_ASSERT(zh!=0);
- CPPUNIT_ASSERT(ensureCondition(SessionExpired(zh),1000)<1000);
- CPPUNIT_ASSERT(ensureCondition(IOThreadStopped(zh),1000)<1000);
- // make sure the watcher has been processed
- CPPUNIT_ASSERT(ensureCondition(closeAction.isWatcherTriggered(),1000)<1000);
- // make sure the threads have not been destroyed yet
- adaptor_threads* adaptor=(adaptor_threads*)zh->adaptor_priv;
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getDestroyCounter(adaptor->io));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getDestroyCounter(adaptor->completion));
- // about to call zookeeper_close() -- no longer need the guard
- guard.disarm();
-
- // do not actually free the memory while in zookeeper_close()
- Mock_free_noop freeMock;
- zookeeper_close(zh);
- zhandle_t* lzh=zh; zh=0;
- // we're done, disable mock's fake free(), use libc's free() instead
- freeMock.disable();
-
- // memory
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(lzh));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(closeAction.lzh.hostname));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(closeAction.lzh.addrs));
- CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(adaptor));
- // threads
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(adaptor->io));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(adaptor->completion));
- // mutexes
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->to_process.lock));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->to_process.lock));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->to_send.lock));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->to_send.lock));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->sent_requests.lock));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->sent_requests.lock));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->completions_to_process.lock));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->completions_to_process.lock));
- // conditionals
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->sent_requests.cond));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->sent_requests.cond));
- CPPUNIT_ASSERT_EQUAL(1,CheckedPthread::getDestroyCounter(&lzh->completions_to_process.cond));
- CPPUNIT_ASSERT_EQUAL(0,CheckedPthread::getInvalidAccessCounter(&lzh->completions_to_process.cond));
- }
- }
-
-#endif
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_close);
[05/20] zookeeper git commit: ZOOKEEPER-3031: 3.4: MAVEN MIGRATION -
move client dir
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/5694559d/zookeeper-client/zookeeper-client-c/src/zookeeper.c
----------------------------------------------------------------------
diff --git a/zookeeper-client/zookeeper-client-c/src/zookeeper.c b/zookeeper-client/zookeeper-client-c/src/zookeeper.c
new file mode 100644
index 0000000..c087864
--- /dev/null
+++ b/zookeeper-client/zookeeper-client-c/src/zookeeper.c
@@ -0,0 +1,3767 @@
+/**
+ * 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.
+ */
+
+#if !defined(DLL_EXPORT) && !defined(USE_STATIC_LIB)
+# define USE_STATIC_LIB
+#endif
+
+#if defined(__CYGWIN__)
+#define USE_IPV6
+#endif
+
+#include "config.h"
+#include <zookeeper.h>
+#include <zookeeper.jute.h>
+#include <proto.h>
+#include "zk_adaptor.h"
+#include "zookeeper_log.h"
+#include "zk_hashtable.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <limits.h>
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_POLL
+#include <poll.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // needed for _POSIX_MONOTONIC_CLOCK
+#endif
+
+#ifdef HAVE_SYS_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+
+#ifdef HAVE_GETPWUID_R
+#include <pwd.h>
+#endif
+
+#ifdef WIN32
+#define random rand /* replace POSIX random with Windows rand */
+#include <process.h> /* for getpid */
+#include <direct.h> /* for getcwd */
+#define EAI_ADDRFAMILY WSAEINVAL /* is this still needed? */
+#define EHOSTDOWN EPIPE
+#define ESTALE ENODEV
+#endif
+
+#define IF_DEBUG(x) if(logLevel==ZOO_LOG_LEVEL_DEBUG) {x;}
+
+const int ZOOKEEPER_WRITE = 1 << 0;
+const int ZOOKEEPER_READ = 1 << 1;
+
+const int ZOO_EPHEMERAL = 1 << 0;
+const int ZOO_SEQUENCE = 1 << 1;
+
+const int ZOO_EXPIRED_SESSION_STATE = EXPIRED_SESSION_STATE_DEF;
+const int ZOO_AUTH_FAILED_STATE = AUTH_FAILED_STATE_DEF;
+const int ZOO_CONNECTING_STATE = CONNECTING_STATE_DEF;
+const int ZOO_ASSOCIATING_STATE = ASSOCIATING_STATE_DEF;
+const int ZOO_CONNECTED_STATE = CONNECTED_STATE_DEF;
+static __attribute__ ((unused)) const char* state2String(int state){
+ switch(state){
+ case 0:
+ return "ZOO_CLOSED_STATE";
+ case CONNECTING_STATE_DEF:
+ return "ZOO_CONNECTING_STATE";
+ case ASSOCIATING_STATE_DEF:
+ return "ZOO_ASSOCIATING_STATE";
+ case CONNECTED_STATE_DEF:
+ return "ZOO_CONNECTED_STATE";
+ case EXPIRED_SESSION_STATE_DEF:
+ return "ZOO_EXPIRED_SESSION_STATE";
+ case AUTH_FAILED_STATE_DEF:
+ return "ZOO_AUTH_FAILED_STATE";
+ }
+ return "INVALID_STATE";
+}
+
+const int ZOO_CREATED_EVENT = CREATED_EVENT_DEF;
+const int ZOO_DELETED_EVENT = DELETED_EVENT_DEF;
+const int ZOO_CHANGED_EVENT = CHANGED_EVENT_DEF;
+const int ZOO_CHILD_EVENT = CHILD_EVENT_DEF;
+const int ZOO_SESSION_EVENT = SESSION_EVENT_DEF;
+const int ZOO_NOTWATCHING_EVENT = NOTWATCHING_EVENT_DEF;
+static __attribute__ ((unused)) const char* watcherEvent2String(int ev){
+ switch(ev){
+ case 0:
+ return "ZOO_ERROR_EVENT";
+ case CREATED_EVENT_DEF:
+ return "ZOO_CREATED_EVENT";
+ case DELETED_EVENT_DEF:
+ return "ZOO_DELETED_EVENT";
+ case CHANGED_EVENT_DEF:
+ return "ZOO_CHANGED_EVENT";
+ case CHILD_EVENT_DEF:
+ return "ZOO_CHILD_EVENT";
+ case SESSION_EVENT_DEF:
+ return "ZOO_SESSION_EVENT";
+ case NOTWATCHING_EVENT_DEF:
+ return "ZOO_NOTWATCHING_EVENT";
+ }
+ return "INVALID_EVENT";
+}
+
+const int ZOO_PERM_READ = 1 << 0;
+const int ZOO_PERM_WRITE = 1 << 1;
+const int ZOO_PERM_CREATE = 1 << 2;
+const int ZOO_PERM_DELETE = 1 << 3;
+const int ZOO_PERM_ADMIN = 1 << 4;
+const int ZOO_PERM_ALL = 0x1f;
+struct Id ZOO_ANYONE_ID_UNSAFE = {"world", "anyone"};
+struct Id ZOO_AUTH_IDS = {"auth", ""};
+static struct ACL _OPEN_ACL_UNSAFE_ACL[] = {{0x1f, {"world", "anyone"}}};
+static struct ACL _READ_ACL_UNSAFE_ACL[] = {{0x01, {"world", "anyone"}}};
+static struct ACL _CREATOR_ALL_ACL_ACL[] = {{0x1f, {"auth", ""}}};
+struct ACL_vector ZOO_OPEN_ACL_UNSAFE = { 1, _OPEN_ACL_UNSAFE_ACL};
+struct ACL_vector ZOO_READ_ACL_UNSAFE = { 1, _READ_ACL_UNSAFE_ACL};
+struct ACL_vector ZOO_CREATOR_ALL_ACL = { 1, _CREATOR_ALL_ACL_ACL};
+
+#define COMPLETION_WATCH -1
+#define COMPLETION_VOID 0
+#define COMPLETION_STAT 1
+#define COMPLETION_DATA 2
+#define COMPLETION_STRINGLIST 3
+#define COMPLETION_STRINGLIST_STAT 4
+#define COMPLETION_ACLLIST 5
+#define COMPLETION_STRING 6
+#define COMPLETION_MULTI 7
+
+typedef struct _auth_completion_list {
+ void_completion_t completion;
+ const char *auth_data;
+ struct _auth_completion_list *next;
+} auth_completion_list_t;
+
+typedef struct completion {
+ int type; /* one of COMPLETION_* values above */
+ union {
+ void_completion_t void_result;
+ stat_completion_t stat_result;
+ data_completion_t data_result;
+ strings_completion_t strings_result;
+ strings_stat_completion_t strings_stat_result;
+ acl_completion_t acl_result;
+ string_completion_t string_result;
+ struct watcher_object_list *watcher_result;
+ };
+ completion_head_t clist; /* For multi-op */
+} completion_t;
+
+typedef struct _completion_list {
+ int xid;
+ completion_t c;
+ const void *data;
+ buffer_list_t *buffer;
+ struct _completion_list *next;
+ watcher_registration_t* watcher;
+} completion_list_t;
+
+const char*err2string(int err);
+static int queue_session_event(zhandle_t *zh, int state);
+static const char* format_endpoint_info(const struct sockaddr_storage* ep);
+static const char* format_current_endpoint_info(zhandle_t* zh);
+
+/* deserialize forward declarations */
+static void deserialize_response(int type, int xid, int failed, int rc, completion_list_t *cptr, struct iarchive *ia);
+static int deserialize_multi(int xid, completion_list_t *cptr, struct iarchive *ia);
+
+/* completion routine forward declarations */
+static int add_completion(zhandle_t *zh, int xid, int completion_type,
+ const void *dc, const void *data, int add_to_front,
+ watcher_registration_t* wo, completion_head_t *clist);
+static completion_list_t* create_completion_entry(int xid, int completion_type,
+ const void *dc, const void *data, watcher_registration_t* wo,
+ completion_head_t *clist);
+static void destroy_completion_entry(completion_list_t* c);
+static void queue_completion_nolock(completion_head_t *list, completion_list_t *c,
+ int add_to_front);
+static void queue_completion(completion_head_t *list, completion_list_t *c,
+ int add_to_front);
+static int handle_socket_error_msg(zhandle_t *zh, int line, int rc,
+ const char* format,...);
+static void cleanup_bufs(zhandle_t *zh,int callCompletion,int rc);
+
+static int disable_conn_permute=0; // permute enabled by default
+
+static __attribute__((unused)) void print_completion_queue(zhandle_t *zh);
+
+static void *SYNCHRONOUS_MARKER = (void*)&SYNCHRONOUS_MARKER;
+static int isValidPath(const char* path, const int flags);
+
+#ifdef _WINDOWS
+static int zookeeper_send(SOCKET s, const char* buf, int len)
+#else
+static ssize_t zookeeper_send(int s, const void* buf, size_t len)
+#endif
+{
+#ifdef __linux__
+ return send(s, buf, len, MSG_NOSIGNAL);
+#else
+ return send(s, buf, len, 0);
+#endif
+}
+
+const void *zoo_get_context(zhandle_t *zh)
+{
+ return zh->context;
+}
+
+void zoo_set_context(zhandle_t *zh, void *context)
+{
+ if (zh != NULL) {
+ zh->context = context;
+ }
+}
+
+int zoo_recv_timeout(zhandle_t *zh)
+{
+ return zh->recv_timeout;
+}
+
+/** these functions are thread unsafe, so make sure that
+ zoo_lock_auth is called before you access them **/
+static auth_info* get_last_auth(auth_list_head_t *auth_list) {
+ auth_info *element;
+ element = auth_list->auth;
+ if (element == NULL) {
+ return NULL;
+ }
+ while (element->next != NULL) {
+ element = element->next;
+ }
+ return element;
+}
+
+static void free_auth_completion(auth_completion_list_t *a_list) {
+ auth_completion_list_t *tmp, *ftmp;
+ if (a_list == NULL) {
+ return;
+ }
+ tmp = a_list->next;
+ while (tmp != NULL) {
+ ftmp = tmp;
+ tmp = tmp->next;
+ ftmp->completion = NULL;
+ ftmp->auth_data = NULL;
+ free(ftmp);
+ }
+ a_list->completion = NULL;
+ a_list->auth_data = NULL;
+ a_list->next = NULL;
+ return;
+}
+
+static void add_auth_completion(auth_completion_list_t* a_list, void_completion_t* completion,
+ const char *data) {
+ auth_completion_list_t *element;
+ auth_completion_list_t *n_element;
+ element = a_list;
+ if (a_list->completion == NULL) {
+ //this is the first element
+ a_list->completion = *completion;
+ a_list->next = NULL;
+ a_list->auth_data = data;
+ return;
+ }
+ while (element->next != NULL) {
+ element = element->next;
+ }
+ n_element = (auth_completion_list_t*) malloc(sizeof(auth_completion_list_t));
+ n_element->next = NULL;
+ n_element->completion = *completion;
+ n_element->auth_data = data;
+ element->next = n_element;
+ return;
+}
+
+static void get_auth_completions(auth_list_head_t *auth_list, auth_completion_list_t *a_list) {
+ auth_info *element;
+ element = auth_list->auth;
+ if (element == NULL) {
+ return;
+ }
+ while (element) {
+ if (element->completion) {
+ add_auth_completion(a_list, &element->completion, element->data);
+ }
+ element->completion = NULL;
+ element = element->next;
+ }
+ return;
+}
+
+static void add_last_auth(auth_list_head_t *auth_list, auth_info *add_el) {
+ auth_info *element;
+ element = auth_list->auth;
+ if (element == NULL) {
+ //first element in the list
+ auth_list->auth = add_el;
+ return;
+ }
+ while (element->next != NULL) {
+ element = element->next;
+ }
+ element->next = add_el;
+ return;
+}
+
+static void init_auth_info(auth_list_head_t *auth_list)
+{
+ auth_list->auth = NULL;
+}
+
+static void mark_active_auth(zhandle_t *zh) {
+ auth_list_head_t auth_h = zh->auth_h;
+ auth_info *element;
+ if (auth_h.auth == NULL) {
+ return;
+ }
+ element = auth_h.auth;
+ while (element != NULL) {
+ element->state = 1;
+ element = element->next;
+ }
+}
+
+static void free_auth_info(auth_list_head_t *auth_list)
+{
+ auth_info *auth = auth_list->auth;
+ while (auth != NULL) {
+ auth_info* old_auth = NULL;
+ if(auth->scheme!=NULL)
+ free(auth->scheme);
+ deallocate_Buffer(&auth->auth);
+ old_auth = auth;
+ auth = auth->next;
+ free(old_auth);
+ }
+ init_auth_info(auth_list);
+}
+
+int is_unrecoverable(zhandle_t *zh)
+{
+ return (zh->state<0)? ZINVALIDSTATE: ZOK;
+}
+
+zk_hashtable *exists_result_checker(zhandle_t *zh, int rc)
+{
+ if (rc == ZOK) {
+ return zh->active_node_watchers;
+ } else if (rc == ZNONODE) {
+ return zh->active_exist_watchers;
+ }
+ return 0;
+}
+
+zk_hashtable *data_result_checker(zhandle_t *zh, int rc)
+{
+ return rc==ZOK ? zh->active_node_watchers : 0;
+}
+
+zk_hashtable *child_result_checker(zhandle_t *zh, int rc)
+{
+ return rc==ZOK ? zh->active_child_watchers : 0;
+}
+
+/**
+ * Frees and closes everything associated with a handle,
+ * including the handle itself.
+ */
+static void destroy(zhandle_t *zh)
+{
+ if (zh == NULL) {
+ return;
+ }
+ /* call any outstanding completions with a special error code */
+ cleanup_bufs(zh,1,ZCLOSING);
+ if (zh->hostname != 0) {
+ free(zh->hostname);
+ zh->hostname = NULL;
+ }
+ if (zh->fd != -1) {
+ close(zh->fd);
+ zh->fd = -1;
+ zh->state = 0;
+ }
+ if (zh->addrs != 0) {
+ free(zh->addrs);
+ zh->addrs = NULL;
+ }
+
+ if (zh->chroot != 0) {
+ free(zh->chroot);
+ zh->chroot = NULL;
+ }
+
+ free_auth_info(&zh->auth_h);
+ destroy_zk_hashtable(zh->active_node_watchers);
+ destroy_zk_hashtable(zh->active_exist_watchers);
+ destroy_zk_hashtable(zh->active_child_watchers);
+}
+
+static void setup_random()
+{
+#ifndef WIN32 // TODO: better seed
+ int seed;
+ int fd = open("/dev/urandom", O_RDONLY);
+ if (fd == -1) {
+ seed = getpid();
+ } else {
+ int seed_len = 0;
+
+ /* Enter a loop to fill in seed with random data from /dev/urandom.
+ * This is done in a loop so that we can safely handle short reads
+ * which can happen due to signal interruptions.
+ */
+ while (seed_len < sizeof(seed)) {
+ /* Assert we either read something or we were interrupted due to a
+ * signal (errno == EINTR) in which case we need to retry.
+ */
+ int rc = read(fd, &seed + seed_len, sizeof(seed) - seed_len);
+ assert(rc > 0 || errno == EINTR);
+ if (rc > 0) {
+ seed_len += rc;
+ }
+ }
+ close(fd);
+ }
+ srandom(seed);
+#endif
+}
+
+#ifndef __CYGWIN__
+/**
+ * get the errno from the return code
+ * of get addrinfo. Errno is not set
+ * with the call to getaddrinfo, so thats
+ * why we have to do this.
+ */
+static int getaddrinfo_errno(int rc) {
+ switch(rc) {
+ case EAI_NONAME:
+// ZOOKEEPER-1323 EAI_NODATA and EAI_ADDRFAMILY are deprecated in FreeBSD.
+#if defined EAI_NODATA && EAI_NODATA != EAI_NONAME
+ case EAI_NODATA:
+#endif
+ return ENOENT;
+ case EAI_MEMORY:
+ return ENOMEM;
+ default:
+ return EINVAL;
+ }
+}
+#endif
+
+/**
+ * fill in the addrs array of the zookeeper servers in the zhandle. after filling
+ * them in, we will permute them for load balancing.
+ */
+int getaddrs(zhandle_t *zh)
+{
+ char *hosts = strdup(zh->hostname);
+ char *host;
+ char *strtok_last;
+ struct sockaddr_storage *addr;
+ int i;
+ int rc;
+ int alen = 0; /* the allocated length of the addrs array */
+
+ zh->addrs_count = 0;
+ if (zh->addrs) {
+ free(zh->addrs);
+ zh->addrs = 0;
+ }
+ if (!hosts) {
+ LOG_ERROR(("out of memory"));
+ errno=ENOMEM;
+ return ZSYSTEMERROR;
+ }
+ zh->addrs = 0;
+ host=strtok_r(hosts, ",", &strtok_last);
+ while(host) {
+ char *port_spec = strrchr(host, ':');
+ char *end_port_spec;
+ int port;
+ if (!port_spec) {
+ LOG_ERROR(("no port in %s", host));
+ errno=EINVAL;
+ rc=ZBADARGUMENTS;
+ goto fail;
+ }
+ *port_spec = '\0';
+ port_spec++;
+ port = strtol(port_spec, &end_port_spec, 0);
+ if (!*port_spec || *end_port_spec || port == 0) {
+ LOG_ERROR(("invalid port in %s", host));
+ errno=EINVAL;
+ rc=ZBADARGUMENTS;
+ goto fail;
+ }
+#if defined(__CYGWIN__)
+ // sadly CYGWIN doesn't have getaddrinfo
+ // but happily gethostbyname is threadsafe in windows
+ {
+ struct hostent *he;
+ char **ptr;
+ struct sockaddr_in *addr4;
+
+ he = gethostbyname(host);
+ if (!he) {
+ LOG_ERROR(("could not resolve %s", host));
+ errno=ENOENT;
+ rc=ZBADARGUMENTS;
+ goto fail;
+ }
+
+ /* Setup the address array */
+ for(ptr = he->h_addr_list;*ptr != 0; ptr++) {
+ if (zh->addrs_count == alen) {
+ alen += 16;
+ zh->addrs = realloc(zh->addrs, sizeof(*zh->addrs)*alen);
+ if (zh->addrs == 0) {
+ LOG_ERROR(("out of memory"));
+ errno=ENOMEM;
+ rc=ZSYSTEMERROR;
+ goto fail;
+ }
+ }
+ addr = &zh->addrs[zh->addrs_count];
+ addr4 = (struct sockaddr_in*)addr;
+ addr->ss_family = he->h_addrtype;
+ if (addr->ss_family == AF_INET) {
+ addr4->sin_port = htons(port);
+ memset(&addr4->sin_zero, 0, sizeof(addr4->sin_zero));
+ memcpy(&addr4->sin_addr, *ptr, he->h_length);
+ zh->addrs_count++;
+ }
+#if defined(AF_INET6)
+ else if (addr->ss_family == AF_INET6) {
+ struct sockaddr_in6 *addr6;
+
+ addr6 = (struct sockaddr_in6*)addr;
+ addr6->sin6_port = htons(port);
+ addr6->sin6_scope_id = 0;
+ addr6->sin6_flowinfo = 0;
+ memcpy(&addr6->sin6_addr, *ptr, he->h_length);
+ zh->addrs_count++;
+ }
+#endif
+ else {
+ LOG_WARN(("skipping unknown address family %x for %s",
+ addr->ss_family, zh->hostname));
+ }
+ }
+ host = strtok_r(0, ",", &strtok_last);
+ }
+#else
+ {
+ struct addrinfo hints, *res, *res0;
+
+ memset(&hints, 0, sizeof(hints));
+#ifdef AI_ADDRCONFIG
+ hints.ai_flags = AI_ADDRCONFIG;
+#else
+ hints.ai_flags = 0;
+#endif
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ while(isspace(*host) && host != strtok_last)
+ host++;
+
+ if ((rc = getaddrinfo(host, port_spec, &hints, &res0)) != 0) {
+ //bug in getaddrinfo implementation when it returns
+ //EAI_BADFLAGS or EAI_ADDRFAMILY with AF_UNSPEC and
+ // ai_flags as AI_ADDRCONFIG
+#ifdef AI_ADDRCONFIG
+ if ((hints.ai_flags == AI_ADDRCONFIG) &&
+// ZOOKEEPER-1323 EAI_NODATA and EAI_ADDRFAMILY are deprecated in FreeBSD.
+#ifdef EAI_ADDRFAMILY
+ ((rc ==EAI_BADFLAGS) || (rc == EAI_ADDRFAMILY))) {
+#else
+ (rc == EAI_BADFLAGS)) {
+#endif
+ //reset ai_flags to null
+ hints.ai_flags = 0;
+ //retry getaddrinfo
+ rc = getaddrinfo(host, port_spec, &hints, &res0);
+ }
+#endif
+ if (rc != 0) {
+ errno = getaddrinfo_errno(rc);
+#ifdef WIN32
+ LOG_ERROR(("Win32 message: %s\n", gai_strerror(rc)));
+#else
+ LOG_ERROR(("getaddrinfo: %s\n", strerror(errno)));
+#endif
+ rc=ZSYSTEMERROR;
+ goto fail;
+ }
+ }
+
+ for (res = res0; res; res = res->ai_next) {
+ // Expand address list if needed
+ if (zh->addrs_count == alen) {
+ void *tmpaddr;
+ alen += 16;
+ tmpaddr = realloc(zh->addrs, sizeof(*zh->addrs)*alen);
+ if (tmpaddr == 0) {
+ LOG_ERROR(("out of memory"));
+ errno=ENOMEM;
+ rc=ZSYSTEMERROR;
+ goto fail;
+ }
+ zh->addrs=tmpaddr;
+ }
+
+ // Copy addrinfo into address list
+ addr = &zh->addrs[zh->addrs_count];
+ switch (res->ai_family) {
+ case AF_INET:
+#if defined(AF_INET6)
+ case AF_INET6:
+#endif
+ memcpy(addr, res->ai_addr, res->ai_addrlen);
+ ++zh->addrs_count;
+ break;
+ default:
+ LOG_WARN(("skipping unknown address family %x for %s",
+ res->ai_family, zh->hostname));
+ break;
+ }
+ }
+
+ freeaddrinfo(res0);
+
+ host = strtok_r(0, ",", &strtok_last);
+ }
+#endif
+ }
+ free(hosts);
+
+ if(!disable_conn_permute){
+ setup_random();
+ /* Permute */
+ for (i = zh->addrs_count - 1; i > 0; --i) {
+ long int j = random()%(i+1);
+ if (i != j) {
+ struct sockaddr_storage t = zh->addrs[i];
+ zh->addrs[i] = zh->addrs[j];
+ zh->addrs[j] = t;
+ }
+ }
+ }
+ return ZOK;
+fail:
+ if (zh->addrs) {
+ free(zh->addrs);
+ zh->addrs=0;
+ }
+ if (hosts) {
+ free(hosts);
+ }
+ return rc;
+}
+
+const clientid_t *zoo_client_id(zhandle_t *zh)
+{
+ return &zh->client_id;
+}
+
+static void null_watcher_fn(zhandle_t* p1, int p2, int p3,const char* p4,void*p5){}
+
+watcher_fn zoo_set_watcher(zhandle_t *zh,watcher_fn newFn)
+{
+ watcher_fn oldWatcher=zh->watcher;
+ if (newFn) {
+ zh->watcher = newFn;
+ } else {
+ zh->watcher = null_watcher_fn;
+ }
+ return oldWatcher;
+}
+
+struct sockaddr* zookeeper_get_connected_host(zhandle_t *zh,
+ struct sockaddr *addr, socklen_t *addr_len)
+{
+ if (zh->state!=ZOO_CONNECTED_STATE) {
+ return NULL;
+ }
+ if (getpeername(zh->fd, addr, addr_len)==-1) {
+ return NULL;
+ }
+ return addr;
+}
+
+static void log_env() {
+ char buf[2048];
+#ifdef HAVE_SYS_UTSNAME_H
+ struct utsname utsname;
+#endif
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID_R)
+ struct passwd pw;
+ struct passwd *pwp = NULL;
+ uid_t uid = 0;
+#endif
+
+ LOG_INFO(("Client environment:zookeeper.version=%s", PACKAGE_STRING));
+
+#ifdef HAVE_GETHOSTNAME
+ gethostname(buf, sizeof(buf));
+ LOG_INFO(("Client environment:host.name=%s", buf));
+#else
+ LOG_INFO(("Client environment:host.name=<not implemented>"));
+#endif
+
+#ifdef HAVE_SYS_UTSNAME_H
+ uname(&utsname);
+ LOG_INFO(("Client environment:os.name=%s", utsname.sysname));
+ LOG_INFO(("Client environment:os.arch=%s", utsname.release));
+ LOG_INFO(("Client environment:os.version=%s", utsname.version));
+#else
+ LOG_INFO(("Client environment:os.name=<not implemented>"));
+ LOG_INFO(("Client environment:os.arch=<not implemented>"));
+ LOG_INFO(("Client environment:os.version=<not implemented>"));
+#endif
+
+#ifdef HAVE_GETLOGIN
+ LOG_INFO(("Client environment:user.name=%s", getlogin()));
+#else
+ LOG_INFO(("Client environment:user.name=<not implemented>"));
+#endif
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID_R)
+ uid = getuid();
+ if (!getpwuid_r(uid, &pw, buf, sizeof(buf), &pwp)) {
+ LOG_INFO(("Client environment:user.home=%s", pw.pw_dir));
+ } else {
+ LOG_INFO(("Client environment:user.home=<NA>"));
+ }
+#else
+ LOG_INFO(("Client environment:user.home=<not implemented>"));
+#endif
+
+#ifdef HAVE_GETCWD
+ if (!getcwd(buf, sizeof(buf))) {
+ LOG_INFO(("Client environment:user.dir=<toolong>"));
+ } else {
+ LOG_INFO(("Client environment:user.dir=%s", buf));
+ }
+#else
+ LOG_INFO(("Client environment:user.dir=<not implemented>"));
+#endif
+}
+
+/**
+ * Create a zookeeper handle associated with the given host and port.
+ */
+zhandle_t *zookeeper_init(const char *host, watcher_fn watcher,
+ int recv_timeout, const clientid_t *clientid, void *context, int flags)
+{
+ int errnosave = 0;
+ zhandle_t *zh = NULL;
+ char *index_chroot = NULL;
+
+ log_env();
+#ifdef WIN32
+ if (Win32WSAStartup()){
+ LOG_ERROR(("Error initializing ws2_32.dll"));
+ return 0;
+ }
+#endif
+ LOG_INFO(("Initiating client connection, host=%s sessionTimeout=%d watcher=%p"
+ " sessionId=%#llx sessionPasswd=%s context=%p flags=%d",
+ host,
+ recv_timeout,
+ watcher,
+ (clientid == 0 ? 0 : clientid->client_id),
+ ((clientid == 0) || (clientid->passwd[0] == 0) ?
+ "<null>" : "<hidden>"),
+ context,
+ flags));
+
+ zh = calloc(1, sizeof(*zh));
+ if (!zh) {
+ return 0;
+ }
+ zh->fd = -1;
+ zh->state = NOTCONNECTED_STATE_DEF;
+ zh->context = context;
+ zh->recv_timeout = recv_timeout;
+ init_auth_info(&zh->auth_h);
+ if (watcher) {
+ zh->watcher = watcher;
+ } else {
+ zh->watcher = null_watcher_fn;
+ }
+ if (host == 0 || *host == 0) { // what we shouldn't dup
+ errno=EINVAL;
+ goto abort;
+ }
+ //parse the host to get the chroot if
+ //available
+ index_chroot = strchr(host, '/');
+ if (index_chroot) {
+ zh->chroot = strdup(index_chroot);
+ if (zh->chroot == NULL) {
+ goto abort;
+ }
+ // if chroot is just / set it to null
+ if (strlen(zh->chroot) == 1) {
+ free(zh->chroot);
+ zh->chroot = NULL;
+ }
+ // cannot use strndup so allocate and strcpy
+ zh->hostname = (char *) malloc(index_chroot - host + 1);
+ zh->hostname = strncpy(zh->hostname, host, (index_chroot - host));
+ //strncpy does not null terminate
+ *(zh->hostname + (index_chroot - host)) = '\0';
+
+ } else {
+ zh->chroot = NULL;
+ zh->hostname = strdup(host);
+ }
+ if (zh->chroot && !isValidPath(zh->chroot, 0)) {
+ errno = EINVAL;
+ goto abort;
+ }
+ if (zh->hostname == 0) {
+ goto abort;
+ }
+ if(getaddrs(zh)!=0) {
+ goto abort;
+ }
+ zh->connect_index = 0;
+ if (clientid) {
+ memcpy(&zh->client_id, clientid, sizeof(zh->client_id));
+ } else {
+ memset(&zh->client_id, 0, sizeof(zh->client_id));
+ }
+ zh->primer_buffer.buffer = zh->primer_storage_buffer;
+ zh->primer_buffer.curr_offset = 0;
+ zh->primer_buffer.len = sizeof(zh->primer_storage_buffer);
+ zh->primer_buffer.next = 0;
+ zh->last_zxid = 0;
+ zh->next_deadline.tv_sec=zh->next_deadline.tv_usec=0;
+ zh->socket_readable.tv_sec=zh->socket_readable.tv_usec=0;
+ zh->active_node_watchers=create_zk_hashtable();
+ zh->active_exist_watchers=create_zk_hashtable();
+ zh->active_child_watchers=create_zk_hashtable();
+
+ if (adaptor_init(zh) == -1) {
+ goto abort;
+ }
+
+ return zh;
+abort:
+ errnosave=errno;
+ destroy(zh);
+ free(zh);
+ errno=errnosave;
+ return 0;
+}
+
+/**
+ * deallocated the free_path only its beeen allocated
+ * and not equal to path
+ */
+void free_duplicate_path(const char *free_path, const char* path) {
+ if (free_path != path) {
+ free((void*)free_path);
+ }
+}
+
+/**
+ prepend the chroot path if available else return the path
+*/
+static char* prepend_string(zhandle_t *zh, const char* client_path) {
+ char *ret_str;
+ if (zh == NULL || zh->chroot == NULL)
+ return (char *) client_path;
+ // handle the chroot itself, client_path = "/"
+ if (strlen(client_path) == 1) {
+ return strdup(zh->chroot);
+ }
+ ret_str = (char *) malloc(strlen(zh->chroot) + strlen(client_path) + 1);
+ strcpy(ret_str, zh->chroot);
+ return strcat(ret_str, client_path);
+}
+
+/**
+ strip off the chroot string from the server path
+ if there is one else return the exact path
+ */
+char* sub_string(zhandle_t *zh, const char* server_path) {
+ char *ret_str;
+ if (zh->chroot == NULL)
+ return (char *) server_path;
+ //ZOOKEEPER-1027
+ if (strncmp(server_path, zh->chroot, strlen(zh->chroot)) != 0) {
+ LOG_ERROR(("server path %s does not include chroot path %s",
+ server_path, zh->chroot));
+ return (char *) server_path;
+ }
+ if (strlen(server_path) == strlen(zh->chroot)) {
+ //return "/"
+ ret_str = strdup("/");
+ return ret_str;
+ }
+ ret_str = strdup(server_path + strlen(zh->chroot));
+ return ret_str;
+}
+
+static buffer_list_t *allocate_buffer(char *buff, int len)
+{
+ buffer_list_t *buffer = calloc(1, sizeof(*buffer));
+ if (buffer == 0)
+ return 0;
+
+ buffer->len = len==0?sizeof(*buffer):len;
+ buffer->curr_offset = 0;
+ buffer->buffer = buff;
+ buffer->next = 0;
+ return buffer;
+}
+
+static void free_buffer(buffer_list_t *b)
+{
+ if (!b) {
+ return;
+ }
+ if (b->buffer) {
+ free(b->buffer);
+ }
+ free(b);
+}
+
+static buffer_list_t *dequeue_buffer(buffer_head_t *list)
+{
+ buffer_list_t *b;
+ lock_buffer_list(list);
+ b = list->head;
+ if (b) {
+ list->head = b->next;
+ if (!list->head) {
+ assert(b == list->last);
+ list->last = 0;
+ }
+ }
+ unlock_buffer_list(list);
+ return b;
+}
+
+static int remove_buffer(buffer_head_t *list)
+{
+ buffer_list_t *b = dequeue_buffer(list);
+ if (!b) {
+ return 0;
+ }
+ free_buffer(b);
+ return 1;
+}
+
+static void queue_buffer(buffer_head_t *list, buffer_list_t *b, int add_to_front)
+{
+ b->next = 0;
+ lock_buffer_list(list);
+ if (list->head) {
+ assert(list->last);
+ // The list is not empty
+ if (add_to_front) {
+ b->next = list->head;
+ list->head = b;
+ } else {
+ list->last->next = b;
+ list->last = b;
+ }
+ }else{
+ // The list is empty
+ assert(!list->head);
+ list->head = b;
+ list->last = b;
+ }
+ unlock_buffer_list(list);
+}
+
+static int queue_buffer_bytes(buffer_head_t *list, char *buff, int len)
+{
+ buffer_list_t *b = allocate_buffer(buff,len);
+ if (!b)
+ return ZSYSTEMERROR;
+ queue_buffer(list, b, 0);
+ return ZOK;
+}
+
+static int queue_front_buffer_bytes(buffer_head_t *list, char *buff, int len)
+{
+ buffer_list_t *b = allocate_buffer(buff,len);
+ if (!b)
+ return ZSYSTEMERROR;
+ queue_buffer(list, b, 1);
+ return ZOK;
+}
+
+static __attribute__ ((unused)) int get_queue_len(buffer_head_t *list)
+{
+ int i;
+ buffer_list_t *ptr;
+ lock_buffer_list(list);
+ ptr = list->head;
+ for (i=0; ptr!=0; ptr=ptr->next, i++)
+ ;
+ unlock_buffer_list(list);
+ return i;
+}
+/* returns:
+ * -1 if send failed,
+ * 0 if send would block while sending the buffer (or a send was incomplete),
+ * 1 if success
+ */
+#ifdef WIN32
+static int send_buffer(SOCKET fd, buffer_list_t *buff)
+#else
+static int send_buffer(int fd, buffer_list_t *buff)
+#endif
+{
+ int len = buff->len;
+ int off = buff->curr_offset;
+ int rc = -1;
+
+ if (off < 4) {
+ /* we need to send the length at the beginning */
+ int nlen = htonl(len);
+ char *b = (char*)&nlen;
+ rc = zookeeper_send(fd, b + off, sizeof(nlen) - off);
+ if (rc == -1) {
+#ifndef _WINDOWS
+ if (errno != EAGAIN) {
+#else
+ if (WSAGetLastError() != WSAEWOULDBLOCK) {
+#endif
+ return -1;
+ } else {
+ return 0;
+ }
+ } else {
+ buff->curr_offset += rc;
+ }
+ off = buff->curr_offset;
+ }
+ if (off >= 4) {
+ /* want off to now represent the offset into the buffer */
+ off -= sizeof(buff->len);
+ rc = zookeeper_send(fd, buff->buffer + off, len - off);
+ if (rc == -1) {
+#ifndef _WINDOWS
+ if (errno != EAGAIN) {
+#else
+ if (WSAGetLastError() != WSAEWOULDBLOCK) {
+#endif
+ return -1;
+ }
+ } else {
+ buff->curr_offset += rc;
+ }
+ }
+ return buff->curr_offset == len + sizeof(buff->len);
+}
+
+/* returns:
+ * -1 if recv call failed,
+ * 0 if recv would block,
+ * 1 if success
+ */
+#ifdef WIN32
+static int recv_buffer(SOCKET fd, buffer_list_t *buff)
+#else
+static int recv_buffer(int fd, buffer_list_t *buff)
+#endif
+{
+ int off = buff->curr_offset;
+ int rc = 0;
+ //fprintf(LOGSTREAM, "rc = %d, off = %d, line %d\n", rc, off, __LINE__);
+
+ /* if buffer is less than 4, we are reading in the length */
+ if (off < 4) {
+ char *buffer = (char*)&(buff->len);
+ rc = recv(fd, buffer+off, sizeof(int)-off, 0);
+ //fprintf(LOGSTREAM, "rc = %d, off = %d, line %d\n", rc, off, __LINE__);
+ switch(rc) {
+ case 0:
+ errno = EHOSTDOWN;
+ case -1:
+#ifndef _WINDOWS
+ if (errno == EAGAIN) {
+#else
+ if (WSAGetLastError() == WSAEWOULDBLOCK) {
+#endif
+ return 0;
+ }
+ return -1;
+ default:
+ buff->curr_offset += rc;
+ }
+ off = buff->curr_offset;
+ if (buff->curr_offset == sizeof(buff->len)) {
+ buff->len = ntohl(buff->len);
+ buff->buffer = calloc(1, buff->len);
+ }
+ }
+ if (buff->buffer) {
+ /* want off to now represent the offset into the buffer */
+ off -= sizeof(buff->len);
+
+ rc = recv(fd, buff->buffer+off, buff->len-off, 0);
+ switch(rc) {
+ case 0:
+ errno = EHOSTDOWN;
+ case -1:
+#ifndef _WINDOWS
+ if (errno == EAGAIN) {
+#else
+ if (WSAGetLastError() == WSAEWOULDBLOCK) {
+#endif
+ break;
+ }
+ return -1;
+ default:
+ buff->curr_offset += rc;
+ }
+ }
+ return buff->curr_offset == buff->len + sizeof(buff->len);
+}
+
+void free_buffers(buffer_head_t *list)
+{
+ while (remove_buffer(list))
+ ;
+}
+
+void free_completions(zhandle_t *zh,int callCompletion,int reason)
+{
+ completion_head_t tmp_list;
+ struct oarchive *oa;
+ struct ReplyHeader h;
+ void_completion_t auth_completion = NULL;
+ auth_completion_list_t a_list, *a_tmp;
+
+ if (lock_completion_list(&zh->sent_requests) == 0) {
+ tmp_list = zh->sent_requests;
+ zh->sent_requests.head = 0;
+ zh->sent_requests.last = 0;
+ unlock_completion_list(&zh->sent_requests);
+
+ while (tmp_list.head) {
+ completion_list_t *cptr = tmp_list.head;
+
+ tmp_list.head = cptr->next;
+ if (cptr->c.data_result == SYNCHRONOUS_MARKER) {
+ struct sync_completion
+ *sc = (struct sync_completion*)cptr->data;
+ sc->rc = reason;
+ notify_sync_completion(sc);
+ zh->outstanding_sync--;
+ destroy_completion_entry(cptr);
+ } else if (callCompletion) {
+ // Fake the response
+ buffer_list_t *bptr;
+ h.xid = cptr->xid;
+ h.zxid = -1;
+ h.err = reason;
+ oa = create_buffer_oarchive();
+ serialize_ReplyHeader(oa, "header", &h);
+ bptr = calloc(sizeof(*bptr), 1);
+ assert(bptr);
+ bptr->len = get_buffer_len(oa);
+ bptr->buffer = get_buffer(oa);
+ close_buffer_oarchive(&oa, 0);
+ cptr->buffer = bptr;
+ queue_completion(&zh->completions_to_process, cptr, 0);
+ }
+ }
+ }
+ if (zoo_lock_auth(zh) == 0) {
+ a_list.completion = NULL;
+ a_list.next = NULL;
+
+ get_auth_completions(&zh->auth_h, &a_list);
+ zoo_unlock_auth(zh);
+
+ a_tmp = &a_list;
+ // chain call user's completion function
+ while (a_tmp->completion != NULL) {
+ auth_completion = a_tmp->completion;
+ auth_completion(reason, a_tmp->auth_data);
+ a_tmp = a_tmp->next;
+ if (a_tmp == NULL)
+ break;
+ }
+ }
+ free_auth_completion(&a_list);
+}
+
+static void cleanup_bufs(zhandle_t *zh,int callCompletion,int rc)
+{
+ enter_critical(zh);
+ free_buffers(&zh->to_send);
+ free_buffers(&zh->to_process);
+ free_completions(zh,callCompletion,rc);
+ leave_critical(zh);
+ if (zh->input_buffer && zh->input_buffer != &zh->primer_buffer) {
+ free_buffer(zh->input_buffer);
+ zh->input_buffer = 0;
+ }
+}
+
+static void handle_error(zhandle_t *zh,int rc)
+{
+ close(zh->fd);
+ if (is_unrecoverable(zh)) {
+ LOG_DEBUG(("Calling a watcher for a ZOO_SESSION_EVENT and the state=%s",
+ state2String(zh->state)));
+ PROCESS_SESSION_EVENT(zh, zh->state);
+ } else if (zh->state == ZOO_CONNECTED_STATE) {
+ LOG_DEBUG(("Calling a watcher for a ZOO_SESSION_EVENT and the state=CONNECTING_STATE"));
+ PROCESS_SESSION_EVENT(zh, ZOO_CONNECTING_STATE);
+ }
+ cleanup_bufs(zh,1,rc);
+ zh->fd = -1;
+ zh->connect_index++;
+ if (!is_unrecoverable(zh)) {
+ zh->state = 0;
+ }
+ if (process_async(zh->outstanding_sync)) {
+ process_completions(zh);
+ }
+}
+
+static int handle_socket_error_msg(zhandle_t *zh, int line, int rc,
+ const char* format, ...)
+{
+ if(logLevel>=ZOO_LOG_LEVEL_ERROR){
+ va_list va;
+ char buf[1024];
+ va_start(va,format);
+ vsnprintf(buf, sizeof(buf)-1,format,va);
+ log_message(ZOO_LOG_LEVEL_ERROR,line,__func__,
+ format_log_message("Socket [%s] zk retcode=%d, errno=%d(%s): %s",
+ format_current_endpoint_info(zh),rc,errno,strerror(errno),buf));
+ va_end(va);
+ }
+ handle_error(zh,rc);
+ return rc;
+}
+
+static void auth_completion_func(int rc, zhandle_t* zh)
+{
+ void_completion_t auth_completion = NULL;
+ auth_completion_list_t a_list;
+ auth_completion_list_t *a_tmp;
+
+ if(zh==NULL)
+ return;
+
+ zoo_lock_auth(zh);
+
+ if(rc!=0){
+ zh->state=ZOO_AUTH_FAILED_STATE;
+ }else{
+ //change state for all auths
+ mark_active_auth(zh);
+ }
+ a_list.completion = NULL;
+ a_list.next = NULL;
+ get_auth_completions(&zh->auth_h, &a_list);
+ zoo_unlock_auth(zh);
+ if (rc) {
+ LOG_ERROR(("Authentication scheme %s failed. Connection closed.",
+ zh->auth_h.auth->scheme));
+ }
+ else {
+ LOG_INFO(("Authentication scheme %s succeeded", zh->auth_h.auth->scheme));
+ }
+ a_tmp = &a_list;
+ // chain call user's completion function
+ while (a_tmp->completion != NULL) {
+ auth_completion = a_tmp->completion;
+ auth_completion(rc, a_tmp->auth_data);
+ a_tmp = a_tmp->next;
+ if (a_tmp == NULL)
+ break;
+ }
+ free_auth_completion(&a_list);
+}
+
+static int send_info_packet(zhandle_t *zh, auth_info* auth) {
+ struct oarchive *oa;
+ struct RequestHeader h = { STRUCT_INITIALIZER(xid , AUTH_XID), STRUCT_INITIALIZER(type , ZOO_SETAUTH_OP)};
+ struct AuthPacket req;
+ int rc;
+ oa = create_buffer_oarchive();
+ rc = serialize_RequestHeader(oa, "header", &h);
+ req.type=0; // ignored by the server
+ req.scheme = auth->scheme;
+ req.auth = auth->auth;
+ rc = rc < 0 ? rc : serialize_AuthPacket(oa, "req", &req);
+ /* add this buffer to the head of the send queue */
+ rc = rc < 0 ? rc : queue_front_buffer_bytes(&zh->to_send, get_buffer(oa),
+ get_buffer_len(oa));
+ /* We queued the buffer, so don't free it */
+ close_buffer_oarchive(&oa, 0);
+
+ return rc;
+}
+
+/** send all auths, not just the last one **/
+static int send_auth_info(zhandle_t *zh) {
+ int rc = 0;
+ auth_info *auth = NULL;
+
+ zoo_lock_auth(zh);
+ auth = zh->auth_h.auth;
+ if (auth == NULL) {
+ zoo_unlock_auth(zh);
+ return ZOK;
+ }
+ while (auth != NULL) {
+ rc = send_info_packet(zh, auth);
+ auth = auth->next;
+ }
+ zoo_unlock_auth(zh);
+ LOG_DEBUG(("Sending all auth info request to %s", format_current_endpoint_info(zh)));
+ return (rc <0) ? ZMARSHALLINGERROR:ZOK;
+}
+
+static int send_last_auth_info(zhandle_t *zh)
+{
+ int rc = 0;
+ auth_info *auth = NULL;
+
+ zoo_lock_auth(zh);
+ auth = get_last_auth(&zh->auth_h);
+ if(auth==NULL) {
+ zoo_unlock_auth(zh);
+ return ZOK; // there is nothing to send
+ }
+ rc = send_info_packet(zh, auth);
+ zoo_unlock_auth(zh);
+ LOG_DEBUG(("Sending auth info request to %s",format_current_endpoint_info(zh)));
+ return (rc < 0)?ZMARSHALLINGERROR:ZOK;
+}
+
+static void free_key_list(char **list, int count)
+{
+ int i;
+
+ for(i = 0; i < count; i++) {
+ free(list[i]);
+ }
+ free(list);
+}
+
+static int send_set_watches(zhandle_t *zh)
+{
+ struct oarchive *oa;
+ struct RequestHeader h = { STRUCT_INITIALIZER(xid , SET_WATCHES_XID), STRUCT_INITIALIZER(type , ZOO_SETWATCHES_OP)};
+ struct SetWatches req;
+ int rc;
+
+ req.relativeZxid = zh->last_zxid;
+ req.dataWatches.data = collect_keys(zh->active_node_watchers, (int*)&req.dataWatches.count);
+ req.existWatches.data = collect_keys(zh->active_exist_watchers, (int*)&req.existWatches.count);
+ req.childWatches.data = collect_keys(zh->active_child_watchers, (int*)&req.childWatches.count);
+
+ // return if there are no pending watches
+ if (!req.dataWatches.count && !req.existWatches.count &&
+ !req.childWatches.count) {
+ free_key_list(req.dataWatches.data, req.dataWatches.count);
+ free_key_list(req.existWatches.data, req.existWatches.count);
+ free_key_list(req.childWatches.data, req.childWatches.count);
+ return ZOK;
+ }
+
+
+ oa = create_buffer_oarchive();
+ rc = serialize_RequestHeader(oa, "header", &h);
+ rc = rc < 0 ? rc : serialize_SetWatches(oa, "req", &req);
+ /* add this buffer to the head of the send queue */
+ rc = rc < 0 ? rc : queue_front_buffer_bytes(&zh->to_send, get_buffer(oa),
+ get_buffer_len(oa));
+ /* We queued the buffer, so don't free it */
+ close_buffer_oarchive(&oa, 0);
+ free_key_list(req.dataWatches.data, req.dataWatches.count);
+ free_key_list(req.existWatches.data, req.existWatches.count);
+ free_key_list(req.childWatches.data, req.childWatches.count);
+ LOG_DEBUG(("Sending set watches request to %s",format_current_endpoint_info(zh)));
+ return (rc < 0)?ZMARSHALLINGERROR:ZOK;
+}
+
+static int serialize_prime_connect(struct connect_req *req, char* buffer){
+ //this should be the order of serialization
+ int offset = 0;
+ req->protocolVersion = htonl(req->protocolVersion);
+ memcpy(buffer + offset, &req->protocolVersion, sizeof(req->protocolVersion));
+ offset = offset + sizeof(req->protocolVersion);
+
+ req->lastZxidSeen = zoo_htonll(req->lastZxidSeen);
+ memcpy(buffer + offset, &req->lastZxidSeen, sizeof(req->lastZxidSeen));
+ offset = offset + sizeof(req->lastZxidSeen);
+
+ req->timeOut = htonl(req->timeOut);
+ memcpy(buffer + offset, &req->timeOut, sizeof(req->timeOut));
+ offset = offset + sizeof(req->timeOut);
+
+ req->sessionId = zoo_htonll(req->sessionId);
+ memcpy(buffer + offset, &req->sessionId, sizeof(req->sessionId));
+ offset = offset + sizeof(req->sessionId);
+
+ req->passwd_len = htonl(req->passwd_len);
+ memcpy(buffer + offset, &req->passwd_len, sizeof(req->passwd_len));
+ offset = offset + sizeof(req->passwd_len);
+
+ memcpy(buffer + offset, req->passwd, sizeof(req->passwd));
+
+ return 0;
+}
+
+ static int deserialize_prime_response(struct prime_struct *req, char* buffer){
+ //this should be the order of deserialization
+ int offset = 0;
+ memcpy(&req->len, buffer + offset, sizeof(req->len));
+ offset = offset + sizeof(req->len);
+
+ req->len = ntohl(req->len);
+ memcpy(&req->protocolVersion, buffer + offset, sizeof(req->protocolVersion));
+ offset = offset + sizeof(req->protocolVersion);
+
+ req->protocolVersion = ntohl(req->protocolVersion);
+ memcpy(&req->timeOut, buffer + offset, sizeof(req->timeOut));
+ offset = offset + sizeof(req->timeOut);
+
+ req->timeOut = ntohl(req->timeOut);
+ memcpy(&req->sessionId, buffer + offset, sizeof(req->sessionId));
+ offset = offset + sizeof(req->sessionId);
+
+ req->sessionId = zoo_htonll(req->sessionId);
+ memcpy(&req->passwd_len, buffer + offset, sizeof(req->passwd_len));
+ offset = offset + sizeof(req->passwd_len);
+
+ req->passwd_len = ntohl(req->passwd_len);
+ memcpy(req->passwd, buffer + offset, sizeof(req->passwd));
+ return 0;
+ }
+
+static int prime_connection(zhandle_t *zh)
+{
+ int rc;
+ /*this is the size of buffer to serialize req into*/
+ char buffer_req[HANDSHAKE_REQ_SIZE];
+ int len = sizeof(buffer_req);
+ int hlen = 0;
+ struct connect_req req;
+ req.protocolVersion = 0;
+ req.sessionId = zh->client_id.client_id;
+ req.passwd_len = sizeof(req.passwd);
+ memcpy(req.passwd, zh->client_id.passwd, sizeof(zh->client_id.passwd));
+ req.timeOut = zh->recv_timeout;
+ req.lastZxidSeen = zh->last_zxid;
+ hlen = htonl(len);
+ /* We are running fast and loose here, but this string should fit in the initial buffer! */
+ rc=zookeeper_send(zh->fd, &hlen, sizeof(len));
+ serialize_prime_connect(&req, buffer_req);
+ rc=rc<0 ? rc : zookeeper_send(zh->fd, buffer_req, len);
+ if (rc<0) {
+ return handle_socket_error_msg(zh, __LINE__, ZCONNECTIONLOSS,
+ "failed to send a handshake packet: %s", strerror(errno));
+ }
+ zh->state = ZOO_ASSOCIATING_STATE;
+
+ zh->input_buffer = &zh->primer_buffer;
+ /* This seems a bit weird to to set the offset to 4, but we already have a
+ * length, so we skip reading the length (and allocating the buffer) by
+ * saying that we are already at offset 4 */
+ zh->input_buffer->curr_offset = 4;
+
+ return ZOK;
+}
+
+static inline int calculate_interval(const struct timeval *start,
+ const struct timeval *end)
+{
+ int interval;
+ struct timeval i = *end;
+ i.tv_sec -= start->tv_sec;
+ i.tv_usec -= start->tv_usec;
+ interval = i.tv_sec * 1000 + (i.tv_usec/1000);
+ return interval;
+}
+
+static struct timeval get_timeval(int interval)
+{
+ struct timeval tv;
+ if (interval < 0) {
+ interval = 0;
+ }
+ tv.tv_sec = interval/1000;
+ tv.tv_usec = (interval%1000)*1000;
+ return tv;
+}
+
+ static int add_void_completion(zhandle_t *zh, int xid, void_completion_t dc,
+ const void *data);
+ static int add_string_completion(zhandle_t *zh, int xid,
+ string_completion_t dc, const void *data);
+
+ int send_ping(zhandle_t* zh)
+ {
+ int rc;
+ struct oarchive *oa = create_buffer_oarchive();
+ struct RequestHeader h = { STRUCT_INITIALIZER(xid ,PING_XID), STRUCT_INITIALIZER (type , ZOO_PING_OP) };
+
+ rc = serialize_RequestHeader(oa, "header", &h);
+ enter_critical(zh);
+ gettimeofday(&zh->last_ping, 0);
+ rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa),
+ get_buffer_len(oa));
+ leave_critical(zh);
+ close_buffer_oarchive(&oa, 0);
+ return rc<0 ? rc : adaptor_send_queue(zh, 0);
+}
+
+#ifdef WIN32
+int zookeeper_interest(zhandle_t *zh, SOCKET *fd, int *interest,
+ struct timeval *tv)
+{
+
+ ULONG nonblocking_flag = 1;
+#else
+int zookeeper_interest(zhandle_t *zh, int *fd, int *interest,
+ struct timeval *tv)
+{
+#endif
+ struct timeval now;
+ if(zh==0 || fd==0 ||interest==0 || tv==0)
+ return ZBADARGUMENTS;
+ if (is_unrecoverable(zh))
+ return ZINVALIDSTATE;
+ gettimeofday(&now, 0);
+ if(zh->next_deadline.tv_sec!=0 || zh->next_deadline.tv_usec!=0){
+ int time_left = calculate_interval(&zh->next_deadline, &now);
+ if (time_left > 10)
+ LOG_WARN(("Exceeded deadline by %dms", time_left));
+ }
+ api_prolog(zh);
+ *fd = zh->fd;
+ *interest = 0;
+ tv->tv_sec = 0;
+ tv->tv_usec = 0;
+ if (*fd == -1) {
+ if (zh->connect_index == zh->addrs_count) {
+ /* Wait a bit before trying again so that we don't spin */
+ zh->connect_index = 0;
+ }else {
+ int rc;
+#ifdef WIN32
+ char enable_tcp_nodelay = 1;
+#else
+ int enable_tcp_nodelay = 1;
+#endif
+ int ssoresult;
+
+ zh->fd = socket(zh->addrs[zh->connect_index].ss_family, SOCK_STREAM, 0);
+ if (zh->fd < 0) {
+ return api_epilog(zh,handle_socket_error_msg(zh,__LINE__,
+ ZSYSTEMERROR, "socket() call failed"));
+ }
+ ssoresult = setsockopt(zh->fd, IPPROTO_TCP, TCP_NODELAY, &enable_tcp_nodelay, sizeof(enable_tcp_nodelay));
+ if (ssoresult != 0) {
+ LOG_WARN(("Unable to set TCP_NODELAY, operation latency may be effected"));
+ }
+#ifdef WIN32
+ ioctlsocket(zh->fd, FIONBIO, &nonblocking_flag);
+#else
+ fcntl(zh->fd, F_SETFL, O_NONBLOCK|fcntl(zh->fd, F_GETFL, 0));
+#endif
+#if defined(AF_INET6)
+ if (zh->addrs[zh->connect_index].ss_family == AF_INET6) {
+ rc = connect(zh->fd, (struct sockaddr*) &zh->addrs[zh->connect_index], sizeof(struct sockaddr_in6));
+ } else {
+#else
+ LOG_DEBUG(("[zk] connect()\n"));
+ {
+#endif
+ rc = connect(zh->fd, (struct sockaddr*) &zh->addrs[zh->connect_index], sizeof(struct sockaddr_in));
+#ifdef WIN32
+ errno = GetLastError();
+
+#ifndef EWOULDBLOCK
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#endif
+
+#ifndef EINPROGRESS
+#define EINPROGRESS WSAEINPROGRESS
+#endif
+
+#if _MSC_VER >= 1600
+ switch (errno) {
+ case WSAEWOULDBLOCK:
+ errno = EWOULDBLOCK;
+ break;
+ case WSAEINPROGRESS:
+ errno = EINPROGRESS;
+ break;
+ }
+#endif
+#endif
+ }
+ if (rc == -1) {
+ /* we are handling the non-blocking connect according to
+ * the description in section 16.3 "Non-blocking connect"
+ * in UNIX Network Programming vol 1, 3rd edition */
+ if (errno == EWOULDBLOCK || errno == EINPROGRESS)
+ zh->state = ZOO_CONNECTING_STATE;
+ else
+ return api_epilog(zh,handle_socket_error_msg(zh,__LINE__,
+ ZCONNECTIONLOSS,"connect() call failed"));
+ } else {
+ if((rc=prime_connection(zh))!=0)
+ return api_epilog(zh,rc);
+
+ LOG_INFO(("Initiated connection to server [%s]",
+ format_endpoint_info(&zh->addrs[zh->connect_index])));
+ }
+ }
+ *fd = zh->fd;
+ *tv = get_timeval(zh->recv_timeout/3);
+ zh->last_recv = now;
+ zh->last_send = now;
+ zh->last_ping = now;
+ }
+ if (zh->fd != -1) {
+ int idle_recv = calculate_interval(&zh->last_recv, &now);
+ int idle_send = calculate_interval(&zh->last_send, &now);
+ int recv_to = zh->recv_timeout*2/3 - idle_recv;
+ int send_to = zh->recv_timeout/3;
+ // have we exceeded the receive timeout threshold?
+ if (recv_to <= 0) {
+ // We gotta cut our losses and connect to someone else
+#ifdef WIN32
+ errno = WSAETIMEDOUT;
+#else
+ errno = ETIMEDOUT;
+#endif
+ *interest=0;
+ *tv = get_timeval(0);
+ return api_epilog(zh,handle_socket_error_msg(zh,
+ __LINE__,ZOPERATIONTIMEOUT,
+ "connection to %s timed out (exceeded timeout by %dms)",
+ format_endpoint_info(&zh->addrs[zh->connect_index]),
+ -recv_to));
+
+ }
+ // We only allow 1/3 of our timeout time to expire before sending
+ // a PING
+ if (zh->state==ZOO_CONNECTED_STATE) {
+ send_to = zh->recv_timeout/3 - idle_send;
+ if (send_to <= 0) {
+ if (zh->sent_requests.head==0) {
+// LOG_DEBUG(("Sending PING to %s (exceeded idle by %dms)",
+// format_current_endpoint_info(zh),-send_to));
+ int rc=send_ping(zh);
+ if (rc < 0){
+ LOG_ERROR(("failed to send PING request (zk retcode=%d)",rc));
+ return api_epilog(zh,rc);
+ }
+ }
+ send_to = zh->recv_timeout/3;
+ }
+ }
+ // choose the lesser value as the timeout
+ *tv = get_timeval(recv_to < send_to? recv_to:send_to);
+ zh->next_deadline.tv_sec = now.tv_sec + tv->tv_sec;
+ zh->next_deadline.tv_usec = now.tv_usec + tv->tv_usec;
+ if (zh->next_deadline.tv_usec > 1000000) {
+ zh->next_deadline.tv_sec += zh->next_deadline.tv_usec / 1000000;
+ zh->next_deadline.tv_usec = zh->next_deadline.tv_usec % 1000000;
+ }
+ *interest = ZOOKEEPER_READ;
+ /* we are interested in a write if we are connected and have something
+ * to send, or we are waiting for a connect to finish. */
+ if ((zh->to_send.head && (zh->state == ZOO_CONNECTED_STATE))
+ || zh->state == ZOO_CONNECTING_STATE) {
+ *interest |= ZOOKEEPER_WRITE;
+ }
+ }
+ return api_epilog(zh,ZOK);
+}
+
+static int check_events(zhandle_t *zh, int events)
+{
+ if (zh->fd == -1)
+ return ZINVALIDSTATE;
+ if ((events&ZOOKEEPER_WRITE)&&(zh->state == ZOO_CONNECTING_STATE)) {
+ int rc, error;
+ socklen_t len = sizeof(error);
+ rc = getsockopt(zh->fd, SOL_SOCKET, SO_ERROR, &error, &len);
+ /* the description in section 16.4 "Non-blocking connect"
+ * in UNIX Network Programming vol 1, 3rd edition, points out
+ * that sometimes the error is in errno and sometimes in error */
+ if (rc < 0 || error) {
+ if (rc == 0)
+ errno = error;
+ return handle_socket_error_msg(zh, __LINE__,ZCONNECTIONLOSS,
+ "server refused to accept the client");
+ }
+ if((rc=prime_connection(zh))!=0)
+ return rc;
+ LOG_INFO(("initiated connection to server [%s]",
+ format_endpoint_info(&zh->addrs[zh->connect_index])));
+ return ZOK;
+ }
+ if (zh->to_send.head && (events&ZOOKEEPER_WRITE)) {
+ /* make the flush call non-blocking by specifying a 0 timeout */
+ int rc=flush_send_queue(zh,0);
+ if (rc < 0)
+ return handle_socket_error_msg(zh,__LINE__,ZCONNECTIONLOSS,
+ "failed while flushing send queue");
+ }
+ if (events&ZOOKEEPER_READ) {
+ int rc;
+ if (zh->input_buffer == 0) {
+ zh->input_buffer = allocate_buffer(0,0);
+ }
+
+ rc = recv_buffer(zh->fd, zh->input_buffer);
+ if (rc < 0) {
+ return handle_socket_error_msg(zh, __LINE__,ZCONNECTIONLOSS,
+ "failed while receiving a server response");
+ }
+ if (rc > 0) {
+ gettimeofday(&zh->last_recv, 0);
+ if (zh->input_buffer != &zh->primer_buffer) {
+ queue_buffer(&zh->to_process, zh->input_buffer, 0);
+ } else {
+ int64_t oldid,newid;
+ //deserialize
+ deserialize_prime_response(&zh->primer_storage, zh->primer_buffer.buffer);
+ /* We are processing the primer_buffer, so we need to finish
+ * the connection handshake */
+ oldid = zh->client_id.client_id;
+ newid = zh->primer_storage.sessionId;
+ if (oldid != 0 && oldid != newid) {
+ zh->state = ZOO_EXPIRED_SESSION_STATE;
+ errno = ESTALE;
+ return handle_socket_error_msg(zh,__LINE__,ZSESSIONEXPIRED,
+ "sessionId=%#llx has expired.",oldid);
+ } else {
+ zh->recv_timeout = zh->primer_storage.timeOut;
+ zh->client_id.client_id = newid;
+
+ memcpy(zh->client_id.passwd, &zh->primer_storage.passwd,
+ sizeof(zh->client_id.passwd));
+ zh->state = ZOO_CONNECTED_STATE;
+ LOG_INFO(("session establishment complete on server [%s], sessionId=%#llx, negotiated timeout=%d",
+ format_endpoint_info(&zh->addrs[zh->connect_index]),
+ newid, zh->recv_timeout));
+ /* we want the auth to be sent for, but since both call push to front
+ we need to call send_watch_set first */
+ send_set_watches(zh);
+ /* send the authentication packet now */
+ send_auth_info(zh);
+ LOG_DEBUG(("Calling a watcher for a ZOO_SESSION_EVENT and the state=ZOO_CONNECTED_STATE"));
+ zh->input_buffer = 0; // just in case the watcher calls zookeeper_process() again
+ PROCESS_SESSION_EVENT(zh, ZOO_CONNECTED_STATE);
+ }
+ }
+ zh->input_buffer = 0;
+ } else {
+ // zookeeper_process was called but there was nothing to read
+ // from the socket
+ return ZNOTHING;
+ }
+ }
+ return ZOK;
+}
+
+void api_prolog(zhandle_t* zh)
+{
+ inc_ref_counter(zh,1);
+}
+
+int api_epilog(zhandle_t *zh,int rc)
+{
+ if(inc_ref_counter(zh,-1)==0 && zh->close_requested!=0)
+ zookeeper_close(zh);
+ return rc;
+}
+
+static __attribute__((unused)) void print_completion_queue(zhandle_t *zh)
+{
+ completion_list_t* cptr;
+
+ if(logLevel<ZOO_LOG_LEVEL_DEBUG) return;
+
+ fprintf(LOGSTREAM,"Completion queue: ");
+ if (zh->sent_requests.head==0) {
+ fprintf(LOGSTREAM,"empty\n");
+ return;
+ }
+
+ cptr=zh->sent_requests.head;
+ while(cptr){
+ fprintf(LOGSTREAM,"%d,",cptr->xid);
+ cptr=cptr->next;
+ }
+ fprintf(LOGSTREAM,"end\n");
+}
+
+//#ifdef THREADED
+// IO thread queues session events to be processed by the completion thread
+static int queue_session_event(zhandle_t *zh, int state)
+{
+ int rc;
+ struct WatcherEvent evt = { ZOO_SESSION_EVENT, state, "" };
+ struct ReplyHeader hdr = { WATCHER_EVENT_XID, 0, 0 };
+ struct oarchive *oa;
+ completion_list_t *cptr;
+
+ if ((oa=create_buffer_oarchive())==NULL) {
+ LOG_ERROR(("out of memory"));
+ goto error;
+ }
+ rc = serialize_ReplyHeader(oa, "hdr", &hdr);
+ rc = rc<0?rc: serialize_WatcherEvent(oa, "event", &evt);
+ if(rc<0){
+ close_buffer_oarchive(&oa, 1);
+ goto error;
+ }
+ cptr = create_completion_entry(WATCHER_EVENT_XID,-1,0,0,0,0);
+ cptr->buffer = allocate_buffer(get_buffer(oa), get_buffer_len(oa));
+ cptr->buffer->curr_offset = get_buffer_len(oa);
+ if (!cptr->buffer) {
+ free(cptr);
+ close_buffer_oarchive(&oa, 1);
+ goto error;
+ }
+ /* We queued the buffer, so don't free it */
+ close_buffer_oarchive(&oa, 0);
+ cptr->c.watcher_result = collectWatchers(zh, ZOO_SESSION_EVENT, "");
+ queue_completion(&zh->completions_to_process, cptr, 0);
+ if (process_async(zh->outstanding_sync)) {
+ process_completions(zh);
+ }
+ return ZOK;
+error:
+ errno=ENOMEM;
+ return ZSYSTEMERROR;
+}
+//#endif
+
+completion_list_t *dequeue_completion(completion_head_t *list)
+{
+ completion_list_t *cptr;
+ lock_completion_list(list);
+ cptr = list->head;
+ if (cptr) {
+ list->head = cptr->next;
+ if (!list->head) {
+ assert(list->last == cptr);
+ list->last = 0;
+ }
+ }
+ unlock_completion_list(list);
+ return cptr;
+}
+
+static void process_sync_completion(
+ completion_list_t *cptr,
+ struct sync_completion *sc,
+ struct iarchive *ia,
+ zhandle_t *zh)
+{
+ LOG_DEBUG(("Processing sync_completion with type=%d xid=%#x rc=%d",
+ cptr->c.type, cptr->xid, sc->rc));
+
+ switch(cptr->c.type) {
+ case COMPLETION_DATA:
+ if (sc->rc==0) {
+ struct GetDataResponse res;
+ int len;
+ deserialize_GetDataResponse(ia, "reply", &res);
+ if (res.data.len <= sc->u.data.buff_len) {
+ len = res.data.len;
+ } else {
+ len = sc->u.data.buff_len;
+ }
+ sc->u.data.buff_len = len;
+ // check if len is negative
+ // just of NULL which is -1 int
+ if (len == -1) {
+ sc->u.data.buffer = NULL;
+ } else {
+ memcpy(sc->u.data.buffer, res.data.buff, len);
+ }
+ sc->u.data.stat = res.stat;
+ deallocate_GetDataResponse(&res);
+ }
+ break;
+ case COMPLETION_STAT:
+ if (sc->rc==0) {
+ struct SetDataResponse res;
+ deserialize_SetDataResponse(ia, "reply", &res);
+ sc->u.stat = res.stat;
+ deallocate_SetDataResponse(&res);
+ }
+ break;
+ case COMPLETION_STRINGLIST:
+ if (sc->rc==0) {
+ struct GetChildrenResponse res;
+ deserialize_GetChildrenResponse(ia, "reply", &res);
+ sc->u.strs2 = res.children;
+ /* We don't deallocate since we are passing it back */
+ // deallocate_GetChildrenResponse(&res);
+ }
+ break;
+ case COMPLETION_STRINGLIST_STAT:
+ if (sc->rc==0) {
+ struct GetChildren2Response res;
+ deserialize_GetChildren2Response(ia, "reply", &res);
+ sc->u.strs_stat.strs2 = res.children;
+ sc->u.strs_stat.stat2 = res.stat;
+ /* We don't deallocate since we are passing it back */
+ // deallocate_GetChildren2Response(&res);
+ }
+ break;
+ case COMPLETION_STRING:
+ if (sc->rc==0) {
+ struct CreateResponse res;
+ int len;
+ const char * client_path;
+ deserialize_CreateResponse(ia, "reply", &res);
+ //ZOOKEEPER-1027
+ client_path = sub_string(zh, res.path);
+ len = strlen(client_path) + 1;if (len > sc->u.str.str_len) {
+ len = sc->u.str.str_len;
+ }
+ if (len > 0) {
+ memcpy(sc->u.str.str, client_path, len - 1);
+ sc->u.str.str[len - 1] = '\0';
+ }
+ free_duplicate_path(client_path, res.path);
+ deallocate_CreateResponse(&res);
+ }
+ break;
+ case COMPLETION_ACLLIST:
+ if (sc->rc==0) {
+ struct GetACLResponse res;
+ deserialize_GetACLResponse(ia, "reply", &res);
+ sc->u.acl.acl = res.acl;
+ sc->u.acl.stat = res.stat;
+ /* We don't deallocate since we are passing it back */
+ //deallocate_GetACLResponse(&res);
+ }
+ break;
+ case COMPLETION_VOID:
+ break;
+ case COMPLETION_MULTI:
+ sc->rc = deserialize_multi(cptr->xid, cptr, ia);
+ break;
+ default:
+ LOG_DEBUG(("Unsupported completion type=%d", cptr->c.type));
+ break;
+ }
+}
+
+static int deserialize_multi(int xid, completion_list_t *cptr, struct iarchive *ia)
+{
+ int rc = 0;
+ completion_head_t *clist = &cptr->c.clist;
+ struct MultiHeader mhdr = { STRUCT_INITIALIZER(type , 0), STRUCT_INITIALIZER(done , 0), STRUCT_INITIALIZER(err , 0) };
+ assert(clist);
+ deserialize_MultiHeader(ia, "multiheader", &mhdr);
+ while (!mhdr.done) {
+ completion_list_t *entry = dequeue_completion(clist);
+ assert(entry);
+
+ if (mhdr.type == -1) {
+ struct ErrorResponse er;
+ deserialize_ErrorResponse(ia, "error", &er);
+ mhdr.err = er.err ;
+ if (rc == 0 && er.err != 0 && er.err != ZRUNTIMEINCONSISTENCY) {
+ rc = er.err;
+ }
+ }
+
+ deserialize_response(entry->c.type, xid, mhdr.type == -1, mhdr.err, entry, ia);
+ deserialize_MultiHeader(ia, "multiheader", &mhdr);
+ //While deserializing the response we must destroy completion entry for each operation in
+ //the zoo_multi transaction. Otherwise this results in memory leak when client invokes zoo_multi
+ //operation.
+ destroy_completion_entry(entry);
+ }
+
+ return rc;
+}
+
+static void deserialize_response(int type, int xid, int failed, int rc, completion_list_t *cptr, struct iarchive *ia)
+{
+ switch (type) {
+ case COMPLETION_DATA:
+ LOG_DEBUG(("Calling COMPLETION_DATA for xid=%#x failed=%d rc=%d",
+ cptr->xid, failed, rc));
+ if (failed) {
+ cptr->c.data_result(rc, 0, 0, 0, cptr->data);
+ } else {
+ struct GetDataResponse res;
+ deserialize_GetDataResponse(ia, "reply", &res);
+ cptr->c.data_result(rc, res.data.buff, res.data.len,
+ &res.stat, cptr->data);
+ deallocate_GetDataResponse(&res);
+ }
+ break;
+ case COMPLETION_STAT:
+ LOG_DEBUG(("Calling COMPLETION_STAT for xid=%#x failed=%d rc=%d",
+ cptr->xid, failed, rc));
+ if (failed) {
+ cptr->c.stat_result(rc, 0, cptr->data);
+ } else {
+ struct SetDataResponse res;
+ deserialize_SetDataResponse(ia, "reply", &res);
+ cptr->c.stat_result(rc, &res.stat, cptr->data);
+ deallocate_SetDataResponse(&res);
+ }
+ break;
+ case COMPLETION_STRINGLIST:
+ LOG_DEBUG(("Calling COMPLETION_STRINGLIST for xid=%#x failed=%d rc=%d",
+ cptr->xid, failed, rc));
+ if (failed) {
+ cptr->c.strings_result(rc, 0, cptr->data);
+ } else {
+ struct GetChildrenResponse res;
+ deserialize_GetChildrenResponse(ia, "reply", &res);
+ cptr->c.strings_result(rc, &res.children, cptr->data);
+ deallocate_GetChildrenResponse(&res);
+ }
+ break;
+ case COMPLETION_STRINGLIST_STAT:
+ LOG_DEBUG(("Calling COMPLETION_STRINGLIST_STAT for xid=%#x failed=%d rc=%d",
+ cptr->xid, failed, rc));
+ if (failed) {
+ cptr->c.strings_stat_result(rc, 0, 0, cptr->data);
+ } else {
+ struct GetChildren2Response res;
+ deserialize_GetChildren2Response(ia, "reply", &res);
+ cptr->c.strings_stat_result(rc, &res.children, &res.stat, cptr->data);
+ deallocate_GetChildren2Response(&res);
+ }
+ break;
+ case COMPLETION_STRING:
+ LOG_DEBUG(("Calling COMPLETION_STRING for xid=%#x failed=%d, rc=%d",
+ cptr->xid, failed, rc));
+ if (failed) {
+ cptr->c.string_result(rc, 0, cptr->data);
+ } else {
+ struct CreateResponse res;
+ memset(&res, 0, sizeof(res));
+ deserialize_CreateResponse(ia, "reply", &res);
+ cptr->c.string_result(rc, res.path, cptr->data);
+ deallocate_CreateResponse(&res);
+ }
+ break;
+ case COMPLETION_ACLLIST:
+ LOG_DEBUG(("Calling COMPLETION_ACLLIST for xid=%#x failed=%d rc=%d",
+ cptr->xid, failed, rc));
+ if (failed) {
+ cptr->c.acl_result(rc, 0, 0, cptr->data);
+ } else {
+ struct GetACLResponse res;
+ deserialize_GetACLResponse(ia, "reply", &res);
+ cptr->c.acl_result(rc, &res.acl, &res.stat, cptr->data);
+ deallocate_GetACLResponse(&res);
+ }
+ break;
+ case COMPLETION_VOID:
+ LOG_DEBUG(("Calling COMPLETION_VOID for xid=%#x failed=%d rc=%d",
+ cptr->xid, failed, rc));
+ assert(cptr->c.void_result);
+ cptr->c.void_result(rc, cptr->data);
+ break;
+ case COMPLETION_MULTI:
+ LOG_DEBUG(("Calling COMPLETION_MULTI for xid=%#x failed=%d rc=%d",
+ cptr->xid, failed, rc));
+ rc = deserialize_multi(xid, cptr, ia);
+ assert(cptr->c.void_result);
+ cptr->c.void_result(rc, cptr->data);
+ break;
+ default:
+ LOG_DEBUG(("Unsupported completion type=%d", cptr->c.type));
+ }
+}
+
+
+/* handles async completion (both single- and multithreaded) */
+void process_completions(zhandle_t *zh)
+{
+ completion_list_t *cptr;
+ while ((cptr = dequeue_completion(&zh->completions_to_process)) != 0) {
+ struct ReplyHeader hdr;
+ buffer_list_t *bptr = cptr->buffer;
+ struct iarchive *ia = create_buffer_iarchive(bptr->buffer,
+ bptr->len);
+ deserialize_ReplyHeader(ia, "hdr", &hdr);
+
+ if (hdr.xid == WATCHER_EVENT_XID) {
+ int type, state;
+ struct WatcherEvent evt;
+ deserialize_WatcherEvent(ia, "event", &evt);
+ /* We are doing a notification, so there is no pending request */
+ type = evt.type;
+ state = evt.state;
+ /* This is a notification so there aren't any pending requests */
+ LOG_DEBUG(("Calling a watcher for node [%s], type = %d event=%s",
+ (evt.path==NULL?"NULL":evt.path), cptr->c.type,
+ watcherEvent2String(type)));
+ deliverWatchers(zh,type,state,evt.path, &cptr->c.watcher_result);
+ deallocate_WatcherEvent(&evt);
+ } else {
+ deserialize_response(cptr->c.type, hdr.xid, hdr.err != 0, hdr.err, cptr, ia);
+ }
+ destroy_completion_entry(cptr);
+ close_buffer_iarchive(&ia);
+ }
+}
+
+static void isSocketReadable(zhandle_t* zh)
+{
+#ifndef WIN32
+ struct pollfd fds;
+ fds.fd = zh->fd;
+ fds.events = POLLIN;
+ if (poll(&fds,1,0)<=0) {
+ // socket not readable -- no more responses to process
+ zh->socket_readable.tv_sec=zh->socket_readable.tv_usec=0;
+ }
+#else
+ fd_set rfds;
+ struct timeval waittime = {0, 0};
+ FD_ZERO(&rfds);
+ FD_SET( zh->fd , &rfds);
+ if (select(0, &rfds, NULL, NULL, &waittime) <= 0){
+ // socket not readable -- no more responses to process
+ zh->socket_readable.tv_sec=zh->socket_readable.tv_usec=0;
+ }
+#endif
+ else{
+ gettimeofday(&zh->socket_readable,0);
+ }
+}
+
+static void checkResponseLatency(zhandle_t* zh)
+{
+ int delay;
+ struct timeval now;
+
+ if(zh->socket_readable.tv_sec==0)
+ return;
+
+ gettimeofday(&now,0);
+ delay=calculate_interval(&zh->socket_readable, &now);
+ if(delay>20)
+ LOG_DEBUG(("The following server response has spent at least %dms sitting in the client socket recv buffer",delay));
+
+ zh->socket_readable.tv_sec=zh->socket_readable.tv_usec=0;
+}
+
+int zookeeper_process(zhandle_t *zh, int events)
+{
+ buffer_list_t *bptr;
+ int rc;
+
+ if (zh==NULL)
+ return ZBADARGUMENTS;
+ if (is_unrecoverable(zh))
+ return ZINVALIDSTATE;
+ api_prolog(zh);
+ IF_DEBUG(checkResponseLatency(zh));
+ rc = check_events(zh, events);
+ if (rc!=ZOK)
+ return api_epilog(zh, rc);
+
+ IF_DEBUG(isSocketReadable(zh));
+
+ while (rc >= 0 && (bptr=dequeue_buffer(&zh->to_process))) {
+ struct ReplyHeader hdr;
+ struct iarchive *ia = create_buffer_iarchive(
+ bptr->buffer, bptr->curr_offset);
+ deserialize_ReplyHeader(ia, "hdr", &hdr);
+ if (hdr.zxid > 0) {
+ zh->last_zxid = hdr.zxid;
+ } else {
+ // fprintf(stderr, "Got %#x for %#x\n", hdr.zxid, hdr.xid);
+ }
+
+ if (hdr.xid == PING_XID) {
+ // Ping replies can arrive out-of-order
+ int elapsed = 0;
+ struct timeval now;
+ gettimeofday(&now, 0);
+ elapsed = calculate_interval(&zh->last_ping, &now);
+ LOG_DEBUG(("Got ping response in %d ms", elapsed));
+ free_buffer(bptr);
+ } else if (hdr.xid == WATCHER_EVENT_XID) {
+ struct WatcherEvent evt;
+ int type = 0;
+ char *path = NULL;
+ completion_list_t *c = NULL;
+
+ LOG_DEBUG(("Processing WATCHER_EVENT"));
+
+ deserialize_WatcherEvent(ia, "event", &evt);
+ type = evt.type;
+ path = evt.path;
+ /* We are doing a notification, so there is no pending request */
+ c = create_completion_entry(WATCHER_EVENT_XID,-1,0,0,0,0);
+ c->buffer = bptr;
+ c->c.watcher_result = collectWatchers(zh, type, path);
+
+ // We cannot free until now, otherwise path will become invalid
+ deallocate_WatcherEvent(&evt);
+ queue_completion(&zh->completions_to_process, c, 0);
+ } else if (hdr.xid == SET_WATCHES_XID) {
+ LOG_DEBUG(("Processing SET_WATCHES"));
+ free_buffer(bptr);
+ } else if (hdr.xid == AUTH_XID){
+ LOG_DEBUG(("Processing AUTH_XID"));
+
+ /* special handling for the AUTH response as it may come back
+ * out-of-band */
+ auth_completion_func(hdr.err,zh);
+ free_buffer(bptr);
+ /* authentication completion may change the connection state to
+ * unrecoverable */
+ if(is_unrecoverable(zh)){
+ handle_error(zh, ZAUTHFAILED);
+ close_buffer_iarchive(&ia);
+ return api_epilog(zh, ZAUTHFAILED);
+ }
+ } else {
+ int rc = hdr.err;
+ /* Find the request corresponding to the response */
+ completion_list_t *cptr = dequeue_completion(&zh->sent_requests);
+
+ /* [ZOOKEEPER-804] Don't assert if zookeeper_close has been called. */
+ if (zh->close_requested == 1 && cptr == NULL) {
+ LOG_DEBUG(("Completion queue has been cleared by zookeeper_close()"));
+ close_buffer_iarchive(&ia);
+ free_buffer(bptr);
+ return api_epilog(zh,ZINVALIDSTATE);
+ }
+ assert(cptr);
+ /* The requests are going to come back in order */
+ if (cptr->xid != hdr.xid) {
+ LOG_DEBUG(("Processing unexpected or out-of-order response!"));
+
+ // received unexpected (or out-of-order) response
+ close_buffer_iarchive(&ia);
+ free_buffer(bptr);
+ // put the completion back on the queue (so it gets properly
+ // signaled and deallocated) and disconnect from the server
+ queue_completion(&zh->sent_requests,cptr,1);
+ return api_epilog(zh,
+ handle_socket_error_msg(zh, __LINE__,ZRUNTIMEINCONSISTENCY,
+ "unexpected server response: expected %#x, but received %#x",
+ hdr.xid,cptr->xid));
+ }
+
+ activateWatcher(zh, cptr->watcher, rc);
+
+ if (cptr->c.void_result != SYNCHRONOUS_MARKER) {
+ LOG_DEBUG(("Queueing asynchronous response"));
+ cptr->buffer = bptr;
+ queue_completion(&zh->completions_to_process, cptr, 0);
+ } else {
+ struct sync_completion
+ *sc = (struct sync_completion*)cptr->data;
+ sc->rc = rc;
+
+ process_sync_completion(cptr, sc, ia, zh);
+
+ notify_sync_completion(sc);
+ free_buffer(bptr);
+ zh->outstanding_sync--;
+ destroy_completion_entry(cptr);
+ }
+ }
+
+ close_buffer_iarchive(&ia);
+
+ }
+ if (process_async(zh->outstanding_sync)) {
+ process_completions(zh);
+ }
+ return api_epilog(zh,ZOK);}
+
+int zoo_state(zhandle_t *zh)
+{
+ if(zh!=0)
+ return zh->state;
+ return 0;
+}
+
+static watcher_registration_t* create_watcher_registration(const char* path,
+ result_checker_fn checker,watcher_fn watcher,void* ctx){
+ watcher_registration_t* wo;
+ if(watcher==0)
+ return 0;
+ wo=calloc(1,sizeof(watcher_registration_t));
+ wo->path=strdup(path);
+ wo->watcher=watcher;
+ wo->context=ctx;
+ wo->checker=checker;
+ return wo;
+}
+
+static void destroy_watcher_registration(watcher_registration_t* wo){
+ if(wo!=0){
+ free((void*)wo->path);
+ free(wo);
+ }
+}
+
+static completion_list_t* create_completion_entry(int xid, int completion_type,
+ const void *dc, const void *data,watcher_registration_t* wo, completion_head_t *clist)
+{
+ completion_list_t *c = calloc(1,sizeof(completion_list_t));
+ if (!c) {
+ LOG_ERROR(("out of memory"));
+ return 0;
+ }
+ c->c.type = completion_type;
+ c->data = data;
+ switch(c->c.type) {
+ case COMPLETION_VOID:
+ c->c.void_result = (void_completion_t)dc;
+ break;
+ case COMPLETION_STRING:
+ c->c.string_result = (string_completion_t)dc;
+ break;
+ case COMPLETION_DATA:
+ c->c.data_result = (data_completion_t)dc;
+ break;
+ case COMPLETION_STAT:
+ c->c.stat_result = (stat_completion_t)dc;
+ break;
+ case COMPLETION_STRINGLIST:
+ c->c.strings_result = (strings_completion_t)dc;
+ break;
+ case COMPLETION_STRINGLIST_STAT:
+ c->c.strings_stat_result = (strings_stat_completion_t)dc;
+ break;
+ case COMPLETION_ACLLIST:
+ c->c.acl_result = (acl_completion_t)dc;
+ break;
+ case COMPLETION_MULTI:
+ assert(clist);
+ c->c.void_result = (void_completion_t)dc;
+ c->c.clist = *clist;
+ break;
+ }
+ c->xid = xid;
+ c->watcher = wo;
+
+ return c;
+}
+
+static void destroy_completion_entry(completion_list_t* c){
+ if(c!=0){
+ destroy_watcher_registration(c->watcher);
+ if(c->buffer!=0)
+ free_buffer(c->buffer);
+ free(c);
+ }
+}
+
+static void queue_completion_nolock(completion_head_t *list,
+ completion_list_t *c,
+ int add_to_front)
+{
+ c->next = 0;
+ /* appending a new entry to the back of the list */
+ if (list->last) {
+ assert(list->head);
+ // List is not empty
+ if (!add_to_front) {
+ list->last->next = c;
+ list->last = c;
+ } else {
+ c->next = list->head;
+ list->head = c;
+ }
+ } else {
+ // List is empty
+ assert(!list->head);
+ list->head = c;
+ list->last = c;
+ }
+}
+
+static void queue_completion(completion_head_t *list, completion_list_t *c,
+ int add_to_front)
+{
+
+ lock_completion_list(list);
+ queue_completion_nolock(list, c, add_to_front);
+ unlock_completion_list(list);
+}
+
+static int add_completion(zhandle_t *zh, int xid, int completion_type,
+ const void *dc, const void *data, int add_to_front,
+ watcher_registration_t* wo, completion_head_t *clist)
+{
+ completion_list_t *c =create_completion_entry(xid, completion_type, dc,
+ data, wo, clist);
+ int rc = 0;
+ if (!c)
+ return ZSYSTEMERROR;
+ lock_completion_list(&zh->sent_requests);
+ if (zh->close_requested != 1) {
+ queue_completion_nolock(&zh->sent_requests, c, add_to_front);
+ if (dc == SYNCHRONOUS_MARKER) {
+ zh->outstanding_sync++;
+ }
+ rc = ZOK;
+ } else {
+ free(c);
+ rc = ZINVALIDSTATE;
+ }
+ unlock_completion_list(&zh->sent_requests);
+ return rc;
+}
+
+static int add_data_completion(zhandle_t *zh, int xid, data_completion_t dc,
+ const void *data,watcher_registration_t* wo)
+{
+ return add_completion(zh, xid, COMPLETION_DATA, dc, data, 0, wo, 0);
+}
+
+static int add_stat_completion(zhandle_t *zh, int xid, stat_completion_t dc,
+ const void *data,watcher_registration_t* wo)
+{
+ return add_completion(zh, xid, COMPLETION_STAT, dc, data, 0, wo, 0);
+}
+
+static int add_strings_completion(zhandle_t *zh, int xid,
+ strings_completion_t dc, const void *data,watcher_registration_t* wo)
+{
+ return add_completion(zh, xid, COMPLETION_STRINGLIST, dc, data, 0, wo, 0);
+}
+
+static int add_strings_stat_completion(zhandle_t *zh, int xid,
+ strings_stat_completion_t dc, const void *data,watcher_registration_t* wo)
+{
+ return add_completion(zh, xid, COMPLETION_STRINGLIST_STAT, dc, data, 0, wo, 0);
+}
+
+static int add_acl_completion(zhandle_t *zh, int xid, acl_completion_t dc,
+ const void *data)
+{
+ return add_completion(zh, xid, COMPLETION_ACLLIST, dc, data, 0, 0, 0);
+}
+
+static int add_void_completion(zhandle_t *zh, int xid, void_completion_t dc,
+ const void *data)
+{
+ return add_completion(zh, xid, COMPLETION_VOID, dc, data, 0, 0, 0);
+}
+
+static int add_string_completion(zhandle_t *zh, int xid,
+ string_completion_t dc, const void *data)
+{
+ return add_completion(zh, xid, COMPLETION_STRING, dc, data, 0, 0, 0);
+}
+
+static int add_multi_completion(zhandle_t *zh, int xid, void_completion_t dc,
+ const void *data, completion_head_t *clist)
+{
+ return add_completion(zh, xid, COMPLETION_MULTI, dc, data, 0,0, clist);
+}
+
+int zookeeper_close(zhandle_t *zh)
+{
+ int rc=ZOK;
+ if (zh==0)
+ return ZBADARGUMENTS;
+
+ zh->close_requested=1;
+ if (inc_ref_counter(zh,1)>1) {
+ /* We have incremented the ref counter to prevent the
+ * completions from calling zookeeper_close before we have
+ * completed the adaptor_finish call below. */
+
+ /* Signal any syncronous completions before joining the threads */
+ enter_critical(zh);
+ free_completions(zh,1,ZCLOSING);
+ leave_critical(zh);
+
+ adaptor_finish(zh);
+ /* Now we can allow the handle to be cleaned up, if the completion
+ * threads finished during the adaptor_finish call. */
+ api_epilog(zh, 0);
+ return ZOK;
+ }
+ /* No need to decrement the counter since we're just going to
+ * destroy the handle later. */
+ if(zh->state==ZOO_CONNECTED_STATE){
+ struct oarchive *oa;
+ struct RequestHeader h = { STRUCT_INITIALIZER (xid , get_xid()), STRUCT_INITIALIZER (type , ZOO_CLOSE_OP)};
+ LOG_INFO(("Closing zookeeper sessionId=%#llx to [%s]\n",
+ zh->client_id.client_id,format_current_endpoint_info(zh)));
+ oa = create_buffer_oarchive();
+ rc = serialize_RequestHeader(oa, "header", &h);
+ rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa),
+ get_buffer_len(oa));
+ /* We queued the buffer, so don't free it */
+ close_buffer_oarchive(&oa, 0);
+ if (rc < 0) {
+ rc = ZMARSHALLINGERROR;
+ goto finish;
+ }
+
+ /* make sure the close request is sent; we set timeout to an arbitrary
+ * (but reasonable) number of milliseconds since we want the call to block*/
+ rc=adaptor_send_queue(zh, 3000);
+ }else{
+ LOG_INFO(("Freeing zookeeper resources for sessionId=%#llx\n",
+ zh->client_id.client_id));
+ rc = ZOK;
+ }
+
+finish:
+ destroy(zh);
+ adaptor_destroy(zh);
+ free(zh);
+#ifdef WIN32
+ Win32WSACleanup();
+#endif
+ return rc;
+}
+
+static int isValidPath(const char* path, const int flags) {
+ int len = 0;
+ char lastc = '/';
+ char c;
+ int i = 0;
+
+ if (path == 0)
+ return 0;
+ len = strlen(path);
+ if (len == 0)
+ return 0;
+ if (path[0] != '/')
+ return 0;
+ if (len == 1) // done checking - it's the root
+ return 1;
+ if (path[len - 1] == '/' && !(flags & ZOO_SEQUENCE))
+ return 0;
+
+ i = 1;
+ for (; i < len; lastc = path[i], i++) {
+ c = path[i];
+
+ if (c == 0) {
+ return 0;
+ } else if (c == '/' && lastc == '/') {
+ return 0;
+ } else if (c == '.' && lastc == '.') {
+ if (path[i-2] == '/' && (((i + 1 == len) && !(flags & ZOO_SEQUENCE))
+ || path[i+1] == '/')) {
+ return 0;
+ }
+ } else if (c == '.') {
+ if ((path[i-1] == '/') && (((i + 1 == len) && !(flags & ZOO_SEQUENCE))
+ || path[i+1] == '/')) {
+ return 0;
+ }
+ } else if (c > 0x00 && c < 0x1f) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*---------------------------------------------------------------------------*
+ * REQUEST INIT HELPERS
+ *---------------------------------------------------------------------------*/
+/* Common Request init helper functions to reduce code duplication */
+static int Request_path_init(zhandle_t *zh, int flags,
+ char **path_out, const char *path)
+{
+ assert(path_out);
+
+ *path_out = prepend_string(zh, path);
+ if (zh == NULL || !isValidPath(*path_out, flags)) {
+ free_duplicate_path(*path_out, path);
+ return ZBADARGUMENTS;
+ }
+ if (is_unrecoverable(zh)) {
+ free_duplicate_path(*path_out, path);
+ return ZINVALIDSTATE;
+ }
+
+ return ZOK;
+}
+
+static int Request_path_watch_init(zhandle_t *zh, int flags,
+ char **path_out, const char *path,
+ int32_t *watch_out, uint32_t watch)
+{
+ int rc = Request_path_init(zh, flags, path_out, path);
+ if (rc != ZOK) {
+ return rc;
+ }
+ *watch_out = watch;
+ return ZOK;
+}
+
+/*---------------------------------------------------------------------------*
+ * ASYNC API
+ *---------------------------------------------------------------------------*/
+int zoo_aget(zhandle_t *zh, const char *path, int watch, data_completion_t dc,
+ const void *data)
+{
+ return zoo_awget(zh,path,watch?zh->watcher:0,zh->context,dc,data);
+}
+
+int zoo_awget(zhandle_t *zh, const char *path,
+ watcher_fn watcher, void* watcherCtx,
+ data_completion_t dc, const void *data)
+{
+ struct oarchive *oa;
+ char *server_path = prepend_string(zh, path);
+ struct RequestHeader h = { STRUCT_INITIALIZER (xid , get_xid()), STRUCT_INITIALIZER (type ,ZOO_GETDATA_OP)};
+ struct GetDataRequest req = { (char*)server_path, watcher!=0 };
+ int rc;
+
+ if (zh==0 || !isValidPath(server_path, 0)) {
+ free_duplicate_path(server_path, path);
+ return ZBADARGUMENTS;
+ }
+ if (is_unrecoverable(zh)) {
+ free_duplicate_path(server_path, path);
+ return ZINVALIDSTATE;
+ }
+ oa=create_buffer_oarchive();
+ rc = serialize_RequestHeader(oa, "header", &h);
+ rc = rc < 0 ? rc : serialize_GetDataRequest(oa, "req", &req);
+ enter_critical(zh);
+ rc = rc < 0 ? rc : add_data_completion(zh, h.xid, dc, data,
+ create_watcher_registration(server_path,data_result_checker,watcher,watcherCtx));
+ rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa),
+ get_buffer_len(oa));
+ leave_critical(zh);
+ free_duplicate_path(server_path, path);
+ /* We queued the buffer, so don't free it */
+ close_buffer_oarchive(&oa, 0);
+
+ LOG_DEBUG(("Sending request xid=%#x for path [%s] to %s",h.xid,path,
+ format_current_endpoint_info(zh)));
+ /* make a best (non-blocking) effort to send the requests asap */
+ adaptor_send_queue(zh, 0);
+ return (rc < 0)?ZMARSHALLINGERROR:ZOK;
+}
+
+static int SetDataRequest_init(zhandle_t *zh, struct SetDataRequest *req,
+ const char *path, const char *buffer, int buflen, int version)
+{
+ int rc;
+ assert(req);
+ rc = Request_path_init(zh, 0, &req->path, path);
+ if (rc != ZOK) {
+ return rc;
+ }
+ req->data.buff = (char*)buffer;
+ req->data.len = buflen;
+ req->version = version;
+
+ return ZOK;
+}
+
+int zoo_aset(zhandle_t *zh, const char *path, const char *buffer, int buflen,
+ int version, stat_completion_t dc, const void *data)
+{
+ struct oarchive *oa;
+ struct RequestHeader h = { STRUCT_INITIALIZER(xid , get_xid()), STRUCT_INITIALIZER (type , ZOO_SETDATA_OP)};
+ struct SetDataRequest req;
+ int rc = SetDataRequest_init(zh, &req, path, buffer, buflen, version);
+ if (rc != ZOK) {
+ return rc;
+ }
+ oa = create_buffer_oarchive();
+ rc = serialize_RequestHeader(oa, "header", &h);
+ rc = rc < 0 ? rc : serialize_SetDataRequest(oa, "req", &req);
+ enter_critical(zh);
+ rc = rc < 0 ? rc : add_stat_completion(zh, h.xid, dc, data,0);
+ rc
<TRUNCATED>