diff --git a/contrib/libzookeeper/CMakeLists.txt b/contrib/libzookeeper/CMakeLists.txt new file mode 100644 index 00000000000..7b19d737c06 --- /dev/null +++ b/contrib/libzookeeper/CMakeLists.txt @@ -0,0 +1,17 @@ +add_definitions( + -DHAVE_CONFIG_H -DTHREADED + -Wno-unused-but-set-variable +) + +include_directories (include/zookeeper src) + +add_library (zookeeper_mt +src/zookeeper.c +src/zookeeper.jute.c +src/zk_hashtable.c +src/zk_log.c +src/mt_adaptor.c +src/recordio.c +src/hashtable/hashtable.c +src/hashtable/hashtable_itr.c +) diff --git a/contrib/libzookeeper/LICENSE b/contrib/libzookeeper/LICENSE new file mode 100644 index 00000000000..d6456956733 --- /dev/null +++ b/contrib/libzookeeper/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. diff --git a/contrib/libzookeeper/README b/contrib/libzookeeper/README new file mode 100644 index 00000000000..22aa35e9176 --- /dev/null +++ b/contrib/libzookeeper/README @@ -0,0 +1 @@ +http://apache-mirror.rbc.ru/pub/apache/zookeeper/stable/zookeeper-3.4.8.tar.gz diff --git a/contrib/libzookeeper/include/zookeeper/proto.h b/contrib/libzookeeper/include/zookeeper/proto.h new file mode 100644 index 00000000000..bce408e6f97 --- /dev/null +++ b/contrib/libzookeeper/include/zookeeper/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_*/ diff --git a/contrib/libzookeeper/include/zookeeper/recordio.h b/contrib/libzookeeper/include/zookeeper/recordio.h new file mode 100644 index 00000000000..90f458b4aaa --- /dev/null +++ b/contrib/libzookeeper/include/zookeeper/recordio.h @@ -0,0 +1,82 @@ +/** + * 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 +#ifndef WIN32 +#define STRUCT_INITIALIZER(l,r) .l = r +#else +#define STRUCT_INITIALIZER(l,r) r +#include "winconfig.h" +#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 diff --git a/contrib/libzookeeper/include/zookeeper/zookeeper.h b/contrib/libzookeeper/include/zookeeper/zookeeper.h new file mode 100644 index 00000000000..7d1066a9313 --- /dev/null +++ b/contrib/libzookeeper/include/zookeeper/zookeeper.h @@ -0,0 +1,1583 @@ +/** + * 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 +#ifndef WIN32 +#include +#include +#else +#include "winconfig.h" +#endif +#include +#include + +#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 /*! + * 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). + *

+ * 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 occured while attempting to send request to server + * ZSYSTEMERROR -- a system (OS) error occured; 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 occured 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 occured; 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 occured 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 occured; 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 occured + */ +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_*/ diff --git a/contrib/libzookeeper/include/zookeeper/zookeeper.jute.h b/contrib/libzookeeper/include/zookeeper/zookeeper.jute.h new file mode 100644 index 00000000000..89733ecff80 --- /dev/null +++ b/contrib/libzookeeper/include/zookeeper/zookeeper.jute.h @@ -0,0 +1,485 @@ +/** +* 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_JUTE__ +#define __ZOOKEEPER_JUTE__ +#include "recordio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Id { + char * scheme; + char * id; +}; +int serialize_Id(struct oarchive *out, const char *tag, struct Id *v); +int deserialize_Id(struct iarchive *in, const char *tag, struct Id*v); +void deallocate_Id(struct Id*); +struct ACL { + int32_t perms; + struct Id id; +}; +int serialize_ACL(struct oarchive *out, const char *tag, struct ACL *v); +int deserialize_ACL(struct iarchive *in, const char *tag, struct ACL*v); +void deallocate_ACL(struct ACL*); +struct Stat { + int64_t czxid; + int64_t mzxid; + int64_t ctime; + int64_t mtime; + int32_t version; + int32_t cversion; + int32_t aversion; + int64_t ephemeralOwner; + int32_t dataLength; + int32_t numChildren; + int64_t pzxid; +}; +int serialize_Stat(struct oarchive *out, const char *tag, struct Stat *v); +int deserialize_Stat(struct iarchive *in, const char *tag, struct Stat*v); +void deallocate_Stat(struct Stat*); +struct StatPersisted { + int64_t czxid; + int64_t mzxid; + int64_t ctime; + int64_t mtime; + int32_t version; + int32_t cversion; + int32_t aversion; + int64_t ephemeralOwner; + int64_t pzxid; +}; +int serialize_StatPersisted(struct oarchive *out, const char *tag, struct StatPersisted *v); +int deserialize_StatPersisted(struct iarchive *in, const char *tag, struct StatPersisted*v); +void deallocate_StatPersisted(struct StatPersisted*); +struct StatPersistedV1 { + int64_t czxid; + int64_t mzxid; + int64_t ctime; + int64_t mtime; + int32_t version; + int32_t cversion; + int32_t aversion; + int64_t ephemeralOwner; +}; +int serialize_StatPersistedV1(struct oarchive *out, const char *tag, struct StatPersistedV1 *v); +int deserialize_StatPersistedV1(struct iarchive *in, const char *tag, struct StatPersistedV1*v); +void deallocate_StatPersistedV1(struct StatPersistedV1*); +struct ConnectRequest { + int32_t protocolVersion; + int64_t lastZxidSeen; + int32_t timeOut; + int64_t sessionId; + struct buffer passwd; +}; +int serialize_ConnectRequest(struct oarchive *out, const char *tag, struct ConnectRequest *v); +int deserialize_ConnectRequest(struct iarchive *in, const char *tag, struct ConnectRequest*v); +void deallocate_ConnectRequest(struct ConnectRequest*); +struct ConnectResponse { + int32_t protocolVersion; + int32_t timeOut; + int64_t sessionId; + struct buffer passwd; +}; +int serialize_ConnectResponse(struct oarchive *out, const char *tag, struct ConnectResponse *v); +int deserialize_ConnectResponse(struct iarchive *in, const char *tag, struct ConnectResponse*v); +void deallocate_ConnectResponse(struct ConnectResponse*); +struct String_vector { + int32_t count; + char * *data; + +}; +int serialize_String_vector(struct oarchive *out, const char *tag, struct String_vector *v); +int deserialize_String_vector(struct iarchive *in, const char *tag, struct String_vector *v); +int allocate_String_vector(struct String_vector *v, int32_t len); +int deallocate_String_vector(struct String_vector *v); +struct SetWatches { + int64_t relativeZxid; + struct String_vector dataWatches; + struct String_vector existWatches; + struct String_vector childWatches; +}; +int serialize_SetWatches(struct oarchive *out, const char *tag, struct SetWatches *v); +int deserialize_SetWatches(struct iarchive *in, const char *tag, struct SetWatches*v); +void deallocate_SetWatches(struct SetWatches*); +struct RequestHeader { + int32_t xid; + int32_t type; +}; +int serialize_RequestHeader(struct oarchive *out, const char *tag, struct RequestHeader *v); +int deserialize_RequestHeader(struct iarchive *in, const char *tag, struct RequestHeader*v); +void deallocate_RequestHeader(struct RequestHeader*); +struct MultiHeader { + int32_t type; + int32_t done; + int32_t err; +}; +int serialize_MultiHeader(struct oarchive *out, const char *tag, struct MultiHeader *v); +int deserialize_MultiHeader(struct iarchive *in, const char *tag, struct MultiHeader*v); +void deallocate_MultiHeader(struct MultiHeader*); +struct AuthPacket { + int32_t type; + char * scheme; + struct buffer auth; +}; +int serialize_AuthPacket(struct oarchive *out, const char *tag, struct AuthPacket *v); +int deserialize_AuthPacket(struct iarchive *in, const char *tag, struct AuthPacket*v); +void deallocate_AuthPacket(struct AuthPacket*); +struct ReplyHeader { + int32_t xid; + int64_t zxid; + int32_t err; +}; +int serialize_ReplyHeader(struct oarchive *out, const char *tag, struct ReplyHeader *v); +int deserialize_ReplyHeader(struct iarchive *in, const char *tag, struct ReplyHeader*v); +void deallocate_ReplyHeader(struct ReplyHeader*); +struct GetDataRequest { + char * path; + int32_t watch; +}; +int serialize_GetDataRequest(struct oarchive *out, const char *tag, struct GetDataRequest *v); +int deserialize_GetDataRequest(struct iarchive *in, const char *tag, struct GetDataRequest*v); +void deallocate_GetDataRequest(struct GetDataRequest*); +struct SetDataRequest { + char * path; + struct buffer data; + int32_t version; +}; +int serialize_SetDataRequest(struct oarchive *out, const char *tag, struct SetDataRequest *v); +int deserialize_SetDataRequest(struct iarchive *in, const char *tag, struct SetDataRequest*v); +void deallocate_SetDataRequest(struct SetDataRequest*); +struct SetDataResponse { + struct Stat stat; +}; +int serialize_SetDataResponse(struct oarchive *out, const char *tag, struct SetDataResponse *v); +int deserialize_SetDataResponse(struct iarchive *in, const char *tag, struct SetDataResponse*v); +void deallocate_SetDataResponse(struct SetDataResponse*); +struct GetSASLRequest { + struct buffer token; +}; +int serialize_GetSASLRequest(struct oarchive *out, const char *tag, struct GetSASLRequest *v); +int deserialize_GetSASLRequest(struct iarchive *in, const char *tag, struct GetSASLRequest*v); +void deallocate_GetSASLRequest(struct GetSASLRequest*); +struct SetSASLRequest { + struct buffer token; +}; +int serialize_SetSASLRequest(struct oarchive *out, const char *tag, struct SetSASLRequest *v); +int deserialize_SetSASLRequest(struct iarchive *in, const char *tag, struct SetSASLRequest*v); +void deallocate_SetSASLRequest(struct SetSASLRequest*); +struct SetSASLResponse { + struct buffer token; +}; +int serialize_SetSASLResponse(struct oarchive *out, const char *tag, struct SetSASLResponse *v); +int deserialize_SetSASLResponse(struct iarchive *in, const char *tag, struct SetSASLResponse*v); +void deallocate_SetSASLResponse(struct SetSASLResponse*); +struct ACL_vector { + int32_t count; + struct ACL *data; + +}; +int serialize_ACL_vector(struct oarchive *out, const char *tag, struct ACL_vector *v); +int deserialize_ACL_vector(struct iarchive *in, const char *tag, struct ACL_vector *v); +int allocate_ACL_vector(struct ACL_vector *v, int32_t len); +int deallocate_ACL_vector(struct ACL_vector *v); +struct CreateRequest { + char * path; + struct buffer data; + struct ACL_vector acl; + int32_t flags; +}; +int serialize_CreateRequest(struct oarchive *out, const char *tag, struct CreateRequest *v); +int deserialize_CreateRequest(struct iarchive *in, const char *tag, struct CreateRequest*v); +void deallocate_CreateRequest(struct CreateRequest*); +struct DeleteRequest { + char * path; + int32_t version; +}; +int serialize_DeleteRequest(struct oarchive *out, const char *tag, struct DeleteRequest *v); +int deserialize_DeleteRequest(struct iarchive *in, const char *tag, struct DeleteRequest*v); +void deallocate_DeleteRequest(struct DeleteRequest*); +struct GetChildrenRequest { + char * path; + int32_t watch; +}; +int serialize_GetChildrenRequest(struct oarchive *out, const char *tag, struct GetChildrenRequest *v); +int deserialize_GetChildrenRequest(struct iarchive *in, const char *tag, struct GetChildrenRequest*v); +void deallocate_GetChildrenRequest(struct GetChildrenRequest*); +struct GetChildren2Request { + char * path; + int32_t watch; +}; +int serialize_GetChildren2Request(struct oarchive *out, const char *tag, struct GetChildren2Request *v); +int deserialize_GetChildren2Request(struct iarchive *in, const char *tag, struct GetChildren2Request*v); +void deallocate_GetChildren2Request(struct GetChildren2Request*); +struct CheckVersionRequest { + char * path; + int32_t version; +}; +int serialize_CheckVersionRequest(struct oarchive *out, const char *tag, struct CheckVersionRequest *v); +int deserialize_CheckVersionRequest(struct iarchive *in, const char *tag, struct CheckVersionRequest*v); +void deallocate_CheckVersionRequest(struct CheckVersionRequest*); +struct GetMaxChildrenRequest { + char * path; +}; +int serialize_GetMaxChildrenRequest(struct oarchive *out, const char *tag, struct GetMaxChildrenRequest *v); +int deserialize_GetMaxChildrenRequest(struct iarchive *in, const char *tag, struct GetMaxChildrenRequest*v); +void deallocate_GetMaxChildrenRequest(struct GetMaxChildrenRequest*); +struct GetMaxChildrenResponse { + int32_t max; +}; +int serialize_GetMaxChildrenResponse(struct oarchive *out, const char *tag, struct GetMaxChildrenResponse *v); +int deserialize_GetMaxChildrenResponse(struct iarchive *in, const char *tag, struct GetMaxChildrenResponse*v); +void deallocate_GetMaxChildrenResponse(struct GetMaxChildrenResponse*); +struct SetMaxChildrenRequest { + char * path; + int32_t max; +}; +int serialize_SetMaxChildrenRequest(struct oarchive *out, const char *tag, struct SetMaxChildrenRequest *v); +int deserialize_SetMaxChildrenRequest(struct iarchive *in, const char *tag, struct SetMaxChildrenRequest*v); +void deallocate_SetMaxChildrenRequest(struct SetMaxChildrenRequest*); +struct SyncRequest { + char * path; +}; +int serialize_SyncRequest(struct oarchive *out, const char *tag, struct SyncRequest *v); +int deserialize_SyncRequest(struct iarchive *in, const char *tag, struct SyncRequest*v); +void deallocate_SyncRequest(struct SyncRequest*); +struct SyncResponse { + char * path; +}; +int serialize_SyncResponse(struct oarchive *out, const char *tag, struct SyncResponse *v); +int deserialize_SyncResponse(struct iarchive *in, const char *tag, struct SyncResponse*v); +void deallocate_SyncResponse(struct SyncResponse*); +struct GetACLRequest { + char * path; +}; +int serialize_GetACLRequest(struct oarchive *out, const char *tag, struct GetACLRequest *v); +int deserialize_GetACLRequest(struct iarchive *in, const char *tag, struct GetACLRequest*v); +void deallocate_GetACLRequest(struct GetACLRequest*); +struct SetACLRequest { + char * path; + struct ACL_vector acl; + int32_t version; +}; +int serialize_SetACLRequest(struct oarchive *out, const char *tag, struct SetACLRequest *v); +int deserialize_SetACLRequest(struct iarchive *in, const char *tag, struct SetACLRequest*v); +void deallocate_SetACLRequest(struct SetACLRequest*); +struct SetACLResponse { + struct Stat stat; +}; +int serialize_SetACLResponse(struct oarchive *out, const char *tag, struct SetACLResponse *v); +int deserialize_SetACLResponse(struct iarchive *in, const char *tag, struct SetACLResponse*v); +void deallocate_SetACLResponse(struct SetACLResponse*); +struct WatcherEvent { + int32_t type; + int32_t state; + char * path; +}; +int serialize_WatcherEvent(struct oarchive *out, const char *tag, struct WatcherEvent *v); +int deserialize_WatcherEvent(struct iarchive *in, const char *tag, struct WatcherEvent*v); +void deallocate_WatcherEvent(struct WatcherEvent*); +struct ErrorResponse { + int32_t err; +}; +int serialize_ErrorResponse(struct oarchive *out, const char *tag, struct ErrorResponse *v); +int deserialize_ErrorResponse(struct iarchive *in, const char *tag, struct ErrorResponse*v); +void deallocate_ErrorResponse(struct ErrorResponse*); +struct CreateResponse { + char * path; +}; +int serialize_CreateResponse(struct oarchive *out, const char *tag, struct CreateResponse *v); +int deserialize_CreateResponse(struct iarchive *in, const char *tag, struct CreateResponse*v); +void deallocate_CreateResponse(struct CreateResponse*); +struct ExistsRequest { + char * path; + int32_t watch; +}; +int serialize_ExistsRequest(struct oarchive *out, const char *tag, struct ExistsRequest *v); +int deserialize_ExistsRequest(struct iarchive *in, const char *tag, struct ExistsRequest*v); +void deallocate_ExistsRequest(struct ExistsRequest*); +struct ExistsResponse { + struct Stat stat; +}; +int serialize_ExistsResponse(struct oarchive *out, const char *tag, struct ExistsResponse *v); +int deserialize_ExistsResponse(struct iarchive *in, const char *tag, struct ExistsResponse*v); +void deallocate_ExistsResponse(struct ExistsResponse*); +struct GetDataResponse { + struct buffer data; + struct Stat stat; +}; +int serialize_GetDataResponse(struct oarchive *out, const char *tag, struct GetDataResponse *v); +int deserialize_GetDataResponse(struct iarchive *in, const char *tag, struct GetDataResponse*v); +void deallocate_GetDataResponse(struct GetDataResponse*); +struct GetChildrenResponse { + struct String_vector children; +}; +int serialize_GetChildrenResponse(struct oarchive *out, const char *tag, struct GetChildrenResponse *v); +int deserialize_GetChildrenResponse(struct iarchive *in, const char *tag, struct GetChildrenResponse*v); +void deallocate_GetChildrenResponse(struct GetChildrenResponse*); +struct GetChildren2Response { + struct String_vector children; + struct Stat stat; +}; +int serialize_GetChildren2Response(struct oarchive *out, const char *tag, struct GetChildren2Response *v); +int deserialize_GetChildren2Response(struct iarchive *in, const char *tag, struct GetChildren2Response*v); +void deallocate_GetChildren2Response(struct GetChildren2Response*); +struct GetACLResponse { + struct ACL_vector acl; + struct Stat stat; +}; +int serialize_GetACLResponse(struct oarchive *out, const char *tag, struct GetACLResponse *v); +int deserialize_GetACLResponse(struct iarchive *in, const char *tag, struct GetACLResponse*v); +void deallocate_GetACLResponse(struct GetACLResponse*); +struct LearnerInfo { + int64_t serverid; + int32_t protocolVersion; +}; +int serialize_LearnerInfo(struct oarchive *out, const char *tag, struct LearnerInfo *v); +int deserialize_LearnerInfo(struct iarchive *in, const char *tag, struct LearnerInfo*v); +void deallocate_LearnerInfo(struct LearnerInfo*); +struct Id_vector { + int32_t count; + struct Id *data; + +}; +int serialize_Id_vector(struct oarchive *out, const char *tag, struct Id_vector *v); +int deserialize_Id_vector(struct iarchive *in, const char *tag, struct Id_vector *v); +int allocate_Id_vector(struct Id_vector *v, int32_t len); +int deallocate_Id_vector(struct Id_vector *v); +struct QuorumPacket { + int32_t type; + int64_t zxid; + struct buffer data; + struct Id_vector authinfo; +}; +int serialize_QuorumPacket(struct oarchive *out, const char *tag, struct QuorumPacket *v); +int deserialize_QuorumPacket(struct iarchive *in, const char *tag, struct QuorumPacket*v); +void deallocate_QuorumPacket(struct QuorumPacket*); +struct FileHeader { + int32_t magic; + int32_t version; + int64_t dbid; +}; +int serialize_FileHeader(struct oarchive *out, const char *tag, struct FileHeader *v); +int deserialize_FileHeader(struct iarchive *in, const char *tag, struct FileHeader*v); +void deallocate_FileHeader(struct FileHeader*); +struct TxnHeader { + int64_t clientId; + int32_t cxid; + int64_t zxid; + int64_t time; + int32_t type; +}; +int serialize_TxnHeader(struct oarchive *out, const char *tag, struct TxnHeader *v); +int deserialize_TxnHeader(struct iarchive *in, const char *tag, struct TxnHeader*v); +void deallocate_TxnHeader(struct TxnHeader*); +struct CreateTxnV0 { + char * path; + struct buffer data; + struct ACL_vector acl; + int32_t ephemeral; +}; +int serialize_CreateTxnV0(struct oarchive *out, const char *tag, struct CreateTxnV0 *v); +int deserialize_CreateTxnV0(struct iarchive *in, const char *tag, struct CreateTxnV0*v); +void deallocate_CreateTxnV0(struct CreateTxnV0*); +struct CreateTxn { + char * path; + struct buffer data; + struct ACL_vector acl; + int32_t ephemeral; + int32_t parentCVersion; +}; +int serialize_CreateTxn(struct oarchive *out, const char *tag, struct CreateTxn *v); +int deserialize_CreateTxn(struct iarchive *in, const char *tag, struct CreateTxn*v); +void deallocate_CreateTxn(struct CreateTxn*); +struct DeleteTxn { + char * path; +}; +int serialize_DeleteTxn(struct oarchive *out, const char *tag, struct DeleteTxn *v); +int deserialize_DeleteTxn(struct iarchive *in, const char *tag, struct DeleteTxn*v); +void deallocate_DeleteTxn(struct DeleteTxn*); +struct SetDataTxn { + char * path; + struct buffer data; + int32_t version; +}; +int serialize_SetDataTxn(struct oarchive *out, const char *tag, struct SetDataTxn *v); +int deserialize_SetDataTxn(struct iarchive *in, const char *tag, struct SetDataTxn*v); +void deallocate_SetDataTxn(struct SetDataTxn*); +struct CheckVersionTxn { + char * path; + int32_t version; +}; +int serialize_CheckVersionTxn(struct oarchive *out, const char *tag, struct CheckVersionTxn *v); +int deserialize_CheckVersionTxn(struct iarchive *in, const char *tag, struct CheckVersionTxn*v); +void deallocate_CheckVersionTxn(struct CheckVersionTxn*); +struct SetACLTxn { + char * path; + struct ACL_vector acl; + int32_t version; +}; +int serialize_SetACLTxn(struct oarchive *out, const char *tag, struct SetACLTxn *v); +int deserialize_SetACLTxn(struct iarchive *in, const char *tag, struct SetACLTxn*v); +void deallocate_SetACLTxn(struct SetACLTxn*); +struct SetMaxChildrenTxn { + char * path; + int32_t max; +}; +int serialize_SetMaxChildrenTxn(struct oarchive *out, const char *tag, struct SetMaxChildrenTxn *v); +int deserialize_SetMaxChildrenTxn(struct iarchive *in, const char *tag, struct SetMaxChildrenTxn*v); +void deallocate_SetMaxChildrenTxn(struct SetMaxChildrenTxn*); +struct CreateSessionTxn { + int32_t timeOut; +}; +int serialize_CreateSessionTxn(struct oarchive *out, const char *tag, struct CreateSessionTxn *v); +int deserialize_CreateSessionTxn(struct iarchive *in, const char *tag, struct CreateSessionTxn*v); +void deallocate_CreateSessionTxn(struct CreateSessionTxn*); +struct ErrorTxn { + int32_t err; +}; +int serialize_ErrorTxn(struct oarchive *out, const char *tag, struct ErrorTxn *v); +int deserialize_ErrorTxn(struct iarchive *in, const char *tag, struct ErrorTxn*v); +void deallocate_ErrorTxn(struct ErrorTxn*); +struct Txn { + int32_t type; + struct buffer data; +}; +int serialize_Txn(struct oarchive *out, const char *tag, struct Txn *v); +int deserialize_Txn(struct iarchive *in, const char *tag, struct Txn*v); +void deallocate_Txn(struct Txn*); +struct Txn_vector { + int32_t count; + struct Txn *data; + +}; +int serialize_Txn_vector(struct oarchive *out, const char *tag, struct Txn_vector *v); +int deserialize_Txn_vector(struct iarchive *in, const char *tag, struct Txn_vector *v); +int allocate_Txn_vector(struct Txn_vector *v, int32_t len); +int deallocate_Txn_vector(struct Txn_vector *v); +struct MultiTxn { + struct Txn_vector txns; +}; +int serialize_MultiTxn(struct oarchive *out, const char *tag, struct MultiTxn *v); +int deserialize_MultiTxn(struct iarchive *in, const char *tag, struct MultiTxn*v); +void deallocate_MultiTxn(struct MultiTxn*); + +#ifdef __cplusplus +} +#endif + +#endif //ZOOKEEPER_JUTE__ diff --git a/contrib/libzookeeper/include/zookeeper/zookeeper_log.h b/contrib/libzookeeper/include/zookeeper/zookeeper_log.h new file mode 100644 index 00000000000..e5917cbc64e --- /dev/null +++ b/contrib/libzookeeper/include/zookeeper/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 + +#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_*/ diff --git a/contrib/libzookeeper/include/zookeeper/zookeeper_version.h b/contrib/libzookeeper/include/zookeeper/zookeeper_version.h new file mode 100644 index 00000000000..92eee134eef --- /dev/null +++ b/contrib/libzookeeper/include/zookeeper/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 8 + +#ifdef __cplusplus +} +#endif + +#endif /* ZOOKEEPER_VERSION_H_ */ diff --git a/contrib/libzookeeper/src/config.h b/contrib/libzookeeper/src/config.h new file mode 100644 index 00000000000..695570623ba --- /dev/null +++ b/contrib/libzookeeper/src/config.h @@ -0,0 +1,149 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the file `generated/zookeeper.jute.c'. */ +#define HAVE_GENERATED_ZOOKEEPER_JUTE_C 1 + +/* Define to 1 if you have the file `generated/zookeeper.jute.h'. */ +#define HAVE_GENERATED_ZOOKEEPER_JUTE_H 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* Define to 1 if you have the `gethostbyname' function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the `gethostname' function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have the `getlogin' function. */ +#define HAVE_GETLOGIN 1 + +/* Define to 1 if you have the `getpwuid_r' function. */ +#define HAVE_GETPWUID_R 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `getuid' function. */ +#define HAVE_GETUID 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the `poll' function. */ +#define HAVE_POLL 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strtol' function. */ +#define HAVE_STRTOL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* Name of package */ +#define PACKAGE "zookeeper" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "user@zookeeper.apache.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "zookeeper C client" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "zookeeper C client 3.4.8" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "zookeeper" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "3.4.8" + +/* poll() second argument type */ +#define POLL_NFDS_TYPE nfds_t + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Version number of package */ +#define VERSION "3.4.8" + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* 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 +/* #undef inline */ +#endif diff --git a/contrib/libzookeeper/src/hashtable/LICENSE.txt b/contrib/libzookeeper/src/hashtable/LICENSE.txt new file mode 100644 index 00000000000..674a6245648 --- /dev/null +++ b/contrib/libzookeeper/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. diff --git a/contrib/libzookeeper/src/hashtable/hashtable.c b/contrib/libzookeeper/src/hashtable/hashtable.c new file mode 100644 index 00000000000..763357edce5 --- /dev/null +++ b/contrib/libzookeeper/src/hashtable/hashtable.c @@ -0,0 +1,274 @@ +/* Copyright (C) 2004 Christopher Clark */ + +#include "hashtable.h" +#include "hashtable_private.h" +#include +#include +#include +#include + +/* +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. +*/ diff --git a/contrib/libzookeeper/src/hashtable/hashtable.h b/contrib/libzookeeper/src/hashtable/hashtable.h new file mode 100644 index 00000000000..cbead182987 --- /dev/null +++ b/contrib/libzookeeper/src/hashtable/hashtable.h @@ -0,0 +1,209 @@ +/* Copyright (C) 2002 Christopher Clark */ + +#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. +*/ diff --git a/contrib/libzookeeper/src/hashtable/hashtable_itr.c b/contrib/libzookeeper/src/hashtable/hashtable_itr.c new file mode 100644 index 00000000000..defac691f03 --- /dev/null +++ b/contrib/libzookeeper/src/hashtable/hashtable_itr.c @@ -0,0 +1,176 @@ +/* Copyright (C) 2002, 2004 Christopher Clark */ + +#include "hashtable.h" +#include "hashtable_private.h" +#include "hashtable_itr.h" +#include /* 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. +*/ diff --git a/contrib/libzookeeper/src/hashtable/hashtable_itr.h b/contrib/libzookeeper/src/hashtable/hashtable_itr.h new file mode 100644 index 00000000000..30379c7ee1e --- /dev/null +++ b/contrib/libzookeeper/src/hashtable/hashtable_itr.h @@ -0,0 +1,119 @@ +/* Copyright (C) 2002, 2004 Christopher Clark */ + +#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. +*/ diff --git a/contrib/libzookeeper/src/hashtable/hashtable_private.h b/contrib/libzookeeper/src/hashtable/hashtable_private.h new file mode 100644 index 00000000000..3e95f600577 --- /dev/null +++ b/contrib/libzookeeper/src/hashtable/hashtable_private.h @@ -0,0 +1,85 @@ +/* Copyright (C) 2002, 2004 Christopher Clark */ + +#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. +*/ diff --git a/contrib/libzookeeper/src/mt_adaptor.c b/contrib/libzookeeper/src/mt_adaptor.c new file mode 100644 index 00000000000..7dc78789f13 --- /dev/null +++ b/contrib/libzookeeper/src/mt_adaptor.c @@ -0,0 +1,536 @@ +/** + * 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 + +#ifndef DLL_EXPORT +# define USE_STATIC_LIB +#endif + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include "zk_adaptor.h" +#include "zookeeper_log.h" + +#include +#include +#include +#include +#include +#include + +#ifndef WIN32 +#include +#include +#include +#include +#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; + int rc; + + 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 + rc = 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 + int32_t result; + asm __volatile__( + "lock xaddl %0,%1\n" + : "=r"(result), "=m"(*(int *)operand) + : "0"(incr) + : "memory"); + return result; +#else + volatile int32_t result; + _asm + { + mov eax, operand; //eax = v; + mov ebx, incr; // ebx = i; + mov ecx, 0x0; // ecx = 0; + lock xadd dword ptr [eax], ecx; + lock xadd dword ptr [eax], ebx; + mov result, ecx; // result = ebx; + } + return result; +#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; + } +} diff --git a/contrib/libzookeeper/src/recordio.c b/contrib/libzookeeper/src/recordio.c new file mode 100644 index 00000000000..41797fbc978 --- /dev/null +++ b/contrib/libzookeeper/src/recordio.c @@ -0,0 +1,360 @@ +/** + * 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 +#include +#include +#include +#include +#ifndef WIN32 +#include +#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 = malloc(sizeof(*ia)); + struct buff_struct *buff = malloc(sizeof(struct buff_struct)); + if (!ia) return 0; + 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 = malloc(sizeof(*oa)); + struct buff_struct *buff = malloc(sizeof(struct buff_struct)); + if (!oa) return 0; + 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; +} diff --git a/contrib/libzookeeper/src/st_adaptor.c b/contrib/libzookeeper/src/st_adaptor.c new file mode 100644 index 00000000000..23573b3aa90 --- /dev/null +++ b/contrib/libzookeeper/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 +#include + +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; +} diff --git a/contrib/libzookeeper/src/zk_adaptor.h b/contrib/libzookeeper/src/zk_adaptor.h new file mode 100644 index 00000000000..b99077963fc --- /dev/null +++ b/contrib/libzookeeper/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 +#ifdef THREADED +#ifndef WIN32 +#include +#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_*/ + + diff --git a/contrib/libzookeeper/src/zk_hashtable.c b/contrib/libzookeeper/src/zk_hashtable.c new file mode 100644 index 00000000000..0efc5aaf440 --- /dev/null +++ b/contrib/libzookeeper/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 +#include +#include + +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)); + } + } +} diff --git a/contrib/libzookeeper/src/zk_hashtable.h b/contrib/libzookeeper/src/zk_hashtable.h new file mode 100644 index 00000000000..31109c11fbe --- /dev/null +++ b/contrib/libzookeeper/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 + +#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_*/ diff --git a/contrib/libzookeeper/src/zk_log.c b/contrib/libzookeeper/src/zk_log.c new file mode 100644 index 00000000000..37ff856ca0d --- /dev/null +++ b/contrib/libzookeeper/src/zk_log.c @@ -0,0 +1,177 @@ +/** + * 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 "zookeeper_log.h" +#ifndef WIN32 +#include +#endif + +#include +#include + +#define TIME_NOW_BUF_SIZE 1024 +#define FORMAT_LOG_BUF_SIZE 4096 + +#ifdef THREADED +#ifndef WIN32 +#include +#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(levelZOO_LOG_LEVEL_DEBUG)level=ZOO_LOG_LEVEL_DEBUG; + logLevel=level; +} + diff --git a/contrib/libzookeeper/src/zookeeper.c b/contrib/libzookeeper/src/zookeeper.c new file mode 100644 index 00000000000..1ba90afa2fc --- /dev/null +++ b/contrib/libzookeeper/src/zookeeper.c @@ -0,0 +1,3729 @@ +/** + * 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 + +#if defined(__CYGWIN__) +#define USE_IPV6 +#endif + +#include +#include +#include +#include "zk_adaptor.h" +#include "zookeeper_log.h" +#include "zk_hashtable.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef WIN32 +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#endif + +#ifdef HAVE_SYS_UTSNAME_H +#include +#endif + +#ifdef HAVE_GETPWUID_R +#include +#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=")); +#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=")); + LOG_INFO(("Client environment:os.arch=")); + LOG_INFO(("Client environment:os.version=")); +#endif + +#ifdef HAVE_GETLOGIN + LOG_INFO(("Client environment:user.name=%s", getlogin())); +#else + LOG_INFO(("Client environment:user.name=")); +#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=")); + } +#else + LOG_INFO(("Client environment:user.home=")); +#endif + +#ifdef HAVE_GETCWD + if (!getcwd(buf, sizeof(buf))) { + LOG_INFO(("Client environment:user.dir=")); + } else { + LOG_INFO(("Client environment:user.dir=%s", buf)); + } +#else + LOG_INFO(("Client environment:user.dir=")); +#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) ? + "" : ""), + 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 + get_errno(); +#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(logLevelsent_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; + 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 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_critical(zh); + free_duplicate_path(req.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 CreateRequest_init(zhandle_t *zh, struct CreateRequest *req, + const char *path, const char *value, + int valuelen, const struct ACL_vector *acl_entries, int flags) +{ + int rc; + assert(req); + rc = Request_path_init(zh, flags, &req->path, path); + assert(req); + if (rc != ZOK) { + return rc; + } + req->flags = flags; + req->data.buff = (char*)value; + req->data.len = valuelen; + if (acl_entries == 0) { + req->acl.count = 0; + req->acl.data = 0; + } else { + req->acl = *acl_entries; + } + + return ZOK; +} + +int zoo_acreate(zhandle_t *zh, const char *path, const char *value, + int valuelen, const struct ACL_vector *acl_entries, int flags, + string_completion_t completion, const void *data) +{ + struct oarchive *oa; + struct RequestHeader h = { STRUCT_INITIALIZER (xid , get_xid()), STRUCT_INITIALIZER (type ,ZOO_CREATE_OP) }; + struct CreateRequest req; + + int rc = CreateRequest_init(zh, &req, + path, value, valuelen, acl_entries, flags); + if (rc != ZOK) { + return rc; + } + oa = create_buffer_oarchive(); + rc = serialize_RequestHeader(oa, "header", &h); + rc = rc < 0 ? rc : serialize_CreateRequest(oa, "req", &req); + enter_critical(zh); + rc = rc < 0 ? rc : add_string_completion(zh, h.xid, completion, data); + rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa), + get_buffer_len(oa)); + leave_critical(zh); + free_duplicate_path(req.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; +} + +int DeleteRequest_init(zhandle_t *zh, struct DeleteRequest *req, + const char *path, int version) +{ + int rc = Request_path_init(zh, 0, &req->path, path); + if (rc != ZOK) { + return rc; + } + req->version = version; + return ZOK; +} + +int zoo_adelete(zhandle_t *zh, const char *path, int version, + void_completion_t completion, const void *data) +{ + struct oarchive *oa; + struct RequestHeader h = { STRUCT_INITIALIZER (xid , get_xid()), STRUCT_INITIALIZER (type , ZOO_DELETE_OP)}; + struct DeleteRequest req; + int rc = DeleteRequest_init(zh, &req, path, version); + if (rc != ZOK) { + return rc; + } + oa = create_buffer_oarchive(); + rc = serialize_RequestHeader(oa, "header", &h); + rc = rc < 0 ? rc : serialize_DeleteRequest(oa, "req", &req); + enter_critical(zh); + rc = rc < 0 ? rc : add_void_completion(zh, h.xid, completion, data); + rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa), + get_buffer_len(oa)); + leave_critical(zh); + free_duplicate_path(req.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; +} + +int zoo_aexists(zhandle_t *zh, const char *path, int watch, + stat_completion_t sc, const void *data) +{ + return zoo_awexists(zh,path,watch?zh->watcher:0,zh->context,sc,data); +} + +int zoo_awexists(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + stat_completion_t completion, const void *data) +{ + struct oarchive *oa; + struct RequestHeader h = { STRUCT_INITIALIZER (xid ,get_xid()), STRUCT_INITIALIZER (type , ZOO_EXISTS_OP) }; + struct ExistsRequest req; + int rc = Request_path_watch_init(zh, 0, &req.path, path, + &req.watch, watcher != NULL); + if (rc != ZOK) { + return rc; + } + oa = create_buffer_oarchive(); + rc = serialize_RequestHeader(oa, "header", &h); + rc = rc < 0 ? rc : serialize_ExistsRequest(oa, "req", &req); + enter_critical(zh); + rc = rc < 0 ? rc : add_stat_completion(zh, h.xid, completion, data, + create_watcher_registration(req.path,exists_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(req.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 zoo_awget_children_(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + strings_completion_t sc, + const void *data) +{ + struct oarchive *oa; + struct RequestHeader h = { STRUCT_INITIALIZER (xid , get_xid()), STRUCT_INITIALIZER (type , ZOO_GETCHILDREN_OP)}; + struct GetChildrenRequest req ; + int rc = Request_path_watch_init(zh, 0, &req.path, path, + &req.watch, watcher != NULL); + if (rc != ZOK) { + return rc; + } + oa = create_buffer_oarchive(); + rc = serialize_RequestHeader(oa, "header", &h); + rc = rc < 0 ? rc : serialize_GetChildrenRequest(oa, "req", &req); + enter_critical(zh); + rc = rc < 0 ? rc : add_strings_completion(zh, h.xid, sc, data, + create_watcher_registration(req.path,child_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(req.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; +} + +int zoo_aget_children(zhandle_t *zh, const char *path, int watch, + strings_completion_t dc, const void *data) +{ + return zoo_awget_children_(zh,path,watch?zh->watcher:0,zh->context,dc,data); +} + +int zoo_awget_children(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + strings_completion_t dc, + const void *data) +{ + return zoo_awget_children_(zh,path,watcher,watcherCtx,dc,data); +} + +static int zoo_awget_children2_(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + strings_stat_completion_t ssc, + const void *data) +{ + /* invariant: (sc == NULL) != (sc == NULL) */ + struct oarchive *oa; + struct RequestHeader h = { STRUCT_INITIALIZER( xid, get_xid()), STRUCT_INITIALIZER (type ,ZOO_GETCHILDREN2_OP)}; + struct GetChildren2Request req ; + int rc = Request_path_watch_init(zh, 0, &req.path, path, + &req.watch, watcher != NULL); + if (rc != ZOK) { + return rc; + } + oa = create_buffer_oarchive(); + rc = serialize_RequestHeader(oa, "header", &h); + rc = rc < 0 ? rc : serialize_GetChildren2Request(oa, "req", &req); + enter_critical(zh); + rc = rc < 0 ? rc : add_strings_stat_completion(zh, h.xid, ssc, data, + create_watcher_registration(req.path,child_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(req.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; +} + +int zoo_aget_children2(zhandle_t *zh, const char *path, int watch, + strings_stat_completion_t dc, const void *data) +{ + return zoo_awget_children2_(zh,path,watch?zh->watcher:0,zh->context,dc,data); +} + +int zoo_awget_children2(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + strings_stat_completion_t dc, + const void *data) +{ + return zoo_awget_children2_(zh,path,watcher,watcherCtx,dc,data); +} + +int zoo_async(zhandle_t *zh, const char *path, + string_completion_t completion, const void *data) +{ + struct oarchive *oa; + struct RequestHeader h = { STRUCT_INITIALIZER (xid , get_xid()), STRUCT_INITIALIZER (type , ZOO_SYNC_OP)}; + struct SyncRequest req; + int rc = Request_path_init(zh, 0, &req.path, path); + if (rc != ZOK) { + return rc; + } + oa = create_buffer_oarchive(); + rc = serialize_RequestHeader(oa, "header", &h); + rc = rc < 0 ? rc : serialize_SyncRequest(oa, "req", &req); + enter_critical(zh); + rc = rc < 0 ? rc : add_string_completion(zh, h.xid, completion, data); + rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa), + get_buffer_len(oa)); + leave_critical(zh); + free_duplicate_path(req.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; +} + + +int zoo_aget_acl(zhandle_t *zh, const char *path, acl_completion_t completion, + const void *data) +{ + struct oarchive *oa; + struct RequestHeader h = { STRUCT_INITIALIZER (xid , get_xid()), STRUCT_INITIALIZER(type ,ZOO_GETACL_OP)}; + struct GetACLRequest req; + int rc = Request_path_init(zh, 0, &req.path, path) ; + if (rc != ZOK) { + return rc; + } + oa = create_buffer_oarchive(); + rc = serialize_RequestHeader(oa, "header", &h); + rc = rc < 0 ? rc : serialize_GetACLRequest(oa, "req", &req); + enter_critical(zh); + rc = rc < 0 ? rc : add_acl_completion(zh, h.xid, completion, data); + rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa), + get_buffer_len(oa)); + leave_critical(zh); + free_duplicate_path(req.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; +} + +int zoo_aset_acl(zhandle_t *zh, const char *path, int version, + struct ACL_vector *acl, void_completion_t completion, const void *data) +{ + struct oarchive *oa; + struct RequestHeader h = { STRUCT_INITIALIZER(xid ,get_xid()), STRUCT_INITIALIZER (type , ZOO_SETACL_OP)}; + struct SetACLRequest req; + int rc = Request_path_init(zh, 0, &req.path, path); + if (rc != ZOK) { + return rc; + } + oa = create_buffer_oarchive(); + req.acl = *acl; + req.version = version; + rc = serialize_RequestHeader(oa, "header", &h); + rc = rc < 0 ? rc : serialize_SetACLRequest(oa, "req", &req); + enter_critical(zh); + rc = rc < 0 ? rc : add_void_completion(zh, h.xid, completion, data); + rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa), + get_buffer_len(oa)); + leave_critical(zh); + free_duplicate_path(req.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; +} + +/* Completions for multi-op results */ +static void op_result_string_completion(int err, const char *value, const void *data) +{ + struct zoo_op_result *result = (struct zoo_op_result *)data; + assert(result); + result->err = err; + + if (result->value && value) { + int len = strlen(value) + 1; + if (len > result->valuelen) { + len = result->valuelen; + } + if (len > 0) { + memcpy(result->value, value, len - 1); + result->value[len - 1] = '\0'; + } + } else { + result->value = NULL; + } +} + +static void op_result_void_completion(int err, const void *data) +{ + struct zoo_op_result *result = (struct zoo_op_result *)data; + assert(result); + result->err = err; +} + +static void op_result_stat_completion(int err, const struct Stat *stat, const void *data) +{ + struct zoo_op_result *result = (struct zoo_op_result *)data; + assert(result); + result->err = err; + + if (result->stat && err == 0 && stat) { + *result->stat = *stat; + } else { + result->stat = NULL ; + } +} + +static int CheckVersionRequest_init(zhandle_t *zh, struct CheckVersionRequest *req, + const char *path, int version) +{ + int rc ; + assert(req); + rc = Request_path_init(zh, 0, &req->path, path); + if (rc != ZOK) { + return rc; + } + req->version = version; + + return ZOK; +} + +int zoo_amulti(zhandle_t *zh, int count, const zoo_op_t *ops, + zoo_op_result_t *results, void_completion_t completion, const void *data) +{ + struct RequestHeader h = { STRUCT_INITIALIZER(xid, get_xid()), STRUCT_INITIALIZER(type, ZOO_MULTI_OP) }; + struct MultiHeader mh = { STRUCT_INITIALIZER(type, -1), STRUCT_INITIALIZER(done, 1), STRUCT_INITIALIZER(err, -1) }; + struct oarchive *oa = create_buffer_oarchive(); + completion_head_t clist = { 0 }; + + int rc = serialize_RequestHeader(oa, "header", &h); + + int index = 0; + for (index=0; index < count; index++) { + const zoo_op_t *op = ops+index; + zoo_op_result_t *result = results+index; + completion_list_t *entry = NULL; + + struct MultiHeader mh = { STRUCT_INITIALIZER(type, op->type), STRUCT_INITIALIZER(done, 0), STRUCT_INITIALIZER(err, -1) }; + rc = rc < 0 ? rc : serialize_MultiHeader(oa, "multiheader", &mh); + + switch(op->type) { + case ZOO_CREATE_OP: { + struct CreateRequest req; + + rc = rc < 0 ? rc : CreateRequest_init(zh, &req, + op->create_op.path, op->create_op.data, + op->create_op.datalen, op->create_op.acl, + op->create_op.flags); + rc = rc < 0 ? rc : serialize_CreateRequest(oa, "req", &req); + result->value = op->create_op.buf; + result->valuelen = op->create_op.buflen; + + enter_critical(zh); + entry = create_completion_entry(h.xid, COMPLETION_STRING, op_result_string_completion, result, 0, 0); + leave_critical(zh); + free_duplicate_path(req.path, op->create_op.path); + break; + } + + case ZOO_DELETE_OP: { + struct DeleteRequest req; + rc = rc < 0 ? rc : DeleteRequest_init(zh, &req, op->delete_op.path, op->delete_op.version); + rc = rc < 0 ? rc : serialize_DeleteRequest(oa, "req", &req); + + enter_critical(zh); + entry = create_completion_entry(h.xid, COMPLETION_VOID, op_result_void_completion, result, 0, 0); + leave_critical(zh); + free_duplicate_path(req.path, op->delete_op.path); + break; + } + + case ZOO_SETDATA_OP: { + struct SetDataRequest req; + rc = rc < 0 ? rc : SetDataRequest_init(zh, &req, + op->set_op.path, op->set_op.data, + op->set_op.datalen, op->set_op.version); + rc = rc < 0 ? rc : serialize_SetDataRequest(oa, "req", &req); + result->stat = op->set_op.stat; + + enter_critical(zh); + entry = create_completion_entry(h.xid, COMPLETION_STAT, op_result_stat_completion, result, 0, 0); + leave_critical(zh); + free_duplicate_path(req.path, op->set_op.path); + break; + } + + case ZOO_CHECK_OP: { + struct CheckVersionRequest req; + rc = rc < 0 ? rc : CheckVersionRequest_init(zh, &req, + op->check_op.path, op->check_op.version); + rc = rc < 0 ? rc : serialize_CheckVersionRequest(oa, "req", &req); + + enter_critical(zh); + entry = create_completion_entry(h.xid, COMPLETION_VOID, op_result_void_completion, result, 0, 0); + leave_critical(zh); + free_duplicate_path(req.path, op->check_op.path); + break; + } + + default: + LOG_ERROR(("Unimplemented sub-op type=%d in multi-op", op->type)); + return ZUNIMPLEMENTED; + } + + queue_completion(&clist, entry, 0); + } + + rc = rc < 0 ? rc : serialize_MultiHeader(oa, "multiheader", &mh); + + /* BEGIN: CRTICIAL SECTION */ + enter_critical(zh); + rc = rc < 0 ? rc : add_multi_completion(zh, h.xid, completion, data, &clist); + rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa), + get_buffer_len(oa)); + leave_critical(zh); + + /* We queued the buffer, so don't free it */ + close_buffer_oarchive(&oa, 0); + + LOG_DEBUG(("Sending multi request xid=%#x with %d subrequests to %s", + h.xid, index, 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; +} + +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) +{ + assert(op); + op->type = ZOO_CREATE_OP; + op->create_op.path = path; + op->create_op.data = value; + op->create_op.datalen = valuelen; + op->create_op.acl = acl; + op->create_op.flags = flags; + op->create_op.buf = path_buffer; + op->create_op.buflen = path_buffer_len; +} + +void zoo_delete_op_init(zoo_op_t *op, const char *path, int version) +{ + assert(op); + op->type = ZOO_DELETE_OP; + op->delete_op.path = path; + op->delete_op.version = version; +} + +void zoo_set_op_init(zoo_op_t *op, const char *path, const char *buffer, + int buflen, int version, struct Stat *stat) +{ + assert(op); + op->type = ZOO_SETDATA_OP; + op->set_op.path = path; + op->set_op.data = buffer; + op->set_op.datalen = buflen; + op->set_op.version = version; + op->set_op.stat = stat; +} + +void zoo_check_op_init(zoo_op_t *op, const char *path, int version) +{ + assert(op); + op->type = ZOO_CHECK_OP; + op->check_op.path = path; + op->check_op.version = version; +} + +int zoo_multi(zhandle_t *zh, int count, const zoo_op_t *ops, zoo_op_result_t *results) +{ + int rc; + + struct sync_completion *sc = alloc_sync_completion(); + if (!sc) { + return ZSYSTEMERROR; + } + + rc = zoo_amulti(zh, count, ops, results, SYNCHRONOUS_MARKER, sc); + if (rc == ZOK) { + wait_sync_completion(sc); + rc = sc->rc; + } + free_sync_completion(sc); + + return rc; +} + +/* specify timeout of 0 to make the function non-blocking */ +/* timeout is in milliseconds */ +int flush_send_queue(zhandle_t*zh, int timeout) +{ + int rc= ZOK; + struct timeval started; +#ifdef WIN32 + fd_set pollSet; + struct timeval wait; +#endif + gettimeofday(&started,0); + // we can't use dequeue_buffer() here because if (non-blocking) send_buffer() + // returns EWOULDBLOCK we'd have to put the buffer back on the queue. + // we use a recursive lock instead and only dequeue the buffer if a send was + // successful + lock_buffer_list(&zh->to_send); + while (zh->to_send.head != 0&& zh->state == ZOO_CONNECTED_STATE) { + if(timeout!=0){ + int elapsed; + struct timeval now; + gettimeofday(&now,0); + elapsed=calculate_interval(&started,&now); + if (elapsed>timeout) { + rc = ZOPERATIONTIMEOUT; + break; + } + +#ifdef WIN32 + wait = get_timeval(timeout-elapsed); + FD_ZERO(&pollSet); + FD_SET(zh->fd, &pollSet); + // Poll the socket + rc = select((int)(zh->fd)+1, NULL, &pollSet, NULL, &wait); +#else + struct pollfd fds; + fds.fd = zh->fd; + fds.events = POLLOUT; + fds.revents = 0; + rc = poll(&fds, 1, timeout-elapsed); +#endif + if (rc<=0) { + /* timed out or an error or POLLERR */ + rc = rc==0 ? ZOPERATIONTIMEOUT : ZSYSTEMERROR; + break; + } + } + + rc = send_buffer(zh->fd, zh->to_send.head); + if(rc==0 && timeout==0){ + /* send_buffer would block while sending this buffer */ + rc = ZOK; + break; + } + if (rc < 0) { + rc = ZCONNECTIONLOSS; + break; + } + // if the buffer has been sent successfully, remove it from the queue + if (rc > 0) + remove_buffer(&zh->to_send); + gettimeofday(&zh->last_send, 0); + rc = ZOK; + } + unlock_buffer_list(&zh->to_send); + return rc; +} + +const char* zerror(int c) +{ + switch (c){ + case ZOK: + return "ok"; + case ZSYSTEMERROR: + return "system error"; + case ZRUNTIMEINCONSISTENCY: + return "run time inconsistency"; + case ZDATAINCONSISTENCY: + return "data inconsistency"; + case ZCONNECTIONLOSS: + return "connection loss"; + case ZMARSHALLINGERROR: + return "marshalling error"; + case ZUNIMPLEMENTED: + return "unimplemented"; + case ZOPERATIONTIMEOUT: + return "operation timeout"; + case ZBADARGUMENTS: + return "bad arguments"; + case ZINVALIDSTATE: + return "invalid zhandle state"; + case ZAPIERROR: + return "api error"; + case ZNONODE: + return "no node"; + case ZNOAUTH: + return "not authenticated"; + case ZBADVERSION: + return "bad version"; + case ZNOCHILDRENFOREPHEMERALS: + return "no children for ephemerals"; + case ZNODEEXISTS: + return "node exists"; + case ZNOTEMPTY: + return "not empty"; + case ZSESSIONEXPIRED: + return "session expired"; + case ZINVALIDCALLBACK: + return "invalid callback"; + case ZINVALIDACL: + return "invalid acl"; + case ZAUTHFAILED: + return "authentication failed"; + case ZCLOSING: + return "zookeeper is closing"; + case ZNOTHING: + return "(not error) no server responses to process"; + case ZSESSIONMOVED: + return "session moved to another server, so operation is ignored"; + } + if (c > 0) { + return strerror(c); + } + return "unknown error"; +} + +int zoo_add_auth(zhandle_t *zh,const char* scheme,const char* cert, + int certLen,void_completion_t completion, const void *data) +{ + struct buffer auth; + auth_info *authinfo; + if(scheme==NULL || zh==NULL) + return ZBADARGUMENTS; + + if (is_unrecoverable(zh)) + return ZINVALIDSTATE; + + // [ZOOKEEPER-800] zoo_add_auth should return ZINVALIDSTATE if + // the connection is closed. + if (zoo_state(zh) == 0) { + return ZINVALIDSTATE; + } + + if(cert!=NULL && certLen!=0){ + auth.buff=calloc(1,certLen); + if(auth.buff==0) { + return ZSYSTEMERROR; + } + memcpy(auth.buff,cert,certLen); + auth.len=certLen; + } else { + auth.buff = 0; + auth.len = 0; + } + + zoo_lock_auth(zh); + authinfo = (auth_info*) malloc(sizeof(auth_info)); + authinfo->scheme=strdup(scheme); + authinfo->auth=auth; + authinfo->completion=completion; + authinfo->data=data; + authinfo->next = NULL; + add_last_auth(&zh->auth_h, authinfo); + zoo_unlock_auth(zh); + + if(zh->state == ZOO_CONNECTED_STATE || zh->state == ZOO_ASSOCIATING_STATE) + return send_last_auth_info(zh); + + return ZOK; +} + +static const char* format_endpoint_info(const struct sockaddr_storage* ep) +{ + static char buf[128]; + char addrstr[128]; + void *inaddr; +#ifdef WIN32 + char * addrstring; +#endif + int port; + if(ep==0) + return "null"; + +#if defined(AF_INET6) + if(ep->ss_family==AF_INET6){ + inaddr=&((struct sockaddr_in6*)ep)->sin6_addr; + port=((struct sockaddr_in6*)ep)->sin6_port; + } else { +#endif + inaddr=&((struct sockaddr_in*)ep)->sin_addr; + port=((struct sockaddr_in*)ep)->sin_port; +#if defined(AF_INET6) + } +#endif +#ifdef WIN32 + addrstring = inet_ntoa (*(struct in_addr*)inaddr); + sprintf(buf,"%s:%d",addrstring,ntohs(port)); +#else + inet_ntop(ep->ss_family,inaddr,addrstr,sizeof(addrstr)-1); + sprintf(buf,"%s:%d",addrstr,ntohs(port)); +#endif + return buf; +} + +static const char* format_current_endpoint_info(zhandle_t* zh) +{ + return format_endpoint_info(&zh->addrs[zh->connect_index]); +} + +void zoo_deterministic_conn_order(int yesOrNo) +{ + disable_conn_permute=yesOrNo; +} + +/*---------------------------------------------------------------------------* + * SYNC API + *---------------------------------------------------------------------------*/ +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) +{ + struct sync_completion *sc = alloc_sync_completion(); + int rc; + if (!sc) { + return ZSYSTEMERROR; + } + sc->u.str.str = path_buffer; + sc->u.str.str_len = path_buffer_len; + rc=zoo_acreate(zh, path, value, valuelen, acl, flags, SYNCHRONOUS_MARKER, sc); + if(rc==ZOK){ + wait_sync_completion(sc); + rc = sc->rc; + } + free_sync_completion(sc); + return rc; +} + +int zoo_delete(zhandle_t *zh, const char *path, int version) +{ + struct sync_completion *sc = alloc_sync_completion(); + int rc; + if (!sc) { + return ZSYSTEMERROR; + } + rc=zoo_adelete(zh, path, version, SYNCHRONOUS_MARKER, sc); + if(rc==ZOK){ + wait_sync_completion(sc); + rc = sc->rc; + } + free_sync_completion(sc); + return rc; +} + +int zoo_exists(zhandle_t *zh, const char *path, int watch, struct Stat *stat) +{ + return zoo_wexists(zh,path,watch?zh->watcher:0,zh->context,stat); +} + +int zoo_wexists(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, struct Stat *stat) +{ + struct sync_completion *sc = alloc_sync_completion(); + int rc; + if (!sc) { + return ZSYSTEMERROR; + } + rc=zoo_awexists(zh,path,watcher,watcherCtx,SYNCHRONOUS_MARKER, sc); + if(rc==ZOK){ + wait_sync_completion(sc); + rc = sc->rc; + if (rc == 0&& stat) { + *stat = sc->u.stat; + } + } + free_sync_completion(sc); + return rc; +} + +int zoo_get(zhandle_t *zh, const char *path, int watch, char *buffer, + int* buffer_len, struct Stat *stat) +{ + return zoo_wget(zh,path,watch?zh->watcher:0,zh->context, + buffer,buffer_len,stat); +} + +int zoo_wget(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + char *buffer, int* buffer_len, struct Stat *stat) +{ + struct sync_completion *sc; + int rc=0; + + if(buffer_len==NULL) + return ZBADARGUMENTS; + if((sc=alloc_sync_completion())==NULL) + return ZSYSTEMERROR; + + sc->u.data.buffer = buffer; + sc->u.data.buff_len = *buffer_len; + rc=zoo_awget(zh, path, watcher, watcherCtx, SYNCHRONOUS_MARKER, sc); + if(rc==ZOK){ + wait_sync_completion(sc); + rc = sc->rc; + if (rc == 0) { + if(stat) + *stat = sc->u.data.stat; + *buffer_len = sc->u.data.buff_len; + } + } + free_sync_completion(sc); + return rc; +} + +int zoo_set(zhandle_t *zh, const char *path, const char *buffer, int buflen, + int version) +{ + return zoo_set2(zh, path, buffer, buflen, version, 0); +} + +int zoo_set2(zhandle_t *zh, const char *path, const char *buffer, int buflen, + int version, struct Stat *stat) +{ + struct sync_completion *sc = alloc_sync_completion(); + int rc; + if (!sc) { + return ZSYSTEMERROR; + } + rc=zoo_aset(zh, path, buffer, buflen, version, SYNCHRONOUS_MARKER, sc); + if(rc==ZOK){ + wait_sync_completion(sc); + rc = sc->rc; + if (rc == 0 && stat) { + *stat = sc->u.stat; + } + } + free_sync_completion(sc); + return rc; +} + +static int zoo_wget_children_(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + struct String_vector *strings) +{ + struct sync_completion *sc = alloc_sync_completion(); + int rc; + if (!sc) { + return ZSYSTEMERROR; + } + rc= zoo_awget_children (zh, path, watcher, watcherCtx, SYNCHRONOUS_MARKER, sc); + if(rc==ZOK){ + wait_sync_completion(sc); + rc = sc->rc; + if (rc == 0) { + if (strings) { + *strings = sc->u.strs2; + } else { + deallocate_String_vector(&sc->u.strs2); + } + } + } + free_sync_completion(sc); + return rc; +} + +static int zoo_wget_children2_(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + struct String_vector *strings, struct Stat *stat) +{ + struct sync_completion *sc = alloc_sync_completion(); + int rc; + if (!sc) { + return ZSYSTEMERROR; + } + rc= zoo_awget_children2(zh, path, watcher, watcherCtx, SYNCHRONOUS_MARKER, sc); + + if(rc==ZOK){ + wait_sync_completion(sc); + rc = sc->rc; + if (rc == 0) { + *stat = sc->u.strs_stat.stat2; + if (strings) { + *strings = sc->u.strs_stat.strs2; + } else { + deallocate_String_vector(&sc->u.strs_stat.strs2); + } + } + } + free_sync_completion(sc); + return rc; +} + +int zoo_get_children(zhandle_t *zh, const char *path, int watch, + struct String_vector *strings) +{ + return zoo_wget_children_(zh,path,watch?zh->watcher:0,zh->context,strings); +} + +int zoo_wget_children(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + struct String_vector *strings) +{ + return zoo_wget_children_(zh,path,watcher,watcherCtx,strings); +} + +int zoo_get_children2(zhandle_t *zh, const char *path, int watch, + struct String_vector *strings, struct Stat *stat) +{ + return zoo_wget_children2_(zh,path,watch?zh->watcher:0,zh->context,strings,stat); +} + +int zoo_wget_children2(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + struct String_vector *strings, struct Stat *stat) +{ + return zoo_wget_children2_(zh,path,watcher,watcherCtx,strings,stat); +} + +int zoo_get_acl(zhandle_t *zh, const char *path, struct ACL_vector *acl, + struct Stat *stat) +{ + struct sync_completion *sc = alloc_sync_completion(); + int rc; + if (!sc) { + return ZSYSTEMERROR; + } + rc=zoo_aget_acl(zh, path, SYNCHRONOUS_MARKER, sc); + if(rc==ZOK){ + wait_sync_completion(sc); + rc = sc->rc; + if (rc == 0&& stat) { + *stat = sc->u.acl.stat; + } + if (rc == 0) { + if (acl) { + *acl = sc->u.acl.acl; + } else { + deallocate_ACL_vector(&sc->u.acl.acl); + } + } + } + free_sync_completion(sc); + return rc; +} + +int zoo_set_acl(zhandle_t *zh, const char *path, int version, + const struct ACL_vector *acl) +{ + struct sync_completion *sc = alloc_sync_completion(); + int rc; + if (!sc) { + return ZSYSTEMERROR; + } + rc=zoo_aset_acl(zh, path, version, (struct ACL_vector*)acl, + SYNCHRONOUS_MARKER, sc); + if(rc==ZOK){ + wait_sync_completion(sc); + rc = sc->rc; + } + free_sync_completion(sc); + return rc; +} diff --git a/contrib/libzookeeper/src/zookeeper.jute.c b/contrib/libzookeeper/src/zookeeper.jute.c new file mode 100644 index 00000000000..5823c2f0123 --- /dev/null +++ b/contrib/libzookeeper/src/zookeeper.jute.c @@ -0,0 +1,1315 @@ +/** +* 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 +#include "zookeeper.jute.h" + +int serialize_Id(struct oarchive *out, const char *tag, struct Id *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "scheme", &v->scheme); + rc = rc ? rc : out->serialize_String(out, "id", &v->id); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_Id(struct iarchive *in, const char *tag, struct Id*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "scheme", &v->scheme); + rc = rc ? rc : in->deserialize_String(in, "id", &v->id); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_Id(struct Id*v){ + deallocate_String(&v->scheme); + deallocate_String(&v->id); +} +int serialize_ACL(struct oarchive *out, const char *tag, struct ACL *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "perms", &v->perms); + rc = rc ? rc : serialize_Id(out, "id", &v->id); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_ACL(struct iarchive *in, const char *tag, struct ACL*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "perms", &v->perms); + rc = rc ? rc : deserialize_Id(in, "id", &v->id); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_ACL(struct ACL*v){ + deallocate_Id(&v->id); +} +int serialize_Stat(struct oarchive *out, const char *tag, struct Stat *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Long(out, "czxid", &v->czxid); + rc = rc ? rc : out->serialize_Long(out, "mzxid", &v->mzxid); + rc = rc ? rc : out->serialize_Long(out, "ctime", &v->ctime); + rc = rc ? rc : out->serialize_Long(out, "mtime", &v->mtime); + rc = rc ? rc : out->serialize_Int(out, "version", &v->version); + rc = rc ? rc : out->serialize_Int(out, "cversion", &v->cversion); + rc = rc ? rc : out->serialize_Int(out, "aversion", &v->aversion); + rc = rc ? rc : out->serialize_Long(out, "ephemeralOwner", &v->ephemeralOwner); + rc = rc ? rc : out->serialize_Int(out, "dataLength", &v->dataLength); + rc = rc ? rc : out->serialize_Int(out, "numChildren", &v->numChildren); + rc = rc ? rc : out->serialize_Long(out, "pzxid", &v->pzxid); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_Stat(struct iarchive *in, const char *tag, struct Stat*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Long(in, "czxid", &v->czxid); + rc = rc ? rc : in->deserialize_Long(in, "mzxid", &v->mzxid); + rc = rc ? rc : in->deserialize_Long(in, "ctime", &v->ctime); + rc = rc ? rc : in->deserialize_Long(in, "mtime", &v->mtime); + rc = rc ? rc : in->deserialize_Int(in, "version", &v->version); + rc = rc ? rc : in->deserialize_Int(in, "cversion", &v->cversion); + rc = rc ? rc : in->deserialize_Int(in, "aversion", &v->aversion); + rc = rc ? rc : in->deserialize_Long(in, "ephemeralOwner", &v->ephemeralOwner); + rc = rc ? rc : in->deserialize_Int(in, "dataLength", &v->dataLength); + rc = rc ? rc : in->deserialize_Int(in, "numChildren", &v->numChildren); + rc = rc ? rc : in->deserialize_Long(in, "pzxid", &v->pzxid); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_Stat(struct Stat*v){ +} +int serialize_StatPersisted(struct oarchive *out, const char *tag, struct StatPersisted *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Long(out, "czxid", &v->czxid); + rc = rc ? rc : out->serialize_Long(out, "mzxid", &v->mzxid); + rc = rc ? rc : out->serialize_Long(out, "ctime", &v->ctime); + rc = rc ? rc : out->serialize_Long(out, "mtime", &v->mtime); + rc = rc ? rc : out->serialize_Int(out, "version", &v->version); + rc = rc ? rc : out->serialize_Int(out, "cversion", &v->cversion); + rc = rc ? rc : out->serialize_Int(out, "aversion", &v->aversion); + rc = rc ? rc : out->serialize_Long(out, "ephemeralOwner", &v->ephemeralOwner); + rc = rc ? rc : out->serialize_Long(out, "pzxid", &v->pzxid); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_StatPersisted(struct iarchive *in, const char *tag, struct StatPersisted*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Long(in, "czxid", &v->czxid); + rc = rc ? rc : in->deserialize_Long(in, "mzxid", &v->mzxid); + rc = rc ? rc : in->deserialize_Long(in, "ctime", &v->ctime); + rc = rc ? rc : in->deserialize_Long(in, "mtime", &v->mtime); + rc = rc ? rc : in->deserialize_Int(in, "version", &v->version); + rc = rc ? rc : in->deserialize_Int(in, "cversion", &v->cversion); + rc = rc ? rc : in->deserialize_Int(in, "aversion", &v->aversion); + rc = rc ? rc : in->deserialize_Long(in, "ephemeralOwner", &v->ephemeralOwner); + rc = rc ? rc : in->deserialize_Long(in, "pzxid", &v->pzxid); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_StatPersisted(struct StatPersisted*v){ +} +int serialize_StatPersistedV1(struct oarchive *out, const char *tag, struct StatPersistedV1 *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Long(out, "czxid", &v->czxid); + rc = rc ? rc : out->serialize_Long(out, "mzxid", &v->mzxid); + rc = rc ? rc : out->serialize_Long(out, "ctime", &v->ctime); + rc = rc ? rc : out->serialize_Long(out, "mtime", &v->mtime); + rc = rc ? rc : out->serialize_Int(out, "version", &v->version); + rc = rc ? rc : out->serialize_Int(out, "cversion", &v->cversion); + rc = rc ? rc : out->serialize_Int(out, "aversion", &v->aversion); + rc = rc ? rc : out->serialize_Long(out, "ephemeralOwner", &v->ephemeralOwner); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_StatPersistedV1(struct iarchive *in, const char *tag, struct StatPersistedV1*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Long(in, "czxid", &v->czxid); + rc = rc ? rc : in->deserialize_Long(in, "mzxid", &v->mzxid); + rc = rc ? rc : in->deserialize_Long(in, "ctime", &v->ctime); + rc = rc ? rc : in->deserialize_Long(in, "mtime", &v->mtime); + rc = rc ? rc : in->deserialize_Int(in, "version", &v->version); + rc = rc ? rc : in->deserialize_Int(in, "cversion", &v->cversion); + rc = rc ? rc : in->deserialize_Int(in, "aversion", &v->aversion); + rc = rc ? rc : in->deserialize_Long(in, "ephemeralOwner", &v->ephemeralOwner); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_StatPersistedV1(struct StatPersistedV1*v){ +} +int serialize_ConnectRequest(struct oarchive *out, const char *tag, struct ConnectRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "protocolVersion", &v->protocolVersion); + rc = rc ? rc : out->serialize_Long(out, "lastZxidSeen", &v->lastZxidSeen); + rc = rc ? rc : out->serialize_Int(out, "timeOut", &v->timeOut); + rc = rc ? rc : out->serialize_Long(out, "sessionId", &v->sessionId); + rc = rc ? rc : out->serialize_Buffer(out, "passwd", &v->passwd); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_ConnectRequest(struct iarchive *in, const char *tag, struct ConnectRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "protocolVersion", &v->protocolVersion); + rc = rc ? rc : in->deserialize_Long(in, "lastZxidSeen", &v->lastZxidSeen); + rc = rc ? rc : in->deserialize_Int(in, "timeOut", &v->timeOut); + rc = rc ? rc : in->deserialize_Long(in, "sessionId", &v->sessionId); + rc = rc ? rc : in->deserialize_Buffer(in, "passwd", &v->passwd); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_ConnectRequest(struct ConnectRequest*v){ + deallocate_Buffer(&v->passwd); +} +int serialize_ConnectResponse(struct oarchive *out, const char *tag, struct ConnectResponse *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "protocolVersion", &v->protocolVersion); + rc = rc ? rc : out->serialize_Int(out, "timeOut", &v->timeOut); + rc = rc ? rc : out->serialize_Long(out, "sessionId", &v->sessionId); + rc = rc ? rc : out->serialize_Buffer(out, "passwd", &v->passwd); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_ConnectResponse(struct iarchive *in, const char *tag, struct ConnectResponse*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "protocolVersion", &v->protocolVersion); + rc = rc ? rc : in->deserialize_Int(in, "timeOut", &v->timeOut); + rc = rc ? rc : in->deserialize_Long(in, "sessionId", &v->sessionId); + rc = rc ? rc : in->deserialize_Buffer(in, "passwd", &v->passwd); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_ConnectResponse(struct ConnectResponse*v){ + deallocate_Buffer(&v->passwd); +} +int allocate_String_vector(struct String_vector *v, int32_t len) { + if (!len) { + v->count = 0; + v->data = 0; + } else { + v->count = len; + v->data = calloc(sizeof(*v->data), len); + } + return 0; +} +int deallocate_String_vector(struct String_vector *v) { + if (v->data) { + int32_t i; + for(i=0;icount; i++) { + deallocate_String(&v->data[i]); + } + free(v->data); + v->data = 0; + } + return 0; +} +int serialize_String_vector(struct oarchive *out, const char *tag, struct String_vector *v) +{ + int32_t count = v->count; + int rc = 0; + int32_t i; + rc = out->start_vector(out, tag, &count); + for(i=0;icount;i++) { + rc = rc ? rc : out->serialize_String(out, "data", &v->data[i]); + } + rc = rc ? rc : out->end_vector(out, tag); + return rc; +} +int deserialize_String_vector(struct iarchive *in, const char *tag, struct String_vector *v) +{ + int rc = 0; + int32_t i; + rc = in->start_vector(in, tag, &v->count); + v->data = calloc(v->count, sizeof(*v->data)); + for(i=0;icount;i++) { + rc = rc ? rc : in->deserialize_String(in, "value", &v->data[i]); + } + rc = in->end_vector(in, tag); + return rc; +} +int serialize_SetWatches(struct oarchive *out, const char *tag, struct SetWatches *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Long(out, "relativeZxid", &v->relativeZxid); + rc = rc ? rc : serialize_String_vector(out, "dataWatches", &v->dataWatches); + rc = rc ? rc : serialize_String_vector(out, "existWatches", &v->existWatches); + rc = rc ? rc : serialize_String_vector(out, "childWatches", &v->childWatches); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_SetWatches(struct iarchive *in, const char *tag, struct SetWatches*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Long(in, "relativeZxid", &v->relativeZxid); + rc = rc ? rc : deserialize_String_vector(in, "dataWatches", &v->dataWatches); + rc = rc ? rc : deserialize_String_vector(in, "existWatches", &v->existWatches); + rc = rc ? rc : deserialize_String_vector(in, "childWatches", &v->childWatches); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_SetWatches(struct SetWatches*v){ + deallocate_String_vector(&v->dataWatches); + deallocate_String_vector(&v->existWatches); + deallocate_String_vector(&v->childWatches); +} +int serialize_RequestHeader(struct oarchive *out, const char *tag, struct RequestHeader *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "xid", &v->xid); + rc = rc ? rc : out->serialize_Int(out, "type", &v->type); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_RequestHeader(struct iarchive *in, const char *tag, struct RequestHeader*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "xid", &v->xid); + rc = rc ? rc : in->deserialize_Int(in, "type", &v->type); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_RequestHeader(struct RequestHeader*v){ +} +int serialize_MultiHeader(struct oarchive *out, const char *tag, struct MultiHeader *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "type", &v->type); + rc = rc ? rc : out->serialize_Bool(out, "done", &v->done); + rc = rc ? rc : out->serialize_Int(out, "err", &v->err); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_MultiHeader(struct iarchive *in, const char *tag, struct MultiHeader*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "type", &v->type); + rc = rc ? rc : in->deserialize_Bool(in, "done", &v->done); + rc = rc ? rc : in->deserialize_Int(in, "err", &v->err); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_MultiHeader(struct MultiHeader*v){ +} +int serialize_AuthPacket(struct oarchive *out, const char *tag, struct AuthPacket *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "type", &v->type); + rc = rc ? rc : out->serialize_String(out, "scheme", &v->scheme); + rc = rc ? rc : out->serialize_Buffer(out, "auth", &v->auth); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_AuthPacket(struct iarchive *in, const char *tag, struct AuthPacket*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "type", &v->type); + rc = rc ? rc : in->deserialize_String(in, "scheme", &v->scheme); + rc = rc ? rc : in->deserialize_Buffer(in, "auth", &v->auth); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_AuthPacket(struct AuthPacket*v){ + deallocate_String(&v->scheme); + deallocate_Buffer(&v->auth); +} +int serialize_ReplyHeader(struct oarchive *out, const char *tag, struct ReplyHeader *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "xid", &v->xid); + rc = rc ? rc : out->serialize_Long(out, "zxid", &v->zxid); + rc = rc ? rc : out->serialize_Int(out, "err", &v->err); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_ReplyHeader(struct iarchive *in, const char *tag, struct ReplyHeader*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "xid", &v->xid); + rc = rc ? rc : in->deserialize_Long(in, "zxid", &v->zxid); + rc = rc ? rc : in->deserialize_Int(in, "err", &v->err); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_ReplyHeader(struct ReplyHeader*v){ +} +int serialize_GetDataRequest(struct oarchive *out, const char *tag, struct GetDataRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->serialize_Bool(out, "watch", &v->watch); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_GetDataRequest(struct iarchive *in, const char *tag, struct GetDataRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->deserialize_Bool(in, "watch", &v->watch); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_GetDataRequest(struct GetDataRequest*v){ + deallocate_String(&v->path); +} +int serialize_SetDataRequest(struct oarchive *out, const char *tag, struct SetDataRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->serialize_Buffer(out, "data", &v->data); + rc = rc ? rc : out->serialize_Int(out, "version", &v->version); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_SetDataRequest(struct iarchive *in, const char *tag, struct SetDataRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->deserialize_Buffer(in, "data", &v->data); + rc = rc ? rc : in->deserialize_Int(in, "version", &v->version); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_SetDataRequest(struct SetDataRequest*v){ + deallocate_String(&v->path); + deallocate_Buffer(&v->data); +} +int serialize_SetDataResponse(struct oarchive *out, const char *tag, struct SetDataResponse *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : serialize_Stat(out, "stat", &v->stat); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_SetDataResponse(struct iarchive *in, const char *tag, struct SetDataResponse*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : deserialize_Stat(in, "stat", &v->stat); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_SetDataResponse(struct SetDataResponse*v){ + deallocate_Stat(&v->stat); +} +int serialize_GetSASLRequest(struct oarchive *out, const char *tag, struct GetSASLRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Buffer(out, "token", &v->token); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_GetSASLRequest(struct iarchive *in, const char *tag, struct GetSASLRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Buffer(in, "token", &v->token); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_GetSASLRequest(struct GetSASLRequest*v){ + deallocate_Buffer(&v->token); +} +int serialize_SetSASLRequest(struct oarchive *out, const char *tag, struct SetSASLRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Buffer(out, "token", &v->token); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_SetSASLRequest(struct iarchive *in, const char *tag, struct SetSASLRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Buffer(in, "token", &v->token); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_SetSASLRequest(struct SetSASLRequest*v){ + deallocate_Buffer(&v->token); +} +int serialize_SetSASLResponse(struct oarchive *out, const char *tag, struct SetSASLResponse *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Buffer(out, "token", &v->token); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_SetSASLResponse(struct iarchive *in, const char *tag, struct SetSASLResponse*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Buffer(in, "token", &v->token); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_SetSASLResponse(struct SetSASLResponse*v){ + deallocate_Buffer(&v->token); +} +int allocate_ACL_vector(struct ACL_vector *v, int32_t len) { + if (!len) { + v->count = 0; + v->data = 0; + } else { + v->count = len; + v->data = calloc(sizeof(*v->data), len); + } + return 0; +} +int deallocate_ACL_vector(struct ACL_vector *v) { + if (v->data) { + int32_t i; + for(i=0;icount; i++) { + deallocate_ACL(&v->data[i]); + } + free(v->data); + v->data = 0; + } + return 0; +} +int serialize_ACL_vector(struct oarchive *out, const char *tag, struct ACL_vector *v) +{ + int32_t count = v->count; + int rc = 0; + int32_t i; + rc = out->start_vector(out, tag, &count); + for(i=0;icount;i++) { + rc = rc ? rc : serialize_ACL(out, "data", &v->data[i]); + } + rc = rc ? rc : out->end_vector(out, tag); + return rc; +} +int deserialize_ACL_vector(struct iarchive *in, const char *tag, struct ACL_vector *v) +{ + int rc = 0; + int32_t i; + rc = in->start_vector(in, tag, &v->count); + v->data = calloc(v->count, sizeof(*v->data)); + for(i=0;icount;i++) { + rc = rc ? rc : deserialize_ACL(in, "value", &v->data[i]); + } + rc = in->end_vector(in, tag); + return rc; +} +int serialize_CreateRequest(struct oarchive *out, const char *tag, struct CreateRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->serialize_Buffer(out, "data", &v->data); + rc = rc ? rc : serialize_ACL_vector(out, "acl", &v->acl); + rc = rc ? rc : out->serialize_Int(out, "flags", &v->flags); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_CreateRequest(struct iarchive *in, const char *tag, struct CreateRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->deserialize_Buffer(in, "data", &v->data); + rc = rc ? rc : deserialize_ACL_vector(in, "acl", &v->acl); + rc = rc ? rc : in->deserialize_Int(in, "flags", &v->flags); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_CreateRequest(struct CreateRequest*v){ + deallocate_String(&v->path); + deallocate_Buffer(&v->data); + deallocate_ACL_vector(&v->acl); +} +int serialize_DeleteRequest(struct oarchive *out, const char *tag, struct DeleteRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->serialize_Int(out, "version", &v->version); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_DeleteRequest(struct iarchive *in, const char *tag, struct DeleteRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->deserialize_Int(in, "version", &v->version); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_DeleteRequest(struct DeleteRequest*v){ + deallocate_String(&v->path); +} +int serialize_GetChildrenRequest(struct oarchive *out, const char *tag, struct GetChildrenRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->serialize_Bool(out, "watch", &v->watch); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_GetChildrenRequest(struct iarchive *in, const char *tag, struct GetChildrenRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->deserialize_Bool(in, "watch", &v->watch); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_GetChildrenRequest(struct GetChildrenRequest*v){ + deallocate_String(&v->path); +} +int serialize_GetChildren2Request(struct oarchive *out, const char *tag, struct GetChildren2Request *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->serialize_Bool(out, "watch", &v->watch); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_GetChildren2Request(struct iarchive *in, const char *tag, struct GetChildren2Request*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->deserialize_Bool(in, "watch", &v->watch); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_GetChildren2Request(struct GetChildren2Request*v){ + deallocate_String(&v->path); +} +int serialize_CheckVersionRequest(struct oarchive *out, const char *tag, struct CheckVersionRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->serialize_Int(out, "version", &v->version); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_CheckVersionRequest(struct iarchive *in, const char *tag, struct CheckVersionRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->deserialize_Int(in, "version", &v->version); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_CheckVersionRequest(struct CheckVersionRequest*v){ + deallocate_String(&v->path); +} +int serialize_GetMaxChildrenRequest(struct oarchive *out, const char *tag, struct GetMaxChildrenRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_GetMaxChildrenRequest(struct iarchive *in, const char *tag, struct GetMaxChildrenRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_GetMaxChildrenRequest(struct GetMaxChildrenRequest*v){ + deallocate_String(&v->path); +} +int serialize_GetMaxChildrenResponse(struct oarchive *out, const char *tag, struct GetMaxChildrenResponse *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "max", &v->max); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_GetMaxChildrenResponse(struct iarchive *in, const char *tag, struct GetMaxChildrenResponse*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "max", &v->max); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_GetMaxChildrenResponse(struct GetMaxChildrenResponse*v){ +} +int serialize_SetMaxChildrenRequest(struct oarchive *out, const char *tag, struct SetMaxChildrenRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->serialize_Int(out, "max", &v->max); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_SetMaxChildrenRequest(struct iarchive *in, const char *tag, struct SetMaxChildrenRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->deserialize_Int(in, "max", &v->max); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_SetMaxChildrenRequest(struct SetMaxChildrenRequest*v){ + deallocate_String(&v->path); +} +int serialize_SyncRequest(struct oarchive *out, const char *tag, struct SyncRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_SyncRequest(struct iarchive *in, const char *tag, struct SyncRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_SyncRequest(struct SyncRequest*v){ + deallocate_String(&v->path); +} +int serialize_SyncResponse(struct oarchive *out, const char *tag, struct SyncResponse *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_SyncResponse(struct iarchive *in, const char *tag, struct SyncResponse*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_SyncResponse(struct SyncResponse*v){ + deallocate_String(&v->path); +} +int serialize_GetACLRequest(struct oarchive *out, const char *tag, struct GetACLRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_GetACLRequest(struct iarchive *in, const char *tag, struct GetACLRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_GetACLRequest(struct GetACLRequest*v){ + deallocate_String(&v->path); +} +int serialize_SetACLRequest(struct oarchive *out, const char *tag, struct SetACLRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : serialize_ACL_vector(out, "acl", &v->acl); + rc = rc ? rc : out->serialize_Int(out, "version", &v->version); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_SetACLRequest(struct iarchive *in, const char *tag, struct SetACLRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : deserialize_ACL_vector(in, "acl", &v->acl); + rc = rc ? rc : in->deserialize_Int(in, "version", &v->version); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_SetACLRequest(struct SetACLRequest*v){ + deallocate_String(&v->path); + deallocate_ACL_vector(&v->acl); +} +int serialize_SetACLResponse(struct oarchive *out, const char *tag, struct SetACLResponse *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : serialize_Stat(out, "stat", &v->stat); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_SetACLResponse(struct iarchive *in, const char *tag, struct SetACLResponse*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : deserialize_Stat(in, "stat", &v->stat); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_SetACLResponse(struct SetACLResponse*v){ + deallocate_Stat(&v->stat); +} +int serialize_WatcherEvent(struct oarchive *out, const char *tag, struct WatcherEvent *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "type", &v->type); + rc = rc ? rc : out->serialize_Int(out, "state", &v->state); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_WatcherEvent(struct iarchive *in, const char *tag, struct WatcherEvent*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "type", &v->type); + rc = rc ? rc : in->deserialize_Int(in, "state", &v->state); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_WatcherEvent(struct WatcherEvent*v){ + deallocate_String(&v->path); +} +int serialize_ErrorResponse(struct oarchive *out, const char *tag, struct ErrorResponse *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "err", &v->err); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_ErrorResponse(struct iarchive *in, const char *tag, struct ErrorResponse*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "err", &v->err); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_ErrorResponse(struct ErrorResponse*v){ +} +int serialize_CreateResponse(struct oarchive *out, const char *tag, struct CreateResponse *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_CreateResponse(struct iarchive *in, const char *tag, struct CreateResponse*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_CreateResponse(struct CreateResponse*v){ + deallocate_String(&v->path); +} +int serialize_ExistsRequest(struct oarchive *out, const char *tag, struct ExistsRequest *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->serialize_Bool(out, "watch", &v->watch); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_ExistsRequest(struct iarchive *in, const char *tag, struct ExistsRequest*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->deserialize_Bool(in, "watch", &v->watch); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_ExistsRequest(struct ExistsRequest*v){ + deallocate_String(&v->path); +} +int serialize_ExistsResponse(struct oarchive *out, const char *tag, struct ExistsResponse *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : serialize_Stat(out, "stat", &v->stat); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_ExistsResponse(struct iarchive *in, const char *tag, struct ExistsResponse*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : deserialize_Stat(in, "stat", &v->stat); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_ExistsResponse(struct ExistsResponse*v){ + deallocate_Stat(&v->stat); +} +int serialize_GetDataResponse(struct oarchive *out, const char *tag, struct GetDataResponse *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Buffer(out, "data", &v->data); + rc = rc ? rc : serialize_Stat(out, "stat", &v->stat); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_GetDataResponse(struct iarchive *in, const char *tag, struct GetDataResponse*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Buffer(in, "data", &v->data); + rc = rc ? rc : deserialize_Stat(in, "stat", &v->stat); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_GetDataResponse(struct GetDataResponse*v){ + deallocate_Buffer(&v->data); + deallocate_Stat(&v->stat); +} +int serialize_GetChildrenResponse(struct oarchive *out, const char *tag, struct GetChildrenResponse *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : serialize_String_vector(out, "children", &v->children); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_GetChildrenResponse(struct iarchive *in, const char *tag, struct GetChildrenResponse*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : deserialize_String_vector(in, "children", &v->children); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_GetChildrenResponse(struct GetChildrenResponse*v){ + deallocate_String_vector(&v->children); +} +int serialize_GetChildren2Response(struct oarchive *out, const char *tag, struct GetChildren2Response *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : serialize_String_vector(out, "children", &v->children); + rc = rc ? rc : serialize_Stat(out, "stat", &v->stat); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_GetChildren2Response(struct iarchive *in, const char *tag, struct GetChildren2Response*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : deserialize_String_vector(in, "children", &v->children); + rc = rc ? rc : deserialize_Stat(in, "stat", &v->stat); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_GetChildren2Response(struct GetChildren2Response*v){ + deallocate_String_vector(&v->children); + deallocate_Stat(&v->stat); +} +int serialize_GetACLResponse(struct oarchive *out, const char *tag, struct GetACLResponse *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : serialize_ACL_vector(out, "acl", &v->acl); + rc = rc ? rc : serialize_Stat(out, "stat", &v->stat); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_GetACLResponse(struct iarchive *in, const char *tag, struct GetACLResponse*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : deserialize_ACL_vector(in, "acl", &v->acl); + rc = rc ? rc : deserialize_Stat(in, "stat", &v->stat); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_GetACLResponse(struct GetACLResponse*v){ + deallocate_ACL_vector(&v->acl); + deallocate_Stat(&v->stat); +} +int serialize_LearnerInfo(struct oarchive *out, const char *tag, struct LearnerInfo *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Long(out, "serverid", &v->serverid); + rc = rc ? rc : out->serialize_Int(out, "protocolVersion", &v->protocolVersion); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_LearnerInfo(struct iarchive *in, const char *tag, struct LearnerInfo*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Long(in, "serverid", &v->serverid); + rc = rc ? rc : in->deserialize_Int(in, "protocolVersion", &v->protocolVersion); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_LearnerInfo(struct LearnerInfo*v){ +} +int allocate_Id_vector(struct Id_vector *v, int32_t len) { + if (!len) { + v->count = 0; + v->data = 0; + } else { + v->count = len; + v->data = calloc(sizeof(*v->data), len); + } + return 0; +} +int deallocate_Id_vector(struct Id_vector *v) { + if (v->data) { + int32_t i; + for(i=0;icount; i++) { + deallocate_Id(&v->data[i]); + } + free(v->data); + v->data = 0; + } + return 0; +} +int serialize_Id_vector(struct oarchive *out, const char *tag, struct Id_vector *v) +{ + int32_t count = v->count; + int rc = 0; + int32_t i; + rc = out->start_vector(out, tag, &count); + for(i=0;icount;i++) { + rc = rc ? rc : serialize_Id(out, "data", &v->data[i]); + } + rc = rc ? rc : out->end_vector(out, tag); + return rc; +} +int deserialize_Id_vector(struct iarchive *in, const char *tag, struct Id_vector *v) +{ + int rc = 0; + int32_t i; + rc = in->start_vector(in, tag, &v->count); + v->data = calloc(v->count, sizeof(*v->data)); + for(i=0;icount;i++) { + rc = rc ? rc : deserialize_Id(in, "value", &v->data[i]); + } + rc = in->end_vector(in, tag); + return rc; +} +int serialize_QuorumPacket(struct oarchive *out, const char *tag, struct QuorumPacket *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "type", &v->type); + rc = rc ? rc : out->serialize_Long(out, "zxid", &v->zxid); + rc = rc ? rc : out->serialize_Buffer(out, "data", &v->data); + rc = rc ? rc : serialize_Id_vector(out, "authinfo", &v->authinfo); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_QuorumPacket(struct iarchive *in, const char *tag, struct QuorumPacket*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "type", &v->type); + rc = rc ? rc : in->deserialize_Long(in, "zxid", &v->zxid); + rc = rc ? rc : in->deserialize_Buffer(in, "data", &v->data); + rc = rc ? rc : deserialize_Id_vector(in, "authinfo", &v->authinfo); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_QuorumPacket(struct QuorumPacket*v){ + deallocate_Buffer(&v->data); + deallocate_Id_vector(&v->authinfo); +} +int serialize_FileHeader(struct oarchive *out, const char *tag, struct FileHeader *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "magic", &v->magic); + rc = rc ? rc : out->serialize_Int(out, "version", &v->version); + rc = rc ? rc : out->serialize_Long(out, "dbid", &v->dbid); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_FileHeader(struct iarchive *in, const char *tag, struct FileHeader*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "magic", &v->magic); + rc = rc ? rc : in->deserialize_Int(in, "version", &v->version); + rc = rc ? rc : in->deserialize_Long(in, "dbid", &v->dbid); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_FileHeader(struct FileHeader*v){ +} +int serialize_TxnHeader(struct oarchive *out, const char *tag, struct TxnHeader *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Long(out, "clientId", &v->clientId); + rc = rc ? rc : out->serialize_Int(out, "cxid", &v->cxid); + rc = rc ? rc : out->serialize_Long(out, "zxid", &v->zxid); + rc = rc ? rc : out->serialize_Long(out, "time", &v->time); + rc = rc ? rc : out->serialize_Int(out, "type", &v->type); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_TxnHeader(struct iarchive *in, const char *tag, struct TxnHeader*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Long(in, "clientId", &v->clientId); + rc = rc ? rc : in->deserialize_Int(in, "cxid", &v->cxid); + rc = rc ? rc : in->deserialize_Long(in, "zxid", &v->zxid); + rc = rc ? rc : in->deserialize_Long(in, "time", &v->time); + rc = rc ? rc : in->deserialize_Int(in, "type", &v->type); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_TxnHeader(struct TxnHeader*v){ +} +int serialize_CreateTxnV0(struct oarchive *out, const char *tag, struct CreateTxnV0 *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->serialize_Buffer(out, "data", &v->data); + rc = rc ? rc : serialize_ACL_vector(out, "acl", &v->acl); + rc = rc ? rc : out->serialize_Bool(out, "ephemeral", &v->ephemeral); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_CreateTxnV0(struct iarchive *in, const char *tag, struct CreateTxnV0*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->deserialize_Buffer(in, "data", &v->data); + rc = rc ? rc : deserialize_ACL_vector(in, "acl", &v->acl); + rc = rc ? rc : in->deserialize_Bool(in, "ephemeral", &v->ephemeral); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_CreateTxnV0(struct CreateTxnV0*v){ + deallocate_String(&v->path); + deallocate_Buffer(&v->data); + deallocate_ACL_vector(&v->acl); +} +int serialize_CreateTxn(struct oarchive *out, const char *tag, struct CreateTxn *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->serialize_Buffer(out, "data", &v->data); + rc = rc ? rc : serialize_ACL_vector(out, "acl", &v->acl); + rc = rc ? rc : out->serialize_Bool(out, "ephemeral", &v->ephemeral); + rc = rc ? rc : out->serialize_Int(out, "parentCVersion", &v->parentCVersion); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_CreateTxn(struct iarchive *in, const char *tag, struct CreateTxn*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->deserialize_Buffer(in, "data", &v->data); + rc = rc ? rc : deserialize_ACL_vector(in, "acl", &v->acl); + rc = rc ? rc : in->deserialize_Bool(in, "ephemeral", &v->ephemeral); + rc = rc ? rc : in->deserialize_Int(in, "parentCVersion", &v->parentCVersion); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_CreateTxn(struct CreateTxn*v){ + deallocate_String(&v->path); + deallocate_Buffer(&v->data); + deallocate_ACL_vector(&v->acl); +} +int serialize_DeleteTxn(struct oarchive *out, const char *tag, struct DeleteTxn *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_DeleteTxn(struct iarchive *in, const char *tag, struct DeleteTxn*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_DeleteTxn(struct DeleteTxn*v){ + deallocate_String(&v->path); +} +int serialize_SetDataTxn(struct oarchive *out, const char *tag, struct SetDataTxn *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->serialize_Buffer(out, "data", &v->data); + rc = rc ? rc : out->serialize_Int(out, "version", &v->version); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_SetDataTxn(struct iarchive *in, const char *tag, struct SetDataTxn*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->deserialize_Buffer(in, "data", &v->data); + rc = rc ? rc : in->deserialize_Int(in, "version", &v->version); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_SetDataTxn(struct SetDataTxn*v){ + deallocate_String(&v->path); + deallocate_Buffer(&v->data); +} +int serialize_CheckVersionTxn(struct oarchive *out, const char *tag, struct CheckVersionTxn *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->serialize_Int(out, "version", &v->version); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_CheckVersionTxn(struct iarchive *in, const char *tag, struct CheckVersionTxn*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->deserialize_Int(in, "version", &v->version); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_CheckVersionTxn(struct CheckVersionTxn*v){ + deallocate_String(&v->path); +} +int serialize_SetACLTxn(struct oarchive *out, const char *tag, struct SetACLTxn *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : serialize_ACL_vector(out, "acl", &v->acl); + rc = rc ? rc : out->serialize_Int(out, "version", &v->version); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_SetACLTxn(struct iarchive *in, const char *tag, struct SetACLTxn*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : deserialize_ACL_vector(in, "acl", &v->acl); + rc = rc ? rc : in->deserialize_Int(in, "version", &v->version); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_SetACLTxn(struct SetACLTxn*v){ + deallocate_String(&v->path); + deallocate_ACL_vector(&v->acl); +} +int serialize_SetMaxChildrenTxn(struct oarchive *out, const char *tag, struct SetMaxChildrenTxn *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_String(out, "path", &v->path); + rc = rc ? rc : out->serialize_Int(out, "max", &v->max); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_SetMaxChildrenTxn(struct iarchive *in, const char *tag, struct SetMaxChildrenTxn*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_String(in, "path", &v->path); + rc = rc ? rc : in->deserialize_Int(in, "max", &v->max); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_SetMaxChildrenTxn(struct SetMaxChildrenTxn*v){ + deallocate_String(&v->path); +} +int serialize_CreateSessionTxn(struct oarchive *out, const char *tag, struct CreateSessionTxn *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "timeOut", &v->timeOut); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_CreateSessionTxn(struct iarchive *in, const char *tag, struct CreateSessionTxn*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "timeOut", &v->timeOut); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_CreateSessionTxn(struct CreateSessionTxn*v){ +} +int serialize_ErrorTxn(struct oarchive *out, const char *tag, struct ErrorTxn *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "err", &v->err); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_ErrorTxn(struct iarchive *in, const char *tag, struct ErrorTxn*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "err", &v->err); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_ErrorTxn(struct ErrorTxn*v){ +} +int serialize_Txn(struct oarchive *out, const char *tag, struct Txn *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : out->serialize_Int(out, "type", &v->type); + rc = rc ? rc : out->serialize_Buffer(out, "data", &v->data); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_Txn(struct iarchive *in, const char *tag, struct Txn*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : in->deserialize_Int(in, "type", &v->type); + rc = rc ? rc : in->deserialize_Buffer(in, "data", &v->data); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_Txn(struct Txn*v){ + deallocate_Buffer(&v->data); +} +int allocate_Txn_vector(struct Txn_vector *v, int32_t len) { + if (!len) { + v->count = 0; + v->data = 0; + } else { + v->count = len; + v->data = calloc(sizeof(*v->data), len); + } + return 0; +} +int deallocate_Txn_vector(struct Txn_vector *v) { + if (v->data) { + int32_t i; + for(i=0;icount; i++) { + deallocate_Txn(&v->data[i]); + } + free(v->data); + v->data = 0; + } + return 0; +} +int serialize_Txn_vector(struct oarchive *out, const char *tag, struct Txn_vector *v) +{ + int32_t count = v->count; + int rc = 0; + int32_t i; + rc = out->start_vector(out, tag, &count); + for(i=0;icount;i++) { + rc = rc ? rc : serialize_Txn(out, "data", &v->data[i]); + } + rc = rc ? rc : out->end_vector(out, tag); + return rc; +} +int deserialize_Txn_vector(struct iarchive *in, const char *tag, struct Txn_vector *v) +{ + int rc = 0; + int32_t i; + rc = in->start_vector(in, tag, &v->count); + v->data = calloc(v->count, sizeof(*v->data)); + for(i=0;icount;i++) { + rc = rc ? rc : deserialize_Txn(in, "value", &v->data[i]); + } + rc = in->end_vector(in, tag); + return rc; +} +int serialize_MultiTxn(struct oarchive *out, const char *tag, struct MultiTxn *v){ + int rc; + rc = out->start_record(out, tag); + rc = rc ? rc : serialize_Txn_vector(out, "txns", &v->txns); + rc = rc ? rc : out->end_record(out, tag); + return rc; +} +int deserialize_MultiTxn(struct iarchive *in, const char *tag, struct MultiTxn*v){ + int rc; + rc = in->start_record(in, tag); + rc = rc ? rc : deserialize_Txn_vector(in, "txns", &v->txns); + rc = rc ? rc : in->end_record(in, tag); + return rc; +} +void deallocate_MultiTxn(struct MultiTxn*v){ + deallocate_Txn_vector(&v->txns); +}