From ca1eb21e02853f26e888bbf64bb5c324a8d50e50 Mon Sep 17 00:00:00 2001 From: cnangel Date: Mon, 22 Feb 2016 17:02:05 +0800 Subject: [PATCH 1/6] Add function and Fixed some question - add new function sum, sum the number of objects that match the specified checks. This will return the number of objects counted by the search. If an error occurs during the sum, the sum may reflect a partial sum. The real sum will be higher than the returned value; - modify interface using latest of po6; - fixed memory leak of value_to_attributes in util.cc; - better free for hyperdex_client_destroy_attrs - add java and python interface --- Makefile.am | 3 + admin/admin.cc | 5 +- admin/raw_backup.cc | 6 +- autogen.sh | 25 ++++ bindings/java/org/hyperdex/client/Client.java | 5 + bindings/java/org_hyperdex_client_Client.c | 11 ++ .../org_hyperdex_client_Client.definitions.c | 44 +++++++ bindings/java/org_hyperdex_client_Client.h | 8 ++ bindings/python/hyperdex/client.pyx | 27 ++++ client/c.cc | 18 ++- client/client.cc | 40 ++++++ client/client.h | 3 + client/pending_sum.cc | 117 ++++++++++++++++++ client/pending_sum.h | 80 ++++++++++++ client/util.cc | 15 ++- common/hyperspace.cc | 2 + common/network_msgtype.cc | 2 + common/network_msgtype.h | 3 + configure.ac | 2 +- daemon/daemon.cc | 25 ++++ daemon/daemon.h | 2 + daemon/main.cc | 9 +- daemon/search_manager.cc | 82 ++++++++++++ daemon/search_manager.h | 5 + include/hyperdex/client.h | 8 ++ include/hyperdex/client.hpp | 6 + 26 files changed, 540 insertions(+), 13 deletions(-) create mode 100755 autogen.sh create mode 100644 client/pending_sum.cc create mode 100644 client/pending_sum.h diff --git a/Makefile.am b/Makefile.am index 362573d83..58e33093b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -132,6 +132,7 @@ noinst_HEADERS += common/funcall.h noinst_HEADERS += common/hash.h noinst_HEADERS += common/hyperspace.h noinst_HEADERS += common/ids.h +noinst_HEADERS += common/ieee.h noinst_HEADERS += common/index.h noinst_HEADERS += common/json_path.h noinst_HEADERS += common/key_change.h @@ -393,6 +394,7 @@ noinst_HEADERS += client/keyop_info.h noinst_HEADERS += client/pending_aggregation.h noinst_HEADERS += client/pending_atomic.h noinst_HEADERS += client/pending_count.h +noinst_HEADERS += client/pending_sum.h noinst_HEADERS += client/pending_get.h noinst_HEADERS += client/pending_get_partial.h noinst_HEADERS += client/pending_group_atomic.h @@ -444,6 +446,7 @@ libhyperdex_client_la_SOURCES += client/pending_atomic.cc libhyperdex_client_la_SOURCES += client/pending_group_atomic.cc libhyperdex_client_la_SOURCES += client/pending.cc libhyperdex_client_la_SOURCES += client/pending_count.cc +libhyperdex_client_la_SOURCES += client/pending_sum.cc libhyperdex_client_la_SOURCES += client/pending_get.cc libhyperdex_client_la_SOURCES += client/pending_get_partial.cc libhyperdex_client_la_SOURCES += client/pending_search.cc diff --git a/admin/admin.cc b/admin/admin.cc index 6c6bda72e..dd71692b7 100644 --- a/admin/admin.cc +++ b/admin/admin.cc @@ -451,7 +451,10 @@ admin :: server_register(uint64_t token, const char* address, server_id sid(token); po6::net::location loc; - loc = po6::net::location(address); + if (!loc.set(address)) + { + return -1; + } int64_t id = m_next_admin_id; ++m_next_admin_id; diff --git a/admin/raw_backup.cc b/admin/raw_backup.cc index 68c3c21fa..7fec8dd9c 100644 --- a/admin/raw_backup.cc +++ b/admin/raw_backup.cc @@ -57,7 +57,11 @@ hyperdex_admin_raw_backup(const char* host, uint16_t port, { try { - busybee_single bbs(po6::net::location(host, port)); + po6::net::location loc; + if (!loc.set(host, port)) { + return -1; + } + busybee_single bbs(loc); const uint8_t type = static_cast(BACKUP); const uint8_t flags = 0; const uint64_t version = 0; diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 000000000..2ab57c41d --- /dev/null +++ b/autogen.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# +# $Id: autogen.sh 1091 2008-06-08 06:37:22Z nicodvb $ +# +# run this to generate all the initial makefiles, etc. + +srcdir=`dirname "$0"` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd "$srcdir" + +AUTORECONF=${AUTORECONF-autoreconf} + +if ! type $AUTORECONF >/dev/null 2>&1; then + echo "**Error**: Missing \`autoreconf' program." >&2 + echo "You will need the autoconf and automake packages." >&2 + echo "You can download them from ftp://ftp.gnu.org/pub/gnu/." >&2 + exit 1 +fi + +test ! -d "$srcdir/m4" && mkdir "$srcdir/m4" +$AUTORECONF -v --install || exit $? +cd "$ORIGDIR" || exit $? + diff --git a/bindings/java/org/hyperdex/client/Client.java b/bindings/java/org/hyperdex/client/Client.java index 1711bb8be..a73bad634 100644 --- a/bindings/java/org/hyperdex/client/Client.java +++ b/bindings/java/org/hyperdex/client/Client.java @@ -831,4 +831,9 @@ public Long count(String spacename, Map predicates) throws Hyper { return (Long) async_count(spacename, predicates).waitForIt(); } + public native Deferred async_sum(String spacename, Map predicates, String sum_key) throws HyperDexClientException; + public Long sum(String spacename, Map predicates, String sum_key) throws HyperDexClientException + { + return (Long) async_sum(spacename, predicates, sum_key).waitForIt(); + } } diff --git a/bindings/java/org_hyperdex_client_Client.c b/bindings/java/org_hyperdex_client_Client.c index 2f60143af..bcd8abaec 100644 --- a/bindings/java/org_hyperdex_client_Client.c +++ b/bindings/java/org_hyperdex_client_Client.c @@ -1315,6 +1315,17 @@ hyperdex_java_client_convert_sortby(JNIEnv* env, jobject client, return *sortby != NULL ? 0 : -1; } +static int +hyperdex_java_client_convert_sum_key(JNIEnv* env, jobject client, + struct hyperdex_ds_arena* arena, + jstring str, + const char** sum_key) +{ + (void)client; + *sum_key = hyperdex_java_client_convert_cstring(env, arena, str); + return *sum_key != NULL ? 0 : -1; +} + static int hyperdex_java_client_convert_spacename(JNIEnv* env, jobject client, struct hyperdex_ds_arena* arena, diff --git a/bindings/java/org_hyperdex_client_Client.definitions.c b/bindings/java/org_hyperdex_client_Client.definitions.c index 685ddaa93..8699a2f3c 100644 --- a/bindings/java/org_hyperdex_client_Client.definitions.c +++ b/bindings/java/org_hyperdex_client_Client.definitions.c @@ -325,6 +325,44 @@ hyperdex_java_client_asynccall__spacename_predicates__status_count(JNIEnv* env, return op; } +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_predicates__status_sum(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const char *sum_key, enum hyperdex_client_returncode* status, uint64_t* count), jstring spacename, jobject predicates, jstring key); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_predicates__status_sum(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const char *sum_key, enum hyperdex_client_returncode* status, uint64_t* count), jstring spacename, jobject predicates, jstring key) +{ + const char* in_space; + const struct hyperdex_client_attribute_check* in_checks; + size_t in_checks_sz; + const char* in_sum_key; + int success = 0; + struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); + struct hyperdex_java_client_deferred* o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_deferred_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); + if (success < 0) return 0; + success = hyperdex_java_client_convert_sum_key(env, obj, o->arena, key, &in_sum_key); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_checks, in_checks_sz, in_sum_key, &o->status, &o->count); + + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + + o->encode_return = hyperdex_java_client_deferred_encode_status_count; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; +} + + JNIEXPORT HYPERDEX_API jobject JNICALL hyperdex_java_client_asynccall__spacename_key_mapattributes__status(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status), jstring spacename, jobject key, jobject mapattributes); @@ -1284,3 +1322,9 @@ Java_org_hyperdex_client_Client_async_1count(JNIEnv* env, jobject obj, jstring s { return hyperdex_java_client_asynccall__spacename_predicates__status_count(env, obj, hyperdex_client_count, spacename, predicates); } + +JNIEXPORT HYPERDEX_API jobject JNICALL +Java_org_hyperdex_client_Client_async_1sum(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jstring key) +{ + return hyperdex_java_client_asynccall__spacename_predicates__status_sum(env, obj, hyperdex_client_sum, spacename, predicates, key); +} diff --git a/bindings/java/org_hyperdex_client_Client.h b/bindings/java/org_hyperdex_client_Client.h index f205a9637..c2b1775ac 100644 --- a/bindings/java/org_hyperdex_client_Client.h +++ b/bindings/java/org_hyperdex_client_Client.h @@ -1023,6 +1023,14 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_sorted_1s JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1count (JNIEnv *, jobject, jstring, jobject); +/* + * Class: org_hyperdex_client_Client + * Method: async_sum + * Signature: (Ljava/lang/String;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; + */ +JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1sum + (JNIEnv *, jobject, jstring, jobject, jstring); + #ifdef __cplusplus } #endif diff --git a/bindings/python/hyperdex/client.pyx b/bindings/python/hyperdex/client.pyx index 6fa957fe8..3498dcc1e 100644 --- a/bindings/python/hyperdex/client.pyx +++ b/bindings/python/hyperdex/client.pyx @@ -314,6 +314,7 @@ cdef extern from "hyperdex/client.h": int64_t hyperdex_client_search_describe(hyperdex_client* client, const char* space, const hyperdex_client_attribute_check* checks, size_t checks_sz, hyperdex_client_returncode* status, const char** description) int64_t hyperdex_client_sorted_search(hyperdex_client* client, const char* space, const hyperdex_client_attribute_check* checks, size_t checks_sz, const char* sort_by, uint64_t limit, int maxmin, hyperdex_client_returncode* status, const hyperdex_client_attribute** attrs, size_t* attrs_sz) int64_t hyperdex_client_count(hyperdex_client* client, const char* space, const hyperdex_client_attribute_check* checks, size_t checks_sz, hyperdex_client_returncode* status, uint64_t* count) + int64_t hyperdex_client_sum(hyperdex_client* client, const char* space, const hyperdex_client_attribute_check* checks, size_t checks_sz, const char* sum_key, hyperdex_client_returncode* status, uint64_t* count) # End Automatically Generated Prototypes @@ -399,6 +400,7 @@ ctypedef int64_t asynccall__spacename_predicates_attributes__status_count_fptr(h ctypedef int64_t asynccall__spacename_key__status_fptr(hyperdex_client* client, const char* space, const char* key, size_t key_sz, hyperdex_client_returncode* status) ctypedef int64_t asynccall__spacename_key_predicates__status_fptr(hyperdex_client* client, const char* space, const char* key, size_t key_sz, const hyperdex_client_attribute_check* checks, size_t checks_sz, hyperdex_client_returncode* status) ctypedef int64_t asynccall__spacename_predicates__status_count_fptr(hyperdex_client* client, const char* space, const hyperdex_client_attribute_check* checks, size_t checks_sz, hyperdex_client_returncode* status, uint64_t* count) +ctypedef int64_t asynccall__spacename_predicates__status_sum_fptr(hyperdex_client* client, const char* space, const hyperdex_client_attribute_check* checks, size_t checks_sz, const char* key, hyperdex_client_returncode* status, uint64_t* count) ctypedef int64_t asynccall__spacename_key_mapattributes__status_fptr(hyperdex_client* client, const char* space, const char* key, size_t key_sz, const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, hyperdex_client_returncode* status) ctypedef int64_t asynccall__spacename_key_predicates_mapattributes__status_fptr(hyperdex_client* client, const char* space, const char* key, size_t key_sz, const hyperdex_client_attribute_check* checks, size_t checks_sz, const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, hyperdex_client_returncode* status) ctypedef int64_t asynccall__spacename_predicates_mapattributes__status_count_fptr(hyperdex_client* client, const char* space, const hyperdex_client_attribute_check* checks, size_t checks_sz, const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, hyperdex_client_returncode* status, uint64_t* count) @@ -1506,6 +1508,9 @@ cdef class Client: cdef convert_sortby(self, hyperdex_ds_arena* arena, bytes sortby, const char** sortby_str): sortby_str[0] = sortby + cdef convert_sum_key(self, hyperdex_ds_arena* arena, bytes key, const char** sum_key_str): + sum_key_str[0] = key + cdef convert_limit(self, hyperdex_ds_arena* arena, long limit, uint64_t* count): count[0] = limit @@ -1695,6 +1700,24 @@ cdef class Client: self.ops[d.reqid] = d return d + cdef asynccall__spacename_predicates__status_sum(self, asynccall__spacename_predicates__status_sum_fptr f, bytes spacename, dict predicates, bytes key, auth=None): + cdef Deferred d = Deferred(self) + cdef const char* in_space + cdef hyperdex_client_attribute_check* in_checks + cdef size_t in_checks_sz + cdef const char* in_sum_key + self.convert_spacename(d.arena, spacename, &in_space); + self.convert_predicates(d.arena, predicates, &in_checks, &in_checks_sz); + self.convert_sum_key(d.arena, key, &in_sum_key); + self.set_auth_context(auth) + d.reqid = f(self.client, in_space, in_checks, in_checks_sz, in_sum_key, &d.status, &d.count); + self.clear_auth_context() + if d.reqid < 0: + raise HyperDexClientException(d.status, hyperdex_client_error_message(self.client)) + d.encode_return = hyperdex_python_client_deferred_encode_status_count + self.ops[d.reqid] = d + return d + cdef asynccall__spacename_key_mapattributes__status(self, asynccall__spacename_key_mapattributes__status_fptr f, bytes spacename, key, dict mapattributes, auth=None): cdef Deferred d = Deferred(self) cdef const char* in_space @@ -2412,4 +2435,8 @@ cdef class Client: return self.asynccall__spacename_predicates__status_count(hyperdex_client_count, spacename, predicates, auth) def count(self, bytes spacename, dict predicates, auth=None): return self.async_count(spacename, predicates, auth).wait() + def async_sum(self, bytes spacename, dict predicates, bytes sum_key, auth=None): + return self.asynccall__spacename_predicates__status_sum(hyperdex_client_sum, spacename, predicates, sum_key, auth) + def sum(self, bytes spacename, dict predicates, bytes sum_key, auth=None): + return self.async_sum(spacename, predicates, sum_key, auth).wait() # End Automatically Generated Methods diff --git a/client/c.cc b/client/c.cc index b2545ed5c..2a49c556d 100644 --- a/client/c.cc +++ b/client/c.cc @@ -216,7 +216,10 @@ hyperdex_client_destroy_attrs(const hyperdex_client_attribute* attrs, size_t /*a { FAKE_STATUS; SIGNAL_PROTECT_VOID; - free(const_cast(attrs)); + if (attrs) { + free(const_cast(attrs)); + attrs = NULL; + } } HYPERDEX_API void @@ -2304,6 +2307,19 @@ hyperdex_client_count(struct hyperdex_client* _cl, ); } +HYPERDEX_API int64_t +hyperdex_client_sum(struct hyperdex_client* _cl, + const char* space, + const struct hyperdex_client_attribute_check* checks, size_t checks_sz, + const char* sum_key, + enum hyperdex_client_returncode* status, + uint64_t* total) +{ + C_WRAP_EXCEPT( + return cl->sum(space, checks, checks_sz, sum_key, status, total); + ); +} + HYPERDEX_API int64_t hyperdex_client_loop(hyperdex_client* _cl, int timeout, hyperdex_client_returncode* status) diff --git a/client/client.cc b/client/client.cc index 0d858daeb..c1df93d03 100644 --- a/client/client.cc +++ b/client/client.cc @@ -55,6 +55,7 @@ #include "client/pending_atomic.h" #include "client/pending_group_atomic.h" #include "client/pending_count.h" +#include "client/pending_sum.h" #include "client/pending_get.h" #include "client/pending_get_partial.h" #include "client/pending_search.h" @@ -392,6 +393,45 @@ client :: count(const char* space, return perform_aggregation(servers, op, REQ_COUNT, msg, status); } +int64_t +client :: sum(const char* space, + const hyperdex_client_attribute_check* chks, size_t chks_sz, + const char* sum_key, + hyperdex_client_returncode* status, + uint64_t* result) +{ + SEARCH_BOILERPLATE + uint16_t sum_idx = sc->lookup_attr(sum_key); + + if (sum_idx== sc->attrs_sz) + { + ERROR(UNKNOWNATTR) << "\"" << e::strescape(sum_key) + << "\" is not an attribute of space \"" + << e::strescape(space) << "\""; + return -1 - chks_sz; + } + + datatype_info* di = datatype_info::lookup(sc->attrs[sum_idx].type); + + if (!di->comparable()) + { + ERROR(WRONGTYPE) << "cannot sort by attribute \"" + << e::strescape(sum_key) + << "\": it is not comparable"; + return -1 - chks_sz; + } + + int64_t client_id = m_next_client_id++; + e::intrusive_ptr op; + op = new pending_sum(client_id, sum_idx, di, status, result); + size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ + + pack_size(checks) + + sizeof(sum_idx); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << checks << sum_idx; + return perform_aggregation(servers, op, REQ_SUM, msg, status); +} + int64_t client :: perform_funcall(const hyperdex_client_keyop_info* opinfo, const char* space, const char* _key, size_t _key_sz, diff --git a/client/client.h b/client/client.h index b3f9252ce..c7b8154ec 100644 --- a/client/client.h +++ b/client/client.h @@ -114,6 +114,9 @@ class client int64_t count(const char* space, const hyperdex_client_attribute_check* checks, size_t checks_sz, hyperdex_client_returncode* status, uint64_t* result); + int64_t sum(const char* space, + const hyperdex_client_attribute_check* checks, size_t checks_sz, + const char* sum_key, hyperdex_client_returncode* status, uint64_t* result); // General keyop call // This will be called by the bindings from c.cc diff --git a/client/pending_sum.cc b/client/pending_sum.cc new file mode 100644 index 000000000..f3549eefb --- /dev/null +++ b/client/pending_sum.cc @@ -0,0 +1,117 @@ +// Copyright (c) 2012-2013, Cornell University +// 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 HyperDex nor the names of its 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. + +// HyperDex +#include "client/pending_sum.h" +#include "common/datatype_info.h" + +using hyperdex::pending_sum; + +pending_sum :: pending_sum(uint64_t id, + uint16_t sum_idx, + datatype_info* sum_di, + hyperdex_client_returncode* status, + uint64_t* count) + : pending_aggregation(id, status) + , m_sum_idx(sum_idx) + , m_sum_di(sum_di) + , m_sum(count) + , m_done(false) +{ + set_status(HYPERDEX_CLIENT_SUCCESS); + set_error(e::error()); +} + +pending_sum :: ~pending_sum() throw () +{ +} + +bool +pending_sum :: can_yield() +{ + return this->aggregation_done() && !m_done; +} + +bool +pending_sum :: yield(hyperdex_client_returncode* status, e::error* err) +{ + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + assert(this->can_yield()); + m_done = true; + return true; +} + +void +pending_sum :: handle_failure(const server_id& si, + const virtual_server_id& vsi) +{ + PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " + << vsi << "/" << si; + return pending_aggregation::handle_failure(si, vsi); +} + +bool +pending_sum :: handle_message(client* cl, + const server_id& si, + const virtual_server_id& vsi, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_client_returncode* status, + e::error* err) +{ + bool handled = pending_aggregation::handle_message(cl, si, vsi, mt, std::auto_ptr(), up, status, err); + assert(handled); + + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + + if (mt != RESP_SUM) + { + PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to SUM with " << mt; + return true; + } + + + uint64_t local_sum; + up = up >> local_sum; + + if (up.error()) + { + PENDING_ERROR(SERVERERROR) << "communication error: server " + << vsi << " sent corrupt message=" + << msg->as_slice().hex() + << " in response to a SUM"; + return true; + } + + *m_sum += local_sum; + // Don't set the status or error so that errors will carry through. It was + // set to the success state in the constructor + return true; +} diff --git a/client/pending_sum.h b/client/pending_sum.h new file mode 100644 index 000000000..6b0df3d75 --- /dev/null +++ b/client/pending_sum.h @@ -0,0 +1,80 @@ +// Copyright (c) 2012-2016, Cornell University +// 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 HyperDex nor the names of its 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. + +#ifndef hyperdex_client_pending_sum_h_ +#define hyperdex_client_pending_sum_h_ + +// HyperDex +#include "namespace.h" +#include "client/pending_aggregation.h" + +BEGIN_HYPERDEX_NAMESPACE + +class datatype_info; +class pending_sum : public pending_aggregation +{ + public: + pending_sum(uint64_t client_visible_id, + uint16_t sum_idx, + datatype_info* sum_di, + hyperdex_client_returncode* status, + uint64_t* count); + virtual ~pending_sum() throw (); + + // return to client + public: + virtual bool can_yield(); + virtual bool yield(hyperdex_client_returncode* status, e::error* error); + + // events + public: + virtual void handle_failure(const server_id& si, + const virtual_server_id& vsi); + virtual bool handle_message(client*, + const server_id& si, + const virtual_server_id& vsi, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_client_returncode* status, + e::error* error); + + // noncopyable + private: + pending_sum(const pending_sum& other); + pending_sum& operator = (const pending_sum& rhs); + + private: + const uint16_t m_sum_idx; + datatype_info *m_sum_di; + uint64_t* m_sum; + bool m_done; +}; + +END_HYPERDEX_NAMESPACE + +#endif // hyperdex_client_pending_sum_h_ diff --git a/client/util.cc b/client/util.cc index 4fddda946..5cfb5634f 100644 --- a/client/util.cc +++ b/client/util.cc @@ -88,9 +88,20 @@ hyperdex :: value_to_attributes(const configuration& config, std::vector ha; ha.reserve(sc->attrs_sz); - char* ret = static_cast(malloc(sz)); + char *ret = NULL; + if (attrs) + { + if (*attrs == NULL) + { + ret = static_cast(malloc(sz)); + } + else + { + ret = static_cast(realloc((void *)*attrs, sz)); + } + } - if (!ret) + if (ret == NULL) { UTIL_ERROR(NOMEM) << "out of memory"; return false; diff --git a/common/hyperspace.cc b/common/hyperspace.cc index 0c2e1a88e..757af47aa 100644 --- a/common/hyperspace.cc +++ b/common/hyperspace.cc @@ -232,6 +232,8 @@ hyperdex :: operator >> (e::unpacker up, space& s) uint16_t num_indices; up = up >> s.id >> name >> s.fault_tolerance >> s.sc.attrs_sz >> num_subspaces >> num_indices; + strs.reserve(s.sc.attrs_sz + 1); + attrs.reserve(s.sc.attrs_sz); strs.push_back(std::string(name.cdata(), name.size())); s.name = strs.back().c_str(); diff --git a/common/network_msgtype.cc b/common/network_msgtype.cc index 01259ada0..7a869f9ca 100644 --- a/common/network_msgtype.cc +++ b/common/network_msgtype.cc @@ -49,6 +49,8 @@ hyperdex :: operator << (std::ostream& lhs, const network_msgtype& rhs) STRINGIFY(RESP_SORTED_SEARCH); STRINGIFY(REQ_COUNT); STRINGIFY(RESP_COUNT); + STRINGIFY(REQ_SUM); + STRINGIFY(RESP_SUM); STRINGIFY(REQ_SEARCH_DESCRIBE); STRINGIFY(RESP_SEARCH_DESCRIBE); STRINGIFY(REQ_GROUP_ATOMIC); diff --git a/common/network_msgtype.h b/common/network_msgtype.h index dbfbc6474..be48f483d 100644 --- a/common/network_msgtype.h +++ b/common/network_msgtype.h @@ -67,6 +67,9 @@ enum network_msgtype REQ_GROUP_ATOMIC = 54, RESP_GROUP_ATOMIC = 55, + REQ_SUM = 58, + RESP_SUM = 59, + CHAIN_OP = 64, CHAIN_SUBSPACE = 65, CHAIN_ACK = 66, diff --git a/configure.ac b/configure.ac index 15f33845a..61dcde91f 100755 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. -AC_PREREQ([2.62]) +AC_PREREQ([2.59]) AC_INIT([HyperDex], [1.8.dev], [robert@hyperdex.org]) m4_define([serial_tests], [ m4_esyscmd([case `automake --version | head -n 1` in diff --git a/daemon/daemon.cc b/daemon/daemon.cc index bfcfb298d..ad81afb78 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -614,6 +614,10 @@ daemon :: loop(size_t thread) process_req_count(from, vfrom, vto, msg, up); m_perf_req_count.tap(); break; + case REQ_SUM: + process_req_sum(from, vfrom, vto, msg, up); + m_perf_req_sum.tap(); + break; case REQ_SEARCH_DESCRIBE: process_req_search_describe(from, vfrom, vto, msg, up); m_perf_req_search_describe.tap(); @@ -673,6 +677,7 @@ daemon :: loop(size_t thread) case RESP_SEARCH_DONE: case RESP_SORTED_SEARCH: case RESP_COUNT: + case RESP_SUM: case RESP_SEARCH_DESCRIBE: case CONFIGMISMATCH: case PACKET_NOP: @@ -982,6 +987,26 @@ daemon :: process_req_count(server_id from, m_sm.count(from, vto, nonce, &checks); } +void +daemon :: process_req_sum(server_id from, + virtual_server_id, + virtual_server_id vto, + std::auto_ptr msg, + e::unpacker up) +{ + uint64_t nonce; + std::vector checks; + uint16_t sum_idx; + + if ((up >> nonce >> checks >> sum_idx).error()) + { + LOG(WARNING) << "unpack of REQ_SUM failed; here's some hex: " << msg->hex(); + return; + } + + m_sm.sum(from, vto, nonce, &checks, sum_idx); +} + void daemon :: process_req_search_describe(server_id from, virtual_server_id, diff --git a/daemon/daemon.h b/daemon/daemon.h index e56175ed4..4c5b02aaa 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -88,6 +88,7 @@ class daemon void process_req_search_stop(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); void process_req_sorted_search(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); void process_req_count(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_req_sum(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); void process_req_search_describe(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); void process_req_group_atomic(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); void process_chain_op(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); @@ -146,6 +147,7 @@ class daemon performance_counter m_perf_req_search_stop; performance_counter m_perf_req_sorted_search; performance_counter m_perf_req_count; + performance_counter m_perf_req_sum; performance_counter m_perf_req_search_describe; performance_counter m_perf_req_group_atomic; performance_counter m_perf_chain_op; diff --git a/daemon/main.cc b/daemon/main.cc index 4eafe1dfa..6859bddcc 100644 --- a/daemon/main.cc +++ b/daemon/main.cc @@ -138,15 +138,10 @@ main(int argc, const char* argv[]) } else { - try + if (listen_ip.set(listen_host)) { - listen_ip = po6::net::ipaddr(listen_host); bind_to = po6::net::location(listen_ip, listen_port); } - catch (std::invalid_argument& e) - { - // fallthrough - } if (bind_to == po6::net::location()) { @@ -161,7 +156,7 @@ main(int argc, const char* argv[]) return EXIT_FAILURE; } - if (bind_to.address == po6::net::ipaddr("0.0.0.0")) + if (bind_to.address == po6::net::ipaddr::ANY()) { std::cerr << "cannot bind to " << bind_to << " because it is not routable" << std::endl; return EXIT_FAILURE; diff --git a/daemon/search_manager.cc b/daemon/search_manager.cc index 79277ecfe..84236ac4d 100644 --- a/daemon/search_manager.cc +++ b/daemon/search_manager.cc @@ -39,6 +39,7 @@ // e #include +#include // HyperDex #include "common/attribute_check.h" @@ -625,6 +626,87 @@ search_manager :: count(const server_id& from, m_daemon->m_comm.send_client(to, from, RESP_COUNT, msg); } +void +search_manager :: sum(const server_id& from, + const virtual_server_id& to, + uint64_t nonce, + std::vector* checks, + uint16_t sum_idx) +{ + region_id ri(m_daemon->m_config.get_region_id(to)); + const schema* sc = m_daemon->m_config.get_schema(ri); + + if (sc->authorization) + { + return; + } + + std::stable_sort(checks->begin(), checks->end()); + datalayer::returncode rc = datalayer::SUCCESS; + datalayer::snapshot snap = m_daemon->m_data.make_snapshot(); + e::intrusive_ptr iter; + iter = m_daemon->m_data.make_search_iterator(snap, ri, *checks, NULL); + uint64_t result = 0; + + switch (rc) + { + case datalayer::SUCCESS: + break; + case datalayer::NOT_FOUND: + case datalayer::BAD_ENCODING: + case datalayer::CORRUPTION: + case datalayer::IO_ERROR: + case datalayer::LEVELDB_ERROR: + LOG(ERROR) << "could not make snapshot for search: " << rc; + result = UINT64_MAX; + break; + default: + abort(); + } + + while (iter->valid() && result < UINT64_MAX) + { + e::slice key; + std::vector val; + uint64_t ver; + datalayer::reference tmp; + m_daemon->m_data.get_from_iterator(ri, *sc, iter.get(), &key, &val, &ver, &tmp); + if (val.size() < sum_idx) + { + LOG(ERROR) << "occur some error for sum: " << val.size(); + } + switch (sc->attrs[sum_idx].type) + { + case HYPERDATATYPE_INT64: + { + uint64_t num = 0; + e::unpack64le(val[sum_idx-1].cdata(), &num); + result += num; + } + break; + case HYPERDATATYPE_FLOAT: + { + double num = 0; + e::unpackdoublele(val[sum_idx-1].cdata(), &num); + result += (uint64_t)num; + } + break; + case HYPERDATATYPE_STRING: + default: + LOG(ERROR) << "could not sum item because of not int and double(" << sc->attrs[sum_idx].type << ")"; + } + iter->next(); + } + //LOG(INFO) << "result(" << result << ")"; + + size_t sz = HYPERDEX_HEADER_SIZE_VC + + sizeof(uint64_t) + + sizeof(uint64_t); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << result; + m_daemon->m_comm.send_client(to, from, RESP_SUM, msg); +} + void search_manager :: search_describe(const server_id& from, const virtual_server_id& to, diff --git a/daemon/search_manager.h b/daemon/search_manager.h index 28e42a0dc..501b9b425 100644 --- a/daemon/search_manager.h +++ b/daemon/search_manager.h @@ -95,6 +95,11 @@ class search_manager const virtual_server_id& to, uint64_t nonce, std::vector* checks); + void sum(const server_id& from, + const virtual_server_id& to, + uint64_t nonce, + std::vector* checks, + uint16_t sum_idx); void search_describe(const server_id& from, const virtual_server_id& to, diff --git a/include/hyperdex/client.h b/include/hyperdex/client.h index 5e0dfe2d1..f2b4a76ab 100644 --- a/include/hyperdex/client.h +++ b/include/hyperdex/client.h @@ -1161,6 +1161,14 @@ hyperdex_client_count(struct hyperdex_client* client, enum hyperdex_client_returncode* status, uint64_t* count); +int64_t +hyperdex_client_sum(struct hyperdex_client* client, + const char* space, + const struct hyperdex_client_attribute_check* checks, size_t checks_sz, + const char* sum_key, + enum hyperdex_client_returncode* status, + uint64_t* sum_count); + int64_t hyperdex_client_loop(struct hyperdex_client* client, int timeout, enum hyperdex_client_returncode* status); diff --git a/include/hyperdex/client.hpp b/include/hyperdex/client.hpp index e74c2e77b..f4233f337 100644 --- a/include/hyperdex/client.hpp +++ b/include/hyperdex/client.hpp @@ -749,6 +749,12 @@ class Client hyperdex_client_returncode* status, uint64_t* count) { return hyperdex_client_count(m_cl, space, checks, checks_sz, status, count); } + int64_t sum(const char* space, + const hyperdex_client_attribute_check* checks, size_t checks_sz, + const char* sum_key, + hyperdex_client_returncode* status, + uint64_t* count) + { return hyperdex_client_sum(m_cl, space, checks, checks_sz, sum_key, status, count); } public: void clear_auth_context() From 47939bc5cf6e3835ec8de90f3f67343ba5659777 Mon Sep 17 00:00:00 2001 From: cnangel Date: Sat, 27 Feb 2016 19:01:33 +0800 Subject: [PATCH 2/6] fixed pointer question when sorted_searched in pop_heap and pop_back --- daemon/search_manager.cc | 59 ++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/daemon/search_manager.cc b/daemon/search_manager.cc index 84236ac4d..4d84c32d9 100644 --- a/daemon/search_manager.cc +++ b/daemon/search_manager.cc @@ -323,11 +323,20 @@ struct _sorted_search_item { _sorted_search_item(_sorted_search_params* p) : params(p), key(), value(), version(), ref() {} + _sorted_search_item(_sorted_search_params* p, uint16_t val_sz) + : params(p), key_str(), version(), ref() + { + value.reserve(val_sz); + value_str.reserve(val_sz); + } _sorted_search_item(const _sorted_search_item& other); ~_sorted_search_item() throw () {} _sorted_search_item& operator = (const _sorted_search_item& other); + void assign(); _sorted_search_params* params; + std::string key_str; e::slice key; + std::vector value_str; std::vector value; uint64_t version; datalayer::reference ref; @@ -335,7 +344,9 @@ struct _sorted_search_item _sorted_search_item :: _sorted_search_item(const _sorted_search_item& other) : params(other.params) + , key_str(other.key_str) , key(other.key) + , value_str(other.value_str) , value(other.value) , version(other.version) , ref(other.ref) @@ -346,13 +357,26 @@ _sorted_search_item& _sorted_search_item :: _sorted_search_item :: operator = (const _sorted_search_item& other) { params = other.params; + key_str = other.key_str; key = other.key; + value_str = other.value_str; value = other.value; version = other.version; ref = other.ref; return *this; } +void +_sorted_search_item :: assign () +{ + key = e::slice(key_str); + value.clear(); + for (size_t i = 0; i < value_str.size(); i ++) + { + value.push_back(e::slice(value_str[i])); + } +} + bool operator < (const _sorted_search_item& lhs, const _sorted_search_item& rhs) { @@ -369,13 +393,16 @@ operator < (const _sorted_search_item& lhs, const _sorted_search_item& rhs) if (params->sort_by == 0) { datatype_info* di = datatype_info::lookup(params->sc->attrs[0].type); - cmp = di->compare(lhs.key, rhs.key); + e::slice lhs_key(lhs.key_str); + e::slice rhs_key(rhs.key_str); + cmp = di->compare(lhs_key, rhs_key); } else { datatype_info* di = datatype_info::lookup(params->sc->attrs[params->sort_by].type); - cmp = di->compare(lhs.value[params->sort_by - 1], - rhs.value[params->sort_by - 1]); + e::slice lhs_value(lhs.value_str[params->sort_by - 1]); + e::slice rhs_value(rhs.value_str[params->sort_by - 1]); + cmp = di->compare(lhs_value, rhs_value); } if (params->maximize) @@ -404,13 +431,16 @@ operator > (const _sorted_search_item& lhs, const _sorted_search_item& rhs) if (params->sort_by == 0) { datatype_info* di = datatype_info::lookup(params->sc->attrs[0].type); - cmp = di->compare(lhs.key, rhs.key); + e::slice lhs_key(lhs.key_str); + e::slice rhs_key(rhs.key_str); + cmp = di->compare(lhs_key, rhs_key); } else { datatype_info* di = datatype_info::lookup(params->sc->attrs[params->sort_by].type); - cmp = di->compare(lhs.value[params->sort_by - 1], - rhs.value[params->sort_by - 1]); + e::slice lhs_value(lhs.value_str[params->sort_by - 1]); + e::slice rhs_value(rhs.value_str[params->sort_by - 1]); + cmp = di->compare(lhs_value, rhs_value); } if (params->maximize) @@ -465,12 +495,22 @@ search_manager :: sorted_search(const server_id& from, _sorted_search_params params(sc, sort_by, maximize); std::vector<_sorted_search_item> top_n; - top_n.reserve(limit); + top_n.reserve(limit + 1); while (iter->valid()) { - top_n.push_back(_sorted_search_item(¶ms)); - m_daemon->m_data.get_from_iterator(ri, *sc, iter.get(), &top_n.back().key, &top_n.back().value, &top_n.back().version, &top_n.back().ref); + e::slice key; + std::vector val; + uint64_t ver; + datalayer::reference tmp; + m_daemon->m_data.get_from_iterator(ri, *sc, iter.get(), &key, &val, &ver, &tmp); + _sorted_search_item ssi(¶ms, sc->attrs_sz); + ssi.key_str = key.str(); + for (size_t i = 0; i < val.size(); i ++) + { + ssi.value_str.push_back(val[i].str()); + } + top_n.push_back(ssi); std::push_heap(top_n.begin(), top_n.end()); if (top_n.size() > limit) @@ -487,6 +527,7 @@ search_manager :: sorted_search(const server_id& from, for (size_t i = 0; i < top_n.size(); ++i) { + top_n[i].assign(); sz += pack_size(top_n[i].key) + pack_size(top_n[i].value); } From a7c6f9d074852243f19b63bfe4cce31828459afe Mon Sep 17 00:00:00 2001 From: cnangel Date: Sat, 27 Feb 2016 21:44:42 +0800 Subject: [PATCH 3/6] fixed m_results_idx is zero --- client/pending_sorted_search.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/pending_sorted_search.cc b/client/pending_sorted_search.cc index 225fb3584..67cda8bb7 100644 --- a/client/pending_sorted_search.cc +++ b/client/pending_sorted_search.cc @@ -56,7 +56,7 @@ pending_sorted_search :: pending_sorted_search(client* cl, , m_attrs(attrs) , m_attrs_sz(attrs_sz) , m_results() - , m_results_idx() + , m_results_idx(0) { } From 01fd4f68bc323c3ce3684bff5f4a7c3edb59292b Mon Sep 17 00:00:00 2001 From: cnangel Date: Sun, 28 Feb 2016 21:56:46 +0800 Subject: [PATCH 4/6] fixed client merge in sorted_search --- client/pending_sorted_search.cc | 110 +++++++++++++++++++------------- client/pending_sorted_search.h | 24 +++++-- 2 files changed, 84 insertions(+), 50 deletions(-) diff --git a/client/pending_sorted_search.cc b/client/pending_sorted_search.cc index 67cda8bb7..121170880 100644 --- a/client/pending_sorted_search.cc +++ b/client/pending_sorted_search.cc @@ -32,6 +32,7 @@ #include "client/client.h" #include "client/pending_sorted_search.h" #include "client/util.h" +#include using hyperdex::datatype_info; using hyperdex::pending_sorted_search; @@ -127,64 +128,77 @@ pending_sorted_search :: handle_failure(const server_id& si, return pending_aggregation::handle_failure(si, vsi); } -namespace +namespace hyperdex { -class sorted_search_comparator -{ - public: - sorted_search_comparator(bool maximize, - uint16_t sort_by_idx, - datatype_info* sort_by_di); - - public: - bool operator () (const pending_sorted_search::item& lhs, - const pending_sorted_search::item& rhs); - - private: - bool m_maximize; - uint16_t m_sort_by_idx; - datatype_info* m_sort_by_di; -}; - -} // namespace - -sorted_search_comparator :: sorted_search_comparator(bool maximize, - uint16_t sort_by_idx, - datatype_info* sort_by_di) - : m_maximize(maximize) - , m_sort_by_idx(sort_by_idx) - , m_sort_by_di(sort_by_di) +bool +operator < (const pending_sorted_search::item& lhs, const pending_sorted_search::item& rhs) { + assert(lhs.ssc_ptr == rhs.ssc_ptr); + const sorted_search_comparator* ssc_ptr = lhs.ssc_ptr; + + if (ssc_ptr->m_sort_by_idx > lhs.value.size() || + ssc_ptr->m_sort_by_idx > rhs.value.size() || + lhs.value.size() != rhs.value.size()) + { + return false; + } + + int cmp = 0; + + if (ssc_ptr->m_sort_by_idx == 0) + { + cmp = ssc_ptr->m_sort_by_di->compare(lhs.key, rhs.key); + } + else + { + cmp = ssc_ptr->m_sort_by_di->compare(lhs.value[ssc_ptr->m_sort_by_idx - 1], rhs.value[ssc_ptr->m_sort_by_idx - 1]); + } + + if (ssc_ptr->m_maximize) + { + return cmp < 0; + } + else + { + return cmp > 0; + } } bool -sorted_search_comparator :: operator () (const pending_sorted_search::item& lhs, - const pending_sorted_search::item& rhs) +operator > (const pending_sorted_search::item& lhs, const pending_sorted_search::item& rhs) { - if (m_sort_by_idx > lhs.value.size() || - m_sort_by_idx > rhs.value.size() || + assert(lhs.ssc_ptr == rhs.ssc_ptr); + const sorted_search_comparator* ssc_ptr = lhs.ssc_ptr; + + if (ssc_ptr->m_sort_by_idx > lhs.value.size() || + ssc_ptr->m_sort_by_idx > rhs.value.size() || lhs.value.size() != rhs.value.size()) { return false; } - e::slice lhs_attr; - e::slice rhs_attr; + int cmp = 0; - if (m_sort_by_idx == 0) + if (ssc_ptr->m_sort_by_idx == 0) { - lhs_attr = lhs.key; - rhs_attr = rhs.key; + cmp = ssc_ptr->m_sort_by_di->compare(lhs.key, rhs.key); } else { - lhs_attr = lhs.value[m_sort_by_idx - 1]; - rhs_attr = rhs.value[m_sort_by_idx - 1]; + cmp = ssc_ptr->m_sort_by_di->compare(lhs.value[ssc_ptr->m_sort_by_idx - 1], rhs.value[ssc_ptr->m_sort_by_idx - 1]); } - int cmp = m_sort_by_di->compare(lhs_attr, rhs_attr); - return m_maximize ? (cmp > 0) : (cmp < 0); + if (ssc_ptr->m_maximize) + { + return cmp > 0; + } + else + { + return cmp < 0; + } +} + } bool @@ -242,12 +256,12 @@ pending_sorted_search :: handle_message(client* cl, return true; } - m_results.push_back(item(key, value, backing)); - std::push_heap(m_results.begin(), m_results.end(), ssc); + m_results.push_back(item(&ssc, key, value, backing)); + std::push_heap(m_results.begin(), m_results.end()); if (m_results.size() > m_limit) { - std::pop_heap(m_results.begin(), m_results.end(), ssc); + std::pop_heap(m_results.begin(), m_results.end()); m_results.pop_back(); } } @@ -258,23 +272,26 @@ pending_sorted_search :: handle_message(client* cl, if (m_yield) { - std::sort(m_results.begin(), m_results.end(), ssc); + std::sort(m_results.begin(), m_results.end(), std::greater()); } return true; } -pending_sorted_search :: item :: item(const e::slice& _key, +pending_sorted_search :: item :: item(const sorted_search_comparator *sscobj, + const e::slice& _key, const std::vector& _value, e::compat::shared_ptr _backing) - : key(_key) + : ssc_ptr(sscobj) + , key(_key) , value(_value) , backing(_backing) { } pending_sorted_search :: item :: item(const item& other) - : key(other.key) + : ssc_ptr(other.ssc_ptr) + , key(other.key) , value(other.value) , backing(other.backing) { @@ -289,6 +306,7 @@ pending_sorted_search :: item :: operator = (const item& other) { if (this != &other) { + ssc_ptr = other.ssc_ptr; key = other.key; value = other.value; backing = other.backing; diff --git a/client/pending_sorted_search.h b/client/pending_sorted_search.h index d5a2f4577..0ad0416ff 100644 --- a/client/pending_sorted_search.h +++ b/client/pending_sorted_search.h @@ -94,11 +94,29 @@ class pending_sorted_search : public pending_aggregation size_t m_results_idx; }; +class sorted_search_comparator +{ + public: + sorted_search_comparator(bool maximize, + uint16_t sort_by_idx, + datatype_info* sort_by_di) + : m_maximize(maximize) + , m_sort_by_idx(sort_by_idx) + , m_sort_by_di(sort_by_di) + { + } + + public: + bool m_maximize; + uint16_t m_sort_by_idx; + datatype_info* m_sort_by_di; +}; class pending_sorted_search :: item { public: item(); - item(const e::slice& key, + item(const sorted_search_comparator *sscobj, + const e::slice& key, const std::vector& value, e::compat::shared_ptr backing); item(const item&); @@ -108,12 +126,10 @@ class pending_sorted_search :: item item& operator = (const item&); public: + const sorted_search_comparator *ssc_ptr; e::slice key; std::vector value; e::compat::shared_ptr backing; - - public: - friend class sorted_search_comparator; }; END_HYPERDEX_NAMESPACE From cf94cd26d6c5a16db2ea98f4d294096d52d8ea8c Mon Sep 17 00:00:00 2001 From: cnangel Date: Thu, 14 Apr 2016 12:42:16 +0800 Subject: [PATCH 5/6] update files --- admin/admin.cc | 1787 +++---- admin/admin.h | 240 +- admin/backup_state_machine.cc | 474 +- admin/backup_state_machine.h | 97 +- admin/c.cc | 668 +-- admin/coord_rpc.cc | 18 +- admin/coord_rpc.h | 32 +- admin/coord_rpc_backup.cc | 79 +- admin/coord_rpc_backup.h | 42 +- admin/coord_rpc_generic.cc | 108 +- admin/coord_rpc_generic.h | 38 +- admin/hyperspace_builder.cc | 940 ++-- admin/hyperspace_builder_internal.h | 10 +- admin/multi_yieldable.cc | 4 +- admin/multi_yieldable.h | 16 +- admin/partition.cc | 166 +- admin/partition.h | 2 +- admin/pending.cc | 4 +- admin/pending.h | 30 +- admin/pending_perf_counters.cc | 288 +- admin/pending_perf_counters.h | 76 +- admin/pending_raw_backup.cc | 98 +- admin/pending_raw_backup.h | 52 +- admin/pending_string.cc | 48 +- admin/pending_string.h | 58 +- admin/raw_backup.cc | 213 +- admin/yieldable.cc | 22 +- admin/yieldable.h | 64 +- bindings/c/admin-testcompile.c | 8 +- bindings/c/client-testcompile.c | 8 +- bindings/cc/admin-testcompile.cc | 8 +- bindings/cc/client-testcompile.cc | 8 +- bindings/java/client-util.h | 56 +- bindings/java/org_hyperdex_client_Client.c | 3756 +++++++------- .../org_hyperdex_client_Client.definitions.c | 1570 +++--- bindings/java/org_hyperdex_client_Client.h | 256 +- bindings/java/org_hyperdex_client_Deferred.h | 8 +- .../java/org_hyperdex_client_GreaterEqual.h | 4 +- .../java/org_hyperdex_client_GreaterThan.h | 4 +- bindings/java/org_hyperdex_client_Iterator.h | 8 +- .../java/org_hyperdex_client_LengthEquals.h | 4 +- .../org_hyperdex_client_LengthGreaterEqual.h | 4 +- .../org_hyperdex_client_LengthLessEqual.h | 4 +- bindings/java/org_hyperdex_client_LessEqual.h | 4 +- bindings/java/org_hyperdex_client_LessThan.h | 4 +- .../org_hyperdex_client_Microtransaction.c | 359 +- bindings/java/org_hyperdex_client_Range.h | 4 +- bindings/java/org_hyperdex_client_Regex.h | 4 +- bindings/node.js/client.cc | 4474 ++++++++-------- bindings/node.js/client.declarations.cc | 272 +- bindings/node.js/client.definitions.cc | 1796 +++---- bindings/ruby/client.c | 2618 +++++----- bindings/ruby/definitions.c | 1546 +++--- bindings/ruby/hyperdex.c | 7 +- cityhash/city.cc | 958 ++-- cityhash/city.h | 23 +- cityhash/test/city.cc | 3151 ++++++----- client/c.cc | 4599 ++++++++--------- client/client.cc | 2493 +++++---- client/client.h | 422 +- client/constants.h | 16 +- client/datastructures.cc | 2840 +++++----- client/keyop_info.h | 14 +- client/pending.cc | 22 +- client/pending.h | 106 +- client/pending_aggregation.cc | 68 +- client/pending_aggregation.h | 68 +- client/pending_atomic.cc | 184 +- client/pending_atomic.h | 48 +- client/pending_count.cc | 99 +- client/pending_count.h | 56 +- client/pending_get.cc | 245 +- client/pending_get.h | 62 +- client/pending_get_partial.cc | 258 +- client/pending_get_partial.h | 62 +- client/pending_group_atomic.cc | 126 +- client/pending_group_atomic.h | 58 +- client/pending_search.cc | 192 +- client/pending_search.h | 60 +- client/pending_search_describe.cc | 113 +- client/pending_search_describe.h | 72 +- client/pending_sorted_search.cc | 399 +- client/pending_sorted_search.h | 161 +- client/pending_sum.cc | 114 +- client/pending_sum.h | 64 +- client/test/datastructures.cc | 1298 +++-- client/util.cc | 340 +- client/util.h | 30 +- common/attribute.cc | 26 +- common/attribute.h | 18 +- common/attribute_check.cc | 371 +- common/attribute_check.h | 44 +- common/auth_wallet.cc | 101 +- common/auth_wallet.h | 36 +- common/configuration.cc | 1831 +++---- common/configuration.h | 242 +- common/coordinator_returncode.cc | 31 +- common/coordinator_returncode.h | 16 +- common/datatype_document.cc | 796 ++- common/datatype_document.h | 74 +- common/datatype_float.cc | 305 +- common/datatype_float.h | 64 +- common/datatype_info.cc | 254 +- common/datatype_info.h | 172 +- common/datatype_int64.cc | 357 +- common/datatype_int64.h | 64 +- common/datatype_list.cc | 278 +- common/datatype_list.h | 50 +- common/datatype_macaroon_secret.cc | 44 +- common/datatype_macaroon_secret.h | 22 +- common/datatype_map.cc | 482 +- common/datatype_map.h | 84 +- common/datatype_set.cc | 345 +- common/datatype_set.h | 50 +- common/datatype_string.cc | 323 +- common/datatype_string.h | 68 +- common/datatype_timestamp.cc | 307 +- common/datatype_timestamp.h | 58 +- common/documents.cc | 41 +- common/documents.h | 10 +- common/funcall.cc | 289 +- common/funcall.h | 120 +- common/hash.cc | 45 +- common/hash.h | 16 +- common/hyperdex.cc | 132 +- common/hyperspace.cc | 758 ++- common/hyperspace.h | 168 +- common/ids.cc | 36 +- common/ids.h | 66 +- common/ieee.h | 33 +- common/index.cc | 104 +- common/index.h | 42 +- common/json_path.h | 153 +- common/key_change.cc | 186 +- common/key_change.h | 58 +- common/mapper.cc | 10 +- common/mapper.h | 20 +- common/network_msgtype.cc | 87 +- common/network_msgtype.h | 72 +- common/network_returncode.h | 18 +- common/ordered_encoding.cc | 96 +- common/range.cc | 56 +- common/range.h | 30 +- common/range_searches.cc | 269 +- common/range_searches.h | 6 +- common/regex_match.cc | 155 +- common/regex_match.h | 4 +- common/schema.cc | 25 +- common/schema.h | 16 +- common/serialization.cc | 40 +- common/serialization.h | 12 +- common/server.cc | 74 +- common/server.h | 42 +- common/test/ordered_encoding.cc | 136 +- common/transfer.cc | 185 +- common/transfer.h | 50 +- configure.ac | 2 +- coordinator/coordinator.cc | 3494 ++++++------- coordinator/coordinator.h | 350 +- coordinator/offline_server.h | 42 +- coordinator/region_intent.h | 77 +- coordinator/replica_sets.cc | 197 +- coordinator/replica_sets.h | 36 +- coordinator/server_barrier.cc | 177 +- coordinator/server_barrier.h | 40 +- coordinator/symtable.c | 62 +- coordinator/transitions.cc | 730 ++- coordinator/transitions.h | 18 +- coordinator/util.h | 58 +- daemon/auth.cc | 275 +- daemon/auth.h | 24 +- daemon/background_thread.cc | 214 +- daemon/background_thread.h | 80 +- daemon/communication.cc | 727 ++- daemon/communication.h | 124 +- daemon/coordinator_link.cc | 780 ++- daemon/coordinator_link.h | 120 +- daemon/daemon.cc | 2410 ++++----- daemon/daemon.h | 214 +- daemon/datalayer.cc | 2163 ++++---- daemon/datalayer.h | 322 +- daemon/datalayer_checkpointer_thread.cc | 167 +- daemon/datalayer_checkpointer_thread.h | 52 +- daemon/datalayer_encodings.cc | 451 +- daemon/datalayer_encodings.h | 80 +- daemon/datalayer_index_state.h | 47 +- daemon/datalayer_indexer_thread.cc | 712 ++- daemon/datalayer_indexer_thread.h | 78 +- daemon/datalayer_iterator.cc | 1062 ++-- daemon/datalayer_iterator.h | 372 +- daemon/datalayer_wiper_indexer_mediator.h | 112 +- daemon/datalayer_wiper_thread.cc | 328 +- daemon/datalayer_wiper_thread.h | 84 +- daemon/identifier_collector.cc | 90 +- daemon/identifier_collector.h | 50 +- daemon/identifier_generator.cc | 96 +- daemon/identifier_generator.h | 52 +- daemon/index_container.cc | 171 +- daemon/index_container.h | 42 +- daemon/index_document.cc | 717 ++- daemon/index_document.h | 124 +- daemon/index_float.cc | 60 +- daemon/index_float.h | 30 +- daemon/index_info.cc | 254 +- daemon/index_info.h | 112 +- daemon/index_int64.cc | 40 +- daemon/index_int64.h | 30 +- daemon/index_list.cc | 40 +- daemon/index_list.h | 26 +- daemon/index_map.cc | 56 +- daemon/index_map.h | 30 +- daemon/index_primitive.cc | 464 +- daemon/index_primitive.h | 118 +- daemon/index_set.cc | 40 +- daemon/index_set.h | 26 +- daemon/index_string.cc | 30 +- daemon/index_string.h | 30 +- daemon/index_timestamp.cc | 32 +- daemon/index_timestamp.h | 36 +- daemon/key_operation.cc | 116 +- daemon/key_operation.h | 172 +- daemon/key_region.cc | 50 +- daemon/key_region.h | 38 +- daemon/key_state.cc | 2360 ++++----- daemon/key_state.h | 430 +- daemon/leveldb.h | 143 +- daemon/main.cc | 293 +- daemon/performance_counter.h | 34 +- daemon/reconfigure_returncode.h | 12 +- daemon/region_timestamp.h | 20 +- daemon/replication_manager.cc | 1337 +++-- daemon/replication_manager.h | 210 +- daemon/search_manager.cc | 1156 ++--- daemon/search_manager.h | 152 +- daemon/state_hash_table.h | 530 +- daemon/state_transfer_manager.cc | 1061 ++-- daemon/state_transfer_manager.h | 138 +- daemon/state_transfer_manager_pending.cc | 20 +- daemon/state_transfer_manager_pending.h | 48 +- ...tate_transfer_manager_transfer_in_state.cc | 28 +- ...state_transfer_manager_transfer_in_state.h | 40 +- ...ate_transfer_manager_transfer_out_state.cc | 36 +- ...tate_transfer_manager_transfer_out_state.h | 50 +- daemon/test/identifier_collector.cc | 91 +- daemon/test/identifier_generator.cc | 52 +- doc/2013-06-28-cloudphysics.pdf | Bin 0 -> 1722299 bytes doc/7427-escriva12-06.pdf | Bin 0 -> 164158 bytes doc/c/client/hello-world.c | 72 +- doc/c/client/iterate.c | 39 +- doc/warp.pdf | Bin 0 -> 435717 bytes hyperdex.cc | 62 +- include/hyperdex.h | 130 +- include/hyperdex/admin.h | 190 +- include/hyperdex/admin.hpp | 152 +- include/hyperdex/client.h | 1652 +++--- include/hyperdex/client.hpp | 1478 +++--- include/hyperdex/datastructures.h | 234 +- include/hyperdex/hyperspace_builder.h | 56 +- maint/generate-test-packages.py | 160 + maint/lib-check.c | 40 +- namespace.h | 2 +- osx/ieee754.h | 228 +- test/replication-stress-test.cc | 729 ++- test/search-stress-test.cc | 1212 ++--- test/sh/bindings.go.Basic.sh | 4 + test/sh/bindings.go.BasicSearch.sh | 4 + test/sh/bindings.go.CondPut.sh | 4 + test/sh/bindings.go.DataTypeFloat.sh | 4 + test/sh/bindings.go.DataTypeInt.sh | 4 + test/sh/bindings.go.DataTypeListFloat.sh | 4 + test/sh/bindings.go.DataTypeListInt.sh | 4 + test/sh/bindings.go.DataTypeListString.sh | 4 + test/sh/bindings.go.DataTypeMapFloatFloat.sh | 4 + test/sh/bindings.go.DataTypeMapFloatInt.sh | 4 + test/sh/bindings.go.DataTypeMapFloatString.sh | 4 + test/sh/bindings.go.DataTypeMapIntFloat.sh | 4 + test/sh/bindings.go.DataTypeMapIntInt.sh | 4 + test/sh/bindings.go.DataTypeMapIntString.sh | 4 + test/sh/bindings.go.DataTypeMapStringFloat.sh | 4 + test/sh/bindings.go.DataTypeMapStringInt.sh | 4 + .../sh/bindings.go.DataTypeMapStringString.sh | 4 + test/sh/bindings.go.DataTypeSetFloat.sh | 4 + test/sh/bindings.go.DataTypeSetInt.sh | 4 + test/sh/bindings.go.DataTypeSetString.sh | 4 + test/sh/bindings.go.DataTypeString.sh | 4 + test/sh/bindings.go.LengthString.sh | 4 + test/sh/bindings.go.MultiAttribute.sh | 4 + test/sh/bindings.go.RangeSearchInt.sh | 4 + test/sh/bindings.go.RangeSearchString.sh | 4 + test/sh/bindings.go.RegexSearch.sh | 4 + test/sh/bindings.java.Basic.sh | 5 + test/sh/bindings.java.BasicSearch.sh | 5 + test/sh/bindings.java.CondPut.sh | 5 + test/sh/bindings.java.DataTypeFloat.sh | 5 + test/sh/bindings.java.DataTypeInt.sh | 5 + test/sh/bindings.java.DataTypeListFloat.sh | 5 + test/sh/bindings.java.DataTypeListInt.sh | 5 + test/sh/bindings.java.DataTypeListString.sh | 5 + .../sh/bindings.java.DataTypeMapFloatFloat.sh | 5 + test/sh/bindings.java.DataTypeMapFloatInt.sh | 5 + .../bindings.java.DataTypeMapFloatString.sh | 5 + test/sh/bindings.java.DataTypeMapIntFloat.sh | 5 + test/sh/bindings.java.DataTypeMapIntInt.sh | 5 + test/sh/bindings.java.DataTypeMapIntString.sh | 5 + .../bindings.java.DataTypeMapStringFloat.sh | 5 + test/sh/bindings.java.DataTypeMapStringInt.sh | 5 + .../bindings.java.DataTypeMapStringString.sh | 5 + test/sh/bindings.java.DataTypeSetFloat.sh | 5 + test/sh/bindings.java.DataTypeSetInt.sh | 5 + test/sh/bindings.java.DataTypeSetString.sh | 5 + test/sh/bindings.java.DataTypeString.sh | 5 + test/sh/bindings.java.LengthString.sh | 5 + test/sh/bindings.java.MultiAttribute.sh | 5 + test/sh/bindings.java.RangeSearchInt.sh | 5 + test/sh/bindings.java.RangeSearchString.sh | 5 + test/sh/bindings.java.RegexSearch.sh | 5 + test/sh/bindings.python.Admin.sh | 4 + test/sh/bindings.python.Basic.sh | 4 + test/sh/bindings.python.BasicSearch.sh | 4 + test/sh/bindings.python.CondPut.sh | 4 + test/sh/bindings.python.DataTypeDocument.sh | 4 + test/sh/bindings.python.DataTypeFloat.sh | 4 + test/sh/bindings.python.DataTypeInt.sh | 4 + test/sh/bindings.python.DataTypeListFloat.sh | 4 + test/sh/bindings.python.DataTypeListInt.sh | 4 + test/sh/bindings.python.DataTypeListString.sh | 4 + .../bindings.python.DataTypeMapFloatFloat.sh | 4 + .../sh/bindings.python.DataTypeMapFloatInt.sh | 4 + .../bindings.python.DataTypeMapFloatString.sh | 4 + .../sh/bindings.python.DataTypeMapIntFloat.sh | 4 + test/sh/bindings.python.DataTypeMapIntInt.sh | 4 + .../bindings.python.DataTypeMapIntString.sh | 4 + .../bindings.python.DataTypeMapStringFloat.sh | 4 + .../bindings.python.DataTypeMapStringInt.sh | 4 + ...bindings.python.DataTypeMapStringString.sh | 4 + test/sh/bindings.python.DataTypeSetFloat.sh | 4 + test/sh/bindings.python.DataTypeSetInt.sh | 4 + test/sh/bindings.python.DataTypeSetString.sh | 4 + test/sh/bindings.python.DataTypeString.sh | 4 + test/sh/bindings.python.GroupAtomic.sh | 4 + test/sh/bindings.python.HyperMongo.sh | 5 + test/sh/bindings.python.LengthString.sh | 4 + test/sh/bindings.python.MultiAttribute.sh | 4 + test/sh/bindings.python.RangeSearchInt.sh | 4 + test/sh/bindings.python.RangeSearchString.sh | 4 + test/sh/bindings.python.RegexSearch.sh | 4 + test/sh/bindings.ruby.Basic.sh | 4 + test/sh/bindings.ruby.BasicSearch.sh | 4 + test/sh/bindings.ruby.CondPut.sh | 4 + test/sh/bindings.ruby.DataTypeFloat.sh | 4 + test/sh/bindings.ruby.DataTypeInt.sh | 4 + test/sh/bindings.ruby.DataTypeListFloat.sh | 4 + test/sh/bindings.ruby.DataTypeListInt.sh | 4 + test/sh/bindings.ruby.DataTypeListString.sh | 4 + .../sh/bindings.ruby.DataTypeMapFloatFloat.sh | 4 + test/sh/bindings.ruby.DataTypeMapFloatInt.sh | 4 + .../bindings.ruby.DataTypeMapFloatString.sh | 4 + test/sh/bindings.ruby.DataTypeMapIntFloat.sh | 4 + test/sh/bindings.ruby.DataTypeMapIntInt.sh | 4 + test/sh/bindings.ruby.DataTypeMapIntString.sh | 4 + .../bindings.ruby.DataTypeMapStringFloat.sh | 4 + test/sh/bindings.ruby.DataTypeMapStringInt.sh | 4 + .../bindings.ruby.DataTypeMapStringString.sh | 4 + test/sh/bindings.ruby.DataTypeSetFloat.sh | 4 + test/sh/bindings.ruby.DataTypeSetInt.sh | 4 + test/sh/bindings.ruby.DataTypeSetString.sh | 4 + test/sh/bindings.ruby.DataTypeString.sh | 4 + test/sh/bindings.ruby.LengthString.sh | 4 + test/sh/bindings.ruby.MultiAttribute.sh | 4 + test/sh/bindings.ruby.RangeSearchInt.sh | 4 + test/sh/bindings.ruby.RangeSearchString.sh | 4 + test/sh/bindings.ruby.RegexSearch.sh | 4 + test/sh/doc.async-ops.sh | 4 + test/sh/doc.atomic-ops.sh | 4 + test/sh/doc.authorization.sh | 4 + test/sh/doc.data-types.sh | 4 + test/sh/doc.documents.sh | 4 + test/sh/doc.quick-start.sh | 4 + ...n.composite.daemons=1.fault-tolerance=0.sh | 4 + ...n.composite.daemons=4.fault-tolerance=0.sh | 4 + ...n.composite.daemons=4.fault-tolerance=1.sh | 4 + ...n.composite.daemons=4.fault-tolerance=2.sh | 4 + ...ion.reverse.daemons=1.fault-tolerance=0.sh | 4 + ...ion.reverse.daemons=4.fault-tolerance=0.sh | 4 + ...ion.reverse.daemons=4.fault-tolerance=1.sh | 4 + ...ion.reverse.daemons=4.fault-tolerance=2.sh | 4 + ...tion.simple.daemons=1.fault-tolerance=0.sh | 4 + ...tion.simple.daemons=4.fault-tolerance=0.sh | 4 + ...tion.simple.daemons=4.fault-tolerance=1.sh | 4 + ...tion.simple.daemons=4.fault-tolerance=2.sh | 4 + ...keytype=int,daemons=1.fault-tolerance=0.sh | 4 + ...keytype=int,daemons=4.fault-tolerance=0.sh | 4 + ...keytype=int,daemons=4.fault-tolerance=1.sh | 4 + ...type=string,daemons=1.fault-tolerance=0.sh | 4 + ...type=string,daemons=4.fault-tolerance=0.sh | 4 + ...type=string,daemons=4.fault-tolerance=1.sh | 4 + ...keytype=int,daemons=1.fault-tolerance=0.sh | 4 + ...keytype=int,daemons=4.fault-tolerance=0.sh | 4 + ...keytype=int,daemons=4.fault-tolerance=1.sh | 4 + ...type=string,daemons=1.fault-tolerance=0.sh | 4 + ...type=string,daemons=4.fault-tolerance=0.sh | 4 + ...type=string,daemons=4.fault-tolerance=1.sh | 4 + ...keytype=int,daemons=1.fault-tolerance=0.sh | 4 + ...keytype=int,daemons=4.fault-tolerance=0.sh | 4 + ...keytype=int,daemons=4.fault-tolerance=1.sh | 4 + ...type=string,daemons=1.fault-tolerance=0.sh | 4 + ...type=string,daemons=4.fault-tolerance=0.sh | 4 + ...type=string,daemons=4.fault-tolerance=1.sh | 4 + ...keytype=int,daemons=1.fault-tolerance=0.sh | 4 + ...keytype=int,daemons=4.fault-tolerance=0.sh | 4 + ...keytype=int,daemons=4.fault-tolerance=1.sh | 4 + ...type=string,daemons=1.fault-tolerance=0.sh | 4 + ...type=string,daemons=4.fault-tolerance=0.sh | 4 + ...type=string,daemons=4.fault-tolerance=1.sh | 4 + test/simple-consistency-stress-test.cc | 665 ++- test/th.cc | 232 +- test/th.h | 134 +- test/th_main.cc | 16 +- tools/add-index.cc | 112 +- tools/add-space.cc | 140 +- tools/backup-manager.cc | 684 ++- tools/backup.cc | 127 +- tools/common.h | 184 +- tools/coordinator.cc | 100 +- tools/list-spaces.cc | 117 +- tools/mv-space.cc | 114 +- tools/perf-counters.cc | 102 +- tools/raw-backup.cc | 154 +- tools/rm-index.cc | 130 +- tools/rm-space.cc | 114 +- tools/server-forget.cc | 132 +- tools/server-kill.cc | 132 +- tools/server-offline.cc | 132 +- tools/server-online.cc | 132 +- tools/server-register.cc | 132 +- tools/set-fault-tolerance.cc | 132 +- tools/set-read-only.cc | 114 +- tools/set-read-write.cc | 114 +- tools/show-config.cc | 116 +- tools/validate-space.cc | 85 +- tools/wait-until-stable.cc | 112 +- windows/hyperclientclr.cpp | 1857 ++++--- windows/hyperclientclr.h | 210 +- windows/ieee754.h | 228 +- windows/marshal.cpp | 762 ++- windows/marshal.h | 144 +- windows/unistd.h | 12 +- 447 files changed, 45938 insertions(+), 48352 deletions(-) mode change 100755 => 100644 common/coordinator_returncode.h mode change 100755 => 100644 common/network_returncode.h create mode 100644 doc/2013-06-28-cloudphysics.pdf create mode 100644 doc/7427-escriva12-06.pdf create mode 100644 doc/warp.pdf create mode 100644 maint/generate-test-packages.py create mode 100755 test/sh/bindings.go.Basic.sh create mode 100755 test/sh/bindings.go.BasicSearch.sh create mode 100755 test/sh/bindings.go.CondPut.sh create mode 100755 test/sh/bindings.go.DataTypeFloat.sh create mode 100755 test/sh/bindings.go.DataTypeInt.sh create mode 100755 test/sh/bindings.go.DataTypeListFloat.sh create mode 100755 test/sh/bindings.go.DataTypeListInt.sh create mode 100755 test/sh/bindings.go.DataTypeListString.sh create mode 100755 test/sh/bindings.go.DataTypeMapFloatFloat.sh create mode 100755 test/sh/bindings.go.DataTypeMapFloatInt.sh create mode 100755 test/sh/bindings.go.DataTypeMapFloatString.sh create mode 100755 test/sh/bindings.go.DataTypeMapIntFloat.sh create mode 100755 test/sh/bindings.go.DataTypeMapIntInt.sh create mode 100755 test/sh/bindings.go.DataTypeMapIntString.sh create mode 100755 test/sh/bindings.go.DataTypeMapStringFloat.sh create mode 100755 test/sh/bindings.go.DataTypeMapStringInt.sh create mode 100755 test/sh/bindings.go.DataTypeMapStringString.sh create mode 100755 test/sh/bindings.go.DataTypeSetFloat.sh create mode 100755 test/sh/bindings.go.DataTypeSetInt.sh create mode 100755 test/sh/bindings.go.DataTypeSetString.sh create mode 100755 test/sh/bindings.go.DataTypeString.sh create mode 100755 test/sh/bindings.go.LengthString.sh create mode 100755 test/sh/bindings.go.MultiAttribute.sh create mode 100755 test/sh/bindings.go.RangeSearchInt.sh create mode 100755 test/sh/bindings.go.RangeSearchString.sh create mode 100755 test/sh/bindings.go.RegexSearch.sh create mode 100755 test/sh/bindings.java.Basic.sh create mode 100755 test/sh/bindings.java.BasicSearch.sh create mode 100755 test/sh/bindings.java.CondPut.sh create mode 100755 test/sh/bindings.java.DataTypeFloat.sh create mode 100755 test/sh/bindings.java.DataTypeInt.sh create mode 100755 test/sh/bindings.java.DataTypeListFloat.sh create mode 100755 test/sh/bindings.java.DataTypeListInt.sh create mode 100755 test/sh/bindings.java.DataTypeListString.sh create mode 100755 test/sh/bindings.java.DataTypeMapFloatFloat.sh create mode 100755 test/sh/bindings.java.DataTypeMapFloatInt.sh create mode 100755 test/sh/bindings.java.DataTypeMapFloatString.sh create mode 100755 test/sh/bindings.java.DataTypeMapIntFloat.sh create mode 100755 test/sh/bindings.java.DataTypeMapIntInt.sh create mode 100755 test/sh/bindings.java.DataTypeMapIntString.sh create mode 100755 test/sh/bindings.java.DataTypeMapStringFloat.sh create mode 100755 test/sh/bindings.java.DataTypeMapStringInt.sh create mode 100755 test/sh/bindings.java.DataTypeMapStringString.sh create mode 100755 test/sh/bindings.java.DataTypeSetFloat.sh create mode 100755 test/sh/bindings.java.DataTypeSetInt.sh create mode 100755 test/sh/bindings.java.DataTypeSetString.sh create mode 100755 test/sh/bindings.java.DataTypeString.sh create mode 100755 test/sh/bindings.java.LengthString.sh create mode 100755 test/sh/bindings.java.MultiAttribute.sh create mode 100755 test/sh/bindings.java.RangeSearchInt.sh create mode 100755 test/sh/bindings.java.RangeSearchString.sh create mode 100755 test/sh/bindings.java.RegexSearch.sh create mode 100755 test/sh/bindings.python.Admin.sh create mode 100755 test/sh/bindings.python.Basic.sh create mode 100755 test/sh/bindings.python.BasicSearch.sh create mode 100755 test/sh/bindings.python.CondPut.sh create mode 100755 test/sh/bindings.python.DataTypeDocument.sh create mode 100755 test/sh/bindings.python.DataTypeFloat.sh create mode 100755 test/sh/bindings.python.DataTypeInt.sh create mode 100755 test/sh/bindings.python.DataTypeListFloat.sh create mode 100755 test/sh/bindings.python.DataTypeListInt.sh create mode 100755 test/sh/bindings.python.DataTypeListString.sh create mode 100755 test/sh/bindings.python.DataTypeMapFloatFloat.sh create mode 100755 test/sh/bindings.python.DataTypeMapFloatInt.sh create mode 100755 test/sh/bindings.python.DataTypeMapFloatString.sh create mode 100755 test/sh/bindings.python.DataTypeMapIntFloat.sh create mode 100755 test/sh/bindings.python.DataTypeMapIntInt.sh create mode 100755 test/sh/bindings.python.DataTypeMapIntString.sh create mode 100755 test/sh/bindings.python.DataTypeMapStringFloat.sh create mode 100755 test/sh/bindings.python.DataTypeMapStringInt.sh create mode 100755 test/sh/bindings.python.DataTypeMapStringString.sh create mode 100755 test/sh/bindings.python.DataTypeSetFloat.sh create mode 100755 test/sh/bindings.python.DataTypeSetInt.sh create mode 100755 test/sh/bindings.python.DataTypeSetString.sh create mode 100755 test/sh/bindings.python.DataTypeString.sh create mode 100755 test/sh/bindings.python.GroupAtomic.sh create mode 100755 test/sh/bindings.python.HyperMongo.sh create mode 100755 test/sh/bindings.python.LengthString.sh create mode 100755 test/sh/bindings.python.MultiAttribute.sh create mode 100755 test/sh/bindings.python.RangeSearchInt.sh create mode 100755 test/sh/bindings.python.RangeSearchString.sh create mode 100755 test/sh/bindings.python.RegexSearch.sh create mode 100755 test/sh/bindings.ruby.Basic.sh create mode 100755 test/sh/bindings.ruby.BasicSearch.sh create mode 100755 test/sh/bindings.ruby.CondPut.sh create mode 100755 test/sh/bindings.ruby.DataTypeFloat.sh create mode 100755 test/sh/bindings.ruby.DataTypeInt.sh create mode 100755 test/sh/bindings.ruby.DataTypeListFloat.sh create mode 100755 test/sh/bindings.ruby.DataTypeListInt.sh create mode 100755 test/sh/bindings.ruby.DataTypeListString.sh create mode 100755 test/sh/bindings.ruby.DataTypeMapFloatFloat.sh create mode 100755 test/sh/bindings.ruby.DataTypeMapFloatInt.sh create mode 100755 test/sh/bindings.ruby.DataTypeMapFloatString.sh create mode 100755 test/sh/bindings.ruby.DataTypeMapIntFloat.sh create mode 100755 test/sh/bindings.ruby.DataTypeMapIntInt.sh create mode 100755 test/sh/bindings.ruby.DataTypeMapIntString.sh create mode 100755 test/sh/bindings.ruby.DataTypeMapStringFloat.sh create mode 100755 test/sh/bindings.ruby.DataTypeMapStringInt.sh create mode 100755 test/sh/bindings.ruby.DataTypeMapStringString.sh create mode 100755 test/sh/bindings.ruby.DataTypeSetFloat.sh create mode 100755 test/sh/bindings.ruby.DataTypeSetInt.sh create mode 100755 test/sh/bindings.ruby.DataTypeSetString.sh create mode 100755 test/sh/bindings.ruby.DataTypeString.sh create mode 100755 test/sh/bindings.ruby.LengthString.sh create mode 100755 test/sh/bindings.ruby.MultiAttribute.sh create mode 100755 test/sh/bindings.ruby.RangeSearchInt.sh create mode 100755 test/sh/bindings.ruby.RangeSearchString.sh create mode 100755 test/sh/bindings.ruby.RegexSearch.sh create mode 100755 test/sh/doc.async-ops.sh create mode 100755 test/sh/doc.atomic-ops.sh create mode 100755 test/sh/doc.authorization.sh create mode 100755 test/sh/doc.data-types.sh create mode 100755 test/sh/doc.documents.sh create mode 100755 test/sh/doc.quick-start.sh create mode 100755 test/sh/replication.composite.daemons=1.fault-tolerance=0.sh create mode 100755 test/sh/replication.composite.daemons=4.fault-tolerance=0.sh create mode 100755 test/sh/replication.composite.daemons=4.fault-tolerance=1.sh create mode 100755 test/sh/replication.composite.daemons=4.fault-tolerance=2.sh create mode 100755 test/sh/replication.reverse.daemons=1.fault-tolerance=0.sh create mode 100755 test/sh/replication.reverse.daemons=4.fault-tolerance=0.sh create mode 100755 test/sh/replication.reverse.daemons=4.fault-tolerance=1.sh create mode 100755 test/sh/replication.reverse.daemons=4.fault-tolerance=2.sh create mode 100755 test/sh/replication.simple.daemons=1.fault-tolerance=0.sh create mode 100755 test/sh/replication.simple.daemons=4.fault-tolerance=0.sh create mode 100755 test/sh/replication.simple.daemons=4.fault-tolerance=1.sh create mode 100755 test/sh/replication.simple.daemons=4.fault-tolerance=2.sh create mode 100755 test/sh/search.combination.keytype=int,daemons=1.fault-tolerance=0.sh create mode 100755 test/sh/search.combination.keytype=int,daemons=4.fault-tolerance=0.sh create mode 100755 test/sh/search.combination.keytype=int,daemons=4.fault-tolerance=1.sh create mode 100755 test/sh/search.combination.keytype=string,daemons=1.fault-tolerance=0.sh create mode 100755 test/sh/search.combination.keytype=string,daemons=4.fault-tolerance=0.sh create mode 100755 test/sh/search.combination.keytype=string,daemons=4.fault-tolerance=1.sh create mode 100755 test/sh/search.index.keytype=int,daemons=1.fault-tolerance=0.sh create mode 100755 test/sh/search.index.keytype=int,daemons=4.fault-tolerance=0.sh create mode 100755 test/sh/search.index.keytype=int,daemons=4.fault-tolerance=1.sh create mode 100755 test/sh/search.index.keytype=string,daemons=1.fault-tolerance=0.sh create mode 100755 test/sh/search.index.keytype=string,daemons=4.fault-tolerance=0.sh create mode 100755 test/sh/search.index.keytype=string,daemons=4.fault-tolerance=1.sh create mode 100755 test/sh/search.simple.keytype=int,daemons=1.fault-tolerance=0.sh create mode 100755 test/sh/search.simple.keytype=int,daemons=4.fault-tolerance=0.sh create mode 100755 test/sh/search.simple.keytype=int,daemons=4.fault-tolerance=1.sh create mode 100755 test/sh/search.simple.keytype=string,daemons=1.fault-tolerance=0.sh create mode 100755 test/sh/search.simple.keytype=string,daemons=4.fault-tolerance=0.sh create mode 100755 test/sh/search.simple.keytype=string,daemons=4.fault-tolerance=1.sh create mode 100755 test/sh/search.subspace.keytype=int,daemons=1.fault-tolerance=0.sh create mode 100755 test/sh/search.subspace.keytype=int,daemons=4.fault-tolerance=0.sh create mode 100755 test/sh/search.subspace.keytype=int,daemons=4.fault-tolerance=1.sh create mode 100755 test/sh/search.subspace.keytype=string,daemons=1.fault-tolerance=0.sh create mode 100755 test/sh/search.subspace.keytype=string,daemons=4.fault-tolerance=0.sh create mode 100755 test/sh/search.subspace.keytype=string,daemons=4.fault-tolerance=1.sh diff --git a/admin/admin.cc b/admin/admin.cc index dd71692b7..e64c91142 100644 --- a/admin/admin.cc +++ b/admin/admin.cc @@ -53,1011 +53,920 @@ #include "admin/yieldable.h" #define ERROR(CODE) \ - *status = HYPERDEX_ADMIN_ ## CODE; \ - m_last_error.set_loc(__FILE__, __LINE__); \ - m_last_error.set_msg() + *status = HYPERDEX_ADMIN_ ## CODE; \ + m_last_error.set_loc(__FILE__, __LINE__); \ + m_last_error.set_msg() using hyperdex::admin; -admin :: admin(const char* coordinator, uint16_t port) - : m_coord(replicant_client_create(coordinator, port)) - , m_busybee_mapper(&m_config) - , m_busybee(&m_busybee_mapper, 0) - , m_config() - , m_config_id(-1) - , m_config_status() - , m_config_state(0) - , m_config_data(NULL) - , m_config_data_sz(0) - , m_next_admin_id(1) - , m_next_server_nonce(1) - , m_handle_coord_ops(false) - , m_coord_ops() - , m_server_ops() - , m_multi_ops() - , m_failed() - , m_yieldable() - , m_yielding() - , m_yielded() - , m_pcs() - , m_last_error() +admin :: admin(const char *coordinator, uint16_t port) + : m_coord(replicant_client_create(coordinator, port)) + , m_busybee_mapper(&m_config) + , m_busybee(&m_busybee_mapper, 0) + , m_config() + , m_config_id(-1) + , m_config_status() + , m_config_state(0) + , m_config_data(NULL) + , m_config_data_sz(0) + , m_next_admin_id(1) + , m_next_server_nonce(1) + , m_handle_coord_ops(false) + , m_coord_ops() + , m_server_ops() + , m_multi_ops() + , m_failed() + , m_yieldable() + , m_yielding() + , m_yielded() + , m_pcs() + , m_last_error() { - m_busybee.set_external_fd(replicant_client_poll_fd(m_coord)); + m_busybee.set_external_fd(replicant_client_poll_fd(m_coord)); } admin :: ~admin() throw () { - replicant_client_destroy(m_coord); + replicant_client_destroy(m_coord); } int64_t -admin :: dump_config(hyperdex_admin_returncode* status, - const char** config) +admin :: dump_config(hyperdex_admin_returncode *status, + const char **config) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - std::string tmp = m_config.dump(); - e::intrusive_ptr op = new pending_string(id, status, HYPERDEX_ADMIN_SUCCESS, tmp, config); - m_yieldable.push_back(op.get()); - return op->admin_visible_id(); + if (!maintain_coord_connection(status)) + { + return -1; + } + int64_t id = m_next_admin_id; + ++m_next_admin_id; + std::string tmp = m_config.dump(); + e::intrusive_ptr op = new pending_string(id, status, HYPERDEX_ADMIN_SUCCESS, tmp, config); + m_yieldable.push_back(op.get()); + return op->admin_visible_id(); } int64_t -admin :: list_subspaces(const char* space, hyperdex_admin_returncode* status, const char** subspaces) +admin :: list_subspaces(const char *space, hyperdex_admin_returncode *status, const char **subspaces) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - std::string tmp = m_config.list_subspaces(space); - e::intrusive_ptr op = new pending_string(id, status, HYPERDEX_ADMIN_SUCCESS, tmp, subspaces); - m_yieldable.push_back(op.get()); - return op->admin_visible_id(); + if (!maintain_coord_connection(status)) + { + return -1; + } + int64_t id = m_next_admin_id; + ++m_next_admin_id; + std::string tmp = m_config.list_subspaces(space); + e::intrusive_ptr op = new pending_string(id, status, HYPERDEX_ADMIN_SUCCESS, tmp, subspaces); + m_yieldable.push_back(op.get()); + return op->admin_visible_id(); } int64_t -admin :: read_only(int ro, hyperdex_admin_returncode* status) +admin :: read_only(int ro, hyperdex_admin_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - bool set = ro != 0; - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op = new coord_rpc_generic(id, status, (set ? "set read-only" : "set read-write")); - char buf[sizeof(uint8_t)]; - buf[0] = set ? 1 : 0; - int64_t cid = rpc("read_only", buf, sizeof(uint8_t), - &op->repl_status, &op->repl_output, &op->repl_output_sz); - - if (cid >= 0) - { - m_coord_ops[cid] = op; - return op->admin_visible_id(); - } - else - { - interpret_replicant_returncode(op->repl_status, status, &m_last_error); - return -1; - } + if (!maintain_coord_connection(status)) + { + return -1; + } + bool set = ro != 0; + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_generic(id, status, (set ? "set read-only" : "set read-write")); + char buf[sizeof(uint8_t)]; + buf[0] = set ? 1 : 0; + int64_t cid = rpc("read_only", buf, sizeof(uint8_t), + &op->repl_status, &op->repl_output, &op->repl_output_sz); + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_replicant_returncode(op->repl_status, status, &m_last_error); + return -1; + } } int64_t -admin :: wait_until_stable(enum hyperdex_admin_returncode* status) +admin :: wait_until_stable(enum hyperdex_admin_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op = new coord_rpc_generic(id, status, "wait for stability"); - int64_t cid = replicant_client_cond_wait(m_coord, "hyperdex", "stable", m_config.version(), &op->repl_status, NULL, NULL); - - if (cid >= 0) - { - m_coord_ops[cid] = op; - return op->admin_visible_id(); - } - else - { - interpret_replicant_returncode(op->repl_status, status, &m_last_error); - return -1; - } + if (!maintain_coord_connection(status)) + { + return -1; + } + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_generic(id, status, "wait for stability"); + int64_t cid = replicant_client_cond_wait(m_coord, "hyperdex", "stable", m_config.version(), &op->repl_status, NULL, NULL); + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_replicant_returncode(op->repl_status, status, &m_last_error); + return -1; + } } int64_t -admin :: fault_tolerance(const char* space, uint64_t ft, - hyperdex_admin_returncode* status) +admin :: fault_tolerance(const char *space, uint64_t ft, + hyperdex_admin_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op = new coord_rpc_generic(id, status, "fault tolerance"); - size_t space_sz = strlen(space); - std::vector buf(space_sz + sizeof(uint64_t)); - memcpy(&buf[0], space, space_sz); - e::pack64be(ft, &buf[0] + space_sz); - - int64_t cid = rpc("fault_tolerance", &buf[0], space_sz + sizeof(uint64_t), - &op->repl_status, &op->repl_output, &op->repl_output_sz); - - if (cid >= 0) - { - m_coord_ops[cid] = op; - return op->admin_visible_id(); - } - else - { - interpret_replicant_returncode(op->repl_status, status, &m_last_error); - return -1; - } + if (!maintain_coord_connection(status)) + { + return -1; + } + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_generic(id, status, "fault tolerance"); + size_t space_sz = strlen(space); + std::vector buf(space_sz + sizeof(uint64_t)); + memcpy(&buf[0], space, space_sz); + e::pack64be(ft, &buf[0] + space_sz); + int64_t cid = rpc("fault_tolerance", &buf[0], space_sz + sizeof(uint64_t), + &op->repl_status, &op->repl_output, &op->repl_output_sz); + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_replicant_returncode(op->repl_status, status, &m_last_error); + return -1; + } } int -admin :: validate_space(const char* description, - hyperdex_admin_returncode* status) +admin :: validate_space(const char *description, + hyperdex_admin_returncode *status) { - struct hyperspace* space_builder = hyperspace_parse(description); - - if (!space_builder) - { - ERROR(NOMEM) << "ran out of memory"; - return -1; - } - - if (hyperspace_error(space_builder)) - { - ERROR(BADSPACE) << "bad space " << hyperspace_error(space_builder); - return -1; - } - - return 0; + struct hyperspace *space_builder = hyperspace_parse(description); + if (!space_builder) + { + ERROR(NOMEM) << "ran out of memory"; + return -1; + } + if (hyperspace_error(space_builder)) + { + ERROR(BADSPACE) << "bad space " << hyperspace_error(space_builder); + return -1; + } + return 0; } int64_t -admin :: add_space(const char* description, - hyperdex_admin_returncode* status) +admin :: add_space(const char *description, + hyperdex_admin_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - struct hyperspace* space_builder = hyperspace_parse(description); - - if (!space_builder) - { - ERROR(NOMEM) << "ran out of memory"; - return -1; - } - - if (hyperspace_error(space_builder)) - { - ERROR(BADSPACE) << "bad space " << hyperspace_error(space_builder); - return -1; - } - - hyperdex::space space; - - if (!space_to_space(space_builder, &space)) - { - ERROR(BADSPACE) << "bad space"; - return -1; - } - - std::auto_ptr msg(e::buffer::create(pack_size(space))); - msg->pack_at(0) << space; - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op = new coord_rpc_generic(id, status, "add space"); - int64_t cid = rpc("space_add", reinterpret_cast(msg->data()), msg->size(), - &op->repl_status, &op->repl_output, &op->repl_output_sz); - - if (cid >= 0) - { - m_coord_ops[cid] = op; - return op->admin_visible_id(); - } - else - { - interpret_replicant_returncode(op->repl_status, status, &m_last_error); - return -1; - } + if (!maintain_coord_connection(status)) + { + return -1; + } + struct hyperspace *space_builder = hyperspace_parse(description); + if (!space_builder) + { + ERROR(NOMEM) << "ran out of memory"; + return -1; + } + if (hyperspace_error(space_builder)) + { + ERROR(BADSPACE) << "bad space " << hyperspace_error(space_builder); + return -1; + } + hyperdex::space space; + if (!space_to_space(space_builder, &space)) + { + ERROR(BADSPACE) << "bad space"; + return -1; + } + std::auto_ptr msg(e::buffer::create(pack_size(space))); + msg->pack_at(0) << space; + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_generic(id, status, "add space"); + int64_t cid = rpc("space_add", reinterpret_cast(msg->data()), msg->size(), + &op->repl_status, &op->repl_output, &op->repl_output_sz); + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_replicant_returncode(op->repl_status, status, &m_last_error); + return -1; + } } int64_t -admin :: rm_space(const char* name, - hyperdex_admin_returncode* status) +admin :: rm_space(const char *name, + hyperdex_admin_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op = new coord_rpc_generic(id, status, "rm space"); - int64_t cid = rpc("space_rm", name, strlen(name) + 1, - &op->repl_status, &op->repl_output, &op->repl_output_sz); - - if (cid >= 0) - { - m_coord_ops[cid] = op; - return op->admin_visible_id(); - } - else - { - interpret_replicant_returncode(op->repl_status, status, &m_last_error); - return -1; - } + if (!maintain_coord_connection(status)) + { + return -1; + } + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_generic(id, status, "rm space"); + int64_t cid = rpc("space_rm", name, strlen(name) + 1, + &op->repl_status, &op->repl_output, &op->repl_output_sz); + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_replicant_returncode(op->repl_status, status, &m_last_error); + return -1; + } } int64_t -admin :: mv_space(const char* source, const char* target, - hyperdex_admin_returncode* status) +admin :: mv_space(const char *source, const char *target, + hyperdex_admin_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - const size_t source_sz = strlen(source); - const size_t target_sz = strlen(target); - std::vector buf(source_sz + target_sz + 2); - memmove(&buf[0], source, source_sz); - buf[source_sz] = '\0'; - memmove(&buf[source_sz + 1], target, target_sz); - buf[source_sz + 1 + target_sz] = '\0'; - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op = new coord_rpc_generic(id, status, "mv space"); - int64_t cid = rpc("space_mv", &buf[0], buf.size(), - &op->repl_status, &op->repl_output, &op->repl_output_sz); - - if (cid >= 0) - { - m_coord_ops[cid] = op; - return op->admin_visible_id(); - } - else - { - interpret_replicant_returncode(op->repl_status, status, &m_last_error); - return -1; - } + if (!maintain_coord_connection(status)) + { + return -1; + } + const size_t source_sz = strlen(source); + const size_t target_sz = strlen(target); + std::vector buf(source_sz + target_sz + 2); + memmove(&buf[0], source, source_sz); + buf[source_sz] = '\0'; + memmove(&buf[source_sz + 1], target, target_sz); + buf[source_sz + 1 + target_sz] = '\0'; + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_generic(id, status, "mv space"); + int64_t cid = rpc("space_mv", &buf[0], buf.size(), + &op->repl_status, &op->repl_output, &op->repl_output_sz); + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_replicant_returncode(op->repl_status, status, &m_last_error); + return -1; + } } int64_t -admin :: add_index(const char* space, const char* attr, - hyperdex_admin_returncode* status) +admin :: add_index(const char *space, const char *attr, + hyperdex_admin_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - size_t space_sz = strlen(space); - size_t attr_sz = strlen(attr); - std::vector buf(space_sz + attr_sz + 2); - memmove(&buf[0], space, space_sz); - memmove(&buf[0] + space_sz + 1, attr, attr_sz); - buf[space_sz] = '\0'; - buf[space_sz + 1 + attr_sz] = '\0'; - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op = new coord_rpc_generic(id, status, "add_index"); - int64_t cid = rpc("index_add", &buf[0], buf.size(), - &op->repl_status, &op->repl_output, &op->repl_output_sz); - - if (cid >= 0) - { - m_coord_ops[cid] = op; - return op->admin_visible_id(); - } - else - { - interpret_replicant_returncode(op->repl_status, status, &m_last_error); - return -1; - } + if (!maintain_coord_connection(status)) + { + return -1; + } + size_t space_sz = strlen(space); + size_t attr_sz = strlen(attr); + std::vector buf(space_sz + attr_sz + 2); + memmove(&buf[0], space, space_sz); + memmove(&buf[0] + space_sz + 1, attr, attr_sz); + buf[space_sz] = '\0'; + buf[space_sz + 1 + attr_sz] = '\0'; + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_generic(id, status, "add_index"); + int64_t cid = rpc("index_add", &buf[0], buf.size(), + &op->repl_status, &op->repl_output, &op->repl_output_sz); + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_replicant_returncode(op->repl_status, status, &m_last_error); + return -1; + } } int64_t admin :: rm_index(uint64_t idxid, - enum hyperdex_admin_returncode* status) + enum hyperdex_admin_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - char buf[sizeof(uint64_t)]; - e::pack64be(idxid, buf); - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op = new coord_rpc_generic(id, status, "rm_index"); - int64_t cid = rpc("index_rm", buf, sizeof(uint64_t), - &op->repl_status, &op->repl_output, &op->repl_output_sz); - - if (cid >= 0) - { - m_coord_ops[cid] = op; - return op->admin_visible_id(); - } - else - { - interpret_replicant_returncode(op->repl_status, status, &m_last_error); - return -1; - } + if (!maintain_coord_connection(status)) + { + return -1; + } + char buf[sizeof(uint64_t)]; + e::pack64be(idxid, buf); + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_generic(id, status, "rm_index"); + int64_t cid = rpc("index_rm", buf, sizeof(uint64_t), + &op->repl_status, &op->repl_output, &op->repl_output_sz); + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_replicant_returncode(op->repl_status, status, &m_last_error); + return -1; + } } int64_t -admin :: list_indices(const char* space, enum hyperdex_admin_returncode* status, - const char** indexes) +admin :: list_indices(const char *space, enum hyperdex_admin_returncode *status, + const char **indexes) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - std::string tmp = m_config.list_indices(space); - e::intrusive_ptr op = new pending_string(id, status, HYPERDEX_ADMIN_SUCCESS, tmp, indexes); - m_yieldable.push_back(op.get()); - return op->admin_visible_id(); + if (!maintain_coord_connection(status)) + { + return -1; + } + int64_t id = m_next_admin_id; + ++m_next_admin_id; + std::string tmp = m_config.list_indices(space); + e::intrusive_ptr op = new pending_string(id, status, HYPERDEX_ADMIN_SUCCESS, tmp, indexes); + m_yieldable.push_back(op.get()); + return op->admin_visible_id(); } int64_t -admin :: list_spaces(hyperdex_admin_returncode* status, - const char** spaces) +admin :: list_spaces(hyperdex_admin_returncode *status, + const char **spaces) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - std::string tmp = m_config.list_spaces(); - e::intrusive_ptr op = new pending_string(id, status, HYPERDEX_ADMIN_SUCCESS, tmp, spaces); - m_yieldable.push_back(op.get()); - return op->admin_visible_id(); + if (!maintain_coord_connection(status)) + { + return -1; + } + int64_t id = m_next_admin_id; + ++m_next_admin_id; + std::string tmp = m_config.list_spaces(); + e::intrusive_ptr op = new pending_string(id, status, HYPERDEX_ADMIN_SUCCESS, tmp, spaces); + m_yieldable.push_back(op.get()); + return op->admin_visible_id(); } int64_t -admin :: server_register(uint64_t token, const char* address, - enum hyperdex_admin_returncode* status) +admin :: server_register(uint64_t token, const char *address, + enum hyperdex_admin_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - server_id sid(token); - po6::net::location loc; - if (!loc.set(address)) + if (!maintain_coord_connection(status)) { return -1; } - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op = new coord_rpc_generic(id, status, "register server"); - std::auto_ptr msg(e::buffer::create(sizeof(uint64_t) + pack_size(loc))); - msg->pack() << sid << loc; - int64_t cid = rpc("server_register", reinterpret_cast(msg->data()), msg->size(), - &op->repl_status, &op->repl_output, &op->repl_output_sz); - - if (cid >= 0) - { - m_coord_ops[cid] = op; - return op->admin_visible_id(); - } - else - { - interpret_replicant_returncode(op->repl_status, status, &m_last_error); - return -1; - } + server_id sid(token); + po6::net::location loc; + if (!loc.set(address)) + { + return -1; + } + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_generic(id, status, "register server"); + std::auto_ptr msg(e::buffer::create(sizeof(uint64_t) + pack_size(loc))); + msg->pack() << sid << loc; + int64_t cid = rpc("server_register", reinterpret_cast(msg->data()), msg->size(), + &op->repl_status, &op->repl_output, &op->repl_output_sz); + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_replicant_returncode(op->repl_status, status, &m_last_error); + return -1; + } } int64_t -admin :: server_online(uint64_t token, enum hyperdex_admin_returncode* status) +admin :: server_online(uint64_t token, enum hyperdex_admin_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op = new coord_rpc_generic(id, status, "bring server online"); - char buf[sizeof(uint64_t)]; - e::pack64be(token, buf); - int64_t cid = rpc("server_online", buf, sizeof(uint64_t), - &op->repl_status, &op->repl_output, &op->repl_output_sz); - - if (cid >= 0) - { - m_coord_ops[cid] = op; - return op->admin_visible_id(); - } - else - { - interpret_replicant_returncode(op->repl_status, status, &m_last_error); - return -1; - } + if (!maintain_coord_connection(status)) + { + return -1; + } + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_generic(id, status, "bring server online"); + char buf[sizeof(uint64_t)]; + e::pack64be(token, buf); + int64_t cid = rpc("server_online", buf, sizeof(uint64_t), + &op->repl_status, &op->repl_output, &op->repl_output_sz); + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_replicant_returncode(op->repl_status, status, &m_last_error); + return -1; + } } int64_t -admin :: server_offline(uint64_t token, enum hyperdex_admin_returncode* status) +admin :: server_offline(uint64_t token, enum hyperdex_admin_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op = new coord_rpc_generic(id, status, "bring server offline"); - char buf[sizeof(uint64_t)]; - e::pack64be(token, buf); - int64_t cid = rpc("server_offline", buf, sizeof(uint64_t), - &op->repl_status, &op->repl_output, &op->repl_output_sz); - - if (cid >= 0) - { - m_coord_ops[cid] = op; - return op->admin_visible_id(); - } - else - { - interpret_replicant_returncode(op->repl_status, status, &m_last_error); - return -1; - } + if (!maintain_coord_connection(status)) + { + return -1; + } + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_generic(id, status, "bring server offline"); + char buf[sizeof(uint64_t)]; + e::pack64be(token, buf); + int64_t cid = rpc("server_offline", buf, sizeof(uint64_t), + &op->repl_status, &op->repl_output, &op->repl_output_sz); + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_replicant_returncode(op->repl_status, status, &m_last_error); + return -1; + } } int64_t -admin :: server_forget(uint64_t token, enum hyperdex_admin_returncode* status) +admin :: server_forget(uint64_t token, enum hyperdex_admin_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op = new coord_rpc_generic(id, status, "forget server"); - char buf[sizeof(uint64_t)]; - e::pack64be(token, buf); - int64_t cid = rpc("server_forget", buf, sizeof(uint64_t), - &op->repl_status, &op->repl_output, &op->repl_output_sz); - - if (cid >= 0) - { - m_coord_ops[cid] = op; - return op->admin_visible_id(); - } - else - { - interpret_replicant_returncode(op->repl_status, status, &m_last_error); - return -1; - } + if (!maintain_coord_connection(status)) + { + return -1; + } + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_generic(id, status, "forget server"); + char buf[sizeof(uint64_t)]; + e::pack64be(token, buf); + int64_t cid = rpc("server_forget", buf, sizeof(uint64_t), + &op->repl_status, &op->repl_output, &op->repl_output_sz); + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_replicant_returncode(op->repl_status, status, &m_last_error); + return -1; + } } int64_t -admin :: server_kill(uint64_t token, enum hyperdex_admin_returncode* status) +admin :: server_kill(uint64_t token, enum hyperdex_admin_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op = new coord_rpc_generic(id, status, "kill server"); - char buf[sizeof(uint64_t)]; - e::pack64be(token, buf); - int64_t cid = rpc("server_kill", buf, sizeof(uint64_t), - &op->repl_status, &op->repl_output, &op->repl_output_sz); - - if (cid >= 0) - { - m_coord_ops[cid] = op; - return op->admin_visible_id(); - } - else - { - interpret_replicant_returncode(op->repl_status, status, &m_last_error); - return -1; - } + if (!maintain_coord_connection(status)) + { + return -1; + } + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_generic(id, status, "kill server"); + char buf[sizeof(uint64_t)]; + e::pack64be(token, buf); + int64_t cid = rpc("server_kill", buf, sizeof(uint64_t), + &op->repl_status, &op->repl_output, &op->repl_output_sz); + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_replicant_returncode(op->repl_status, status, &m_last_error); + return -1; + } } int64_t -admin :: backup(const char* name, enum hyperdex_admin_returncode* status, const char** backups) +admin :: backup(const char *name, enum hyperdex_admin_returncode *status, const char **backups) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op; - op = new backup_state_machine(name, id, status, backups); - - if (!op->initialize(this, status)) - { - return -1; - } - - return op->admin_visible_id(); + if (!maintain_coord_connection(status)) + { + return -1; + } + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op; + op = new backup_state_machine(name, id, status, backups); + if (!op->initialize(this, status)) + { + return -1; + } + return op->admin_visible_id(); } int64_t -admin :: coord_backup(const char* path, - enum hyperdex_admin_returncode* status) +admin :: coord_backup(const char *path, + enum hyperdex_admin_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - int64_t id = m_next_admin_id; - ++m_next_admin_id; - e::intrusive_ptr op = new coord_rpc_backup(id, status, path); - int64_t cid = replicant_client_backup_object(m_coord, "hyperdex", &op->repl_status, &op->repl_output, &op->repl_output_sz); - - if (cid >= 0) - { - m_coord_ops[cid] = op; - return op->admin_visible_id(); - } - else - { - interpret_replicant_returncode(op->repl_status, status, &m_last_error); - return -1; - } + if (!maintain_coord_connection(status)) + { + return -1; + } + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_backup(id, status, path); + int64_t cid = replicant_client_backup_object(m_coord, "hyperdex", &op->repl_status, &op->repl_output, &op->repl_output_sz); + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_replicant_returncode(op->repl_status, status, &m_last_error); + return -1; + } } int64_t -admin :: raw_backup(const server_id& sid, const char* name, - enum hyperdex_admin_returncode* status, - const char** path) +admin :: raw_backup(const server_id &sid, const char *name, + enum hyperdex_admin_returncode *status, + const char **path) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - e::slice name_s(name, strlen(name) + 1); - size_t sz = HYPERDEX_ADMIN_HEADER_SIZE_REQ - + pack_size(name_s); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_ADMIN_HEADER_SIZE_REQ) << name_s; - uint64_t id = m_next_admin_id; - ++m_next_admin_id; - uint64_t nonce = m_next_server_nonce; - ++m_next_server_nonce; - e::intrusive_ptr op = new pending_raw_backup(id, status, path); - - if (!send(BACKUP, sid, nonce, msg, op, status)) - { - return -1; - } - - return op->admin_visible_id(); + if (!maintain_coord_connection(status)) + { + return -1; + } + e::slice name_s(name, strlen(name) + 1); + size_t sz = HYPERDEX_ADMIN_HEADER_SIZE_REQ + + pack_size(name_s); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_ADMIN_HEADER_SIZE_REQ) << name_s; + uint64_t id = m_next_admin_id; + ++m_next_admin_id; + uint64_t nonce = m_next_server_nonce; + ++m_next_server_nonce; + e::intrusive_ptr op = new pending_raw_backup(id, status, path); + if (!send(BACKUP, sid, nonce, msg, op, status)) + { + return -1; + } + return op->admin_visible_id(); } int64_t -admin :: enable_perf_counters(hyperdex_admin_returncode* status, - hyperdex_admin_perf_counter* pc) +admin :: enable_perf_counters(hyperdex_admin_returncode *status, + hyperdex_admin_perf_counter *pc) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - if (m_pcs) - { - return m_pcs->admin_visible_id(); - } - else - { - int64_t id = m_next_admin_id; - ++m_next_admin_id; - m_pcs = new pending_perf_counters(id, status, pc); - m_pcs->send_perf_reqs(this, &m_config, status); - return m_pcs->admin_visible_id(); - } + if (!maintain_coord_connection(status)) + { + return -1; + } + if (m_pcs) + { + return m_pcs->admin_visible_id(); + } + else + { + int64_t id = m_next_admin_id; + ++m_next_admin_id; + m_pcs = new pending_perf_counters(id, status, pc); + m_pcs->send_perf_reqs(this, &m_config, status); + return m_pcs->admin_visible_id(); + } } void admin :: disable_perf_counters() { - m_pcs = NULL; + m_pcs = NULL; } int64_t -admin :: loop(int timeout, hyperdex_admin_returncode* status) +admin :: loop(int timeout, hyperdex_admin_returncode *status) { - *status = HYPERDEX_ADMIN_SUCCESS; - - while (m_pcs || - m_yielding || - !m_failed.empty() || - !m_yieldable.empty() || - !m_coord_ops.empty() || - !m_server_ops.empty()) - { - if (m_yielding) - { - if (!m_yielding->can_yield()) - { - m_yielding = NULL; - continue; - } - - if (!m_yielding->yield(status)) - { - return -1; - } - - int64_t admin_id = m_yielding->admin_visible_id(); - m_last_error = m_yielding->error(); - - if (!m_yielding->can_yield()) - { - m_yielded = m_yielding; - m_yielding = NULL; - } - - multi_yieldable_map_t::iterator it = m_multi_ops.find(admin_id); - - if (it != m_multi_ops.end()) - { - e::intrusive_ptr op = it->second; - m_multi_ops.erase(it); - - if (!op->callback(this, admin_id, status)) - { - return -1; - } - - m_yielding = op.get(); - continue; - } - - return admin_id; - } - else if (!m_yieldable.empty()) - { - m_yielding = m_yieldable.front(); - m_yieldable.pop_front(); - continue; - } - else if (!m_failed.empty()) - { - const pending_server_pair& psp(m_failed.front()); - psp.op->handle_failure(psp.si); - m_yielding = psp.op.get(); - m_failed.pop_front(); - continue; - } - - m_yielded = NULL; - - if (!maintain_coord_connection(status)) - { - return -1; - } - - assert(!m_coord_ops.empty() || !m_server_ops.empty() || m_pcs); - - if (m_pcs) - { - int t = m_pcs->millis_to_next_send(); - - if (t <= 0) - { - m_pcs->send_perf_reqs(this, &m_config, status); - t = m_pcs->millis_to_next_send(); - } - - if (timeout > t) - { - m_busybee.set_timeout(t); - timeout -= t; - } - else if (timeout < 0) - { - m_busybee.set_timeout(t); - } - else - { - m_busybee.set_timeout(timeout); - timeout = 0; - } - } - else - { - m_busybee.set_timeout(timeout); - } - - if (m_handle_coord_ops) - { - m_handle_coord_ops = false; - replicant_returncode lrc = REPLICANT_GARBAGE; - int64_t lid = replicant_client_loop(m_coord, 0, &lrc); - - if (lid < 0 && lrc != REPLICANT_TIMEOUT) - { - interpret_replicant_returncode(lrc, status, &m_last_error); - return -1; - } - - coord_rpc_map_t::iterator it = m_coord_ops.find(lid); - - if (it == m_coord_ops.end()) - { - continue; - } - - e::intrusive_ptr op = it->second; - m_coord_ops.erase(it); - - if (!op->handle_response(this, status)) - { - return -1; - } - - m_yielding = op.get(); - continue; - } - - uint64_t sid_num; - std::auto_ptr msg; - busybee_returncode rc = m_busybee.recv(&sid_num, &msg); - server_id id(sid_num); - - switch (rc) - { - case BUSYBEE_SUCCESS: - break; - case BUSYBEE_POLLFAILED: - case BUSYBEE_ADDFDFAIL: - ERROR(POLLFAILED) << "poll failed"; - return -1; - case BUSYBEE_DISRUPTED: - handle_disruption(id); - continue; - case BUSYBEE_TIMEOUT: - if (m_pcs && timeout != 0) - { - continue; - } - - ERROR(TIMEOUT) << "operation timed out"; - return -1; - case BUSYBEE_INTERRUPTED: - ERROR(INTERRUPTED) << "signal received"; - return -1; - case BUSYBEE_EXTERNAL: - m_handle_coord_ops = true; - continue; - case BUSYBEE_SHUTDOWN: - default: - abort(); - } - - e::unpacker up = msg->unpack_from(BUSYBEE_HEADER_SIZE); - uint8_t mt; - virtual_server_id vfrom; - int64_t nonce; - up = up >> mt >> vfrom >> nonce; - - if (up.error()) - { - ERROR(SERVERERROR) << "communication error: server " - << sid_num << " sent message=" - << msg->as_slice().hex() - << " with invalid header"; - return -1; - } - - network_msgtype msg_type = static_cast(mt); - pending_map_t::iterator it = m_server_ops.find(nonce); - - if (it == m_server_ops.end()) - { - continue; - } - - const pending_server_pair psp(it->second); - e::intrusive_ptr op = psp.op; - - if (msg_type == CONFIGMISMATCH) - { - m_failed.push_back(psp); - continue; - } - - if (id == it->second.si) - { - m_server_ops.erase(it); - - if (!op->handle_message(this, id, msg_type, msg, up, status)) - { - return -1; - } - - m_yielding = psp.op.get(); - } - else - { - ERROR(SERVERERROR) << "server " << sid_num - << " responded for nonce " << nonce - << " which belongs to server " << it->second.si.get(); - return -1; - } - } - - ERROR(NONEPENDING) << "no outstanding operations to process"; - return -1; + *status = HYPERDEX_ADMIN_SUCCESS; + while (m_pcs || + m_yielding || + !m_failed.empty() || + !m_yieldable.empty() || + !m_coord_ops.empty() || + !m_server_ops.empty()) + { + if (m_yielding) + { + if (!m_yielding->can_yield()) + { + m_yielding = NULL; + continue; + } + if (!m_yielding->yield(status)) + { + return -1; + } + int64_t admin_id = m_yielding->admin_visible_id(); + m_last_error = m_yielding->error(); + if (!m_yielding->can_yield()) + { + m_yielded = m_yielding; + m_yielding = NULL; + } + multi_yieldable_map_t::iterator it = m_multi_ops.find(admin_id); + if (it != m_multi_ops.end()) + { + e::intrusive_ptr op = it->second; + m_multi_ops.erase(it); + if (!op->callback(this, admin_id, status)) + { + return -1; + } + m_yielding = op.get(); + continue; + } + return admin_id; + } + else if (!m_yieldable.empty()) + { + m_yielding = m_yieldable.front(); + m_yieldable.pop_front(); + continue; + } + else if (!m_failed.empty()) + { + const pending_server_pair &psp(m_failed.front()); + psp.op->handle_failure(psp.si); + m_yielding = psp.op.get(); + m_failed.pop_front(); + continue; + } + m_yielded = NULL; + if (!maintain_coord_connection(status)) + { + return -1; + } + assert(!m_coord_ops.empty() || !m_server_ops.empty() || m_pcs); + if (m_pcs) + { + int t = m_pcs->millis_to_next_send(); + if (t <= 0) + { + m_pcs->send_perf_reqs(this, &m_config, status); + t = m_pcs->millis_to_next_send(); + } + if (timeout > t) + { + m_busybee.set_timeout(t); + timeout -= t; + } + else if (timeout < 0) + { + m_busybee.set_timeout(t); + } + else + { + m_busybee.set_timeout(timeout); + timeout = 0; + } + } + else + { + m_busybee.set_timeout(timeout); + } + if (m_handle_coord_ops) + { + m_handle_coord_ops = false; + replicant_returncode lrc = REPLICANT_GARBAGE; + int64_t lid = replicant_client_loop(m_coord, 0, &lrc); + if (lid < 0 && lrc != REPLICANT_TIMEOUT) + { + interpret_replicant_returncode(lrc, status, &m_last_error); + return -1; + } + coord_rpc_map_t::iterator it = m_coord_ops.find(lid); + if (it == m_coord_ops.end()) + { + continue; + } + e::intrusive_ptr op = it->second; + m_coord_ops.erase(it); + if (!op->handle_response(this, status)) + { + return -1; + } + m_yielding = op.get(); + continue; + } + uint64_t sid_num; + std::auto_ptr msg; + busybee_returncode rc = m_busybee.recv(&sid_num, &msg); + server_id id(sid_num); + switch (rc) + { + case BUSYBEE_SUCCESS: + break; + case BUSYBEE_POLLFAILED: + case BUSYBEE_ADDFDFAIL: + ERROR(POLLFAILED) << "poll failed"; + return -1; + case BUSYBEE_DISRUPTED: + handle_disruption(id); + continue; + case BUSYBEE_TIMEOUT: + if (m_pcs && timeout != 0) + { + continue; + } + ERROR(TIMEOUT) << "operation timed out"; + return -1; + case BUSYBEE_INTERRUPTED: + ERROR(INTERRUPTED) << "signal received"; + return -1; + case BUSYBEE_EXTERNAL: + m_handle_coord_ops = true; + continue; + case BUSYBEE_SHUTDOWN: + default: + abort(); + } + e::unpacker up = msg->unpack_from(BUSYBEE_HEADER_SIZE); + uint8_t mt; + virtual_server_id vfrom; + int64_t nonce; + up = up >> mt >> vfrom >> nonce; + if (up.error()) + { + ERROR(SERVERERROR) << "communication error: server " + << sid_num << " sent message=" + << msg->as_slice().hex() + << " with invalid header"; + return -1; + } + network_msgtype msg_type = static_cast(mt); + pending_map_t::iterator it = m_server_ops.find(nonce); + if (it == m_server_ops.end()) + { + continue; + } + const pending_server_pair psp(it->second); + e::intrusive_ptr op = psp.op; + if (msg_type == CONFIGMISMATCH) + { + m_failed.push_back(psp); + continue; + } + if (id == it->second.si) + { + m_server_ops.erase(it); + if (!op->handle_message(this, id, msg_type, msg, up, status)) + { + return -1; + } + m_yielding = psp.op.get(); + } + else + { + ERROR(SERVERERROR) << "server " << sid_num + << " responded for nonce " << nonce + << " which belongs to server " << it->second.si.get(); + return -1; + } + } + ERROR(NONEPENDING) << "no outstanding operations to process"; + return -1; } -const char* +const char * admin :: error_message() { - return m_last_error.msg(); + return m_last_error.msg(); } -const char* +const char * admin :: error_location() { - return m_last_error.loc(); + return m_last_error.loc(); } void -admin :: set_error_message(const char* msg) +admin :: set_error_message(const char *msg) { - m_last_error = e::error(); - m_last_error.set_loc(__FILE__, __LINE__); - m_last_error.set_msg() << msg; + m_last_error = e::error(); + m_last_error.set_loc(__FILE__, __LINE__); + m_last_error.set_msg() << msg; } #define INTERPRET_ERROR(CODE) \ - *status = HYPERDEX_ADMIN_ ## CODE; \ - err->set_loc(__FILE__, __LINE__); \ - err->set_msg() + *status = HYPERDEX_ADMIN_ ## CODE; \ + err->set_loc(__FILE__, __LINE__); \ + err->set_msg() void admin :: interpret_replicant_returncode(replicant_returncode rstatus, - hyperdex_admin_returncode* status, - e::error* err) + hyperdex_admin_returncode *status, + e::error *err) { - switch (rstatus) - { - case REPLICANT_SUCCESS: - *status = HYPERDEX_ADMIN_SUCCESS; - break; - case REPLICANT_OBJ_NOT_FOUND: - case REPLICANT_OBJ_EXIST: - case REPLICANT_FUNC_NOT_FOUND: - case REPLICANT_COND_NOT_FOUND: - case REPLICANT_COND_DESTROYED: - INTERPRET_ERROR(COORDFAIL) << "persistent coordinator error: " - << replicant_client_error_message(m_coord); - break; - case REPLICANT_MAYBE: - INTERPRET_ERROR(COORDFAIL) << "transient coordinator error: " - << "operation may or may not have completed"; - break; - case REPLICANT_SEE_ERRNO: - INTERPRET_ERROR(COORDFAIL) << "transient coordinator error: " - << po6::strerror(errno); - break; - case REPLICANT_CLUSTER_JUMP: - case REPLICANT_SERVER_ERROR: - case REPLICANT_COMM_FAILED: - INTERPRET_ERROR(COORDFAIL) << "transient coordinator error: " - << replicant_client_error_message(m_coord); - break; - case REPLICANT_TIMEOUT: - INTERPRET_ERROR(TIMEOUT) << "operation timed out"; - break; - case REPLICANT_INTERRUPTED: - INTERPRET_ERROR(INTERRUPTED) << "signal received"; - break; - case REPLICANT_NONE_PENDING: - INTERPRET_ERROR(NONEPENDING) << "no operations pending"; - break; - case REPLICANT_INTERNAL: - case REPLICANT_EXCEPTION: - case REPLICANT_GARBAGE: - default: - INTERPRET_ERROR(INTERNAL) << "internal library error: " - << replicant_client_error_message(m_coord); - break; - } + switch (rstatus) + { + case REPLICANT_SUCCESS: + *status = HYPERDEX_ADMIN_SUCCESS; + break; + case REPLICANT_OBJ_NOT_FOUND: + case REPLICANT_OBJ_EXIST: + case REPLICANT_FUNC_NOT_FOUND: + case REPLICANT_COND_NOT_FOUND: + case REPLICANT_COND_DESTROYED: + INTERPRET_ERROR(COORDFAIL) << "persistent coordinator error: " + << replicant_client_error_message(m_coord); + break; + case REPLICANT_MAYBE: + INTERPRET_ERROR(COORDFAIL) << "transient coordinator error: " + << "operation may or may not have completed"; + break; + case REPLICANT_SEE_ERRNO: + INTERPRET_ERROR(COORDFAIL) << "transient coordinator error: " + << po6::strerror(errno); + break; + case REPLICANT_CLUSTER_JUMP: + case REPLICANT_SERVER_ERROR: + case REPLICANT_COMM_FAILED: + INTERPRET_ERROR(COORDFAIL) << "transient coordinator error: " + << replicant_client_error_message(m_coord); + break; + case REPLICANT_TIMEOUT: + INTERPRET_ERROR(TIMEOUT) << "operation timed out"; + break; + case REPLICANT_INTERRUPTED: + INTERPRET_ERROR(INTERRUPTED) << "signal received"; + break; + case REPLICANT_NONE_PENDING: + INTERPRET_ERROR(NONEPENDING) << "no operations pending"; + break; + case REPLICANT_INTERNAL: + case REPLICANT_EXCEPTION: + case REPLICANT_GARBAGE: + default: + INTERPRET_ERROR(INTERNAL) << "internal library error: " + << replicant_client_error_message(m_coord); + break; + } } bool -admin :: maintain_coord_connection(hyperdex_admin_returncode* status) +admin :: maintain_coord_connection(hyperdex_admin_returncode *status) { - if (m_config_status != REPLICANT_SUCCESS) - { - replicant_client_kill(m_coord, m_config_id); - m_config_id = -1; - } - - replicant_returncode rc; - - if (m_config_id < 0) - { - m_config_status = REPLICANT_SUCCESS; - m_config_id = replicant_client_cond_follow(m_coord, "hyperdex", "config", - &m_config_status, &m_config_state, - &m_config_data, &m_config_data_sz); - if (replicant_client_wait(m_coord, m_config_id, -1, &rc) < 0) - { - ERROR(COORDFAIL) << "coordinator failure: " << replicant_client_error_message(m_coord); - return false; - } - } - - if (replicant_client_wait(m_coord, m_config_id, 0, &rc) < 0) - { - if (rc == REPLICANT_INTERRUPTED) - { - ERROR(INTERRUPTED) << "interrupted by a signal"; - return false; - } - else if (rc != REPLICANT_NONE_PENDING && rc != REPLICANT_TIMEOUT) - { - ERROR(COORDFAIL) << "coordinator failure: " << replicant_client_error_message(m_coord); - return false; - } - } - - if (m_config.version() < m_config_state) - { - configuration new_config; - e::unpacker up(m_config_data, m_config_data_sz); - up = up >> new_config; - - if (!up.error()) - { - m_config = new_config; - } - } - - return true; + if (m_config_status != REPLICANT_SUCCESS) + { + replicant_client_kill(m_coord, m_config_id); + m_config_id = -1; + } + replicant_returncode rc; + if (m_config_id < 0) + { + m_config_status = REPLICANT_SUCCESS; + m_config_id = replicant_client_cond_follow(m_coord, "hyperdex", "config", + &m_config_status, &m_config_state, + &m_config_data, &m_config_data_sz); + if (replicant_client_wait(m_coord, m_config_id, -1, &rc) < 0) + { + ERROR(COORDFAIL) << "coordinator failure: " << replicant_client_error_message(m_coord); + return false; + } + } + if (replicant_client_wait(m_coord, m_config_id, 0, &rc) < 0) + { + if (rc == REPLICANT_INTERRUPTED) + { + ERROR(INTERRUPTED) << "interrupted by a signal"; + return false; + } + else if (rc != REPLICANT_NONE_PENDING && rc != REPLICANT_TIMEOUT) + { + ERROR(COORDFAIL) << "coordinator failure: " << replicant_client_error_message(m_coord); + return false; + } + } + if (m_config.version() < m_config_state) + { + configuration new_config; + e::unpacker up(m_config_data, m_config_data_sz); + up = up >> new_config; + if (!up.error()) + { + m_config = new_config; + } + } + return true; } int64_t -admin :: rpc(const char* func, - const char* data, size_t data_sz, - replicant_returncode* status, - char** output, size_t* output_sz) +admin :: rpc(const char *func, + const char *data, size_t data_sz, + replicant_returncode *status, + char **output, size_t *output_sz) { - return replicant_client_call(m_coord, "hyperdex", func, data, data_sz, - REPLICANT_CALL_ROBUST, status, output, output_sz); + return replicant_client_call(m_coord, "hyperdex", func, data, data_sz, + REPLICANT_CALL_ROBUST, status, output, output_sz); } bool @@ -1066,84 +975,80 @@ admin :: send(network_msgtype mt, uint64_t nonce, std::auto_ptr msg, e::intrusive_ptr op, - hyperdex_admin_returncode* status) + hyperdex_admin_returncode *status) { - const uint8_t type = static_cast(mt); - const uint8_t flags = 0; - const uint64_t version = m_config.version(); - msg->pack_at(BUSYBEE_HEADER_SIZE) - << type << flags << version << uint64_t(UINT64_MAX) << nonce; - m_busybee.set_timeout(-1); - - switch (m_busybee.send(id.get(), msg)) - { - case BUSYBEE_SUCCESS: - op->handle_sent_to(id); - m_server_ops.insert(std::make_pair(nonce, pending_server_pair(id, op))); - return true; - case BUSYBEE_DISRUPTED: - handle_disruption(id); - ERROR(SERVERERROR) << "server " << id.get() << " had a communication disruption"; - return false; - case BUSYBEE_POLLFAILED: - case BUSYBEE_ADDFDFAIL: - ERROR(POLLFAILED) << "poll failed"; - return false; - case BUSYBEE_SHUTDOWN: - case BUSYBEE_TIMEOUT: - case BUSYBEE_EXTERNAL: - case BUSYBEE_INTERRUPTED: - default: - abort(); - } + const uint8_t type = static_cast(mt); + const uint8_t flags = 0; + const uint64_t version = m_config.version(); + msg->pack_at(BUSYBEE_HEADER_SIZE) + << type << flags << version << uint64_t(UINT64_MAX) << nonce; + m_busybee.set_timeout(-1); + switch (m_busybee.send(id.get(), msg)) + { + case BUSYBEE_SUCCESS: + op->handle_sent_to(id); + m_server_ops.insert(std::make_pair(nonce, pending_server_pair(id, op))); + return true; + case BUSYBEE_DISRUPTED: + handle_disruption(id); + ERROR(SERVERERROR) << "server " << id.get() << " had a communication disruption"; + return false; + case BUSYBEE_POLLFAILED: + case BUSYBEE_ADDFDFAIL: + ERROR(POLLFAILED) << "poll failed"; + return false; + case BUSYBEE_SHUTDOWN: + case BUSYBEE_TIMEOUT: + case BUSYBEE_EXTERNAL: + case BUSYBEE_INTERRUPTED: + default: + abort(); + } } void -admin :: handle_disruption(const server_id& si) +admin :: handle_disruption(const server_id &si) { - pending_map_t::iterator it = m_server_ops.begin(); - - while (it != m_server_ops.end()) - { - if (it->second.si == si) - { - m_failed.push_back(it->second); - pending_map_t::iterator tmp = it; - ++it; - m_server_ops.erase(tmp); - } - else - { - ++it; - } - } - - m_busybee.drop(si.get()); + pending_map_t::iterator it = m_server_ops.begin(); + while (it != m_server_ops.end()) + { + if (it->second.si == si) + { + m_failed.push_back(it->second); + pending_map_t::iterator tmp = it; + ++it; + m_server_ops.erase(tmp); + } + else + { + ++it; + } + } + m_busybee.drop(si.get()); } -HYPERDEX_API std::ostream& -operator << (std::ostream& lhs, hyperdex_admin_returncode rhs) +HYPERDEX_API std::ostream & +operator << (std::ostream &lhs, hyperdex_admin_returncode rhs) { - switch (rhs) - { - STRINGIFY(HYPERDEX_ADMIN_SUCCESS); - STRINGIFY(HYPERDEX_ADMIN_NOMEM); - STRINGIFY(HYPERDEX_ADMIN_NONEPENDING); - STRINGIFY(HYPERDEX_ADMIN_POLLFAILED); - STRINGIFY(HYPERDEX_ADMIN_TIMEOUT); - STRINGIFY(HYPERDEX_ADMIN_INTERRUPTED); - STRINGIFY(HYPERDEX_ADMIN_SERVERERROR); - STRINGIFY(HYPERDEX_ADMIN_COORDFAIL); - STRINGIFY(HYPERDEX_ADMIN_BADSPACE); - STRINGIFY(HYPERDEX_ADMIN_DUPLICATE); - STRINGIFY(HYPERDEX_ADMIN_NOTFOUND); - STRINGIFY(HYPERDEX_ADMIN_LOCALERROR); - STRINGIFY(HYPERDEX_ADMIN_INTERNAL); - STRINGIFY(HYPERDEX_ADMIN_EXCEPTION); - STRINGIFY(HYPERDEX_ADMIN_GARBAGE); - default: - lhs << "unknown hyperdex_admin_returncode"; - } - - return lhs; + switch (rhs) + { + STRINGIFY(HYPERDEX_ADMIN_SUCCESS); + STRINGIFY(HYPERDEX_ADMIN_NOMEM); + STRINGIFY(HYPERDEX_ADMIN_NONEPENDING); + STRINGIFY(HYPERDEX_ADMIN_POLLFAILED); + STRINGIFY(HYPERDEX_ADMIN_TIMEOUT); + STRINGIFY(HYPERDEX_ADMIN_INTERRUPTED); + STRINGIFY(HYPERDEX_ADMIN_SERVERERROR); + STRINGIFY(HYPERDEX_ADMIN_COORDFAIL); + STRINGIFY(HYPERDEX_ADMIN_BADSPACE); + STRINGIFY(HYPERDEX_ADMIN_DUPLICATE); + STRINGIFY(HYPERDEX_ADMIN_NOTFOUND); + STRINGIFY(HYPERDEX_ADMIN_LOCALERROR); + STRINGIFY(HYPERDEX_ADMIN_INTERNAL); + STRINGIFY(HYPERDEX_ADMIN_EXCEPTION); + STRINGIFY(HYPERDEX_ADMIN_GARBAGE); + default: + lhs << "unknown hyperdex_admin_returncode"; + } + return lhs; } diff --git a/admin/admin.h b/admin/admin.h index 4b1a2c8b9..64d059138 100644 --- a/admin/admin.h +++ b/admin/admin.h @@ -53,131 +53,131 @@ BEGIN_HYPERDEX_NAMESPACE class admin { - public: - admin(const char* coordinator, uint16_t port); - ~admin() throw (); +public: + admin(const char *coordinator, uint16_t port); + ~admin() throw (); - public: - // introspect the config - int64_t dump_config(enum hyperdex_admin_returncode* status, - const char** config); - // cluster - int64_t read_only(int ro, - enum hyperdex_admin_returncode* status); - int64_t wait_until_stable(enum hyperdex_admin_returncode* status); - int64_t fault_tolerance(const char* space, uint64_t ft, - enum hyperdex_admin_returncode* status); - // manage spaces - int validate_space(const char* description, - enum hyperdex_admin_returncode* status); - int64_t add_space(const char* description, - enum hyperdex_admin_returncode* status); - int64_t rm_space(const char* name, - enum hyperdex_admin_returncode* status); - int64_t mv_space(const char* source, const char* target, - enum hyperdex_admin_returncode* status); - int64_t add_index(const char* space, const char* attr, - enum hyperdex_admin_returncode* status); - int64_t list_indices(const char* space, enum hyperdex_admin_returncode* status, - const char** spaces); - int64_t rm_index(uint64_t idxid, - enum hyperdex_admin_returncode* status); - int64_t list_spaces(enum hyperdex_admin_returncode* status, - const char** spaces); - int64_t list_subspaces(const char* space, - enum hyperdex_admin_returncode* status, - const char** subspaces); - // manage servers - int64_t server_register(uint64_t token, const char* address, - enum hyperdex_admin_returncode* status); - int64_t server_online(uint64_t token, enum hyperdex_admin_returncode* status); - int64_t server_offline(uint64_t token, enum hyperdex_admin_returncode* status); - int64_t server_forget(uint64_t token, enum hyperdex_admin_returncode* status); - int64_t server_kill(uint64_t token, enum hyperdex_admin_returncode* status); - // backups - int64_t backup(const char* name, enum hyperdex_admin_returncode* status, const char** backups); - int64_t coord_backup(const char* path, - enum hyperdex_admin_returncode* status); - int64_t raw_backup(const server_id& sid, const char* name, - enum hyperdex_admin_returncode* status, - const char** path); - // read performance counters - int64_t enable_perf_counters(hyperdex_admin_returncode* status, - hyperdex_admin_perf_counter* pc); - void disable_perf_counters(); - // looping/polling - int64_t loop(int timeout, hyperdex_admin_returncode* status); - // error handling - const char* error_message(); - const char* error_location(); - void set_error_message(const char* msg); - void interpret_replicant_returncode(replicant_returncode rstatus, - hyperdex_admin_returncode* status, - e::error* err); +public: + // introspect the config + int64_t dump_config(enum hyperdex_admin_returncode *status, + const char **config); + // cluster + int64_t read_only(int ro, + enum hyperdex_admin_returncode *status); + int64_t wait_until_stable(enum hyperdex_admin_returncode *status); + int64_t fault_tolerance(const char *space, uint64_t ft, + enum hyperdex_admin_returncode *status); + // manage spaces + int validate_space(const char *description, + enum hyperdex_admin_returncode *status); + int64_t add_space(const char *description, + enum hyperdex_admin_returncode *status); + int64_t rm_space(const char *name, + enum hyperdex_admin_returncode *status); + int64_t mv_space(const char *source, const char *target, + enum hyperdex_admin_returncode *status); + int64_t add_index(const char *space, const char *attr, + enum hyperdex_admin_returncode *status); + int64_t list_indices(const char *space, enum hyperdex_admin_returncode *status, + const char **spaces); + int64_t rm_index(uint64_t idxid, + enum hyperdex_admin_returncode *status); + int64_t list_spaces(enum hyperdex_admin_returncode *status, + const char **spaces); + int64_t list_subspaces(const char *space, + enum hyperdex_admin_returncode *status, + const char **subspaces); + // manage servers + int64_t server_register(uint64_t token, const char *address, + enum hyperdex_admin_returncode *status); + int64_t server_online(uint64_t token, enum hyperdex_admin_returncode *status); + int64_t server_offline(uint64_t token, enum hyperdex_admin_returncode *status); + int64_t server_forget(uint64_t token, enum hyperdex_admin_returncode *status); + int64_t server_kill(uint64_t token, enum hyperdex_admin_returncode *status); + // backups + int64_t backup(const char *name, enum hyperdex_admin_returncode *status, const char **backups); + int64_t coord_backup(const char *path, + enum hyperdex_admin_returncode *status); + int64_t raw_backup(const server_id &sid, const char *name, + enum hyperdex_admin_returncode *status, + const char **path); + // read performance counters + int64_t enable_perf_counters(hyperdex_admin_returncode *status, + hyperdex_admin_perf_counter *pc); + void disable_perf_counters(); + // looping/polling + int64_t loop(int timeout, hyperdex_admin_returncode *status); + // error handling + const char *error_message(); + const char *error_location(); + void set_error_message(const char *msg); + void interpret_replicant_returncode(replicant_returncode rstatus, + hyperdex_admin_returncode *status, + e::error *err); - private: - struct pending_server_pair - { - pending_server_pair() - : si(), op() {} - pending_server_pair(const server_id& s, - const e::intrusive_ptr& o) - : si(s), op(o) {} - ~pending_server_pair() throw () {} - server_id si; - e::intrusive_ptr op; - }; - typedef std::map pending_map_t; - typedef std::map > coord_rpc_map_t; - typedef std::map > multi_yieldable_map_t; - typedef std::list pending_queue_t; - friend class backup_state_machine; - friend class pending_perf_counters; +private: + struct pending_server_pair + { + pending_server_pair() + : si(), op() {} + pending_server_pair(const server_id &s, + const e::intrusive_ptr &o) + : si(s), op(o) {} + ~pending_server_pair() throw () {} + server_id si; + e::intrusive_ptr op; + }; + typedef std::map pending_map_t; + typedef std::map > coord_rpc_map_t; + typedef std::map > multi_yieldable_map_t; + typedef std::list pending_queue_t; + friend class backup_state_machine; + friend class pending_perf_counters; - private: - bool maintain_coord_connection(hyperdex_admin_returncode* status); - int64_t rpc(const char* func, - const char* data, size_t data_sz, - replicant_returncode* status, - char** output, size_t* output_sz); - bool send(network_msgtype mt, - server_id id, - uint64_t nonce, - std::auto_ptr msg, - e::intrusive_ptr op, - hyperdex_admin_returncode* status); - void handle_disruption(const server_id& si); +private: + bool maintain_coord_connection(hyperdex_admin_returncode *status); + int64_t rpc(const char *func, + const char *data, size_t data_sz, + replicant_returncode *status, + char **output, size_t *output_sz); + bool send(network_msgtype mt, + server_id id, + uint64_t nonce, + std::auto_ptr msg, + e::intrusive_ptr op, + hyperdex_admin_returncode *status); + void handle_disruption(const server_id &si); - private: - replicant_client* m_coord; - mapper m_busybee_mapper; - busybee_st m_busybee; - // configuration - configuration m_config; - int64_t m_config_id; - replicant_returncode m_config_status; - uint64_t m_config_state; - char* m_config_data; - size_t m_config_data_sz; - // nonces - int64_t m_next_admin_id; - uint64_t m_next_server_nonce; - // operations - bool m_handle_coord_ops; - coord_rpc_map_t m_coord_ops; - pending_map_t m_server_ops; - multi_yieldable_map_t m_multi_ops; - pending_queue_t m_failed; - std::list > m_yieldable; - e::intrusive_ptr m_yielding; - e::intrusive_ptr m_yielded; - e::intrusive_ptr m_pcs; - // misc - e::error m_last_error; +private: + replicant_client *m_coord; + mapper m_busybee_mapper; + busybee_st m_busybee; + // configuration + configuration m_config; + int64_t m_config_id; + replicant_returncode m_config_status; + uint64_t m_config_state; + char *m_config_data; + size_t m_config_data_sz; + // nonces + int64_t m_next_admin_id; + uint64_t m_next_server_nonce; + // operations + bool m_handle_coord_ops; + coord_rpc_map_t m_coord_ops; + pending_map_t m_server_ops; + multi_yieldable_map_t m_multi_ops; + pending_queue_t m_failed; + std::list > m_yieldable; + e::intrusive_ptr m_yielding; + e::intrusive_ptr m_yielded; + e::intrusive_ptr m_pcs; + // misc + e::error m_last_error; - private: - admin(const admin&); - admin& operator = (const admin&); +private: + admin(const admin &); + admin &operator = (const admin &); }; END_HYPERDEX_NAMESPACE diff --git a/admin/backup_state_machine.cc b/admin/backup_state_machine.cc index f92217686..24d78698e 100644 --- a/admin/backup_state_machine.cc +++ b/admin/backup_state_machine.cc @@ -34,21 +34,21 @@ using hyperdex::backup_state_machine; -backup_state_machine :: backup_state_machine(const char* name, +backup_state_machine :: backup_state_machine(const char *name, uint64_t id, - hyperdex_admin_returncode* status, - const char** backups) - : multi_yieldable(id, status) - , m_name(name) - , m_state(INITIALIZED) - , m_nested_id() - , m_nested_rc() - , m_configuration_version(0) - , m_servers() - , m_backup(NULL) - , m_backups() - , m_backups_str() - , m_backups_c_str(backups) + hyperdex_admin_returncode *status, + const char **backups) + : multi_yieldable(id, status) + , m_name(name) + , m_state(INITIALIZED) + , m_nested_id() + , m_nested_rc() + , m_configuration_version(0) + , m_servers() + , m_backup(NULL) + , m_backups() + , m_backups_str() + , m_backups_c_str(backups) { } @@ -59,298 +59,268 @@ backup_state_machine :: ~backup_state_machine() throw () bool backup_state_machine :: can_yield() { - return m_state == DONE || m_state == ERROR; + return m_state == DONE || m_state == ERROR; } bool -backup_state_machine :: yield(hyperdex_admin_returncode* status) +backup_state_machine :: yield(hyperdex_admin_returncode *status) { - assert(this->can_yield()); - *status = HYPERDEX_ADMIN_SUCCESS; - m_state = YIELDED; - m_backups_str = m_backups.str(); - *m_backups_c_str = m_backups_str.c_str(); - return true; + assert(this->can_yield()); + *status = HYPERDEX_ADMIN_SUCCESS; + m_state = YIELDED; + m_backups_str = m_backups.str(); + *m_backups_c_str = m_backups_str.c_str(); + return true; } bool -backup_state_machine :: initialize(admin* adm, hyperdex_admin_returncode* status) +backup_state_machine :: initialize(admin *adm, hyperdex_admin_returncode *status) { - *status = HYPERDEX_ADMIN_SUCCESS; - m_nested_id = adm->read_only(1, &m_nested_rc); - - if (!check_nested(adm)) - { - *status = m_nested_rc; - return false; - } - - adm->m_multi_ops[m_nested_id] = this; - m_state = SET_READ_ONLY; - return true; + *status = HYPERDEX_ADMIN_SUCCESS; + m_nested_id = adm->read_only(1, &m_nested_rc); + if (!check_nested(adm)) + { + *status = m_nested_rc; + return false; + } + adm->m_multi_ops[m_nested_id] = this; + m_state = SET_READ_ONLY; + return true; } bool -backup_state_machine :: callback(admin* adm, int64_t id, hyperdex_admin_returncode* status) +backup_state_machine :: callback(admin *adm, int64_t id, hyperdex_admin_returncode *status) { - *status = HYPERDEX_ADMIN_SUCCESS; - - switch (m_state) - { - case INITIALIZED: - callback_unexpected(adm, id); - return true; - case SET_READ_ONLY: - callback_set_read_only(adm, id); - return true; - case WAIT_TO_QUIESCE: - callback_wait_to_quiesce(adm, id); - return true; - case DAEMON_BACKUP: - callback_daemon_backup(adm, id); - return true; - case COORD_BACKUP: - callback_coord_backup(adm, id); - return true; - case WAIT_TO_QUIESCE_AGAIN: - callback_wait_to_quiesce_again(adm, id); - return true; - case SET_READ_WRITE: - callback_set_read_write(adm, id); - return true; - case DONE: - callback_unexpected(adm, id); - return true; - case BACKOUT: - callback_backout(adm, id); - return true; - case ERROR: - callback_unexpected(adm, id); - return true; - case YIELDED: - callback_unexpected(adm, id); - return true; - default: - YIELDING_ERROR(INTERNAL) << "wandered into undefined state"; - return true; - } + *status = HYPERDEX_ADMIN_SUCCESS; + switch (m_state) + { + case INITIALIZED: + callback_unexpected(adm, id); + return true; + case SET_READ_ONLY: + callback_set_read_only(adm, id); + return true; + case WAIT_TO_QUIESCE: + callback_wait_to_quiesce(adm, id); + return true; + case DAEMON_BACKUP: + callback_daemon_backup(adm, id); + return true; + case COORD_BACKUP: + callback_coord_backup(adm, id); + return true; + case WAIT_TO_QUIESCE_AGAIN: + callback_wait_to_quiesce_again(adm, id); + return true; + case SET_READ_WRITE: + callback_set_read_write(adm, id); + return true; + case DONE: + callback_unexpected(adm, id); + return true; + case BACKOUT: + callback_backout(adm, id); + return true; + case ERROR: + callback_unexpected(adm, id); + return true; + case YIELDED: + callback_unexpected(adm, id); + return true; + default: + YIELDING_ERROR(INTERNAL) << "wandered into undefined state"; + return true; + } } void -backup_state_machine :: backout(admin* adm) +backup_state_machine :: backout(admin *adm) { - m_nested_id = adm->read_only(0, &m_nested_rc); - - if (m_nested_id < 0) - { - m_state = ERROR; - } - else - { - adm->m_multi_ops[m_nested_id] = this; - } + m_nested_id = adm->read_only(0, &m_nested_rc); + if (m_nested_id < 0) + { + m_state = ERROR; + } + else + { + adm->m_multi_ops[m_nested_id] = this; + } } bool -backup_state_machine :: common_callback(admin* adm, int64_t id) +backup_state_machine :: common_callback(admin *adm, int64_t id) { - bool ret = true; - - if (m_state == ERROR || m_state == YIELDED) - { - ret = false; - } - else if (m_nested_id != id) - { - YIELDING_ERROR(INTERNAL) << "callback had id=" << id - << " when it should have id=" << m_nested_id; - m_state = m_state > SET_READ_ONLY ? BACKOUT : ERROR; - ret = false; - } - else if (m_nested_rc != HYPERDEX_ADMIN_SUCCESS) - { - this->set_status(m_nested_rc); - this->set_error(adm->m_last_error); - m_state = m_state > SET_READ_ONLY ? BACKOUT : ERROR; - ret = false; - } - - if (!ret && m_state == BACKOUT) - { - backout(adm); - } - - return ret; + bool ret = true; + if (m_state == ERROR || m_state == YIELDED) + { + ret = false; + } + else if (m_nested_id != id) + { + YIELDING_ERROR(INTERNAL) << "callback had id=" << id + << " when it should have id=" << m_nested_id; + m_state = m_state > SET_READ_ONLY ? BACKOUT : ERROR; + ret = false; + } + else if (m_nested_rc != HYPERDEX_ADMIN_SUCCESS) + { + this->set_status(m_nested_rc); + this->set_error(adm->m_last_error); + m_state = m_state > SET_READ_ONLY ? BACKOUT : ERROR; + ret = false; + } + if (!ret && m_state == BACKOUT) + { + backout(adm); + } + return ret; } bool -backup_state_machine :: check_nested(admin* adm) +backup_state_machine :: check_nested(admin *adm) { - if (m_nested_id >= 0) - { - return true; - } - - this->set_status(m_nested_rc); - this->set_error(adm->m_last_error); - m_state = m_state >= SET_READ_ONLY ? BACKOUT : ERROR; - - if (m_state == BACKOUT) - { - backout(adm); - } - - return false; + if (m_nested_id >= 0) + { + return true; + } + this->set_status(m_nested_rc); + this->set_error(adm->m_last_error); + m_state = m_state >= SET_READ_ONLY ? BACKOUT : ERROR; + if (m_state == BACKOUT) + { + backout(adm); + } + return false; } void -backup_state_machine :: callback_unexpected(admin*, int64_t) +backup_state_machine :: callback_unexpected(admin *, int64_t) { - YIELDING_ERROR(INTERNAL) << "wandered into undefined state"; - m_state = ERROR; + YIELDING_ERROR(INTERNAL) << "wandered into undefined state"; + m_state = ERROR; } void -backup_state_machine :: callback_set_read_only(admin* adm, int64_t id) +backup_state_machine :: callback_set_read_only(admin *adm, int64_t id) { - if (!common_callback(adm, id)) - { - return; - } - - m_nested_id = adm->wait_until_stable(&m_nested_rc); - - if (!check_nested(adm)) - { - return; - } - - adm->m_multi_ops[m_nested_id] = this; - m_state = WAIT_TO_QUIESCE; + if (!common_callback(adm, id)) + { + return; + } + m_nested_id = adm->wait_until_stable(&m_nested_rc); + if (!check_nested(adm)) + { + return; + } + adm->m_multi_ops[m_nested_id] = this; + m_state = WAIT_TO_QUIESCE; } void -backup_state_machine :: callback_wait_to_quiesce(admin* adm, int64_t id) +backup_state_machine :: callback_wait_to_quiesce(admin *adm, int64_t id) { - if (!common_callback(adm, id)) - { - return; - } - - // at this point we know that: - // 1. the cluster is in read-only mode - // 2. every write initiated before setting it to read-only mode is complete - m_configuration_version = adm->m_config.version(); - - // now figure out the servers to take a backup on - adm->m_config.get_all_addresses(&m_servers); - std::sort(m_servers.rbegin(), m_servers.rend()); - return callback_daemon_backup(adm, id); + if (!common_callback(adm, id)) + { + return; + } + // at this point we know that: + // 1. the cluster is in read-only mode + // 2. every write initiated before setting it to read-only mode is complete + m_configuration_version = adm->m_config.version(); + // now figure out the servers to take a backup on + adm->m_config.get_all_addresses(&m_servers); + std::sort(m_servers.rbegin(), m_servers.rend()); + return callback_daemon_backup(adm, id); } void -backup_state_machine :: callback_daemon_backup(admin* adm, int64_t id) +backup_state_machine :: callback_daemon_backup(admin *adm, int64_t id) { - if (!common_callback(adm, id)) - { - return; - } - - if (m_backup) - { - m_backups << m_backup << "\n"; - m_backup = NULL; - } - - if (m_servers.empty()) - { - std::string path = m_name + ".coordinator.bin"; - m_nested_id = adm->coord_backup(path.c_str(), &m_nested_rc); - - if (!check_nested(adm)) - { - return; - } - - adm->m_multi_ops[m_nested_id] = this; - m_state = COORD_BACKUP; - return; - } - - server_id sid = m_servers.back().first; - po6::net::location loc = m_servers.back().second; - m_servers.pop_back(); - m_nested_id = adm->raw_backup(sid, m_name.c_str(), &m_nested_rc, &m_backup); - m_backups << sid.get() << " " << loc.address << " "; - - if (!check_nested(adm)) - { - return; - } - - adm->m_multi_ops[m_nested_id] = this; - m_state = DAEMON_BACKUP; + if (!common_callback(adm, id)) + { + return; + } + if (m_backup) + { + m_backups << m_backup << "\n"; + m_backup = NULL; + } + if (m_servers.empty()) + { + std::string path = m_name + ".coordinator.bin"; + m_nested_id = adm->coord_backup(path.c_str(), &m_nested_rc); + if (!check_nested(adm)) + { + return; + } + adm->m_multi_ops[m_nested_id] = this; + m_state = COORD_BACKUP; + return; + } + server_id sid = m_servers.back().first; + po6::net::location loc = m_servers.back().second; + m_servers.pop_back(); + m_nested_id = adm->raw_backup(sid, m_name.c_str(), &m_nested_rc, &m_backup); + m_backups << sid.get() << " " << loc.address << " "; + if (!check_nested(adm)) + { + return; + } + adm->m_multi_ops[m_nested_id] = this; + m_state = DAEMON_BACKUP; } void -backup_state_machine :: callback_coord_backup(admin* adm, int64_t id) +backup_state_machine :: callback_coord_backup(admin *adm, int64_t id) { - if (!common_callback(adm, id)) - { - return; - } - - m_nested_id = adm->wait_until_stable(&m_nested_rc); - - if (!check_nested(adm)) - { - return; - } - - adm->m_multi_ops[m_nested_id] = this; - m_state = WAIT_TO_QUIESCE_AGAIN; + if (!common_callback(adm, id)) + { + return; + } + m_nested_id = adm->wait_until_stable(&m_nested_rc); + if (!check_nested(adm)) + { + return; + } + adm->m_multi_ops[m_nested_id] = this; + m_state = WAIT_TO_QUIESCE_AGAIN; } void -backup_state_machine :: callback_wait_to_quiesce_again(admin* adm, int64_t id) +backup_state_machine :: callback_wait_to_quiesce_again(admin *adm, int64_t id) { - if (!common_callback(adm, id)) - { - return; - } - - if (m_configuration_version != adm->m_config.version()) - { - YIELDING_ERROR(INTERNAL) << "configuration changed while taking backup"; - backout(adm); - } - - m_nested_id = adm->read_only(0, &m_nested_rc); - - if (!check_nested(adm)) - { - return; - } - - adm->m_multi_ops[m_nested_id] = this; - m_state = SET_READ_WRITE; + if (!common_callback(adm, id)) + { + return; + } + if (m_configuration_version != adm->m_config.version()) + { + YIELDING_ERROR(INTERNAL) << "configuration changed while taking backup"; + backout(adm); + } + m_nested_id = adm->read_only(0, &m_nested_rc); + if (!check_nested(adm)) + { + return; + } + adm->m_multi_ops[m_nested_id] = this; + m_state = SET_READ_WRITE; } void -backup_state_machine :: callback_set_read_write(admin* adm, int64_t id) +backup_state_machine :: callback_set_read_write(admin *adm, int64_t id) { - if (!common_callback(adm, id)) - { - return; - } - - this->set_status(HYPERDEX_ADMIN_SUCCESS); - this->set_error(e::error()); - m_state = DONE; + if (!common_callback(adm, id)) + { + return; + } + this->set_status(HYPERDEX_ADMIN_SUCCESS); + this->set_error(e::error()); + m_state = DONE; } void -backup_state_machine :: callback_backout(admin*, int64_t) +backup_state_machine :: callback_backout(admin *, int64_t) { - m_state = ERROR; + m_state = ERROR; } diff --git a/admin/backup_state_machine.h b/admin/backup_state_machine.h index d70be441c..38dfe55e3 100644 --- a/admin/backup_state_machine.h +++ b/admin/backup_state_machine.h @@ -49,58 +49,59 @@ class admin; class backup_state_machine : public multi_yieldable { - public: - backup_state_machine(const char* name, - uint64_t admin_visible_id, - hyperdex_admin_returncode* status, - const char** backups); - ~backup_state_machine() throw (); +public: + backup_state_machine(const char *name, + uint64_t admin_visible_id, + hyperdex_admin_returncode *status, + const char **backups); + ~backup_state_machine() throw (); - public: - bool can_yield(); - bool yield(hyperdex_admin_returncode* status); - bool initialize(admin* adm, hyperdex_admin_returncode* status); - bool callback(admin* adm, int64_t id, hyperdex_admin_returncode* status); +public: + bool can_yield(); + bool yield(hyperdex_admin_returncode *status); + bool initialize(admin *adm, hyperdex_admin_returncode *status); + bool callback(admin *adm, int64_t id, hyperdex_admin_returncode *status); - private: - friend class e::intrusive_ptr; - backup_state_machine(const backup_state_machine&); - backup_state_machine& operator = (const backup_state_machine&); +private: + friend class e::intrusive_ptr; + backup_state_machine(const backup_state_machine &); + backup_state_machine &operator = (const backup_state_machine &); - private: - void backout(admin* adm); - bool common_callback(admin* adm, int64_t id); - bool check_nested(admin* adm); - void callback_unexpected(admin* adm, int64_t id); - void callback_set_read_only(admin* adm, int64_t id); - void callback_wait_to_quiesce(admin* adm, int64_t id); - void callback_daemon_backup(admin* adm, int64_t id); - void callback_coord_backup(admin* adm, int64_t id); - void callback_wait_to_quiesce_again(admin* adm, int64_t id); - void callback_set_read_write(admin* adm, int64_t id); - void callback_backout(admin* adm, int64_t id); +private: + void backout(admin *adm); + bool common_callback(admin *adm, int64_t id); + bool check_nested(admin *adm); + void callback_unexpected(admin *adm, int64_t id); + void callback_set_read_only(admin *adm, int64_t id); + void callback_wait_to_quiesce(admin *adm, int64_t id); + void callback_daemon_backup(admin *adm, int64_t id); + void callback_coord_backup(admin *adm, int64_t id); + void callback_wait_to_quiesce_again(admin *adm, int64_t id); + void callback_set_read_write(admin *adm, int64_t id); + void callback_backout(admin *adm, int64_t id); - private: - std::string m_name; - enum { INITIALIZED, - SET_READ_ONLY, - WAIT_TO_QUIESCE, - DAEMON_BACKUP, - COORD_BACKUP, - WAIT_TO_QUIESCE_AGAIN, - SET_READ_WRITE, - DONE, - BACKOUT, - ERROR, - YIELDED } m_state; - int64_t m_nested_id; - hyperdex_admin_returncode m_nested_rc; - uint64_t m_configuration_version; - std::vector > m_servers; - const char* m_backup; - std::ostringstream m_backups; - std::string m_backups_str; - const char** m_backups_c_str; +private: + std::string m_name; + enum { INITIALIZED, + SET_READ_ONLY, + WAIT_TO_QUIESCE, + DAEMON_BACKUP, + COORD_BACKUP, + WAIT_TO_QUIESCE_AGAIN, + SET_READ_WRITE, + DONE, + BACKOUT, + ERROR, + YIELDED + } m_state; + int64_t m_nested_id; + hyperdex_admin_returncode m_nested_rc; + uint64_t m_configuration_version; + std::vector > m_servers; + const char *m_backup; + std::ostringstream m_backups; + std::string m_backups_str; + const char **m_backups_c_str; }; END_HYPERDEX_NAMESPACE diff --git a/admin/c.cc b/admin/c.cc index 442eddb02..a6a38327b 100644 --- a/admin/c.cc +++ b/admin/c.cc @@ -41,349 +41,349 @@ #include "admin/admin.h" #define SIGNAL_PROTECT_ERR(X) \ - do \ - { \ - sigset_t old_sigs; \ - sigset_t all_sigs; \ - sigfillset(&all_sigs); \ - if (pthread_sigmask(SIG_BLOCK, &all_sigs, &old_sigs) < 0) \ - { \ - *status = HYPERDEX_ADMIN_INTERNAL; \ - return (X); \ - } \ - e::guard g = e::makeguard(pthread_sigmask, SIG_SETMASK, (sigset_t*)&old_sigs, (sigset_t*)NULL); \ - g.use_variable(); \ - } \ - while (0) + do \ + { \ + sigset_t old_sigs; \ + sigset_t all_sigs; \ + sigfillset(&all_sigs); \ + if (pthread_sigmask(SIG_BLOCK, &all_sigs, &old_sigs) < 0) \ + { \ + *status = HYPERDEX_ADMIN_INTERNAL; \ + return (X); \ + } \ + e::guard g = e::makeguard(pthread_sigmask, SIG_SETMASK, (sigset_t*)&old_sigs, (sigset_t*)NULL); \ + g.use_variable(); \ + } \ + while (0) #define SIGNAL_PROTECT SIGNAL_PROTECT_ERR(-1); inline void return_void() {} #define SIGNAL_PROTECT_VOID SIGNAL_PROTECT_ERR(return_void()); #define C_WRAP_EXCEPT(X) \ - SIGNAL_PROTECT; \ - try \ - { \ - X \ - } \ - catch (std::bad_alloc& ba) \ - { \ - errno = ENOMEM; \ - *status = HYPERDEX_ADMIN_NOMEM; \ - return -1; \ - } \ - catch (...) \ - { \ - *status = HYPERDEX_ADMIN_EXCEPTION; \ - return -1; \ - } + SIGNAL_PROTECT; \ + try \ + { \ + X \ + } \ + catch (std::bad_alloc& ba) \ + { \ + errno = ENOMEM; \ + *status = HYPERDEX_ADMIN_NOMEM; \ + return -1; \ + } \ + catch (...) \ + { \ + *status = HYPERDEX_ADMIN_EXCEPTION; \ + return -1; \ + } extern "C" { -HYPERDEX_API struct hyperdex_admin* -hyperdex_admin_create(const char* coordinator, uint16_t port) -{ - try - { - return reinterpret_cast(new hyperdex::admin(coordinator, port)); - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - return NULL; - } - catch (...) - { - return NULL; - } -} - -HYPERDEX_API void -hyperdex_admin_destroy(struct hyperdex_admin* admin) -{ - delete reinterpret_cast(admin); -} - -HYPERDEX_API int64_t -hyperdex_admin_dump_config(struct hyperdex_admin* _adm, - hyperdex_admin_returncode* status, - const char** config) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->dump_config(status, config); - ); -} -HYPERDEX_API int64_t -hyperdex_admin_read_only(struct hyperdex_admin* _adm, - int ro, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->read_only(ro, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_wait_until_stable(struct hyperdex_admin* _adm, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->wait_until_stable(status); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_fault_tolerance(struct hyperdex_admin* _adm, - const char* space, - uint64_t ft, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->fault_tolerance(space, ft, status); - ); -} - -HYPERDEX_API int -hyperdex_admin_validate_space(struct hyperdex_admin* _adm, - const char* description, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->validate_space(description, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_add_space(struct hyperdex_admin* _adm, - const char* description, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->add_space(description, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_rm_space(struct hyperdex_admin* _adm, - const char* space, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->rm_space(space, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_mv_space(struct hyperdex_admin* _adm, - const char* source, - const char* target, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->mv_space(source, target, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_list_spaces(struct hyperdex_admin* _adm, - enum hyperdex_admin_returncode* status, - const char** spaces) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->list_spaces(status, spaces); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_list_indices(struct hyperdex_admin* _adm, - const char* space, - enum hyperdex_admin_returncode* status, - const char** indexes) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->list_indices(space, status, indexes); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_list_subspaces(struct hyperdex_admin* _adm, - const char* space, - enum hyperdex_admin_returncode* status, - const char** subspaces) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->list_subspaces(space, status, subspaces); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_add_index(struct hyperdex_admin* _adm, - const char* space, - const char* attribute, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->add_index(space, attribute, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_rm_index(struct hyperdex_admin* _adm, - uint64_t idxid, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->rm_index(idxid, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_server_register(struct hyperdex_admin* _adm, - uint64_t token, - const char* address, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->server_register(token, address, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_server_online(struct hyperdex_admin* _adm, - uint64_t token, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->server_online(token, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_server_offline(struct hyperdex_admin* _adm, - uint64_t token, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->server_offline(token, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_server_forget(struct hyperdex_admin* _adm, - uint64_t token, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->server_forget(token, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_server_kill(struct hyperdex_admin* _adm, - uint64_t token, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->server_kill(token, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_backup(struct hyperdex_admin* _adm, - const char* backup, - enum hyperdex_admin_returncode* status, - const char** backups) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->backup(backup, status, backups); - ); -} - -HYPERDEX_API int64_t -hyperdex_admin_enable_perf_counters(struct hyperdex_admin* _adm, - enum hyperdex_admin_returncode* status, - struct hyperdex_admin_perf_counter* pc) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->enable_perf_counters(status, pc); - ); -} - -HYPERDEX_API void -hyperdex_admin_disable_perf_counters(struct hyperdex_admin* _adm) -{ - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->disable_perf_counters(); -} - -HYPERDEX_API int64_t -hyperdex_admin_loop(struct hyperdex_admin* _adm, int timeout, - enum hyperdex_admin_returncode* status) -{ - C_WRAP_EXCEPT( - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->loop(timeout, status); - ); -} - -HYPERDEX_API const char* -hyperdex_admin_error_message(struct hyperdex_admin* _adm) -{ - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->error_message(); -} - -HYPERDEX_API const char* -hyperdex_admin_error_location(struct hyperdex_admin* _adm) -{ - hyperdex::admin* adm = reinterpret_cast(_adm); - return adm->error_location(); -} - -HYPERDEX_API const char* -hyperdex_admin_returncode_to_string(enum hyperdex_admin_returncode status) -{ - switch (status) - { - CSTRINGIFY(HYPERDEX_ADMIN_SUCCESS); - CSTRINGIFY(HYPERDEX_ADMIN_NOMEM); - CSTRINGIFY(HYPERDEX_ADMIN_NONEPENDING); - CSTRINGIFY(HYPERDEX_ADMIN_POLLFAILED); - CSTRINGIFY(HYPERDEX_ADMIN_TIMEOUT); - CSTRINGIFY(HYPERDEX_ADMIN_INTERRUPTED); - CSTRINGIFY(HYPERDEX_ADMIN_SERVERERROR); - CSTRINGIFY(HYPERDEX_ADMIN_COORDFAIL); - CSTRINGIFY(HYPERDEX_ADMIN_BADSPACE); - CSTRINGIFY(HYPERDEX_ADMIN_DUPLICATE); - CSTRINGIFY(HYPERDEX_ADMIN_NOTFOUND); - CSTRINGIFY(HYPERDEX_ADMIN_LOCALERROR); - CSTRINGIFY(HYPERDEX_ADMIN_INTERNAL); - CSTRINGIFY(HYPERDEX_ADMIN_EXCEPTION); - CSTRINGIFY(HYPERDEX_ADMIN_GARBAGE); - default: - return "unknown hyperdex_admin_returncode"; - } -} + HYPERDEX_API struct hyperdex_admin * + hyperdex_admin_create(const char *coordinator, uint16_t port) + { + try + { + return reinterpret_cast(new hyperdex::admin(coordinator, port)); + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + return NULL; + } + catch (...) + { + return NULL; + } + } + + HYPERDEX_API void + hyperdex_admin_destroy(struct hyperdex_admin *admin) + { + delete reinterpret_cast(admin); + } + + HYPERDEX_API int64_t + hyperdex_admin_dump_config(struct hyperdex_admin *_adm, + hyperdex_admin_returncode *status, + const char **config) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->dump_config(status, config); + ); + } + HYPERDEX_API int64_t + hyperdex_admin_read_only(struct hyperdex_admin *_adm, + int ro, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->read_only(ro, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_wait_until_stable(struct hyperdex_admin *_adm, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->wait_until_stable(status); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_fault_tolerance(struct hyperdex_admin *_adm, + const char *space, + uint64_t ft, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->fault_tolerance(space, ft, status); + ); + } + + HYPERDEX_API int + hyperdex_admin_validate_space(struct hyperdex_admin *_adm, + const char *description, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->validate_space(description, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_add_space(struct hyperdex_admin *_adm, + const char *description, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->add_space(description, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_rm_space(struct hyperdex_admin *_adm, + const char *space, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->rm_space(space, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_mv_space(struct hyperdex_admin *_adm, + const char *source, + const char *target, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->mv_space(source, target, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_list_spaces(struct hyperdex_admin *_adm, + enum hyperdex_admin_returncode *status, + const char **spaces) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->list_spaces(status, spaces); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_list_indices(struct hyperdex_admin *_adm, + const char *space, + enum hyperdex_admin_returncode *status, + const char **indexes) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->list_indices(space, status, indexes); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_list_subspaces(struct hyperdex_admin *_adm, + const char *space, + enum hyperdex_admin_returncode *status, + const char **subspaces) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->list_subspaces(space, status, subspaces); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_add_index(struct hyperdex_admin *_adm, + const char *space, + const char *attribute, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->add_index(space, attribute, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_rm_index(struct hyperdex_admin *_adm, + uint64_t idxid, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->rm_index(idxid, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_server_register(struct hyperdex_admin *_adm, + uint64_t token, + const char *address, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->server_register(token, address, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_server_online(struct hyperdex_admin *_adm, + uint64_t token, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->server_online(token, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_server_offline(struct hyperdex_admin *_adm, + uint64_t token, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->server_offline(token, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_server_forget(struct hyperdex_admin *_adm, + uint64_t token, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->server_forget(token, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_server_kill(struct hyperdex_admin *_adm, + uint64_t token, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->server_kill(token, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_backup(struct hyperdex_admin *_adm, + const char *backup, + enum hyperdex_admin_returncode *status, + const char **backups) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->backup(backup, status, backups); + ); + } + + HYPERDEX_API int64_t + hyperdex_admin_enable_perf_counters(struct hyperdex_admin *_adm, + enum hyperdex_admin_returncode *status, + struct hyperdex_admin_perf_counter *pc) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->enable_perf_counters(status, pc); + ); + } + + HYPERDEX_API void + hyperdex_admin_disable_perf_counters(struct hyperdex_admin *_adm) + { + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->disable_perf_counters(); + } + + HYPERDEX_API int64_t + hyperdex_admin_loop(struct hyperdex_admin *_adm, int timeout, + enum hyperdex_admin_returncode *status) + { + C_WRAP_EXCEPT( + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->loop(timeout, status); + ); + } + + HYPERDEX_API const char * + hyperdex_admin_error_message(struct hyperdex_admin *_adm) + { + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->error_message(); + } + + HYPERDEX_API const char * + hyperdex_admin_error_location(struct hyperdex_admin *_adm) + { + hyperdex::admin *adm = reinterpret_cast(_adm); + return adm->error_location(); + } + + HYPERDEX_API const char * + hyperdex_admin_returncode_to_string(enum hyperdex_admin_returncode status) + { + switch (status) + { + CSTRINGIFY(HYPERDEX_ADMIN_SUCCESS); + CSTRINGIFY(HYPERDEX_ADMIN_NOMEM); + CSTRINGIFY(HYPERDEX_ADMIN_NONEPENDING); + CSTRINGIFY(HYPERDEX_ADMIN_POLLFAILED); + CSTRINGIFY(HYPERDEX_ADMIN_TIMEOUT); + CSTRINGIFY(HYPERDEX_ADMIN_INTERRUPTED); + CSTRINGIFY(HYPERDEX_ADMIN_SERVERERROR); + CSTRINGIFY(HYPERDEX_ADMIN_COORDFAIL); + CSTRINGIFY(HYPERDEX_ADMIN_BADSPACE); + CSTRINGIFY(HYPERDEX_ADMIN_DUPLICATE); + CSTRINGIFY(HYPERDEX_ADMIN_NOTFOUND); + CSTRINGIFY(HYPERDEX_ADMIN_LOCALERROR); + CSTRINGIFY(HYPERDEX_ADMIN_INTERNAL); + CSTRINGIFY(HYPERDEX_ADMIN_EXCEPTION); + CSTRINGIFY(HYPERDEX_ADMIN_GARBAGE); + default: + return "unknown hyperdex_admin_returncode"; + } + } } // extern "C" diff --git a/admin/coord_rpc.cc b/admin/coord_rpc.cc index 131c2ccc6..a8f76faa3 100644 --- a/admin/coord_rpc.cc +++ b/admin/coord_rpc.cc @@ -31,18 +31,18 @@ using hyperdex::coord_rpc; coord_rpc :: coord_rpc(uint64_t id, - hyperdex_admin_returncode* s) - : yieldable(id, s) - , repl_status(REPLICANT_GARBAGE) - , repl_output(NULL) - , repl_output_sz(0) + hyperdex_admin_returncode *s) + : yieldable(id, s) + , repl_status(REPLICANT_GARBAGE) + , repl_output(NULL) + , repl_output_sz(0) { } coord_rpc :: ~coord_rpc() throw () { - if (repl_output) - { - free(repl_output); - } + if (repl_output) + { + free(repl_output); + } } diff --git a/admin/coord_rpc.h b/admin/coord_rpc.h index f92102250..693b71f53 100644 --- a/admin/coord_rpc.h +++ b/admin/coord_rpc.h @@ -52,26 +52,26 @@ class admin; class coord_rpc : public yieldable { - public: - coord_rpc(uint64_t admin_visible_id, - hyperdex_admin_returncode* status); - virtual ~coord_rpc() throw (); +public: + coord_rpc(uint64_t admin_visible_id, + hyperdex_admin_returncode *status); + virtual ~coord_rpc() throw (); - public: - virtual bool handle_response(admin* adm, - hyperdex_admin_returncode* status) = 0; +public: + virtual bool handle_response(admin *adm, + hyperdex_admin_returncode *status) = 0; - public: - replicant_returncode repl_status; - char* repl_output; - size_t repl_output_sz; +public: + replicant_returncode repl_status; + char *repl_output; + size_t repl_output_sz; - protected: - friend class e::intrusive_ptr; +protected: + friend class e::intrusive_ptr; - private: - coord_rpc(const coord_rpc&); - coord_rpc& operator = (const coord_rpc&); +private: + coord_rpc(const coord_rpc &); + coord_rpc &operator = (const coord_rpc &); }; END_HYPERDEX_NAMESPACE diff --git a/admin/coord_rpc_backup.cc b/admin/coord_rpc_backup.cc index 7ca7b7215..d85df0cc0 100644 --- a/admin/coord_rpc_backup.cc +++ b/admin/coord_rpc_backup.cc @@ -42,11 +42,11 @@ using hyperdex::coord_rpc_backup; coord_rpc_backup :: coord_rpc_backup(uint64_t id, - hyperdex_admin_returncode* status, - const char* path) - : coord_rpc(id, status) - , m_path(path) - , m_done(false) + hyperdex_admin_returncode *status, + const char *path) + : coord_rpc(id, status) + , m_path(path) + , m_done(false) { } @@ -57,49 +57,44 @@ coord_rpc_backup :: ~coord_rpc_backup() throw () bool coord_rpc_backup :: can_yield() { - return !m_done; + return !m_done; } bool -coord_rpc_backup :: yield(hyperdex_admin_returncode* status) +coord_rpc_backup :: yield(hyperdex_admin_returncode *status) { - assert(this->can_yield()); - m_done = true; - *status = HYPERDEX_ADMIN_SUCCESS; - return true; + assert(this->can_yield()); + m_done = true; + *status = HYPERDEX_ADMIN_SUCCESS; + return true; } bool -coord_rpc_backup :: handle_response(admin* adm, - hyperdex_admin_returncode* status) +coord_rpc_backup :: handle_response(admin *adm, + hyperdex_admin_returncode *status) { - *status = HYPERDEX_ADMIN_SUCCESS; - hyperdex_admin_returncode resp_status; - e::error err; - adm->interpret_replicant_returncode(repl_status, &resp_status, &err); - set_status(resp_status); - set_error(err); - - if (resp_status != HYPERDEX_ADMIN_SUCCESS) - { - return true; - } - - po6::io::fd fd(open(m_path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)); - - if (fd.get() < 0) - { - YIELDING_ERROR(LOCALERROR) << "could not open coordinator backup file \"" - << e::strescape(m_path) << "\": " << strerror(errno); - return true; - } - - if (fd.xwrite(repl_output, repl_output_sz) != static_cast(repl_output_sz)) - { - YIELDING_ERROR(LOCALERROR) << "could not write coordinator backup file \"" - << e::strescape(m_path) << "\": " << strerror(errno); - return true; - } - - return true; + *status = HYPERDEX_ADMIN_SUCCESS; + hyperdex_admin_returncode resp_status; + e::error err; + adm->interpret_replicant_returncode(repl_status, &resp_status, &err); + set_status(resp_status); + set_error(err); + if (resp_status != HYPERDEX_ADMIN_SUCCESS) + { + return true; + } + po6::io::fd fd(open(m_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); + if (fd.get() < 0) + { + YIELDING_ERROR(LOCALERROR) << "could not open coordinator backup file \"" + << e::strescape(m_path) << "\": " << strerror(errno); + return true; + } + if (fd.xwrite(repl_output, repl_output_sz) != static_cast(repl_output_sz)) + { + YIELDING_ERROR(LOCALERROR) << "could not write coordinator backup file \"" + << e::strescape(m_path) << "\": " << strerror(errno); + return true; + } + return true; } diff --git a/admin/coord_rpc_backup.h b/admin/coord_rpc_backup.h index db556a78c..23087e117 100644 --- a/admin/coord_rpc_backup.h +++ b/admin/coord_rpc_backup.h @@ -35,27 +35,27 @@ BEGIN_HYPERDEX_NAMESPACE class coord_rpc_backup : public coord_rpc { - public: - coord_rpc_backup(uint64_t admin_visible_id, - hyperdex_admin_returncode* status, - const char* path); - virtual ~coord_rpc_backup() throw (); - - public: - virtual bool can_yield(); - virtual bool yield(hyperdex_admin_returncode* status); - - public: - virtual bool handle_response(admin* adm, - hyperdex_admin_returncode* status); - - private: - coord_rpc_backup(const coord_rpc_backup&); - coord_rpc_backup& operator = (const coord_rpc_backup&); - - private: - std::string m_path; - bool m_done; +public: + coord_rpc_backup(uint64_t admin_visible_id, + hyperdex_admin_returncode *status, + const char *path); + virtual ~coord_rpc_backup() throw (); + +public: + virtual bool can_yield(); + virtual bool yield(hyperdex_admin_returncode *status); + +public: + virtual bool handle_response(admin *adm, + hyperdex_admin_returncode *status); + +private: + coord_rpc_backup(const coord_rpc_backup &); + coord_rpc_backup &operator = (const coord_rpc_backup &); + +private: + std::string m_path; + bool m_done; }; END_HYPERDEX_NAMESPACE diff --git a/admin/coord_rpc_generic.cc b/admin/coord_rpc_generic.cc index 4d7bfc379..d8f759b0b 100644 --- a/admin/coord_rpc_generic.cc +++ b/admin/coord_rpc_generic.cc @@ -38,11 +38,11 @@ using hyperdex::coord_rpc_generic; coord_rpc_generic :: coord_rpc_generic(uint64_t id, - hyperdex_admin_returncode* s, - const char* opname) - : coord_rpc(id, s) - , m_opname(opname) - , m_done(false) + hyperdex_admin_returncode *s, + const char *opname) + : coord_rpc(id, s) + , m_opname(opname) + , m_done(false) { } @@ -53,63 +53,59 @@ coord_rpc_generic :: ~coord_rpc_generic() throw () bool coord_rpc_generic :: can_yield() { - return !m_done; + return !m_done; } bool -coord_rpc_generic :: yield(hyperdex_admin_returncode* status) +coord_rpc_generic :: yield(hyperdex_admin_returncode *status) { - assert(this->can_yield()); - m_done = true; - *status = HYPERDEX_ADMIN_SUCCESS; - return true; + assert(this->can_yield()); + m_done = true; + *status = HYPERDEX_ADMIN_SUCCESS; + return true; } bool -coord_rpc_generic :: handle_response(admin* adm, - hyperdex_admin_returncode* status) +coord_rpc_generic :: handle_response(admin *adm, + hyperdex_admin_returncode *status) { - *status = HYPERDEX_ADMIN_SUCCESS; - hyperdex_admin_returncode resp_status; - e::error err; - adm->interpret_replicant_returncode(repl_status, &resp_status, &err); - set_status(resp_status); - set_error(err); - - if (resp_status != HYPERDEX_ADMIN_SUCCESS) - { - return true; - } - - if (repl_output_sz >= 2) - { - uint16_t x; - e::unpack16be(repl_output, &x); - coordinator_returncode rc = static_cast(x); - - switch (rc) - { - case hyperdex::COORD_SUCCESS: - set_status(HYPERDEX_ADMIN_SUCCESS); - break; - case hyperdex::COORD_NOT_FOUND: - YIELDING_ERROR(NOTFOUND) << "cannot " << m_opname << ": does not exist"; - break; - case hyperdex::COORD_DUPLICATE: - YIELDING_ERROR(DUPLICATE) << "cannot " << m_opname << ": already exists"; - break; - case hyperdex::COORD_UNINITIALIZED: - YIELDING_ERROR(COORDFAIL) << "cannot " << m_opname << ": coordinator is uninitialized"; - break; - case hyperdex::COORD_NO_CAN_DO: - YIELDING_ERROR(COORDFAIL) << "cannot " << m_opname << ": see coordinator log for details"; - break; - case hyperdex::COORD_MALFORMED: - default: - YIELDING_ERROR(INTERNAL) << "internal error interfacing with coordinator"; - break; - } - } - - return true; + *status = HYPERDEX_ADMIN_SUCCESS; + hyperdex_admin_returncode resp_status; + e::error err; + adm->interpret_replicant_returncode(repl_status, &resp_status, &err); + set_status(resp_status); + set_error(err); + if (resp_status != HYPERDEX_ADMIN_SUCCESS) + { + return true; + } + if (repl_output_sz >= 2) + { + uint16_t x; + e::unpack16be(repl_output, &x); + coordinator_returncode rc = static_cast(x); + switch (rc) + { + case hyperdex::COORD_SUCCESS: + set_status(HYPERDEX_ADMIN_SUCCESS); + break; + case hyperdex::COORD_NOT_FOUND: + YIELDING_ERROR(NOTFOUND) << "cannot " << m_opname << ": does not exist"; + break; + case hyperdex::COORD_DUPLICATE: + YIELDING_ERROR(DUPLICATE) << "cannot " << m_opname << ": already exists"; + break; + case hyperdex::COORD_UNINITIALIZED: + YIELDING_ERROR(COORDFAIL) << "cannot " << m_opname << ": coordinator is uninitialized"; + break; + case hyperdex::COORD_NO_CAN_DO: + YIELDING_ERROR(COORDFAIL) << "cannot " << m_opname << ": see coordinator log for details"; + break; + case hyperdex::COORD_MALFORMED: + default: + YIELDING_ERROR(INTERNAL) << "internal error interfacing with coordinator"; + break; + } + } + return true; } diff --git a/admin/coord_rpc_generic.h b/admin/coord_rpc_generic.h index 61930efa6..2202a0a8e 100644 --- a/admin/coord_rpc_generic.h +++ b/admin/coord_rpc_generic.h @@ -35,30 +35,30 @@ BEGIN_HYPERDEX_NAMESPACE class coord_rpc_generic : public coord_rpc { - public: - coord_rpc_generic(uint64_t admin_visible_id, - hyperdex_admin_returncode* status, - const char* opname); - virtual ~coord_rpc_generic() throw (); +public: + coord_rpc_generic(uint64_t admin_visible_id, + hyperdex_admin_returncode *status, + const char *opname); + virtual ~coord_rpc_generic() throw (); - public: - virtual bool can_yield(); - virtual bool yield(hyperdex_admin_returncode* status); +public: + virtual bool can_yield(); + virtual bool yield(hyperdex_admin_returncode *status); - public: - virtual bool handle_response(admin* adm, - hyperdex_admin_returncode* status); +public: + virtual bool handle_response(admin *adm, + hyperdex_admin_returncode *status); - protected: - friend class e::intrusive_ptr; +protected: + friend class e::intrusive_ptr; - private: - coord_rpc_generic(const coord_rpc_generic&); - coord_rpc_generic& operator = (const coord_rpc_generic&); +private: + coord_rpc_generic(const coord_rpc_generic &); + coord_rpc_generic &operator = (const coord_rpc_generic &); - private: - const char* m_opname; - bool m_done; +private: + const char *m_opname; + bool m_done; }; END_HYPERDEX_NAMESPACE diff --git a/admin/hyperspace_builder.cc b/admin/hyperspace_builder.cc index fdf5b1b05..7e77d8a98 100644 --- a/admin/hyperspace_builder.cc +++ b/admin/hyperspace_builder.cc @@ -56,8 +56,8 @@ extern "C" { #include "admin/parse_space_y.h" -extern int -yyparse(struct hyperspace* space, void* scanner); + extern int + yyparse(struct hyperspace *space, void *scanner); } #pragma GCC diagnostic pop @@ -69,63 +69,63 @@ namespace class hypersubspace { - public: - hypersubspace() : attrs() {} - ~hypersubspace() throw () {} +public: + hypersubspace() : attrs() {} + ~hypersubspace() throw () {} - public: - std::vector attrs; +public: + std::vector attrs; }; } class hyperspace { - public: - hyperspace(); - ~hyperspace() throw (); - - public: - // copy the string and return a pointer to the copy - const char* internalize(const char*); - bool has_attr(const char* name); - hyperdatatype attr_type(const char* name); - - public: - void* scanner; - const char* error; - char buffer[BUFFER_SIZE]; - std::list strings; - - // parsed components - const char* name; - hyperdex::attribute key; - std::vector attributes; - std::vector subspaces; - std::vector indices; - uint64_t fault_tolerance; - uint64_t partitions; - bool authorization; - - private: - hyperspace(const hyperspace&); - hyperspace& operator = (const hyperspace&); +public: + hyperspace(); + ~hyperspace() throw (); + +public: + // copy the string and return a pointer to the copy + const char *internalize(const char *); + bool has_attr(const char *name); + hyperdatatype attr_type(const char *name); + +public: + void *scanner; + const char *error; + char buffer[BUFFER_SIZE]; + std::list strings; + + // parsed components + const char *name; + hyperdex::attribute key; + std::vector attributes; + std::vector subspaces; + std::vector indices; + uint64_t fault_tolerance; + uint64_t partitions; + bool authorization; + +private: + hyperspace(const hyperspace &); + hyperspace &operator = (const hyperspace &); }; hyperspace :: hyperspace() - : scanner(NULL) - , error(NULL) - , strings() - , name(NULL) - , key() - , attributes() - , subspaces() - , indices() - , fault_tolerance(1) - , partitions(64) - , authorization(false) + : scanner(NULL) + , error(NULL) + , strings() + , name(NULL) + , key() + , attributes() + , subspaces() + , indices() + , fault_tolerance(1) + , partitions(64) + , authorization(false) { - memset(buffer, 0, 1024); + memset(buffer, 0, 1024); } hyperspace :: ~hyperspace() throw () @@ -133,473 +133,443 @@ hyperspace :: ~hyperspace() throw () } bool -hyperspace :: has_attr(const char* attr) +hyperspace :: has_attr(const char *attr) { - for (size_t i = 0; i < attributes.size(); ++i) - { - if (strcmp(attributes[i].name, attr) == 0) - { - return true; - } - } - - return false; + for (size_t i = 0; i < attributes.size(); ++i) + { + if (strcmp(attributes[i].name, attr) == 0) + { + return true; + } + } + return false; } hyperdatatype -hyperspace :: attr_type(const char* attr) +hyperspace :: attr_type(const char *attr) { - for (size_t i = 0; i < attributes.size(); ++i) - { - if (strcmp(attributes[i].name, attr) == 0) - { - return attributes[i].type; - } - } - - abort(); + for (size_t i = 0; i < attributes.size(); ++i) + { + if (strcmp(attributes[i].name, attr) == 0) + { + return attributes[i].type; + } + } + abort(); } -const char* -hyperspace :: internalize(const char* str) +const char * +hyperspace :: internalize(const char *str) { - strings.push_back(std::string(str)); - return strings.back().c_str(); + strings.push_back(std::string(str)); + return strings.back().c_str(); } static bool -is_identifier(const char* str) +is_identifier(const char *str) { - size_t i = 0; - - for (i = 0; str[i]; ++i) - { - if (!(i > 0 && isdigit(str[i])) && - !(isalpha(str[i])) && - str[i] != '_') - { - return false; - } - } - - if (i >= 2 && strncmp(str, "__", 2) == 0) - { - return false; - } - - return i > 0; + size_t i = 0; + for (i = 0; str[i]; ++i) + { + if (!(i > 0 && isdigit(str[i])) && + !(isalpha(str[i])) && + str[i] != '_') + { + return false; + } + } + if (i >= 2 && strncmp(str, "__", 2) == 0) + { + return false; + } + return i > 0; } static bool is_key_datatype(hyperdatatype type) { - hyperdex::datatype_info* di = hyperdex::datatype_info::lookup(type); - return di && di->hashable(); + hyperdex::datatype_info *di = hyperdex::datatype_info::lookup(type); + return di && di->hashable(); } static bool is_concrete_datatype(hyperdatatype type) { - return hyperdex::datatype_info::lookup(type) != NULL; + return hyperdex::datatype_info::lookup(type) != NULL; } extern "C" { -extern int -yylex_init(void* scanner); - -extern int -yylex_destroy(void* scanner); - -extern struct yy_buffer_state* -yy_scan_string(const char *bytes, void* scanner); - -extern void -yy_switch_to_buffer(yy_buffer_state* new_buffer, void* scanner); - -extern void -yyset_lineno(int line_number, void* scanner); - -HYPERDEX_API hyperspace* -hyperspace_create() -{ - hyperspace* space = new (std::nothrow) hyperspace(); - - if (!space) - { - return NULL; - } - - return space; -} - -HYPERDEX_API hyperspace* -hyperspace_parse(const char* desc) -{ - hyperspace* space = hyperspace_create(); - yy_buffer_state* buf = NULL; - - if (!space) - { - return NULL; - } - - if (yylex_init(&space->scanner) < 0) - { - space->error = "yylex_init failed"; - return space; - } - - buf = yy_scan_string(desc, space->scanner); - - if (!buf) - { - space->error = "yy_scan_string failed"; - yylex_destroy(space->scanner); - return space; - } - - yy_switch_to_buffer(buf, space->scanner); - yyset_lineno(1, space->scanner); - - if (yyparse(space, space->scanner) < 0) - { - space->error = "yyparse failed"; - yylex_destroy(space->scanner); - return space; - } - - if (yylex_destroy(space->scanner) < 0) - { - space->error = "yylex_destroy failed"; - return space; - } - - space->scanner = NULL; - return space; -} - -HYPERDEX_API void -hyperspace_destroy(hyperspace* space) -{ - delete space; -} - -HYPERDEX_API const char* -hyperspace_error(hyperspace* space) -{ - if (!space) - { - return "failed to allocate memory"; - } - - return space->error; -} - -HYPERDEX_API enum hyperspace_returncode -hyperspace_set_name(hyperspace* space, const char* name) -{ - if (!is_identifier(name)) - { - snprintf(space->buffer, BUFFER_SIZE, "\"%s\" is not a valid name for a space", name); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_INVALID_NAME; - } - - space->name = space->internalize(name); - return HYPERSPACE_SUCCESS; -} - -HYPERDEX_API enum hyperspace_returncode -hyperspace_set_key(hyperspace* space, - const char* attr, - enum hyperdatatype datatype) -{ - if (!is_identifier(attr)) - { - snprintf(space->buffer, BUFFER_SIZE, "\"%s\" is not a valid name for the key", attr); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_INVALID_NAME; - } - - if (!is_key_datatype(datatype)) - { - snprintf(space->buffer, BUFFER_SIZE, "\"%d\" is not a valid type for the key", datatype); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_INVALID_TYPE; - } - - if (space->has_attr(attr)) - { - snprintf(space->buffer, BUFFER_SIZE, "cannot call the key \"%s\" because there is already an attribute by that name", attr); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_DUPLICATE; - } - - space->key = hyperdex::attribute(space->internalize(attr), datatype); - return HYPERSPACE_SUCCESS; -} - -HYPERDEX_API enum hyperspace_returncode -hyperspace_add_attribute(hyperspace* space, - const char* attr, - enum hyperdatatype datatype) -{ - if (!is_identifier(attr)) - { - snprintf(space->buffer, BUFFER_SIZE, "\"%s\" is not a valid name for an attribute", attr); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_INVALID_NAME; - } - - if (!is_concrete_datatype(datatype)) - { - snprintf(space->buffer, BUFFER_SIZE, "\"%d\" is not a valid type for an attribute", datatype); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_INVALID_TYPE; - } - - if (space->has_attr(attr)) - { - snprintf(space->buffer, BUFFER_SIZE, "cannot create attribute \"%s\" because there is already an attribute by that name", attr); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_DUPLICATE; - } - - if (strcmp(space->key.name, attr) == 0) - { - snprintf(space->buffer, BUFFER_SIZE, "cannot create attribute \"%s\" because the key is called \"%s\"", attr, attr); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_DUPLICATE; - } - - space->attributes.push_back(hyperdex::attribute(space->internalize(attr), datatype)); - return HYPERSPACE_SUCCESS; -} - -HYPERDEX_API enum hyperspace_returncode -hyperspace_add_subspace(hyperspace* space) -{ - space->subspaces.push_back(hypersubspace()); - return HYPERSPACE_SUCCESS; -} - -HYPERDEX_API enum hyperspace_returncode -hyperspace_add_subspace_attribute(hyperspace* space, const char* attr) -{ - if (space->subspaces.empty()) - { - snprintf(space->buffer, BUFFER_SIZE, "cannot add attribute to subspace, because there is no subspace"); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_NO_SUBSPACE; - } - - if (!space->has_attr(attr)) - { - snprintf(space->buffer, BUFFER_SIZE, "cannot add attribute \"%s\" to subspace because there is no attribute by that name", attr); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_UNKNOWN_ATTR; - } - - if (!hyperdex::datatype_info::lookup(space->attr_type(attr))->hashable()) - { - snprintf(space->buffer, BUFFER_SIZE, "cannot add attribute \"%s\" to subspace because the type is not hashable", attr); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_UNINDEXABLE; - } - - for (size_t i = 0; i < space->subspaces.back().attrs.size(); ++i) - { - if (strcmp(space->subspaces.back().attrs[i], attr) == 0) - { - snprintf(space->buffer, BUFFER_SIZE, "cannot add attribute \"%s\" to subspace because it is already a subspace attribute", attr); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_DUPLICATE; - } - } - - space->subspaces.back().attrs.push_back(space->internalize(attr)); - return HYPERSPACE_SUCCESS; -} - -HYPERDEX_API enum hyperspace_returncode -hyperspace_add_index(hyperspace* space, const char* attr) -{ - if (strcmp(space->key.name, attr) == 0) - { - snprintf(space->buffer, BUFFER_SIZE, "cannot create index on \"%s\" because it is the key", attr); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_IS_KEY; - } - - if (!space->has_attr(attr)) - { - snprintf(space->buffer, BUFFER_SIZE, "cannot create index on \"%s\" because there is no attribute by that name", attr); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_UNKNOWN_ATTR; - } - - if (!hyperdex::datatype_info::lookup(space->attr_type(attr))->indexable()) - { - snprintf(space->buffer, BUFFER_SIZE, "cannot create index on \"%s\" because the type is not indexable", attr); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_UNINDEXABLE; - } - - space->indices.push_back(space->internalize(attr)); - return HYPERSPACE_SUCCESS; -} - -HYPERDEX_API enum hyperspace_returncode -hyperspace_set_fault_tolerance(hyperspace* space, uint64_t num) -{ - space->fault_tolerance = num; - return HYPERSPACE_SUCCESS; -} - -HYPERDEX_API enum hyperspace_returncode -hyperspace_set_number_of_partitions(hyperspace* space, uint64_t num) -{ - if (num < 1) - { - snprintf(space->buffer, BUFFER_SIZE, "the number of partitions must be positive, not 0"); - space->buffer[BUFFER_SIZE - 1] = '\0'; - space->error = space->buffer; - return HYPERSPACE_NO_SUBSPACE; - } - - space->partitions = num; - return HYPERSPACE_SUCCESS; -} - -HYPERDEX_API enum hyperspace_returncode -hyperspace_use_authorization(struct hyperspace* space) -{ - space->authorization = true; - return HYPERSPACE_SUCCESS; -} - -char* -hyperspace_buffer(hyperspace* space) -{ - return space->buffer; -} - -size_t -hyperspace_buffer_sz(hyperspace*) -{ - return BUFFER_SIZE; -} - -void -hyperspace_set_error(hyperspace* space, const char* msg) -{ - space->error = msg; -} + extern int + yylex_init(void *scanner); + + extern int + yylex_destroy(void *scanner); + + extern struct yy_buffer_state * + yy_scan_string(const char *bytes, void *scanner); + + extern void + yy_switch_to_buffer(yy_buffer_state *new_buffer, void *scanner); + + extern void + yyset_lineno(int line_number, void *scanner); + + HYPERDEX_API hyperspace * + hyperspace_create() + { + hyperspace *space = new (std::nothrow) hyperspace(); + if (!space) + { + return NULL; + } + return space; + } + + HYPERDEX_API hyperspace * + hyperspace_parse(const char *desc) + { + hyperspace *space = hyperspace_create(); + yy_buffer_state *buf = NULL; + if (!space) + { + return NULL; + } + if (yylex_init(&space->scanner) < 0) + { + space->error = "yylex_init failed"; + return space; + } + buf = yy_scan_string(desc, space->scanner); + if (!buf) + { + space->error = "yy_scan_string failed"; + yylex_destroy(space->scanner); + return space; + } + yy_switch_to_buffer(buf, space->scanner); + yyset_lineno(1, space->scanner); + if (yyparse(space, space->scanner) < 0) + { + space->error = "yyparse failed"; + yylex_destroy(space->scanner); + return space; + } + if (yylex_destroy(space->scanner) < 0) + { + space->error = "yylex_destroy failed"; + return space; + } + space->scanner = NULL; + return space; + } + + HYPERDEX_API void + hyperspace_destroy(hyperspace *space) + { + delete space; + } + + HYPERDEX_API const char * + hyperspace_error(hyperspace *space) + { + if (!space) + { + return "failed to allocate memory"; + } + return space->error; + } + + HYPERDEX_API enum hyperspace_returncode + hyperspace_set_name(hyperspace *space, const char *name) + { + if (!is_identifier(name)) + { + snprintf(space->buffer, BUFFER_SIZE, "\"%s\" is not a valid name for a space", name); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_INVALID_NAME; + } + + space->name = space->internalize(name); + return HYPERSPACE_SUCCESS; + } + + HYPERDEX_API enum hyperspace_returncode + hyperspace_set_key(hyperspace *space, + const char *attr, + enum hyperdatatype datatype) + { + if (!is_identifier(attr)) + { + snprintf(space->buffer, BUFFER_SIZE, "\"%s\" is not a valid name for the key", attr); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_INVALID_NAME; + } + + if (!is_key_datatype(datatype)) + { + snprintf(space->buffer, BUFFER_SIZE, "\"%d\" is not a valid type for the key", datatype); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_INVALID_TYPE; + } + + if (space->has_attr(attr)) + { + snprintf(space->buffer, BUFFER_SIZE, "cannot call the key \"%s\" because there is already an attribute by that name", attr); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_DUPLICATE; + } + + space->key = hyperdex::attribute(space->internalize(attr), datatype); + return HYPERSPACE_SUCCESS; + } + + HYPERDEX_API enum hyperspace_returncode + hyperspace_add_attribute(hyperspace *space, + const char *attr, + enum hyperdatatype datatype) + { + if (!is_identifier(attr)) + { + snprintf(space->buffer, BUFFER_SIZE, "\"%s\" is not a valid name for an attribute", attr); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_INVALID_NAME; + } + + if (!is_concrete_datatype(datatype)) + { + snprintf(space->buffer, BUFFER_SIZE, "\"%d\" is not a valid type for an attribute", datatype); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_INVALID_TYPE; + } + + if (space->has_attr(attr)) + { + snprintf(space->buffer, BUFFER_SIZE, "cannot create attribute \"%s\" because there is already an attribute by that name", attr); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_DUPLICATE; + } + + if (strcmp(space->key.name, attr) == 0) + { + snprintf(space->buffer, BUFFER_SIZE, "cannot create attribute \"%s\" because the key is called \"%s\"", attr, attr); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_DUPLICATE; + } + + space->attributes.push_back(hyperdex::attribute(space->internalize(attr), datatype)); + return HYPERSPACE_SUCCESS; + } + + HYPERDEX_API enum hyperspace_returncode + hyperspace_add_subspace(hyperspace *space) + { + space->subspaces.push_back(hypersubspace()); + return HYPERSPACE_SUCCESS; + } + + HYPERDEX_API enum hyperspace_returncode + hyperspace_add_subspace_attribute(hyperspace *space, const char *attr) + { + if (space->subspaces.empty()) + { + snprintf(space->buffer, BUFFER_SIZE, "cannot add attribute to subspace, because there is no subspace"); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_NO_SUBSPACE; + } + + if (!space->has_attr(attr)) + { + snprintf(space->buffer, BUFFER_SIZE, "cannot add attribute \"%s\" to subspace because there is no attribute by that name", attr); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_UNKNOWN_ATTR; + } + + if (!hyperdex::datatype_info::lookup(space->attr_type(attr))->hashable()) + { + snprintf(space->buffer, BUFFER_SIZE, "cannot add attribute \"%s\" to subspace because the type is not hashable", attr); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_UNINDEXABLE; + } + + for (size_t i = 0; i < space->subspaces.back().attrs.size(); ++i) + { + if (strcmp(space->subspaces.back().attrs[i], attr) == 0) + { + snprintf(space->buffer, BUFFER_SIZE, "cannot add attribute \"%s\" to subspace because it is already a subspace attribute", attr); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_DUPLICATE; + } + } + + space->subspaces.back().attrs.push_back(space->internalize(attr)); + return HYPERSPACE_SUCCESS; + } + + HYPERDEX_API enum hyperspace_returncode + hyperspace_add_index(hyperspace *space, const char *attr) + { + if (strcmp(space->key.name, attr) == 0) + { + snprintf(space->buffer, BUFFER_SIZE, "cannot create index on \"%s\" because it is the key", attr); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_IS_KEY; + } + + if (!space->has_attr(attr)) + { + snprintf(space->buffer, BUFFER_SIZE, "cannot create index on \"%s\" because there is no attribute by that name", attr); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_UNKNOWN_ATTR; + } + + if (!hyperdex::datatype_info::lookup(space->attr_type(attr))->indexable()) + { + snprintf(space->buffer, BUFFER_SIZE, "cannot create index on \"%s\" because the type is not indexable", attr); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_UNINDEXABLE; + } + + space->indices.push_back(space->internalize(attr)); + return HYPERSPACE_SUCCESS; + } + + HYPERDEX_API enum hyperspace_returncode + hyperspace_set_fault_tolerance(hyperspace *space, uint64_t num) + { + space->fault_tolerance = num; + return HYPERSPACE_SUCCESS; + } + + HYPERDEX_API enum hyperspace_returncode + hyperspace_set_number_of_partitions(hyperspace *space, uint64_t num) + { + if (num < 1) + { + snprintf(space->buffer, BUFFER_SIZE, "the number of partitions must be positive, not 0"); + space->buffer[BUFFER_SIZE - 1] = '\0'; + space->error = space->buffer; + return HYPERSPACE_NO_SUBSPACE; + } + + space->partitions = num; + return HYPERSPACE_SUCCESS; + } + + HYPERDEX_API enum hyperspace_returncode + hyperspace_use_authorization(struct hyperspace *space) + { + space->authorization = true; + return HYPERSPACE_SUCCESS; + } + + char * + hyperspace_buffer(hyperspace *space) + { + return space->buffer; + } + + size_t + hyperspace_buffer_sz(hyperspace *) + { + return BUFFER_SIZE; + } + + void + hyperspace_set_error(hyperspace *space, const char *msg) + { + space->error = msg; + } } // extern "C" bool -hyperdex :: space_to_space(hyperspace* in, hyperdex::space* out) +hyperdex :: space_to_space(hyperspace *in, hyperdex::space *out) { - assert(!hyperspace_error(in)); - std::vector attrs; - attrs.push_back(in->key); - - for (size_t i = 0; i < in->attributes.size(); ++i) - { - attrs.push_back(in->attributes[i]); - } - - if (in->authorization) - { - attrs.push_back(hyperdex::attribute(HYPERDEX_ATTRIBUTE_SECRET, HYPERDATATYPE_MACAROON_SECRET)); - } - - schema sc; - sc.attrs_sz = attrs.size(); - sc.attrs = &attrs.front(); - space sp(in->name, sc); - sp.subspaces.push_back(subspace()); - sp.subspaces.back().attrs.push_back(0); - - for (size_t i = 0; i < in->subspaces.size(); ++i) - { - if (in->subspaces[i].attrs.empty()) - { - continue; - } - - sp.subspaces.push_back(subspace()); - - for (size_t j = 0; j < in->subspaces[i].attrs.size(); ++j) - { - uint16_t attr = sc.lookup_attr(in->subspaces[i].attrs[j]); - assert(attr < sc.attrs_sz); - sp.subspaces.back().attrs.push_back(attr); - } - } - - sp.fault_tolerance = in->fault_tolerance; - - if (!sp.validate()) - { - return false; - } - - for (size_t i = 0; i < sp.subspaces.size(); ++i) - { - hyperdex::partition(sp.subspaces[i].attrs.size(), in->partitions, &sp.subspaces[i].regions); - } - - for (size_t i = 0; i < in->indices.size(); ++i) - { - uint16_t attr = sc.lookup_attr(in->indices[i]); - assert(attr < sc.attrs_sz); - index idx(index::NORMAL, index_id(), attr, e::slice()); - sp.indices.push_back(idx); - } - - for (size_t ss_idx = 0; ss_idx < sp.subspaces.size(); ++ ss_idx) - { - for (size_t a_idx = 0; a_idx < sp.subspaces[ss_idx].attrs.size(); ++a_idx) - { - uint16_t attr = sp.subspaces[ss_idx].attrs[a_idx]; - bool found = false; - - for (size_t i_idx = 0; i_idx < sp.indices.size(); ++i_idx) - { - if (sp.indices[i_idx].type == index::NORMAL && - sp.indices[i_idx].attr == attr) - { - found = true; - } - } - - if (!found && attr > 0) - { - index idx(index::NORMAL, index_id(), attr, e::slice()); - sp.indices.push_back(idx); - } - } - } - - *out = sp; - return true; + assert(!hyperspace_error(in)); + std::vector attrs; + attrs.push_back(in->key); + for (size_t i = 0; i < in->attributes.size(); ++i) + { + attrs.push_back(in->attributes[i]); + } + if (in->authorization) + { + attrs.push_back(hyperdex::attribute(HYPERDEX_ATTRIBUTE_SECRET, HYPERDATATYPE_MACAROON_SECRET)); + } + schema sc; + sc.attrs_sz = attrs.size(); + sc.attrs = &attrs.front(); + space sp(in->name, sc); + sp.subspaces.push_back(subspace()); + sp.subspaces.back().attrs.push_back(0); + for (size_t i = 0; i < in->subspaces.size(); ++i) + { + if (in->subspaces[i].attrs.empty()) + { + continue; + } + sp.subspaces.push_back(subspace()); + for (size_t j = 0; j < in->subspaces[i].attrs.size(); ++j) + { + uint16_t attr = sc.lookup_attr(in->subspaces[i].attrs[j]); + assert(attr < sc.attrs_sz); + sp.subspaces.back().attrs.push_back(attr); + } + } + sp.fault_tolerance = in->fault_tolerance; + if (!sp.validate()) + { + return false; + } + for (size_t i = 0; i < sp.subspaces.size(); ++i) + { + hyperdex::partition(sp.subspaces[i].attrs.size(), in->partitions, &sp.subspaces[i].regions); + } + for (size_t i = 0; i < in->indices.size(); ++i) + { + uint16_t attr = sc.lookup_attr(in->indices[i]); + assert(attr < sc.attrs_sz); + index idx(index::NORMAL, index_id(), attr, e::slice()); + sp.indices.push_back(idx); + } + for (size_t ss_idx = 0; ss_idx < sp.subspaces.size(); ++ ss_idx) + { + for (size_t a_idx = 0; a_idx < sp.subspaces[ss_idx].attrs.size(); ++a_idx) + { + uint16_t attr = sp.subspaces[ss_idx].attrs[a_idx]; + bool found = false; + for (size_t i_idx = 0; i_idx < sp.indices.size(); ++i_idx) + { + if (sp.indices[i_idx].type == index::NORMAL && + sp.indices[i_idx].attr == attr) + { + found = true; + } + } + if (!found && attr > 0) + { + index idx(index::NORMAL, index_id(), attr, e::slice()); + sp.indices.push_back(idx); + } + } + } + *out = sp; + return true; } diff --git a/admin/hyperspace_builder_internal.h b/admin/hyperspace_builder_internal.h index bec83d0cc..97269a5c2 100644 --- a/admin/hyperspace_builder_internal.h +++ b/admin/hyperspace_builder_internal.h @@ -33,14 +33,14 @@ extern "C" { #endif /* __cplusplus */ -char* -hyperspace_buffer(struct hyperspace* space); +char * +hyperspace_buffer(struct hyperspace *space); size_t -hyperspace_buffer_sz(struct hyperspace* space); +hyperspace_buffer_sz(struct hyperspace *space); void -hyperspace_set_error(struct hyperspace* space, const char* msg); +hyperspace_set_error(struct hyperspace *space, const char *msg); #ifdef __cplusplus } /* extern "C" */ @@ -53,7 +53,7 @@ BEGIN_HYPERDEX_NAMESPACE class space; bool -space_to_space(hyperspace* in, hyperdex::space* out); +space_to_space(hyperspace *in, hyperdex::space *out); END_HYPERDEX_NAMESPACE diff --git a/admin/multi_yieldable.cc b/admin/multi_yieldable.cc index c27ff7539..b8a4d7245 100644 --- a/admin/multi_yieldable.cc +++ b/admin/multi_yieldable.cc @@ -31,8 +31,8 @@ using hyperdex::multi_yieldable; multi_yieldable :: multi_yieldable(uint64_t id, - hyperdex_admin_returncode* s) - : yieldable(id, s) + hyperdex_admin_returncode *s) + : yieldable(id, s) { } diff --git a/admin/multi_yieldable.h b/admin/multi_yieldable.h index dc61f9b77..58ee9e7cc 100644 --- a/admin/multi_yieldable.h +++ b/admin/multi_yieldable.h @@ -47,16 +47,16 @@ class admin; class multi_yieldable : public yieldable { - public: - multi_yieldable(uint64_t admin_visible_id, - hyperdex_admin_returncode* status); - virtual ~multi_yieldable() throw (); +public: + multi_yieldable(uint64_t admin_visible_id, + hyperdex_admin_returncode *status); + virtual ~multi_yieldable() throw (); - public: - virtual bool callback(admin* adm, int64_t id, hyperdex_admin_returncode* status) = 0; +public: + virtual bool callback(admin *adm, int64_t id, hyperdex_admin_returncode *status) = 0; - protected: - friend class e::intrusive_ptr; +protected: + friend class e::intrusive_ptr; }; END_HYPERDEX_NAMESPACE diff --git a/admin/partition.cc b/admin/partition.cc index ccacf00d4..b2464c04d 100644 --- a/admin/partition.cc +++ b/admin/partition.cc @@ -35,101 +35,91 @@ static void generate_points(uint64_t intervals, - std::vector* lbs, - std::vector* ubs) + std::vector *lbs, + std::vector *ubs) { - uint64_t interval = (0x8000000000000000ULL / intervals) * 2; - - for (uint64_t i = 0; i < intervals; ++i) - { - lbs->push_back(i * interval); - } - - for (size_t i = 1; i < lbs->size(); ++i) - { - ubs->push_back((*lbs)[i] - 1); - } - - ubs->push_back(UINT64_MAX); - assert(lbs->size() == ubs->size()); + uint64_t interval = (0x8000000000000000ULL / intervals) * 2; + for (uint64_t i = 0; i < intervals; ++i) + { + lbs->push_back(i * interval); + } + for (size_t i = 1; i < lbs->size(); ++i) + { + ubs->push_back((*lbs)[i] - 1); + } + ubs->push_back(UINT64_MAX); + assert(lbs->size() == ubs->size()); } void -recursively_generate(size_t idx, const std::vector& dimensions, - uint64_t bigger, const std::vector& bigger_lbs, const std::vector& bigger_ubs, - uint64_t smaller, const std::vector& smaller_lbs, const std::vector& smaller_ubs, - std::vector* lower_coord, std::vector* upper_coord, - std::vector* regions) +recursively_generate(size_t idx, const std::vector &dimensions, + uint64_t bigger, const std::vector &bigger_lbs, const std::vector &bigger_ubs, + uint64_t smaller, const std::vector &smaller_lbs, const std::vector &smaller_ubs, + std::vector *lower_coord, std::vector *upper_coord, + std::vector *regions) { - assert(dimensions.size() == lower_coord->size()); - assert(lower_coord->size() == upper_coord->size()); - - if (idx >= dimensions.size()) - { - regions->push_back(hyperdex::region()); - regions->back().lower_coord = *lower_coord; - regions->back().upper_coord = *upper_coord; - } - else - { - const std::vector* lbs; - const std::vector* ubs; - - if (dimensions[idx] == bigger) - { - lbs = &bigger_lbs; - ubs = &bigger_ubs; - } - else - { - assert(dimensions[idx] == smaller); - lbs = &smaller_lbs; - ubs = &smaller_ubs; - } - - for (size_t i = 0; i < lbs->size(); ++i) - { - (*lower_coord)[idx] = (*lbs)[i]; - (*upper_coord)[idx] = (*ubs)[i]; - recursively_generate(idx + 1, dimensions, - bigger, bigger_lbs, bigger_ubs, - smaller, smaller_lbs, smaller_ubs, - lower_coord, upper_coord, regions); - } - } + assert(dimensions.size() == lower_coord->size()); + assert(lower_coord->size() == upper_coord->size()); + if (idx >= dimensions.size()) + { + regions->push_back(hyperdex::region()); + regions->back().lower_coord = *lower_coord; + regions->back().upper_coord = *upper_coord; + } + else + { + const std::vector *lbs; + const std::vector *ubs; + if (dimensions[idx] == bigger) + { + lbs = &bigger_lbs; + ubs = &bigger_ubs; + } + else + { + assert(dimensions[idx] == smaller); + lbs = &smaller_lbs; + ubs = &smaller_ubs; + } + for (size_t i = 0; i < lbs->size(); ++i) + { + (*lower_coord)[idx] = (*lbs)[i]; + (*upper_coord)[idx] = (*ubs)[i]; + recursively_generate(idx + 1, dimensions, + bigger, bigger_lbs, bigger_ubs, + smaller, smaller_lbs, smaller_ubs, + lower_coord, upper_coord, regions); + } + } } void -hyperdex :: partition(uint16_t num_attrs, uint32_t num_servers, std::vector* regions) +hyperdex :: partition(uint16_t num_attrs, uint32_t num_servers, std::vector *regions) { - assert(num_attrs > 0); - double attrs_per_dimension(num_servers); - attrs_per_dimension = pow(attrs_per_dimension, 1/double(num_attrs)); - std::vector dimensions(num_attrs, uint64_t(attrs_per_dimension)); - uint64_t partitions = dimensions.size() * dimensions[0]; - - for (size_t i = 0; partitions < num_servers && i < num_attrs; ++i) - { - partitions = partitions / dimensions[i]; - ++dimensions[i]; - partitions = partitions * dimensions[i]; - } - - uint64_t bigger = dimensions[0]; - std::vector bigger_lbs; - std::vector bigger_ubs; - generate_points(bigger, &bigger_lbs, &bigger_ubs); - uint64_t smaller = dimensions[dimensions.size() - 1]; - std::vector smaller_lbs; - std::vector smaller_ubs; - generate_points(smaller, &smaller_lbs, &smaller_ubs); - - regions->clear(); - std::vector lower_coord(num_attrs, 0); - std::vector upper_coord(num_attrs, 0); - - recursively_generate(0, dimensions, - bigger, bigger_lbs, bigger_ubs, - smaller, smaller_lbs, smaller_ubs, - &lower_coord, &upper_coord, regions); + assert(num_attrs > 0); + double attrs_per_dimension(num_servers); + attrs_per_dimension = pow(attrs_per_dimension, 1 / double(num_attrs)); + std::vector dimensions(num_attrs, uint64_t(attrs_per_dimension)); + uint64_t partitions = dimensions.size() * dimensions[0]; + for (size_t i = 0; partitions < num_servers && i < num_attrs; ++i) + { + partitions = partitions / dimensions[i]; + ++dimensions[i]; + partitions = partitions * dimensions[i]; + } + uint64_t bigger = dimensions[0]; + std::vector bigger_lbs; + std::vector bigger_ubs; + generate_points(bigger, &bigger_lbs, &bigger_ubs); + uint64_t smaller = dimensions[dimensions.size() - 1]; + std::vector smaller_lbs; + std::vector smaller_ubs; + generate_points(smaller, &smaller_lbs, &smaller_ubs); + regions->clear(); + std::vector lower_coord(num_attrs, 0); + std::vector upper_coord(num_attrs, 0); + recursively_generate(0, dimensions, + bigger, bigger_lbs, bigger_ubs, + smaller, smaller_lbs, smaller_ubs, + &lower_coord, &upper_coord, regions); } diff --git a/admin/partition.h b/admin/partition.h index 817a0142e..a6987c8b9 100644 --- a/admin/partition.h +++ b/admin/partition.h @@ -35,7 +35,7 @@ BEGIN_HYPERDEX_NAMESPACE void -partition(uint16_t num_attrs, uint32_t num_servers, std::vector* regions); +partition(uint16_t num_attrs, uint32_t num_servers, std::vector *regions); END_HYPERDEX_NAMESPACE diff --git a/admin/pending.cc b/admin/pending.cc index 58b72d2cb..b7c9e88b4 100644 --- a/admin/pending.cc +++ b/admin/pending.cc @@ -31,8 +31,8 @@ using hyperdex::pending; pending :: pending(uint64_t id, - hyperdex_admin_returncode* s) - : yieldable(id, s) + hyperdex_admin_returncode *s) + : yieldable(id, s) { } diff --git a/admin/pending.h b/admin/pending.h index 75f056f6f..0626d981f 100644 --- a/admin/pending.h +++ b/admin/pending.h @@ -47,23 +47,23 @@ class admin; class pending : public yieldable { - public: - pending(uint64_t admin_visible_id, - hyperdex_admin_returncode* status); - virtual ~pending() throw (); +public: + pending(uint64_t admin_visible_id, + hyperdex_admin_returncode *status); + virtual ~pending() throw (); - public: - virtual void handle_sent_to(const server_id& si) = 0; - virtual void handle_failure(const server_id& si) = 0; - virtual bool handle_message(admin* cl, - const server_id& si, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_admin_returncode* status) = 0; +public: + virtual void handle_sent_to(const server_id &si) = 0; + virtual void handle_failure(const server_id &si) = 0; + virtual bool handle_message(admin *cl, + const server_id &si, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_admin_returncode *status) = 0; - protected: - friend class e::intrusive_ptr; +protected: + friend class e::intrusive_ptr; }; END_HYPERDEX_NAMESPACE diff --git a/admin/pending_perf_counters.cc b/admin/pending_perf_counters.cc index a99e55552..98a1fdf43 100644 --- a/admin/pending_perf_counters.cc +++ b/admin/pending_perf_counters.cc @@ -39,23 +39,23 @@ using hyperdex::pending_perf_counters; struct pending_perf_counters::perf_counter { - perf_counter(uint64_t i, uint64_t t, const std::string& p, uint64_t m) - : id(i), time(t), property(p), measurement(m) {} - uint64_t id; - uint64_t time; - std::string property; - uint64_t measurement; + perf_counter(uint64_t i, uint64_t t, const std::string &p, uint64_t m) + : id(i), time(t), property(p), measurement(m) {} + uint64_t id; + uint64_t time; + std::string property; + uint64_t measurement; }; pending_perf_counters :: pending_perf_counters(uint64_t id, - hyperdex_admin_returncode* s, - hyperdex_admin_perf_counter* pc) - : pending(id, s) - , m_pc(pc) - , m_next_send(0) - , m_pcs() - , m_scratch() - , m_cutoffs() + hyperdex_admin_returncode *s, + hyperdex_admin_perf_counter *pc) + : pending(id, s) + , m_pc(pc) + , m_next_send(0) + , m_pcs() + , m_scratch() + , m_cutoffs() { } @@ -64,174 +64,154 @@ pending_perf_counters :: ~pending_perf_counters() throw () } void -pending_perf_counters :: send_perf_reqs(admin* adm, - const configuration* config, - hyperdex_admin_returncode* status) +pending_perf_counters :: send_perf_reqs(admin *adm, + const configuration *config, + hyperdex_admin_returncode *status) { - std::vector > addrs; - config->get_all_addresses(&addrs); - uint64_t failed = 0; - - for (size_t i = 0; i < addrs.size(); ++i) - { - uint64_t nonce = adm->m_next_server_nonce; - ++adm->m_next_server_nonce; - uint64_t when = 0; - std::map::iterator it = m_cutoffs.find(addrs[i].first); - - if (it == m_cutoffs.end()) - { - m_cutoffs[addrs[i].first] = 0; - } - else - { - when = it->second; - } - - size_t sz = HYPERDEX_ADMIN_HEADER_SIZE_REQ + sizeof(uint64_t); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_ADMIN_HEADER_SIZE_REQ) << when; - - if (!adm->send(PERF_COUNTERS, addrs[i].first, nonce, msg, this, status)) - { - ++failed; - } - } - - std::map::iterator it = m_cutoffs.begin(); - - while (it != m_cutoffs.end()) - { - bool found = false; - - for (size_t i = 0; i < addrs.size(); ++i) - { - if (it->first == addrs[i].first) - { - found = true; - break; - } - } - - if (found) - { - ++it; - } - else - { - m_cutoffs.erase(it); - it = m_cutoffs.begin(); - } - } + std::vector > addrs; + config->get_all_addresses(&addrs); + uint64_t failed = 0; + for (size_t i = 0; i < addrs.size(); ++i) + { + uint64_t nonce = adm->m_next_server_nonce; + ++adm->m_next_server_nonce; + uint64_t when = 0; + std::map::iterator it = m_cutoffs.find(addrs[i].first); + if (it == m_cutoffs.end()) + { + m_cutoffs[addrs[i].first] = 0; + } + else + { + when = it->second; + } + size_t sz = HYPERDEX_ADMIN_HEADER_SIZE_REQ + sizeof(uint64_t); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_ADMIN_HEADER_SIZE_REQ) << when; + if (!adm->send(PERF_COUNTERS, addrs[i].first, nonce, msg, this, status)) + { + ++failed; + } + } + std::map::iterator it = m_cutoffs.begin(); + while (it != m_cutoffs.end()) + { + bool found = false; + for (size_t i = 0; i < addrs.size(); ++i) + { + if (it->first == addrs[i].first) + { + found = true; + break; + } + } + if (found) + { + ++it; + } + else + { + m_cutoffs.erase(it); + it = m_cutoffs.begin(); + } + } } int pending_perf_counters :: millis_to_next_send() { - const uint64_t one_second = 1000ULL * 1000ULL * 1000ULL; - uint64_t now = po6::monotonic_time(); - - if (now >= m_next_send) - { - m_next_send = now + one_second; - return 0; - } - - return ((m_next_send - now) / one_second) + 1; + const uint64_t one_second = 1000ULL * 1000ULL * 1000ULL; + uint64_t now = po6::monotonic_time(); + if (now >= m_next_send) + { + m_next_send = now + one_second; + return 0; + } + return ((m_next_send - now) / one_second) + 1; } bool pending_perf_counters :: can_yield() { - return !m_pcs.empty(); + return !m_pcs.empty(); } bool -pending_perf_counters :: yield(hyperdex_admin_returncode* status) +pending_perf_counters :: yield(hyperdex_admin_returncode *status) { - assert(can_yield()); - m_scratch = m_pcs.front().property; - m_pc->id = m_pcs.front().id; - m_pc->time = m_pcs.front().time; - m_pc->property = m_scratch.c_str(); - m_pc->measurement = m_pcs.front().measurement; - m_pcs.pop_front(); - *status = HYPERDEX_ADMIN_SUCCESS; - return true; + assert(can_yield()); + m_scratch = m_pcs.front().property; + m_pc->id = m_pcs.front().id; + m_pc->time = m_pcs.front().time; + m_pc->property = m_scratch.c_str(); + m_pc->measurement = m_pcs.front().measurement; + m_pcs.pop_front(); + *status = HYPERDEX_ADMIN_SUCCESS; + return true; } void -pending_perf_counters :: handle_sent_to(const server_id&) +pending_perf_counters :: handle_sent_to(const server_id &) { } void -pending_perf_counters :: handle_failure(const server_id&) +pending_perf_counters :: handle_failure(const server_id &) { } bool -pending_perf_counters :: handle_message(admin*, - const server_id& si, +pending_perf_counters :: handle_message(admin *, + const server_id &si, network_msgtype mt, std::auto_ptr, e::unpacker up, - hyperdex_admin_returncode* status) + hyperdex_admin_returncode *status) { - *status = HYPERDEX_ADMIN_SUCCESS; - set_status(HYPERDEX_ADMIN_SUCCESS); - - if (mt != PERF_COUNTERS) - { - YIELDING_ERROR(SERVERERROR) << "server " << si.get() << " responded to PERF_COUNTERS with wrong message type"; - return true; - } - - e::slice rem = up.remainder(); - char* ptr = const_cast(reinterpret_cast(rem.data())); - char* end = ptr + rem.size() - 1; - uint64_t max_time = 0; - - // parse one line at a time - while (ptr < end) - { - char* eol = reinterpret_cast(memchr(ptr, '\n', end - ptr)); - eol = eol ? eol : end; - *eol = '\0'; - char* tmp = ptr; - - // parse the time - tmp = strchr(ptr, ' '); - tmp = tmp ? tmp : eol; - *tmp = '\0'; - uint64_t time = strtoull(ptr, NULL, 0); - max_time = std::max(time, max_time); - ptr = tmp + 1; - - while (ptr < eol) - { - tmp = strchr(ptr, ' '); - tmp = tmp ? tmp : eol; - *tmp = '\0'; - - char* equals = strchr(ptr, '='); - equals = equals ? equals: tmp; - *equals = '\0'; - uint64_t value = 0; - - if (equals < tmp) - { - ++equals; - value = strtoull(equals, NULL, 0); - } - - m_pcs.push_back(perf_counter(si.get(), time, ptr, value)); - ptr = tmp + 1; - } - - ptr = eol + 1; - } - - m_cutoffs[si] = max_time; - return true; + *status = HYPERDEX_ADMIN_SUCCESS; + set_status(HYPERDEX_ADMIN_SUCCESS); + if (mt != PERF_COUNTERS) + { + YIELDING_ERROR(SERVERERROR) << "server " << si.get() << " responded to PERF_COUNTERS with wrong message type"; + return true; + } + e::slice rem = up.remainder(); + char *ptr = const_cast(reinterpret_cast(rem.data())); + char *end = ptr + rem.size() - 1; + uint64_t max_time = 0; + // parse one line at a time + while (ptr < end) + { + char *eol = reinterpret_cast(memchr(ptr, '\n', end - ptr)); + eol = eol ? eol : end; + *eol = '\0'; + char *tmp = ptr; + // parse the time + tmp = strchr(ptr, ' '); + tmp = tmp ? tmp : eol; + *tmp = '\0'; + uint64_t time = strtoull(ptr, NULL, 0); + max_time = std::max(time, max_time); + ptr = tmp + 1; + while (ptr < eol) + { + tmp = strchr(ptr, ' '); + tmp = tmp ? tmp : eol; + *tmp = '\0'; + char *equals = strchr(ptr, '='); + equals = equals ? equals : tmp; + *equals = '\0'; + uint64_t value = 0; + if (equals < tmp) + { + ++equals; + value = strtoull(equals, NULL, 0); + } + m_pcs.push_back(perf_counter(si.get(), time, ptr, value)); + ptr = tmp + 1; + } + ptr = eol + 1; + } + m_cutoffs[si] = max_time; + return true; } diff --git a/admin/pending_perf_counters.h b/admin/pending_perf_counters.h index ff1354c75..54a3a307f 100644 --- a/admin/pending_perf_counters.h +++ b/admin/pending_perf_counters.h @@ -38,51 +38,51 @@ BEGIN_HYPERDEX_NAMESPACE class pending_perf_counters : public pending { - public: - pending_perf_counters(uint64_t admin_visible_id, - hyperdex_admin_returncode* status, - hyperdex_admin_perf_counter* pc); - virtual ~pending_perf_counters() throw (); +public: + pending_perf_counters(uint64_t admin_visible_id, + hyperdex_admin_returncode *status, + hyperdex_admin_perf_counter *pc); + virtual ~pending_perf_counters() throw (); - // manipulate perf counters - public: - void send_perf_reqs(admin* adm, - const configuration* config, - hyperdex_admin_returncode* status); - int millis_to_next_send(); + // manipulate perf counters +public: + void send_perf_reqs(admin *adm, + const configuration *config, + hyperdex_admin_returncode *status); + int millis_to_next_send(); - // return to admin - public: - virtual bool can_yield(); - virtual bool yield(hyperdex_admin_returncode* status); + // return to admin +public: + virtual bool can_yield(); + virtual bool yield(hyperdex_admin_returncode *status); - // events - public: - virtual void handle_sent_to(const server_id& si); - virtual void handle_failure(const server_id& si); - virtual bool handle_message(admin* adm, - const server_id& si, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_admin_returncode* status); + // events +public: + virtual void handle_sent_to(const server_id &si); + virtual void handle_failure(const server_id &si); + virtual bool handle_message(admin *adm, + const server_id &si, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_admin_returncode *status); - protected: - friend class e::intrusive_ptr; +protected: + friend class e::intrusive_ptr; - private: - class perf_counter; +private: + class perf_counter; - private: - pending_perf_counters(const pending_perf_counters& other); - pending_perf_counters& operator = (const pending_perf_counters& rhs); +private: + pending_perf_counters(const pending_perf_counters &other); + pending_perf_counters &operator = (const pending_perf_counters &rhs); - private: - hyperdex_admin_perf_counter* m_pc; - uint64_t m_next_send; - std::list m_pcs; - std::string m_scratch; - std::map m_cutoffs; +private: + hyperdex_admin_perf_counter *m_pc; + uint64_t m_next_send; + std::list m_pcs; + std::string m_scratch; + std::map m_cutoffs; }; END_HYPERDEX_NAMESPACE diff --git a/admin/pending_raw_backup.cc b/admin/pending_raw_backup.cc index f8d8946ce..34e07faf6 100644 --- a/admin/pending_raw_backup.cc +++ b/admin/pending_raw_backup.cc @@ -32,12 +32,12 @@ using hyperdex::pending_raw_backup; pending_raw_backup :: pending_raw_backup(uint64_t id, - hyperdex_admin_returncode* status, - const char** path) - : pending(id, status) - , m_path() - , m_path_c_str(path) - , m_done(false) + hyperdex_admin_returncode *status, + const char **path) + : pending(id, status) + , m_path() + , m_path_c_str(path) + , m_done(false) { } @@ -48,69 +48,63 @@ pending_raw_backup :: ~pending_raw_backup() throw () bool pending_raw_backup :: can_yield() { - return !m_done; + return !m_done; } bool -pending_raw_backup :: yield(hyperdex_admin_returncode* status) +pending_raw_backup :: yield(hyperdex_admin_returncode *status) { - *status = HYPERDEX_ADMIN_SUCCESS; - m_done = true; - return true; + *status = HYPERDEX_ADMIN_SUCCESS; + m_done = true; + return true; } void -pending_raw_backup :: handle_sent_to(const server_id&) +pending_raw_backup :: handle_sent_to(const server_id &) { } void -pending_raw_backup :: handle_failure(const server_id& si) +pending_raw_backup :: handle_failure(const server_id &si) { - YIELDING_ERROR(SERVERERROR) << "communication with " << si << "failed"; + YIELDING_ERROR(SERVERERROR) << "communication with " << si << "failed"; } bool -pending_raw_backup :: handle_message(admin*, - const server_id& si, +pending_raw_backup :: handle_message(admin *, + const server_id &si, network_msgtype mt, std::auto_ptr msg, e::unpacker up, - hyperdex_admin_returncode* status) + hyperdex_admin_returncode *status) { - *status = HYPERDEX_ADMIN_SUCCESS; - - if (mt != BACKUP) - { - YIELDING_ERROR(SERVERERROR) << "server " << si << " responded to BACKUP with " << mt; - return true; - } - - uint16_t rt; - e::slice path; - up = up >> rt >> path; - - if (up.error()) - { - YIELDING_ERROR(SERVERERROR) << "communication error: server " - << si << " sent corrupt message=" - << msg->as_slice().hex() - << " in response to a BACKUP"; - return true; - } - - network_returncode rc = static_cast(rt); - - if (rc != NET_SUCCESS) - { - YIELDING_ERROR(SERVERERROR) << "backup of server " << si - << " failed; see the server's log for details"; - return true; - } - - m_path.assign(reinterpret_cast(path.data()), path.size()); - *m_path_c_str = m_path.c_str(); - this->set_status(HYPERDEX_ADMIN_SUCCESS); - this->set_error(e::error()); - return true; + *status = HYPERDEX_ADMIN_SUCCESS; + if (mt != BACKUP) + { + YIELDING_ERROR(SERVERERROR) << "server " << si << " responded to BACKUP with " << mt; + return true; + } + uint16_t rt; + e::slice path; + up = up >> rt >> path; + if (up.error()) + { + YIELDING_ERROR(SERVERERROR) << "communication error: server " + << si << " sent corrupt message=" + << msg->as_slice().hex() + << " in response to a BACKUP"; + return true; + } + network_returncode rc = static_cast(rt); + if (rc != NET_SUCCESS) + { + YIELDING_ERROR(SERVERERROR) << "backup of server " << si + << " failed; see the server's log for details"; + return true; + } + m_path.assign(reinterpret_cast(path.data()), path.size()); + *m_path_c_str = m_path.c_str(); + this->set_status(HYPERDEX_ADMIN_SUCCESS); + this->set_error(e::error()); + return true; } diff --git a/admin/pending_raw_backup.h b/admin/pending_raw_backup.h index a4ced95c7..9f437861c 100644 --- a/admin/pending_raw_backup.h +++ b/admin/pending_raw_backup.h @@ -38,36 +38,36 @@ BEGIN_HYPERDEX_NAMESPACE class pending_raw_backup : public pending { - public: - pending_raw_backup(uint64_t admin_visible_id, - hyperdex_admin_returncode* status, - const char** path); - virtual ~pending_raw_backup() throw (); +public: + pending_raw_backup(uint64_t admin_visible_id, + hyperdex_admin_returncode *status, + const char **path); + virtual ~pending_raw_backup() throw (); - // return to admin - public: - virtual bool can_yield(); - virtual bool yield(hyperdex_admin_returncode* status); + // return to admin +public: + virtual bool can_yield(); + virtual bool yield(hyperdex_admin_returncode *status); - // events - public: - virtual void handle_sent_to(const server_id& si); - virtual void handle_failure(const server_id& si); - virtual bool handle_message(admin* adm, - const server_id& si, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_admin_returncode* status); + // events +public: + virtual void handle_sent_to(const server_id &si); + virtual void handle_failure(const server_id &si); + virtual bool handle_message(admin *adm, + const server_id &si, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_admin_returncode *status); - private: - pending_raw_backup(const pending_raw_backup& other); - pending_raw_backup& operator = (const pending_raw_backup& rhs); +private: + pending_raw_backup(const pending_raw_backup &other); + pending_raw_backup &operator = (const pending_raw_backup &rhs); - private: - std::string m_path; - const char** m_path_c_str; - bool m_done; +private: + std::string m_path; + const char **m_path_c_str; + bool m_done; }; END_HYPERDEX_NAMESPACE diff --git a/admin/pending_string.cc b/admin/pending_string.cc index 197d05e58..91171e4e1 100644 --- a/admin/pending_string.cc +++ b/admin/pending_string.cc @@ -31,15 +31,15 @@ using hyperdex::pending_string; pending_string :: pending_string(uint64_t id, - hyperdex_admin_returncode* status, + hyperdex_admin_returncode *status, hyperdex_admin_returncode _status, - const std::string& string, - const char** store) - : pending(id, status) - , m_status(_status) - , m_string(string) - , m_store(store) - , m_done(false) + const std::string &string, + const char **store) + : pending(id, status) + , m_status(_status) + , m_string(string) + , m_store(store) + , m_done(false) { } @@ -50,39 +50,39 @@ pending_string :: ~pending_string() throw () bool pending_string :: can_yield() { - return !m_done; + return !m_done; } bool -pending_string :: yield(hyperdex_admin_returncode* status) +pending_string :: yield(hyperdex_admin_returncode *status) { - assert(this->can_yield()); - m_done = true; - *status = HYPERDEX_ADMIN_SUCCESS; - set_status(m_status); - *m_store = m_string.c_str(); - return true; + assert(this->can_yield()); + m_done = true; + *status = HYPERDEX_ADMIN_SUCCESS; + set_status(m_status); + *m_store = m_string.c_str(); + return true; } void -pending_string :: handle_sent_to(const server_id&) +pending_string :: handle_sent_to(const server_id &) { - abort(); + abort(); } void -pending_string :: handle_failure(const server_id&) +pending_string :: handle_failure(const server_id &) { - abort(); + abort(); } bool -pending_string :: handle_message(admin*, - const server_id&, +pending_string :: handle_message(admin *, + const server_id &, network_msgtype, std::auto_ptr, e::unpacker, - hyperdex_admin_returncode*) + hyperdex_admin_returncode *) { - abort(); + abort(); } diff --git a/admin/pending_string.h b/admin/pending_string.h index 22057b8b4..c68a70c07 100644 --- a/admin/pending_string.h +++ b/admin/pending_string.h @@ -36,39 +36,39 @@ class admin; class pending_string : public pending { - public: - pending_string(uint64_t admin_visible_id, - hyperdex_admin_returncode* status, - hyperdex_admin_returncode set_status, - const std::string& string, - const char** store); - virtual ~pending_string() throw (); +public: + pending_string(uint64_t admin_visible_id, + hyperdex_admin_returncode *status, + hyperdex_admin_returncode set_status, + const std::string &string, + const char **store); + virtual ~pending_string() throw (); - // return to admin - public: - virtual bool can_yield(); - virtual bool yield(hyperdex_admin_returncode* status); + // return to admin +public: + virtual bool can_yield(); + virtual bool yield(hyperdex_admin_returncode *status); - // events - public: - virtual void handle_sent_to(const server_id& si); - virtual void handle_failure(const server_id& si); - virtual bool handle_message(admin* cl, - const server_id& si, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_admin_returncode* status); + // events +public: + virtual void handle_sent_to(const server_id &si); + virtual void handle_failure(const server_id &si); + virtual bool handle_message(admin *cl, + const server_id &si, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_admin_returncode *status); - private: - pending_string(const pending_string&); - pending_string& operator = (const pending_string&); +private: + pending_string(const pending_string &); + pending_string &operator = (const pending_string &); - private: - hyperdex_admin_returncode m_status; - std::string m_string; - const char** m_store; - bool m_done; +private: + hyperdex_admin_returncode m_status; + std::string m_string; + const char **m_store; + bool m_done; }; END_HYPERDEX_NAMESPACE diff --git a/admin/raw_backup.cc b/admin/raw_backup.cc index 7fec8dd9c..b76948d88 100644 --- a/admin/raw_backup.cc +++ b/admin/raw_backup.cc @@ -48,117 +48,112 @@ extern "C" { -using namespace hyperdex; + using namespace hyperdex; -HYPERDEX_API int -hyperdex_admin_raw_backup(const char* host, uint16_t port, - const char* name, - enum hyperdex_admin_returncode* status) -{ - try - { - po6::net::location loc; - if (!loc.set(host, port)) { + HYPERDEX_API int + hyperdex_admin_raw_backup(const char *host, uint16_t port, + const char *name, + enum hyperdex_admin_returncode *status) + { + try + { + po6::net::location loc; + if (!loc.set(host, port)) + { + return -1; + } + busybee_single bbs(loc); + const uint8_t type = static_cast(BACKUP); + const uint8_t flags = 0; + const uint64_t version = 0; + virtual_server_id to(UINT64_MAX); + const uint64_t nonce = 0xdeadbeefcafebabe; + size_t name_sz = strlen(name) + 1; + e::slice name_s(name, name_sz); + size_t sz = BUSYBEE_HEADER_SIZE + + sizeof(uint8_t) /*mt*/ + + sizeof(uint8_t) /*flags*/ + + sizeof(uint64_t) /*version*/ + + sizeof(uint64_t) /*vidt*/ + + sizeof(uint64_t) /*nonce*/ + + pack_size(name_s); + std::auto_ptr msg(e::buffer::create(sz)); + e::packer pa = msg->pack_at(BUSYBEE_HEADER_SIZE); + pa = pa << type << flags << version << to << nonce << name_s; + bbs.set_timeout(-1); + switch (bbs.send(msg)) + { + case BUSYBEE_SUCCESS: + break; + case BUSYBEE_TIMEOUT: + *status = HYPERDEX_ADMIN_TIMEOUT; + return -1; + case BUSYBEE_INTERRUPTED: + *status = HYPERDEX_ADMIN_INTERRUPTED; + return -1; + case BUSYBEE_SHUTDOWN: + case BUSYBEE_POLLFAILED: + case BUSYBEE_DISRUPTED: + case BUSYBEE_ADDFDFAIL: + case BUSYBEE_EXTERNAL: + *status = HYPERDEX_ADMIN_SERVERERROR; + return -1; + default: + abort(); + } + switch (bbs.recv(&msg)) + { + case BUSYBEE_SUCCESS: + break; + case BUSYBEE_TIMEOUT: + *status = HYPERDEX_ADMIN_TIMEOUT; + return -1; + case BUSYBEE_INTERRUPTED: + *status = HYPERDEX_ADMIN_INTERRUPTED; + return -1; + case BUSYBEE_SHUTDOWN: + case BUSYBEE_POLLFAILED: + case BUSYBEE_DISRUPTED: + case BUSYBEE_ADDFDFAIL: + case BUSYBEE_EXTERNAL: + *status = HYPERDEX_ADMIN_SERVERERROR; + return -1; + default: + abort(); + } + e::unpacker up = msg->unpack_from(BUSYBEE_HEADER_SIZE + + sizeof(uint8_t) /*mt*/ + + sizeof(uint64_t) /*vidt*/ + + sizeof(uint64_t) /*nonce*/); + uint16_t rt; + if ((up >> rt).error()) + { + *status = HYPERDEX_ADMIN_SERVERERROR; + return -1; + } + network_returncode rc = static_cast(rt); + if (rc == NET_SUCCESS) + { + *status = HYPERDEX_ADMIN_SUCCESS; + return 0; + } + else + { + *status = HYPERDEX_ADMIN_SERVERERROR; + return -1; + } + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + *status = HYPERDEX_ADMIN_NOMEM; return -1; } - busybee_single bbs(loc); - const uint8_t type = static_cast(BACKUP); - const uint8_t flags = 0; - const uint64_t version = 0; - virtual_server_id to(UINT64_MAX); - const uint64_t nonce = 0xdeadbeefcafebabe; - size_t name_sz = strlen(name) + 1; - e::slice name_s(name, name_sz); - size_t sz = BUSYBEE_HEADER_SIZE - + sizeof(uint8_t) /*mt*/ - + sizeof(uint8_t) /*flags*/ - + sizeof(uint64_t) /*version*/ - + sizeof(uint64_t) /*vidt*/ - + sizeof(uint64_t) /*nonce*/ - + pack_size(name_s); - std::auto_ptr msg(e::buffer::create(sz)); - e::packer pa = msg->pack_at(BUSYBEE_HEADER_SIZE); - pa = pa << type << flags << version << to << nonce << name_s; - bbs.set_timeout(-1); - - switch (bbs.send(msg)) - { - case BUSYBEE_SUCCESS: - break; - case BUSYBEE_TIMEOUT: - *status = HYPERDEX_ADMIN_TIMEOUT; - return -1; - case BUSYBEE_INTERRUPTED: - *status = HYPERDEX_ADMIN_INTERRUPTED; - return -1; - case BUSYBEE_SHUTDOWN: - case BUSYBEE_POLLFAILED: - case BUSYBEE_DISRUPTED: - case BUSYBEE_ADDFDFAIL: - case BUSYBEE_EXTERNAL: - *status = HYPERDEX_ADMIN_SERVERERROR; - return -1; - default: - abort(); - } - - switch (bbs.recv(&msg)) - { - case BUSYBEE_SUCCESS: - break; - case BUSYBEE_TIMEOUT: - *status = HYPERDEX_ADMIN_TIMEOUT; - return -1; - case BUSYBEE_INTERRUPTED: - *status = HYPERDEX_ADMIN_INTERRUPTED; - return -1; - case BUSYBEE_SHUTDOWN: - case BUSYBEE_POLLFAILED: - case BUSYBEE_DISRUPTED: - case BUSYBEE_ADDFDFAIL: - case BUSYBEE_EXTERNAL: - *status = HYPERDEX_ADMIN_SERVERERROR; - return -1; - default: - abort(); - } - - e::unpacker up = msg->unpack_from(BUSYBEE_HEADER_SIZE - + sizeof(uint8_t) /*mt*/ - + sizeof(uint64_t) /*vidt*/ - + sizeof(uint64_t) /*nonce*/); - uint16_t rt; - - if ((up >> rt).error()) - { - *status = HYPERDEX_ADMIN_SERVERERROR; - return -1; - } - - network_returncode rc = static_cast(rt); - - if (rc == NET_SUCCESS) - { - *status = HYPERDEX_ADMIN_SUCCESS; - return 0; - } - else - { - *status = HYPERDEX_ADMIN_SERVERERROR; - return -1; - } - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - *status = HYPERDEX_ADMIN_NOMEM; - return -1; - } - catch (...) - { - *status = HYPERDEX_ADMIN_EXCEPTION; - return -1; - } -} + catch (...) + { + *status = HYPERDEX_ADMIN_EXCEPTION; + return -1; + } + } } // extern "C" diff --git a/admin/yieldable.cc b/admin/yieldable.cc index b4acd7d29..0123d2d69 100644 --- a/admin/yieldable.cc +++ b/admin/yieldable.cc @@ -31,11 +31,11 @@ using hyperdex::yieldable; yieldable :: yieldable(uint64_t id, - hyperdex_admin_returncode* s) - : m_ref(0) - , m_admin_visible_id(id) - , m_status(s) - , m_error() + hyperdex_admin_returncode *s) + : m_ref(0) + , m_admin_visible_id(id) + , m_status(s) + , m_error() { } @@ -43,15 +43,15 @@ yieldable :: ~yieldable() throw () { } -std::ostream& -yieldable :: error(const char* file, size_t line) +std::ostream & +yieldable :: error(const char *file, size_t line) { - m_error.set_loc(file, line); - return m_error.set_msg(); + m_error.set_loc(file, line); + return m_error.set_msg(); } void -yieldable :: set_error(const e::error& err) +yieldable :: set_error(const e::error &err) { - m_error = err; + m_error = err; } diff --git a/admin/yieldable.h b/admin/yieldable.h index 4780077de..55dee8020 100644 --- a/admin/yieldable.h +++ b/admin/yieldable.h @@ -47,47 +47,47 @@ class admin; class yieldable { - public: - yieldable(uint64_t admin_visible_id, - hyperdex_admin_returncode* status); - virtual ~yieldable() throw (); +public: + yieldable(uint64_t admin_visible_id, + hyperdex_admin_returncode *status); + virtual ~yieldable() throw (); - public: - int64_t admin_visible_id() const { return m_admin_visible_id; } - void set_status(hyperdex_admin_returncode status) { *m_status = status; } - e::error error() const { return m_error; } +public: + int64_t admin_visible_id() const { return m_admin_visible_id; } + void set_status(hyperdex_admin_returncode status) { *m_status = status; } + e::error error() const { return m_error; } - // return to admin - public: - virtual bool can_yield() = 0; - virtual bool yield(hyperdex_admin_returncode* status) = 0; + // return to admin +public: + virtual bool can_yield() = 0; + virtual bool yield(hyperdex_admin_returncode *status) = 0; - // refcount - protected: - friend class e::intrusive_ptr; - void inc() { ++m_ref; } - void dec() { if (--m_ref == 0) delete this; } - size_t m_ref; + // refcount +protected: + friend class e::intrusive_ptr; + void inc() { ++m_ref; } + void dec() { if (--m_ref == 0) delete this; } + size_t m_ref; - protected: - std::ostream& error(const char* file, size_t line); - void set_error(const e::error& err); +protected: + std::ostream &error(const char *file, size_t line); + void set_error(const e::error &err); - // noncopyable - private: - yieldable(const yieldable& other); - yieldable& operator = (const yieldable& rhs); + // noncopyable +private: + yieldable(const yieldable &other); + yieldable &operator = (const yieldable &rhs); - // operation state - private: - int64_t m_admin_visible_id; - hyperdex_admin_returncode* m_status; - e::error m_error; + // operation state +private: + int64_t m_admin_visible_id; + hyperdex_admin_returncode *m_status; + e::error m_error; }; #define YIELDING_ERROR(CODE) \ - this->set_status(HYPERDEX_ADMIN_ ## CODE); \ - this->error(__FILE__, __LINE__) + this->set_status(HYPERDEX_ADMIN_ ## CODE); \ + this->error(__FILE__, __LINE__) END_HYPERDEX_NAMESPACE diff --git a/bindings/c/admin-testcompile.c b/bindings/c/admin-testcompile.c index a64cb4300..2695804cc 100644 --- a/bindings/c/admin-testcompile.c +++ b/bindings/c/admin-testcompile.c @@ -33,9 +33,9 @@ #endif int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - argc = argc; - argv = argv; - return 0; + argc = argc; + argv = argv; + return 0; } diff --git a/bindings/c/client-testcompile.c b/bindings/c/client-testcompile.c index 686ce94e4..eaf9e41d0 100644 --- a/bindings/c/client-testcompile.c +++ b/bindings/c/client-testcompile.c @@ -33,9 +33,9 @@ #endif int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - argc = argc; - argv = argv; - return 0; + argc = argc; + argv = argv; + return 0; } diff --git a/bindings/cc/admin-testcompile.cc b/bindings/cc/admin-testcompile.cc index e77fef306..8cd588d05 100644 --- a/bindings/cc/admin-testcompile.cc +++ b/bindings/cc/admin-testcompile.cc @@ -32,9 +32,9 @@ #endif int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - argc = argc; - argv = argv; - return 0; + argc = argc; + argv = argv; + return 0; } diff --git a/bindings/cc/client-testcompile.cc b/bindings/cc/client-testcompile.cc index d23b23afe..fbb8f8d07 100644 --- a/bindings/cc/client-testcompile.cc +++ b/bindings/cc/client-testcompile.cc @@ -32,9 +32,9 @@ #endif int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - argc = argc; - argv = argv; - return 0; + argc = argc; + argv = argv; + return 0; } diff --git a/bindings/java/client-util.h b/bindings/java/client-util.h index 51ffbc787..12202d760 100644 --- a/bindings/java/client-util.h +++ b/bindings/java/client-util.h @@ -35,54 +35,54 @@ #include #include -const char* -hyperdex_java_client_convert_cstring(JNIEnv* env, - struct hyperdex_ds_arena* arena, +const char * +hyperdex_java_client_convert_cstring(JNIEnv *env, + struct hyperdex_ds_arena *arena, jobject str); int -hyperdex_java_client_convert_attributes(JNIEnv* env, jobject client, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_attributes(JNIEnv *env, jobject client, + struct hyperdex_ds_arena *arena, jobject x, - const struct hyperdex_client_attribute** _attrs, - size_t* _attrs_sz); + const struct hyperdex_client_attribute **_attrs, + size_t *_attrs_sz); int -hyperdex_java_client_convert_key(JNIEnv* env, jobject client, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_key(JNIEnv *env, jobject client, + struct hyperdex_ds_arena *arena, jobject x, - const char** key, - size_t* key_sz); + const char **key, + size_t *key_sz); int -hyperdex_java_client_convert_predicates(JNIEnv* env, jobject client, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_predicates(JNIEnv *env, jobject client, + struct hyperdex_ds_arena *arena, jobject x, - const struct hyperdex_client_attribute_check** _checks, - size_t* _checks_sz); + const struct hyperdex_client_attribute_check **_checks, + size_t *_checks_sz); int -hyperdex_java_client_throw_exception(JNIEnv* env, +hyperdex_java_client_throw_exception(JNIEnv *env, enum hyperdex_client_returncode _rc, - const char* message); + const char *message); struct hyperdex_java_client_deferred { - struct hyperdex_ds_arena* arena; - int64_t reqid; - enum hyperdex_client_returncode status; - const struct hyperdex_client_attribute* attrs; - size_t attrs_sz; - const char* description; - uint64_t count; - int finished; - jobject (*encode_return)(JNIEnv* env, jobject obj, struct hyperdex_java_client_deferred* d); + struct hyperdex_ds_arena *arena; + int64_t reqid; + enum hyperdex_client_returncode status; + const struct hyperdex_client_attribute *attrs; + size_t attrs_sz; + const char *description; + uint64_t count; + int finished; + jobject (*encode_return)(JNIEnv *env, jobject obj, struct hyperdex_java_client_deferred *d); }; jobject -hyperdex_java_client_deferred_encode_status_count(JNIEnv* env, jobject obj, struct hyperdex_java_client_deferred* d); +hyperdex_java_client_deferred_encode_status_count(JNIEnv *env, jobject obj, struct hyperdex_java_client_deferred *d); jobject -hyperdex_java_client_deferred_encode_status(JNIEnv* env, jobject obj, struct hyperdex_java_client_deferred* d); +hyperdex_java_client_deferred_encode_status(JNIEnv *env, jobject obj, struct hyperdex_java_client_deferred *d); #endif diff --git a/bindings/java/org_hyperdex_client_Client.c b/bindings/java/org_hyperdex_client_Client.c index bcd8abaec..0f69e04dc 100644 --- a/bindings/java/org_hyperdex_client_Client.c +++ b/bindings/java/org_hyperdex_client_Client.c @@ -162,2116 +162,1922 @@ static jfieldID _pred_length_greater_equal_x; #define ERROR_CHECK_VOID() if ((*env)->ExceptionCheck(env) == JNI_TRUE) return #define REF(NAME, DEF) \ - tmp_cls = (DEF); \ - NAME = (jclass) (*env)->NewGlobalRef(env, tmp_cls); \ - (*env)->DeleteLocalRef(env, tmp_cls); + tmp_cls = (DEF); \ + NAME = (jclass) (*env)->NewGlobalRef(env, tmp_cls); \ + (*env)->DeleteLocalRef(env, tmp_cls); JNIEXPORT HYPERDEX_API void JNICALL -Java_org_hyperdex_client_Client_initialize(JNIEnv* env, jclass client) +Java_org_hyperdex_client_Client_initialize(JNIEnv *env, jclass client) { - jclass tmp_cls; - - /* cache class String */ - REF(_string, (*env)->FindClass(env, "java/lang/String")); - /* cache class Document */ - REF(_document, (*env)->FindClass(env, "org/hyperdex/client/Document")); - _document_init = (*env)->GetMethodID(env, _document, "", "(Lorg/hyperdex/client/ByteString;)V"); - _document_to_string = (*env)->GetMethodID(env, _document, "toString", "()Ljava/lang/String;"); - /* cache class ByteString */ - REF(_byte_string, (*env)->FindClass(env, "org/hyperdex/client/ByteString")); - _byte_string_init = (*env)->GetMethodID(env, _byte_string, "", "([B)V"); - _byte_string_get = (*env)->GetMethodID(env, _byte_string, "getBytes", "()[B"); - _byte_string_to_string = (*env)->GetMethodID(env, _byte_string, "toString", "()Ljava/lang/String;"); - /* cache class Boolean */ - REF(_boolean, (*env)->FindClass(env, "java/lang/Boolean")); - _boolean_init = (*env)->GetMethodID(env, _boolean, "", "(Z)V"); - /* cache class Integer */ - REF(_long, (*env)->FindClass(env, "java/lang/Long")); - _long_init = (*env)->GetMethodID(env, _long, "", "(J)V"); - _long_longValue = (*env)->GetMethodID(env, _long, "longValue", "()J"); - /* cache class Integer */ - REF(_integer, (*env)->FindClass(env, "java/lang/Integer")); - _integer_init = (*env)->GetMethodID(env, _integer, "", "(I)V"); - _integer_intValue = (*env)->GetMethodID(env, _integer, "intValue", "()I"); - /* cache class Double */ - REF(_double, (*env)->FindClass(env, "java/lang/Double")); - _double_init = (*env)->GetMethodID(env, _double, "", "(D)V"); - _double_doubleValue = (*env)->GetMethodID(env, _double, "doubleValue", "()D"); - /* cache class List */ - REF(_list, (*env)->FindClass(env, "java/util/List")); - _list_iterator = (*env)->GetMethodID(env, _list, "iterator", "()Ljava/util/Iterator;"); - _list_get = (*env)->GetMethodID(env, _list, "get", "(I)Ljava/lang/Object;"); - _list_size = (*env)->GetMethodID(env, _list, "size", "()I"); - /* cache class ArrayList */ - REF(_array_list, (*env)->FindClass(env, "java/util/ArrayList")); - _array_list_init = (*env)->GetMethodID(env, _array_list, "", "()V"); - _array_list_add = (*env)->GetMethodID(env, _array_list, "add", "(Ljava/lang/Object;)Z"); - /* cache class Set */ - REF(_set, (*env)->FindClass(env, "java/util/Set")); - _set_iterator = (*env)->GetMethodID(env, _set, "iterator", "()Ljava/util/Iterator;"); - /* cache class HashSet */ - REF(_hash_set, (*env)->FindClass(env, "java/util/HashSet")); - _hash_set_init = (*env)->GetMethodID(env, _hash_set, "", "()V"); - _hash_set_add = (*env)->GetMethodID(env, _hash_set, "add", "(Ljava/lang/Object;)Z"); - /* cache class Map */ - REF(_map, (*env)->FindClass(env, "java/util/Map")); - _map_entrySet = (*env)->GetMethodID(env, _map, "entrySet", "()Ljava/util/Set;"); - _map_size = (*env)->GetMethodID(env, _map, "size", "()I"); - /* cache class Map$Entry */ - REF(_map_entry, (*env)->FindClass(env, "java/util/Map$Entry")); - _map_entry_getKey = (*env)->GetMethodID(env, _map_entry, "getKey", "()Ljava/lang/Object;"); - _map_entry_getValue = (*env)->GetMethodID(env, _map_entry, "getValue", "()Ljava/lang/Object;"); - /* cache class HashMap */ - REF(_hash_map, (*env)->FindClass(env, "java/util/HashMap")); - _hash_map_init = (*env)->GetMethodID(env, _hash_map, "", "()V"); - _hash_map_put = (*env)->GetMethodID(env, _hash_map, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); - /* cache class Iterator */ - REF(_java_iterator, (*env)->FindClass(env, "java/util/Iterator")); - _java_iterator_hasNext = (*env)->GetMethodID(env, _java_iterator, "hasNext", "()Z"); - _java_iterator_next = (*env)->GetMethodID(env, _java_iterator, "next", "()Ljava/lang/Object;"); - /* cache class HyperDexException */ - REF(_hd_except, (*env)->FindClass(env, "org/hyperdex/client/HyperDexClientException")); - _hd_except_init = (*env)->GetMethodID(env, _hd_except, "", "(JLjava/lang/String;Ljava/lang/String;)V"); - /* cache class Predicate */ - REF(_predicate, (*env)->FindClass(env, "org/hyperdex/client/Predicate")); - _predicate_checksSize = (*env)->GetMethodID(env, _predicate, "checksSize", "()J"); - _predicate_convertChecks = (*env)->GetMethodID(env, _predicate, "convertChecks", "(JJJ)J"); - /* cache class Deferred */ - REF(_deferred, (*env)->FindClass(env, "org/hyperdex/client/Deferred")); - _deferred_c = (*env)->GetFieldID(env, _deferred, "c", "Lorg/hyperdex/client/Client;"); - _deferred_ptr = (*env)->GetFieldID(env, _deferred, "ptr", "J"); - _deferred_init = (*env)->GetMethodID(env, _deferred, "", "(Lorg/hyperdex/client/Client;)V"); - _deferred_loop = (*env)->GetMethodID(env, _deferred, "loop", "()V"); - /* cache class Iterator */ - REF(_iterator, (*env)->FindClass(env, "org/hyperdex/client/Iterator")); - _iterator_c = (*env)->GetFieldID(env, _iterator, "c", "Lorg/hyperdex/client/Client;"); - _iterator_ptr = (*env)->GetFieldID(env, _iterator, "ptr", "J"); - _iterator_init = (*env)->GetMethodID(env, _iterator, "", "(Lorg/hyperdex/client/Client;)V"); - _iterator_appendBacklogged = (*env)->GetMethodID(env, _iterator, "appendBacklogged", "(Ljava/lang/Object;)V"); - /* cache class Client */ - REF(_client, (*env)->FindClass(env, "org/hyperdex/client/Client")); - _client_ptr = (*env)->GetFieldID(env, _client, "ptr", "J"); - _client_add_op = (*env)->GetMethodID(env, _client, "add_op", "(JLorg/hyperdex/client/Operation;)V"); - _client_remove_op = (*env)->GetMethodID(env, _client, "remove_op", "(J)V"); - /* cache class LessEqual */ - REF(_pred_less_equal, (*env)->FindClass(env, "org/hyperdex/client/LessEqual")); - _pred_less_equal_x = (*env)->GetFieldID(env, _pred_less_equal, "x", "Ljava/lang/Object;"); - /* cache class GreaterEqual */ - REF(_pred_greater_equal, (*env)->FindClass(env, "org/hyperdex/client/GreaterEqual")); - _pred_greater_equal_x = (*env)->GetFieldID(env, _pred_greater_equal, "x", "Ljava/lang/Object;"); - /* cache class Range */ - REF(_pred_range, (*env)->FindClass(env, "org/hyperdex/client/Range")); - _pred_range_x = (*env)->GetFieldID(env, _pred_range, "x", "Ljava/lang/Object;"); - _pred_range_y = (*env)->GetFieldID(env, _pred_range, "y", "Ljava/lang/Object;"); - /* cache class Regex */ - REF(_pred_regex, (*env)->FindClass(env, "org/hyperdex/client/Regex")); - _pred_regex_x = (*env)->GetFieldID(env, _pred_regex, "x", "Ljava/lang/String;"); - /* cache class LengthEquals */ - REF(_pred_length_equals, (*env)->FindClass(env, "org/hyperdex/client/LengthEquals")); - _pred_length_equals_x = (*env)->GetFieldID(env, _pred_length_equals, "x", "Ljava/lang/Object;"); - /* cache class LengthLessEqual */ - REF(_pred_length_less_equal, (*env)->FindClass(env, "org/hyperdex/client/LengthLessEqual")); - _pred_length_less_equal_x = (*env)->GetFieldID(env, _pred_length_less_equal, "x", "Ljava/lang/Object;"); - /* cache class LengthGreaterEqual */ - REF(_pred_length_greater_equal, (*env)->FindClass(env, "org/hyperdex/client/LengthGreaterEqual")); - _pred_length_greater_equal_x = (*env)->GetFieldID(env, _pred_length_greater_equal, "x", "Ljava/lang/Object;"); - - CHECK_CACHE(_string); - CHECK_CACHE(_document); - CHECK_CACHE(_document_init); - CHECK_CACHE(_document_to_string); - CHECK_CACHE(_byte_string); - CHECK_CACHE(_byte_string_init); - CHECK_CACHE(_byte_string_get); - CHECK_CACHE(_byte_string_to_string); - CHECK_CACHE(_boolean); - CHECK_CACHE(_boolean_init); - CHECK_CACHE(_long); - CHECK_CACHE(_long_init); - CHECK_CACHE(_long_longValue); - CHECK_CACHE(_integer); - CHECK_CACHE(_integer_init); - CHECK_CACHE(_integer_intValue); - CHECK_CACHE(_double); - CHECK_CACHE(_double_init); - CHECK_CACHE(_double_doubleValue); - CHECK_CACHE(_list); - CHECK_CACHE(_list_iterator); - CHECK_CACHE(_list_get); - CHECK_CACHE(_list_size); - CHECK_CACHE(_array_list); - CHECK_CACHE(_array_list_init); - CHECK_CACHE(_array_list_add); - CHECK_CACHE(_set); - CHECK_CACHE(_set_iterator); - CHECK_CACHE(_hash_set); - CHECK_CACHE(_hash_set_init); - CHECK_CACHE(_hash_set_add); - CHECK_CACHE(_map); - CHECK_CACHE(_map_entrySet); - CHECK_CACHE(_map_size); - CHECK_CACHE(_map_entry); - CHECK_CACHE(_map_entry_getKey); - CHECK_CACHE(_map_entry_getValue); - CHECK_CACHE(_hash_map); - CHECK_CACHE(_hash_map_init); - CHECK_CACHE(_hash_map_put); - CHECK_CACHE(_java_iterator); - CHECK_CACHE(_java_iterator_hasNext); - CHECK_CACHE(_java_iterator_next); - CHECK_CACHE(_hd_except); - CHECK_CACHE(_hd_except_init); - CHECK_CACHE(_predicate); - CHECK_CACHE(_predicate_checksSize); - CHECK_CACHE(_predicate_convertChecks); - CHECK_CACHE(_deferred); - CHECK_CACHE(_deferred_c); - CHECK_CACHE(_deferred_ptr); - CHECK_CACHE(_deferred_init); - CHECK_CACHE(_deferred_loop); - CHECK_CACHE(_iterator); - CHECK_CACHE(_iterator_c); - CHECK_CACHE(_iterator_ptr); - CHECK_CACHE(_iterator_init); - CHECK_CACHE(_iterator_appendBacklogged); - CHECK_CACHE(_client); - CHECK_CACHE(_client_ptr); - CHECK_CACHE(_client_add_op); - CHECK_CACHE(_client_remove_op); - CHECK_CACHE(_pred_less_equal); - CHECK_CACHE(_pred_less_equal_x); - CHECK_CACHE(_pred_greater_equal); - CHECK_CACHE(_pred_greater_equal_x); - CHECK_CACHE(_pred_range); - CHECK_CACHE(_pred_range_x); - CHECK_CACHE(_pred_range_y); - CHECK_CACHE(_pred_regex); - CHECK_CACHE(_pred_regex_x); - CHECK_CACHE(_pred_length_equals); - CHECK_CACHE(_pred_length_equals_x); - CHECK_CACHE(_pred_length_less_equal); - CHECK_CACHE(_pred_length_less_equal_x); - CHECK_CACHE(_pred_length_greater_equal); - CHECK_CACHE(_pred_length_greater_equal_x); - - (void) client; + jclass tmp_cls; + /* cache class String */ + REF(_string, (*env)->FindClass(env, "java/lang/String")); + /* cache class Document */ + REF(_document, (*env)->FindClass(env, "org/hyperdex/client/Document")); + _document_init = (*env)->GetMethodID(env, _document, "", "(Lorg/hyperdex/client/ByteString;)V"); + _document_to_string = (*env)->GetMethodID(env, _document, "toString", "()Ljava/lang/String;"); + /* cache class ByteString */ + REF(_byte_string, (*env)->FindClass(env, "org/hyperdex/client/ByteString")); + _byte_string_init = (*env)->GetMethodID(env, _byte_string, "", "([B)V"); + _byte_string_get = (*env)->GetMethodID(env, _byte_string, "getBytes", "()[B"); + _byte_string_to_string = (*env)->GetMethodID(env, _byte_string, "toString", "()Ljava/lang/String;"); + /* cache class Boolean */ + REF(_boolean, (*env)->FindClass(env, "java/lang/Boolean")); + _boolean_init = (*env)->GetMethodID(env, _boolean, "", "(Z)V"); + /* cache class Integer */ + REF(_long, (*env)->FindClass(env, "java/lang/Long")); + _long_init = (*env)->GetMethodID(env, _long, "", "(J)V"); + _long_longValue = (*env)->GetMethodID(env, _long, "longValue", "()J"); + /* cache class Integer */ + REF(_integer, (*env)->FindClass(env, "java/lang/Integer")); + _integer_init = (*env)->GetMethodID(env, _integer, "", "(I)V"); + _integer_intValue = (*env)->GetMethodID(env, _integer, "intValue", "()I"); + /* cache class Double */ + REF(_double, (*env)->FindClass(env, "java/lang/Double")); + _double_init = (*env)->GetMethodID(env, _double, "", "(D)V"); + _double_doubleValue = (*env)->GetMethodID(env, _double, "doubleValue", "()D"); + /* cache class List */ + REF(_list, (*env)->FindClass(env, "java/util/List")); + _list_iterator = (*env)->GetMethodID(env, _list, "iterator", "()Ljava/util/Iterator;"); + _list_get = (*env)->GetMethodID(env, _list, "get", "(I)Ljava/lang/Object;"); + _list_size = (*env)->GetMethodID(env, _list, "size", "()I"); + /* cache class ArrayList */ + REF(_array_list, (*env)->FindClass(env, "java/util/ArrayList")); + _array_list_init = (*env)->GetMethodID(env, _array_list, "", "()V"); + _array_list_add = (*env)->GetMethodID(env, _array_list, "add", "(Ljava/lang/Object;)Z"); + /* cache class Set */ + REF(_set, (*env)->FindClass(env, "java/util/Set")); + _set_iterator = (*env)->GetMethodID(env, _set, "iterator", "()Ljava/util/Iterator;"); + /* cache class HashSet */ + REF(_hash_set, (*env)->FindClass(env, "java/util/HashSet")); + _hash_set_init = (*env)->GetMethodID(env, _hash_set, "", "()V"); + _hash_set_add = (*env)->GetMethodID(env, _hash_set, "add", "(Ljava/lang/Object;)Z"); + /* cache class Map */ + REF(_map, (*env)->FindClass(env, "java/util/Map")); + _map_entrySet = (*env)->GetMethodID(env, _map, "entrySet", "()Ljava/util/Set;"); + _map_size = (*env)->GetMethodID(env, _map, "size", "()I"); + /* cache class Map$Entry */ + REF(_map_entry, (*env)->FindClass(env, "java/util/Map$Entry")); + _map_entry_getKey = (*env)->GetMethodID(env, _map_entry, "getKey", "()Ljava/lang/Object;"); + _map_entry_getValue = (*env)->GetMethodID(env, _map_entry, "getValue", "()Ljava/lang/Object;"); + /* cache class HashMap */ + REF(_hash_map, (*env)->FindClass(env, "java/util/HashMap")); + _hash_map_init = (*env)->GetMethodID(env, _hash_map, "", "()V"); + _hash_map_put = (*env)->GetMethodID(env, _hash_map, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + /* cache class Iterator */ + REF(_java_iterator, (*env)->FindClass(env, "java/util/Iterator")); + _java_iterator_hasNext = (*env)->GetMethodID(env, _java_iterator, "hasNext", "()Z"); + _java_iterator_next = (*env)->GetMethodID(env, _java_iterator, "next", "()Ljava/lang/Object;"); + /* cache class HyperDexException */ + REF(_hd_except, (*env)->FindClass(env, "org/hyperdex/client/HyperDexClientException")); + _hd_except_init = (*env)->GetMethodID(env, _hd_except, "", "(JLjava/lang/String;Ljava/lang/String;)V"); + /* cache class Predicate */ + REF(_predicate, (*env)->FindClass(env, "org/hyperdex/client/Predicate")); + _predicate_checksSize = (*env)->GetMethodID(env, _predicate, "checksSize", "()J"); + _predicate_convertChecks = (*env)->GetMethodID(env, _predicate, "convertChecks", "(JJJ)J"); + /* cache class Deferred */ + REF(_deferred, (*env)->FindClass(env, "org/hyperdex/client/Deferred")); + _deferred_c = (*env)->GetFieldID(env, _deferred, "c", "Lorg/hyperdex/client/Client;"); + _deferred_ptr = (*env)->GetFieldID(env, _deferred, "ptr", "J"); + _deferred_init = (*env)->GetMethodID(env, _deferred, "", "(Lorg/hyperdex/client/Client;)V"); + _deferred_loop = (*env)->GetMethodID(env, _deferred, "loop", "()V"); + /* cache class Iterator */ + REF(_iterator, (*env)->FindClass(env, "org/hyperdex/client/Iterator")); + _iterator_c = (*env)->GetFieldID(env, _iterator, "c", "Lorg/hyperdex/client/Client;"); + _iterator_ptr = (*env)->GetFieldID(env, _iterator, "ptr", "J"); + _iterator_init = (*env)->GetMethodID(env, _iterator, "", "(Lorg/hyperdex/client/Client;)V"); + _iterator_appendBacklogged = (*env)->GetMethodID(env, _iterator, "appendBacklogged", "(Ljava/lang/Object;)V"); + /* cache class Client */ + REF(_client, (*env)->FindClass(env, "org/hyperdex/client/Client")); + _client_ptr = (*env)->GetFieldID(env, _client, "ptr", "J"); + _client_add_op = (*env)->GetMethodID(env, _client, "add_op", "(JLorg/hyperdex/client/Operation;)V"); + _client_remove_op = (*env)->GetMethodID(env, _client, "remove_op", "(J)V"); + /* cache class LessEqual */ + REF(_pred_less_equal, (*env)->FindClass(env, "org/hyperdex/client/LessEqual")); + _pred_less_equal_x = (*env)->GetFieldID(env, _pred_less_equal, "x", "Ljava/lang/Object;"); + /* cache class GreaterEqual */ + REF(_pred_greater_equal, (*env)->FindClass(env, "org/hyperdex/client/GreaterEqual")); + _pred_greater_equal_x = (*env)->GetFieldID(env, _pred_greater_equal, "x", "Ljava/lang/Object;"); + /* cache class Range */ + REF(_pred_range, (*env)->FindClass(env, "org/hyperdex/client/Range")); + _pred_range_x = (*env)->GetFieldID(env, _pred_range, "x", "Ljava/lang/Object;"); + _pred_range_y = (*env)->GetFieldID(env, _pred_range, "y", "Ljava/lang/Object;"); + /* cache class Regex */ + REF(_pred_regex, (*env)->FindClass(env, "org/hyperdex/client/Regex")); + _pred_regex_x = (*env)->GetFieldID(env, _pred_regex, "x", "Ljava/lang/String;"); + /* cache class LengthEquals */ + REF(_pred_length_equals, (*env)->FindClass(env, "org/hyperdex/client/LengthEquals")); + _pred_length_equals_x = (*env)->GetFieldID(env, _pred_length_equals, "x", "Ljava/lang/Object;"); + /* cache class LengthLessEqual */ + REF(_pred_length_less_equal, (*env)->FindClass(env, "org/hyperdex/client/LengthLessEqual")); + _pred_length_less_equal_x = (*env)->GetFieldID(env, _pred_length_less_equal, "x", "Ljava/lang/Object;"); + /* cache class LengthGreaterEqual */ + REF(_pred_length_greater_equal, (*env)->FindClass(env, "org/hyperdex/client/LengthGreaterEqual")); + _pred_length_greater_equal_x = (*env)->GetFieldID(env, _pred_length_greater_equal, "x", "Ljava/lang/Object;"); + CHECK_CACHE(_string); + CHECK_CACHE(_document); + CHECK_CACHE(_document_init); + CHECK_CACHE(_document_to_string); + CHECK_CACHE(_byte_string); + CHECK_CACHE(_byte_string_init); + CHECK_CACHE(_byte_string_get); + CHECK_CACHE(_byte_string_to_string); + CHECK_CACHE(_boolean); + CHECK_CACHE(_boolean_init); + CHECK_CACHE(_long); + CHECK_CACHE(_long_init); + CHECK_CACHE(_long_longValue); + CHECK_CACHE(_integer); + CHECK_CACHE(_integer_init); + CHECK_CACHE(_integer_intValue); + CHECK_CACHE(_double); + CHECK_CACHE(_double_init); + CHECK_CACHE(_double_doubleValue); + CHECK_CACHE(_list); + CHECK_CACHE(_list_iterator); + CHECK_CACHE(_list_get); + CHECK_CACHE(_list_size); + CHECK_CACHE(_array_list); + CHECK_CACHE(_array_list_init); + CHECK_CACHE(_array_list_add); + CHECK_CACHE(_set); + CHECK_CACHE(_set_iterator); + CHECK_CACHE(_hash_set); + CHECK_CACHE(_hash_set_init); + CHECK_CACHE(_hash_set_add); + CHECK_CACHE(_map); + CHECK_CACHE(_map_entrySet); + CHECK_CACHE(_map_size); + CHECK_CACHE(_map_entry); + CHECK_CACHE(_map_entry_getKey); + CHECK_CACHE(_map_entry_getValue); + CHECK_CACHE(_hash_map); + CHECK_CACHE(_hash_map_init); + CHECK_CACHE(_hash_map_put); + CHECK_CACHE(_java_iterator); + CHECK_CACHE(_java_iterator_hasNext); + CHECK_CACHE(_java_iterator_next); + CHECK_CACHE(_hd_except); + CHECK_CACHE(_hd_except_init); + CHECK_CACHE(_predicate); + CHECK_CACHE(_predicate_checksSize); + CHECK_CACHE(_predicate_convertChecks); + CHECK_CACHE(_deferred); + CHECK_CACHE(_deferred_c); + CHECK_CACHE(_deferred_ptr); + CHECK_CACHE(_deferred_init); + CHECK_CACHE(_deferred_loop); + CHECK_CACHE(_iterator); + CHECK_CACHE(_iterator_c); + CHECK_CACHE(_iterator_ptr); + CHECK_CACHE(_iterator_init); + CHECK_CACHE(_iterator_appendBacklogged); + CHECK_CACHE(_client); + CHECK_CACHE(_client_ptr); + CHECK_CACHE(_client_add_op); + CHECK_CACHE(_client_remove_op); + CHECK_CACHE(_pred_less_equal); + CHECK_CACHE(_pred_less_equal_x); + CHECK_CACHE(_pred_greater_equal); + CHECK_CACHE(_pred_greater_equal_x); + CHECK_CACHE(_pred_range); + CHECK_CACHE(_pred_range_x); + CHECK_CACHE(_pred_range_y); + CHECK_CACHE(_pred_regex); + CHECK_CACHE(_pred_regex_x); + CHECK_CACHE(_pred_length_equals); + CHECK_CACHE(_pred_length_equals_x); + CHECK_CACHE(_pred_length_less_equal); + CHECK_CACHE(_pred_length_less_equal_x); + CHECK_CACHE(_pred_length_greater_equal); + CHECK_CACHE(_pred_length_greater_equal_x); + (void) client; } JNIEXPORT HYPERDEX_API void JNICALL -Java_org_hyperdex_client_Client_terminate(JNIEnv* env, jclass client) +Java_org_hyperdex_client_Client_terminate(JNIEnv *env, jclass client) { - (*env)->DeleteGlobalRef(env, _document); - (*env)->DeleteGlobalRef(env, _string); - (*env)->DeleteGlobalRef(env, _byte_string); - (*env)->DeleteGlobalRef(env, _boolean); - (*env)->DeleteGlobalRef(env, _long); - (*env)->DeleteGlobalRef(env, _integer); - (*env)->DeleteGlobalRef(env, _double); - (*env)->DeleteGlobalRef(env, _list); - (*env)->DeleteGlobalRef(env, _array_list); - (*env)->DeleteGlobalRef(env, _set); - (*env)->DeleteGlobalRef(env, _hash_set); - (*env)->DeleteGlobalRef(env, _map); - (*env)->DeleteGlobalRef(env, _map_entry); - (*env)->DeleteGlobalRef(env, _hash_map); - (*env)->DeleteGlobalRef(env, _java_iterator); - (*env)->DeleteGlobalRef(env, _hd_except); - (*env)->DeleteGlobalRef(env, _predicate); - (*env)->DeleteGlobalRef(env, _deferred); - (*env)->DeleteGlobalRef(env, _iterator); - (*env)->DeleteGlobalRef(env, _client); - (*env)->DeleteGlobalRef(env, _pred_less_equal); - (*env)->DeleteGlobalRef(env, _pred_greater_equal); - (*env)->DeleteGlobalRef(env, _pred_range); - (*env)->DeleteGlobalRef(env, _pred_regex); - (*env)->DeleteGlobalRef(env, _pred_length_equals); - (*env)->DeleteGlobalRef(env, _pred_length_less_equal); - (*env)->DeleteGlobalRef(env, _pred_length_greater_equal); - - (void) client; + (*env)->DeleteGlobalRef(env, _document); + (*env)->DeleteGlobalRef(env, _string); + (*env)->DeleteGlobalRef(env, _byte_string); + (*env)->DeleteGlobalRef(env, _boolean); + (*env)->DeleteGlobalRef(env, _long); + (*env)->DeleteGlobalRef(env, _integer); + (*env)->DeleteGlobalRef(env, _double); + (*env)->DeleteGlobalRef(env, _list); + (*env)->DeleteGlobalRef(env, _array_list); + (*env)->DeleteGlobalRef(env, _set); + (*env)->DeleteGlobalRef(env, _hash_set); + (*env)->DeleteGlobalRef(env, _map); + (*env)->DeleteGlobalRef(env, _map_entry); + (*env)->DeleteGlobalRef(env, _hash_map); + (*env)->DeleteGlobalRef(env, _java_iterator); + (*env)->DeleteGlobalRef(env, _hd_except); + (*env)->DeleteGlobalRef(env, _predicate); + (*env)->DeleteGlobalRef(env, _deferred); + (*env)->DeleteGlobalRef(env, _iterator); + (*env)->DeleteGlobalRef(env, _client); + (*env)->DeleteGlobalRef(env, _pred_less_equal); + (*env)->DeleteGlobalRef(env, _pred_greater_equal); + (*env)->DeleteGlobalRef(env, _pred_range); + (*env)->DeleteGlobalRef(env, _pred_regex); + (*env)->DeleteGlobalRef(env, _pred_length_equals); + (*env)->DeleteGlobalRef(env, _pred_length_less_equal); + (*env)->DeleteGlobalRef(env, _pred_length_greater_equal); + (void) client; } /******************************* Pointer Unwrap *******************************/ -static struct hyperdex_client* -hyperdex_get_client_ptr(JNIEnv* env, jobject obj) +static struct hyperdex_client * +hyperdex_get_client_ptr(JNIEnv *env, jobject obj) { - struct hyperdex_client* x; - x = (struct hyperdex_client*) (*env)->GetLongField(env, obj, _client_ptr); - assert(x); - return x; + struct hyperdex_client *x; + x = (struct hyperdex_client *) (*env)->GetLongField(env, obj, _client_ptr); + assert(x); + return x; } -static struct hyperdex_java_client_deferred* -hyperdex_get_deferred_ptr(JNIEnv* env, jobject obj) +static struct hyperdex_java_client_deferred * +hyperdex_get_deferred_ptr(JNIEnv *env, jobject obj) { - struct hyperdex_java_client_deferred* x; - x = (struct hyperdex_java_client_deferred*) (*env)->GetLongField(env, obj, _deferred_ptr); - assert(x); - return x; + struct hyperdex_java_client_deferred *x; + x = (struct hyperdex_java_client_deferred *) (*env)->GetLongField(env, obj, _deferred_ptr); + assert(x); + return x; } -static struct hyperdex_java_client_iterator* -hyperdex_get_iterator_ptr(JNIEnv* env, jobject obj) +static struct hyperdex_java_client_iterator * +hyperdex_get_iterator_ptr(JNIEnv *env, jobject obj) { - struct hyperdex_java_client_iterator* x; - x = (struct hyperdex_java_client_iterator*) (*env)->GetLongField(env, obj, _iterator_ptr); - assert(x); - return x; + struct hyperdex_java_client_iterator *x; + x = (struct hyperdex_java_client_iterator *) (*env)->GetLongField(env, obj, _iterator_ptr); + assert(x); + return x; } /******************************* Error Handling *******************************/ static int -hyperdex_java_out_of_memory(JNIEnv* env) +hyperdex_java_out_of_memory(JNIEnv *env) { - jclass oom; - jmethodID init; - jobject exc; - - oom = (*env)->FindClass(env, "java/lang/OutOfMemoryError"); - ERROR_CHECK(-1); - init = (*env)->GetMethodID(env, oom, "", "()V"); - ERROR_CHECK(-1); - exc = (*env)->NewObject(env, oom, init); - ERROR_CHECK(-1); - - (*env)->ExceptionClear(env); - (*env)->Throw(env, exc); - return -1; + jclass oom; + jmethodID init; + jobject exc; + oom = (*env)->FindClass(env, "java/lang/OutOfMemoryError"); + ERROR_CHECK(-1); + init = (*env)->GetMethodID(env, oom, "", "()V"); + ERROR_CHECK(-1); + exc = (*env)->NewObject(env, oom, init); + ERROR_CHECK(-1); + (*env)->ExceptionClear(env); + (*env)->Throw(env, exc); + return -1; } static jobject -hyperdex_java_client_create_exception(JNIEnv* env, +hyperdex_java_client_create_exception(JNIEnv *env, enum hyperdex_client_returncode _rc, - const char* message) + const char *message) { - jlong rc = _rc; - jstring str = (*env)->NewStringUTF(env, hyperdex_client_returncode_to_string(_rc)); - jstring msg = (*env)->NewStringUTF(env, message); - jobject err = (*env)->NewObject(env, _hd_except, _hd_except_init, rc, str, msg); - ERROR_CHECK(0); - return err; + jlong rc = _rc; + jstring str = (*env)->NewStringUTF(env, hyperdex_client_returncode_to_string(_rc)); + jstring msg = (*env)->NewStringUTF(env, message); + jobject err = (*env)->NewObject(env, _hd_except, _hd_except_init, rc, str, msg); + ERROR_CHECK(0); + return err; } int -hyperdex_java_client_throw_exception(JNIEnv* env, +hyperdex_java_client_throw_exception(JNIEnv *env, enum hyperdex_client_returncode _rc, - const char* message) + const char *message) { - jobject err = hyperdex_java_client_create_exception(env, _rc, message); - ERROR_CHECK(-1); - (*env)->ExceptionClear(env); - return (*env)->Throw(env, err); + jobject err = hyperdex_java_client_create_exception(env, _rc, message); + ERROR_CHECK(-1); + (*env)->ExceptionClear(env); + return (*env)->Throw(env, err); } /********************************** Java -> C *********************************/ -typedef int (*elem_string_fptr)(void*, const char*, size_t, enum hyperdex_ds_returncode*); -typedef int (*elem_int_fptr)(void*, int64_t, enum hyperdex_ds_returncode*); -typedef int (*elem_float_fptr)(void*, double, enum hyperdex_ds_returncode*); +typedef int (*elem_string_fptr)(void *, const char *, size_t, enum hyperdex_ds_returncode *); +typedef int (*elem_int_fptr)(void *, int64_t, enum hyperdex_ds_returncode *); +typedef int (*elem_float_fptr)(void *, double, enum hyperdex_ds_returncode *); #define HDJAVA_HANDLE_ELEM_ERROR(X, TYPE) \ - switch (X) \ - { \ - case HYPERDEX_DS_NOMEM: \ - hyperdex_java_out_of_memory(env); \ - return -1; \ - case HYPERDEX_DS_MIXED_TYPES: \ - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_WRONGTYPE, "Cannot add " TYPE " to a heterogenous container"); \ - return -1; \ - case HYPERDEX_DS_SUCCESS: \ - case HYPERDEX_DS_STRING_TOO_LONG: \ - case HYPERDEX_DS_WRONG_STATE: \ - default: \ - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_WRONGTYPE, "Cannot convert " TYPE " to a HyperDex type"); \ - return -1; \ - } + switch (X) \ + { \ + case HYPERDEX_DS_NOMEM: \ + hyperdex_java_out_of_memory(env); \ + return -1; \ + case HYPERDEX_DS_MIXED_TYPES: \ + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_WRONGTYPE, "Cannot add " TYPE " to a heterogenous container"); \ + return -1; \ + case HYPERDEX_DS_SUCCESS: \ + case HYPERDEX_DS_STRING_TOO_LONG: \ + case HYPERDEX_DS_WRONG_STATE: \ + default: \ + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_WRONGTYPE, "Cannot convert " TYPE " to a HyperDex type"); \ + return -1; \ + } /* Convert a single elment of a list, map, or set*/ static int -hyperdex_java_client_convert_elem(JNIEnv* env, +hyperdex_java_client_convert_elem(JNIEnv *env, jobject obj, - void* container, + void *container, elem_string_fptr f_string, elem_int_fptr f_int, elem_float_fptr f_float) { - enum hyperdex_ds_returncode error; - int success; - const char* tmp_str; - size_t tmp_str_sz; - jbyte* tmp_bytes; - size_t tmp_bytes_sz; - int64_t tmp_l; - int32_t tmp_i; - double tmp_d; - - if ((*env)->IsInstanceOf(env, obj, _string) == JNI_TRUE) - { - tmp_str = (*env)->GetStringUTFChars(env, obj, 0); - ERROR_CHECK(-1); - tmp_str_sz = (*env)->GetStringUTFLength(env, obj); - ERROR_CHECK(-1); - success = f_string(container, tmp_str, tmp_str_sz, &error); - (*env)->ReleaseStringUTFChars(env, obj, tmp_str); - ERROR_CHECK(-1); - - if (success < 0) - { - HDJAVA_HANDLE_ELEM_ERROR(error, "string"); - } - - return 0; - } - else if ((*env)->IsInstanceOf(env, obj, _byte_string) == JNI_TRUE) - { - obj = (*env)->CallObjectMethod(env, obj, _byte_string_get); - ERROR_CHECK(-1); - tmp_bytes = (*env)->GetByteArrayElements(env, obj, 0); - ERROR_CHECK(-1); - tmp_bytes_sz = (*env)->GetArrayLength(env, obj); - ERROR_CHECK(-1); - success = f_string(container, (const char*)tmp_bytes, tmp_bytes_sz, &error); - (*env)->ReleaseByteArrayElements(env, obj, tmp_bytes, 0); - ERROR_CHECK(-1); - - if (success < 0) - { - HDJAVA_HANDLE_ELEM_ERROR(error, "bytes"); - } - - return 0; - } - else if ((*env)->IsInstanceOf(env, obj, _long) == JNI_TRUE) - { - tmp_l = (*env)->CallLongMethod(env, obj, _long_longValue); - ERROR_CHECK(-1); - - if (f_int(container, tmp_l, &error) < 0) - { - HDJAVA_HANDLE_ELEM_ERROR(error, "long"); - } - - return 0; - } - else if ((*env)->IsInstanceOf(env, obj, _integer) == JNI_TRUE) - { - tmp_i = (*env)->CallIntMethod(env, obj, _integer_intValue); - ERROR_CHECK(-1); - - if (f_int(container, tmp_i, &error) < 0) - { - HDJAVA_HANDLE_ELEM_ERROR(error, "int"); - } - - return 0; - } - else if ((*env)->IsInstanceOf(env, obj, _double) == JNI_TRUE) - { - tmp_d = (*env)->CallDoubleMethod(env, obj, _double_doubleValue); - ERROR_CHECK(-1); - - if (f_float(container, tmp_d, &error) < 0) - { - HDJAVA_HANDLE_ELEM_ERROR(error, "float"); - } - - return 0; - } - else - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_WRONGTYPE, - "Cannot convert unknown type to a HyperDex type"); - return -1; - } + enum hyperdex_ds_returncode error; + int success; + const char *tmp_str; + size_t tmp_str_sz; + jbyte *tmp_bytes; + size_t tmp_bytes_sz; + int64_t tmp_l; + int32_t tmp_i; + double tmp_d; + if ((*env)->IsInstanceOf(env, obj, _string) == JNI_TRUE) + { + tmp_str = (*env)->GetStringUTFChars(env, obj, 0); + ERROR_CHECK(-1); + tmp_str_sz = (*env)->GetStringUTFLength(env, obj); + ERROR_CHECK(-1); + success = f_string(container, tmp_str, tmp_str_sz, &error); + (*env)->ReleaseStringUTFChars(env, obj, tmp_str); + ERROR_CHECK(-1); + if (success < 0) + { + HDJAVA_HANDLE_ELEM_ERROR(error, "string"); + } + return 0; + } + else if ((*env)->IsInstanceOf(env, obj, _byte_string) == JNI_TRUE) + { + obj = (*env)->CallObjectMethod(env, obj, _byte_string_get); + ERROR_CHECK(-1); + tmp_bytes = (*env)->GetByteArrayElements(env, obj, 0); + ERROR_CHECK(-1); + tmp_bytes_sz = (*env)->GetArrayLength(env, obj); + ERROR_CHECK(-1); + success = f_string(container, (const char *)tmp_bytes, tmp_bytes_sz, &error); + (*env)->ReleaseByteArrayElements(env, obj, tmp_bytes, 0); + ERROR_CHECK(-1); + if (success < 0) + { + HDJAVA_HANDLE_ELEM_ERROR(error, "bytes"); + } + return 0; + } + else if ((*env)->IsInstanceOf(env, obj, _long) == JNI_TRUE) + { + tmp_l = (*env)->CallLongMethod(env, obj, _long_longValue); + ERROR_CHECK(-1); + if (f_int(container, tmp_l, &error) < 0) + { + HDJAVA_HANDLE_ELEM_ERROR(error, "long"); + } + return 0; + } + else if ((*env)->IsInstanceOf(env, obj, _integer) == JNI_TRUE) + { + tmp_i = (*env)->CallIntMethod(env, obj, _integer_intValue); + ERROR_CHECK(-1); + if (f_int(container, tmp_i, &error) < 0) + { + HDJAVA_HANDLE_ELEM_ERROR(error, "int"); + } + return 0; + } + else if ((*env)->IsInstanceOf(env, obj, _double) == JNI_TRUE) + { + tmp_d = (*env)->CallDoubleMethod(env, obj, _double_doubleValue); + ERROR_CHECK(-1); + if (f_float(container, tmp_d, &error) < 0) + { + HDJAVA_HANDLE_ELEM_ERROR(error, "float"); + } + return 0; + } + else + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_WRONGTYPE, + "Cannot convert unknown type to a HyperDex type"); + return -1; + } } static int -hyperdex_java_client_convert_list(JNIEnv* env, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_list(JNIEnv *env, + struct hyperdex_ds_arena *arena, jobject x, - const char** value, - size_t* value_sz, - enum hyperdatatype* datatype) + const char **value, + size_t *value_sz, + enum hyperdatatype *datatype) { - struct hyperdex_ds_list* list; - enum hyperdex_ds_returncode error; - jobject entry; - jobject it = (*env)->CallObjectMethod(env, x, _list_iterator); - ERROR_CHECK(-1); - - list = hyperdex_ds_allocate_list(arena); - - if (!list) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) - { - entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); - ERROR_CHECK(-1); - - if (hyperdex_java_client_convert_elem(env, entry, list, - (elem_string_fptr) hyperdex_ds_list_append_string, - (elem_int_fptr) hyperdex_ds_list_append_int, - (elem_float_fptr) hyperdex_ds_list_append_float) < 0) - { - return -1; - } - - (*env)->DeleteLocalRef(env, entry); - } - - if (hyperdex_ds_list_finalize(list, &error, value, value_sz, datatype) < 0) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - (*env)->DeleteLocalRef(env, it); - return 0; + struct hyperdex_ds_list *list; + enum hyperdex_ds_returncode error; + jobject entry; + jobject it = (*env)->CallObjectMethod(env, x, _list_iterator); + ERROR_CHECK(-1); + list = hyperdex_ds_allocate_list(arena); + if (!list) + { + hyperdex_java_out_of_memory(env); + return -1; + } + while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) + { + entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); + ERROR_CHECK(-1); + if (hyperdex_java_client_convert_elem(env, entry, list, + (elem_string_fptr) hyperdex_ds_list_append_string, + (elem_int_fptr) hyperdex_ds_list_append_int, + (elem_float_fptr) hyperdex_ds_list_append_float) < 0) + { + return -1; + } + (*env)->DeleteLocalRef(env, entry); + } + if (hyperdex_ds_list_finalize(list, &error, value, value_sz, datatype) < 0) + { + hyperdex_java_out_of_memory(env); + return -1; + } + (*env)->DeleteLocalRef(env, it); + return 0; } static int -hyperdex_java_client_convert_set(JNIEnv* env, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_set(JNIEnv *env, + struct hyperdex_ds_arena *arena, jobject x, - const char** value, - size_t* value_sz, - enum hyperdatatype* datatype) + const char **value, + size_t *value_sz, + enum hyperdatatype *datatype) { - struct hyperdex_ds_set* set; - enum hyperdex_ds_returncode error; - jobject it = (*env)->CallObjectMethod(env, x, _set_iterator); - jobject entry; - ERROR_CHECK(-1); - - set = hyperdex_ds_allocate_set(arena); - - if (!set) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) - { - entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); - ERROR_CHECK(-1); - - if (hyperdex_java_client_convert_elem(env, entry, set, - (elem_string_fptr) hyperdex_ds_set_insert_string, - (elem_int_fptr) hyperdex_ds_set_insert_int, - (elem_float_fptr) hyperdex_ds_set_insert_float) < 0) - { - return -1; - } - - (*env)->DeleteLocalRef(env, entry); - } - - if (hyperdex_ds_set_finalize(set, &error, value, value_sz, datatype) < 0) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - (*env)->DeleteLocalRef(env, it); - return 0; + struct hyperdex_ds_set *set; + enum hyperdex_ds_returncode error; + jobject it = (*env)->CallObjectMethod(env, x, _set_iterator); + jobject entry; + ERROR_CHECK(-1); + set = hyperdex_ds_allocate_set(arena); + if (!set) + { + hyperdex_java_out_of_memory(env); + return -1; + } + while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) + { + entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); + ERROR_CHECK(-1); + if (hyperdex_java_client_convert_elem(env, entry, set, + (elem_string_fptr) hyperdex_ds_set_insert_string, + (elem_int_fptr) hyperdex_ds_set_insert_int, + (elem_float_fptr) hyperdex_ds_set_insert_float) < 0) + { + return -1; + } + (*env)->DeleteLocalRef(env, entry); + } + if (hyperdex_ds_set_finalize(set, &error, value, value_sz, datatype) < 0) + { + hyperdex_java_out_of_memory(env); + return -1; + } + (*env)->DeleteLocalRef(env, it); + return 0; } static int -hyperdex_java_client_convert_map(JNIEnv* env, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_map(JNIEnv *env, + struct hyperdex_ds_arena *arena, jobject x, - const char** value, - size_t* value_sz, - enum hyperdatatype* datatype) + const char **value, + size_t *value_sz, + enum hyperdatatype *datatype) { - struct hyperdex_ds_map* map; - enum hyperdex_ds_returncode error; - jobject set; - jobject it; - jobject entry; - jobject key; - jobject val; - - set = (*env)->CallObjectMethod(env, x, _map_entrySet); - ERROR_CHECK(-1); - it = (*env)->CallObjectMethod(env, set, _set_iterator); - ERROR_CHECK(-1); - - map = hyperdex_ds_allocate_map(arena); - - if (!map) - { - return hyperdex_java_out_of_memory(env); - } - - while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) - { - entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); - ERROR_CHECK(-1); - key = (*env)->CallObjectMethod(env, entry, _map_entry_getKey); - ERROR_CHECK(-1); - val = (*env)->CallObjectMethod(env, entry, _map_entry_getValue); - ERROR_CHECK(-1); - - if (hyperdex_java_client_convert_elem(env, key, map, - (elem_string_fptr) hyperdex_ds_map_insert_key_string, - (elem_int_fptr) hyperdex_ds_map_insert_key_int, - (elem_float_fptr) hyperdex_ds_map_insert_key_float) < 0) - { - return -1; - } - - if (hyperdex_java_client_convert_elem(env, val, map, - (elem_string_fptr) hyperdex_ds_map_insert_val_string, - (elem_int_fptr) hyperdex_ds_map_insert_val_int, - (elem_float_fptr) hyperdex_ds_map_insert_val_float) < 0) - { - return -1; - } - - (*env)->DeleteLocalRef(env, entry); - (*env)->DeleteLocalRef(env, key); - (*env)->DeleteLocalRef(env, val); - } - - if (hyperdex_ds_map_finalize(map, &error, value, value_sz, datatype) < 0) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - (*env)->DeleteLocalRef(env, it); - (*env)->DeleteLocalRef(env, set); - return 0; + struct hyperdex_ds_map *map; + enum hyperdex_ds_returncode error; + jobject set; + jobject it; + jobject entry; + jobject key; + jobject val; + set = (*env)->CallObjectMethod(env, x, _map_entrySet); + ERROR_CHECK(-1); + it = (*env)->CallObjectMethod(env, set, _set_iterator); + ERROR_CHECK(-1); + map = hyperdex_ds_allocate_map(arena); + if (!map) + { + return hyperdex_java_out_of_memory(env); + } + while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) + { + entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); + ERROR_CHECK(-1); + key = (*env)->CallObjectMethod(env, entry, _map_entry_getKey); + ERROR_CHECK(-1); + val = (*env)->CallObjectMethod(env, entry, _map_entry_getValue); + ERROR_CHECK(-1); + if (hyperdex_java_client_convert_elem(env, key, map, + (elem_string_fptr) hyperdex_ds_map_insert_key_string, + (elem_int_fptr) hyperdex_ds_map_insert_key_int, + (elem_float_fptr) hyperdex_ds_map_insert_key_float) < 0) + { + return -1; + } + if (hyperdex_java_client_convert_elem(env, val, map, + (elem_string_fptr) hyperdex_ds_map_insert_val_string, + (elem_int_fptr) hyperdex_ds_map_insert_val_int, + (elem_float_fptr) hyperdex_ds_map_insert_val_float) < 0) + { + return -1; + } + (*env)->DeleteLocalRef(env, entry); + (*env)->DeleteLocalRef(env, key); + (*env)->DeleteLocalRef(env, val); + } + if (hyperdex_ds_map_finalize(map, &error, value, value_sz, datatype) < 0) + { + hyperdex_java_out_of_memory(env); + return -1; + } + (*env)->DeleteLocalRef(env, it); + (*env)->DeleteLocalRef(env, set); + return 0; } static int -hyperdex_java_client_convert_type(JNIEnv* env, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_type(JNIEnv *env, + struct hyperdex_ds_arena *arena, jobject x, - const char** value, - size_t* value_sz, - enum hyperdatatype* datatype) + const char **value, + size_t *value_sz, + enum hyperdatatype *datatype) { - enum hyperdex_ds_returncode error; - int success; - const char* tmp_str; - size_t tmp_str_sz; - jbyte* tmp_bytes; - size_t tmp_bytes_sz; - int64_t tmp_l; - int32_t tmp_i; - double tmp_d; - - if (x == NULL) - { - *value = ""; - *value_sz = 0; - *datatype = HYPERDATATYPE_GENERIC; - return 0; - } - else if ((*env)->IsInstanceOf(env, x, _document) == JNI_TRUE) - { - x = (*env)->CallObjectMethod(env, x, _document_to_string); - tmp_str = (*env)->GetStringUTFChars(env, x, 0); - ERROR_CHECK(-1); - tmp_str_sz = (*env)->GetStringUTFLength(env, x); - ERROR_CHECK(-1); - success = hyperdex_ds_copy_string(arena, tmp_str, tmp_str_sz, - &error, value, value_sz); - (*env)->ReleaseStringUTFChars(env, x, tmp_str); - ERROR_CHECK(-1); - *datatype = HYPERDATATYPE_DOCUMENT; - - if (success < 0) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - return 0; - } - else if ((*env)->IsInstanceOf(env, x, _string) == JNI_TRUE) - { - tmp_str = (*env)->GetStringUTFChars(env, x, 0); - ERROR_CHECK(-1); - tmp_str_sz = (*env)->GetStringUTFLength(env, x); - ERROR_CHECK(-1); - success = hyperdex_ds_copy_string(arena, tmp_str, tmp_str_sz, - &error, value, value_sz); - (*env)->ReleaseStringUTFChars(env, x, tmp_str); - ERROR_CHECK(-1); - *datatype = HYPERDATATYPE_STRING; - - if (success < 0) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - return 0; - } - else if ((*env)->IsInstanceOf(env, x, _byte_string) == JNI_TRUE) - { - x = (*env)->CallObjectMethod(env, x, _byte_string_get); - tmp_bytes = (*env)->GetByteArrayElements(env, x, 0); - ERROR_CHECK(-1); - tmp_bytes_sz = (*env)->GetArrayLength(env, x); - ERROR_CHECK(-1); - success = hyperdex_ds_copy_string(arena, (const char*)tmp_bytes, tmp_bytes_sz, - &error, value, value_sz); - (*env)->ReleaseByteArrayElements(env, x, tmp_bytes, 0); - ERROR_CHECK(-1); - *datatype = HYPERDATATYPE_STRING; - - if (success < 0) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - return 0; - } - else if ((*env)->IsInstanceOf(env, x, _long) == JNI_TRUE) - { - tmp_l = (*env)->CallLongMethod(env, x, _long_longValue); - ERROR_CHECK(-1); - - if (hyperdex_ds_copy_int(arena, tmp_l, &error, value, value_sz) < 0) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - *datatype = HYPERDATATYPE_INT64; - return 0; - } - else if ((*env)->IsInstanceOf(env, x, _integer) == JNI_TRUE) - { - tmp_i = (*env)->CallIntMethod(env, x, _integer_intValue); - ERROR_CHECK(-1); - - if (hyperdex_ds_copy_int(arena, tmp_i, &error, value, value_sz) < 0) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - *datatype = HYPERDATATYPE_INT64; - return 0; - } - else if ((*env)->IsInstanceOf(env, x, _double) == JNI_TRUE) - { - tmp_d = (*env)->CallDoubleMethod(env, x, _double_doubleValue); - ERROR_CHECK(-1); - - if (hyperdex_ds_copy_float(arena, tmp_d, &error, value, value_sz) < 0) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - *datatype = HYPERDATATYPE_FLOAT; - return 0; - } - else if ((*env)->IsInstanceOf(env, x, _list) == JNI_TRUE) - { - return hyperdex_java_client_convert_list(env, arena, x, - value, value_sz, datatype); - } - else if ((*env)->IsInstanceOf(env, x, _set) == JNI_TRUE) - { - return hyperdex_java_client_convert_set(env, arena, x, - value, value_sz, datatype); - } - else if ((*env)->IsInstanceOf(env, x, _map) == JNI_TRUE) - { - return hyperdex_java_client_convert_map(env, arena, x, - value, value_sz, datatype); - } - else - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_WRONGTYPE, - "Cannot convert unknown type to a HyperDex type"); - return -1; - } + enum hyperdex_ds_returncode error; + int success; + const char *tmp_str; + size_t tmp_str_sz; + jbyte *tmp_bytes; + size_t tmp_bytes_sz; + int64_t tmp_l; + int32_t tmp_i; + double tmp_d; + if (x == NULL) + { + *value = ""; + *value_sz = 0; + *datatype = HYPERDATATYPE_GENERIC; + return 0; + } + else if ((*env)->IsInstanceOf(env, x, _document) == JNI_TRUE) + { + x = (*env)->CallObjectMethod(env, x, _document_to_string); + tmp_str = (*env)->GetStringUTFChars(env, x, 0); + ERROR_CHECK(-1); + tmp_str_sz = (*env)->GetStringUTFLength(env, x); + ERROR_CHECK(-1); + success = hyperdex_ds_copy_string(arena, tmp_str, tmp_str_sz, + &error, value, value_sz); + (*env)->ReleaseStringUTFChars(env, x, tmp_str); + ERROR_CHECK(-1); + *datatype = HYPERDATATYPE_DOCUMENT; + if (success < 0) + { + hyperdex_java_out_of_memory(env); + return -1; + } + return 0; + } + else if ((*env)->IsInstanceOf(env, x, _string) == JNI_TRUE) + { + tmp_str = (*env)->GetStringUTFChars(env, x, 0); + ERROR_CHECK(-1); + tmp_str_sz = (*env)->GetStringUTFLength(env, x); + ERROR_CHECK(-1); + success = hyperdex_ds_copy_string(arena, tmp_str, tmp_str_sz, + &error, value, value_sz); + (*env)->ReleaseStringUTFChars(env, x, tmp_str); + ERROR_CHECK(-1); + *datatype = HYPERDATATYPE_STRING; + if (success < 0) + { + hyperdex_java_out_of_memory(env); + return -1; + } + return 0; + } + else if ((*env)->IsInstanceOf(env, x, _byte_string) == JNI_TRUE) + { + x = (*env)->CallObjectMethod(env, x, _byte_string_get); + tmp_bytes = (*env)->GetByteArrayElements(env, x, 0); + ERROR_CHECK(-1); + tmp_bytes_sz = (*env)->GetArrayLength(env, x); + ERROR_CHECK(-1); + success = hyperdex_ds_copy_string(arena, (const char *)tmp_bytes, tmp_bytes_sz, + &error, value, value_sz); + (*env)->ReleaseByteArrayElements(env, x, tmp_bytes, 0); + ERROR_CHECK(-1); + *datatype = HYPERDATATYPE_STRING; + if (success < 0) + { + hyperdex_java_out_of_memory(env); + return -1; + } + return 0; + } + else if ((*env)->IsInstanceOf(env, x, _long) == JNI_TRUE) + { + tmp_l = (*env)->CallLongMethod(env, x, _long_longValue); + ERROR_CHECK(-1); + if (hyperdex_ds_copy_int(arena, tmp_l, &error, value, value_sz) < 0) + { + hyperdex_java_out_of_memory(env); + return -1; + } + *datatype = HYPERDATATYPE_INT64; + return 0; + } + else if ((*env)->IsInstanceOf(env, x, _integer) == JNI_TRUE) + { + tmp_i = (*env)->CallIntMethod(env, x, _integer_intValue); + ERROR_CHECK(-1); + if (hyperdex_ds_copy_int(arena, tmp_i, &error, value, value_sz) < 0) + { + hyperdex_java_out_of_memory(env); + return -1; + } + *datatype = HYPERDATATYPE_INT64; + return 0; + } + else if ((*env)->IsInstanceOf(env, x, _double) == JNI_TRUE) + { + tmp_d = (*env)->CallDoubleMethod(env, x, _double_doubleValue); + ERROR_CHECK(-1); + if (hyperdex_ds_copy_float(arena, tmp_d, &error, value, value_sz) < 0) + { + hyperdex_java_out_of_memory(env); + return -1; + } + *datatype = HYPERDATATYPE_FLOAT; + return 0; + } + else if ((*env)->IsInstanceOf(env, x, _list) == JNI_TRUE) + { + return hyperdex_java_client_convert_list(env, arena, x, + value, value_sz, datatype); + } + else if ((*env)->IsInstanceOf(env, x, _set) == JNI_TRUE) + { + return hyperdex_java_client_convert_set(env, arena, x, + value, value_sz, datatype); + } + else if ((*env)->IsInstanceOf(env, x, _map) == JNI_TRUE) + { + return hyperdex_java_client_convert_map(env, arena, x, + value, value_sz, datatype); + } + else + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_WRONGTYPE, + "Cannot convert unknown type to a HyperDex type"); + return -1; + } } int -hyperdex_java_client_convert_key(JNIEnv* env, jobject client, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_key(JNIEnv *env, jobject client, + struct hyperdex_ds_arena *arena, jobject x, - const char** key, - size_t* key_sz) + const char **key, + size_t *key_sz) { - enum hyperdatatype datatype; - (void)client; - return hyperdex_java_client_convert_type(env, arena, x, key, key_sz, &datatype); + enum hyperdatatype datatype; + (void)client; + return hyperdex_java_client_convert_type(env, arena, x, key, key_sz, &datatype); } static int -hyperdex_java_client_convert_limit(JNIEnv* env, jobject client, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_limit(JNIEnv *env, jobject client, + struct hyperdex_ds_arena *arena, jint x, - uint64_t* limit) + uint64_t *limit) { - *limit = x; - (void)env; - (void)client; - (void)arena; - return 0; + *limit = x; + (void)env; + (void)client; + (void)arena; + return 0; } static int -hyperdex_java_client_convert_maxmin(JNIEnv* env, jobject client, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_maxmin(JNIEnv *env, jobject client, + struct hyperdex_ds_arena *arena, jboolean x, - int* maxmin) + int *maxmin) { - *maxmin = x == JNI_TRUE ? 1 : 0; - (void)env; - (void)client; - (void)arena; - return 0; + *maxmin = x == JNI_TRUE ? 1 : 0; + (void)env; + (void)client; + (void)arena; + return 0; } static int -hyperdex_java_client_convert_mapattributes(JNIEnv* env, jobject client, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_mapattributes(JNIEnv *env, jobject client, + struct hyperdex_ds_arena *arena, jobject x, - const struct hyperdex_client_map_attribute** _mapattrs, - size_t* _mapattrs_sz) + const struct hyperdex_client_map_attribute **_mapattrs, + size_t *_mapattrs_sz) { - jobject outer_set; - jobject outer_it; - jobject outer_entry; - jobject inner_map; - jobject inner_set; - jobject inner_it; - jobject inner_entry; - jobject attr; - const char* attr_cstr; - jobject key; - jobject val; - struct hyperdex_client_map_attribute* mapattrs = NULL; - size_t mapattrs_sz = 0; - size_t mapattrs_idx = 0; - - outer_set = (*env)->CallObjectMethod(env, x, _map_entrySet); - ERROR_CHECK(-1); - outer_it = (*env)->CallObjectMethod(env, outer_set, _set_iterator); - ERROR_CHECK(-1); - - while ((*env)->CallBooleanMethod(env, outer_it, _java_iterator_hasNext) == JNI_TRUE) - { - outer_entry = (*env)->CallObjectMethod(env, outer_it, _java_iterator_next); - ERROR_CHECK(-1); - inner_map = (*env)->CallObjectMethod(env, outer_entry, _map_entry_getValue); - ERROR_CHECK(-1); - mapattrs_sz += (*env)->CallIntMethod(env, inner_map, _map_size); - ERROR_CHECK(-1); - (*env)->DeleteLocalRef(env, outer_entry); - ERROR_CHECK(-1); - (*env)->DeleteLocalRef(env, inner_map); - ERROR_CHECK(-1); - } - - mapattrs = hyperdex_ds_allocate_map_attribute(arena, mapattrs_sz); - - if (!mapattrs) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - *_mapattrs = mapattrs; - *_mapattrs_sz = mapattrs_sz; - mapattrs_idx = 0; - - (*env)->DeleteLocalRef(env, outer_it); - ERROR_CHECK(-1); - outer_it = (*env)->CallObjectMethod(env, outer_set, _set_iterator); - ERROR_CHECK(-1); - - while ((*env)->CallBooleanMethod(env, outer_it, _java_iterator_hasNext) == JNI_TRUE) - { - outer_entry = (*env)->CallObjectMethod(env, outer_it, _java_iterator_next); - ERROR_CHECK(-1); - attr = (*env)->CallObjectMethod(env, outer_entry, _map_entry_getKey); - ERROR_CHECK(-1); - inner_map = (*env)->CallObjectMethod(env, outer_entry, _map_entry_getValue); - ERROR_CHECK(-1); - inner_set = (*env)->CallObjectMethod(env, inner_map, _map_entrySet); - ERROR_CHECK(-1); - inner_it = (*env)->CallObjectMethod(env, inner_set, _set_iterator); - ERROR_CHECK(-1); - attr_cstr = hyperdex_java_client_convert_cstring(env, arena, attr); - - if (!attr_cstr) - { - return -1; - } - - while ((*env)->CallBooleanMethod(env, inner_it, _java_iterator_hasNext) == JNI_TRUE) - { - assert(mapattrs_idx < mapattrs_sz); - inner_entry = (*env)->CallObjectMethod(env, inner_it, _java_iterator_next); - ERROR_CHECK(-1); - key = (*env)->CallObjectMethod(env, inner_entry, _map_entry_getKey); - ERROR_CHECK(-1); - val = (*env)->CallObjectMethod(env, inner_entry, _map_entry_getValue); - ERROR_CHECK(-1); - mapattrs[mapattrs_idx].attr = attr_cstr; - - if (hyperdex_java_client_convert_type(env, arena, key, - &mapattrs[mapattrs_idx].map_key, - &mapattrs[mapattrs_idx].map_key_sz, - &mapattrs[mapattrs_idx].map_key_datatype) < 0) - { - return -1; - } - - if (hyperdex_java_client_convert_type(env, arena, val, - &mapattrs[mapattrs_idx].value, - &mapattrs[mapattrs_idx].value_sz, - &mapattrs[mapattrs_idx].value_datatype) < 0) - { - return -1; - } - - ++mapattrs_idx; - (*env)->DeleteLocalRef(env, val); - ERROR_CHECK(-1); - (*env)->DeleteLocalRef(env, key); - ERROR_CHECK(-1); - (*env)->DeleteLocalRef(env, inner_entry); - ERROR_CHECK(-1); - } - - (*env)->DeleteLocalRef(env, inner_it); - ERROR_CHECK(-1); - (*env)->DeleteLocalRef(env, inner_set); - ERROR_CHECK(-1); - (*env)->DeleteLocalRef(env, inner_map); - ERROR_CHECK(-1); - (*env)->DeleteLocalRef(env, attr); - ERROR_CHECK(-1); - (*env)->DeleteLocalRef(env, outer_entry); - ERROR_CHECK(-1); - } - - (void)client; - return 0; + jobject outer_set; + jobject outer_it; + jobject outer_entry; + jobject inner_map; + jobject inner_set; + jobject inner_it; + jobject inner_entry; + jobject attr; + const char *attr_cstr; + jobject key; + jobject val; + struct hyperdex_client_map_attribute *mapattrs = NULL; + size_t mapattrs_sz = 0; + size_t mapattrs_idx = 0; + outer_set = (*env)->CallObjectMethod(env, x, _map_entrySet); + ERROR_CHECK(-1); + outer_it = (*env)->CallObjectMethod(env, outer_set, _set_iterator); + ERROR_CHECK(-1); + while ((*env)->CallBooleanMethod(env, outer_it, _java_iterator_hasNext) == JNI_TRUE) + { + outer_entry = (*env)->CallObjectMethod(env, outer_it, _java_iterator_next); + ERROR_CHECK(-1); + inner_map = (*env)->CallObjectMethod(env, outer_entry, _map_entry_getValue); + ERROR_CHECK(-1); + mapattrs_sz += (*env)->CallIntMethod(env, inner_map, _map_size); + ERROR_CHECK(-1); + (*env)->DeleteLocalRef(env, outer_entry); + ERROR_CHECK(-1); + (*env)->DeleteLocalRef(env, inner_map); + ERROR_CHECK(-1); + } + mapattrs = hyperdex_ds_allocate_map_attribute(arena, mapattrs_sz); + if (!mapattrs) + { + hyperdex_java_out_of_memory(env); + return -1; + } + *_mapattrs = mapattrs; + *_mapattrs_sz = mapattrs_sz; + mapattrs_idx = 0; + (*env)->DeleteLocalRef(env, outer_it); + ERROR_CHECK(-1); + outer_it = (*env)->CallObjectMethod(env, outer_set, _set_iterator); + ERROR_CHECK(-1); + while ((*env)->CallBooleanMethod(env, outer_it, _java_iterator_hasNext) == JNI_TRUE) + { + outer_entry = (*env)->CallObjectMethod(env, outer_it, _java_iterator_next); + ERROR_CHECK(-1); + attr = (*env)->CallObjectMethod(env, outer_entry, _map_entry_getKey); + ERROR_CHECK(-1); + inner_map = (*env)->CallObjectMethod(env, outer_entry, _map_entry_getValue); + ERROR_CHECK(-1); + inner_set = (*env)->CallObjectMethod(env, inner_map, _map_entrySet); + ERROR_CHECK(-1); + inner_it = (*env)->CallObjectMethod(env, inner_set, _set_iterator); + ERROR_CHECK(-1); + attr_cstr = hyperdex_java_client_convert_cstring(env, arena, attr); + if (!attr_cstr) + { + return -1; + } + while ((*env)->CallBooleanMethod(env, inner_it, _java_iterator_hasNext) == JNI_TRUE) + { + assert(mapattrs_idx < mapattrs_sz); + inner_entry = (*env)->CallObjectMethod(env, inner_it, _java_iterator_next); + ERROR_CHECK(-1); + key = (*env)->CallObjectMethod(env, inner_entry, _map_entry_getKey); + ERROR_CHECK(-1); + val = (*env)->CallObjectMethod(env, inner_entry, _map_entry_getValue); + ERROR_CHECK(-1); + mapattrs[mapattrs_idx].attr = attr_cstr; + if (hyperdex_java_client_convert_type(env, arena, key, + &mapattrs[mapattrs_idx].map_key, + &mapattrs[mapattrs_idx].map_key_sz, + &mapattrs[mapattrs_idx].map_key_datatype) < 0) + { + return -1; + } + if (hyperdex_java_client_convert_type(env, arena, val, + &mapattrs[mapattrs_idx].value, + &mapattrs[mapattrs_idx].value_sz, + &mapattrs[mapattrs_idx].value_datatype) < 0) + { + return -1; + } + ++mapattrs_idx; + (*env)->DeleteLocalRef(env, val); + ERROR_CHECK(-1); + (*env)->DeleteLocalRef(env, key); + ERROR_CHECK(-1); + (*env)->DeleteLocalRef(env, inner_entry); + ERROR_CHECK(-1); + } + (*env)->DeleteLocalRef(env, inner_it); + ERROR_CHECK(-1); + (*env)->DeleteLocalRef(env, inner_set); + ERROR_CHECK(-1); + (*env)->DeleteLocalRef(env, inner_map); + ERROR_CHECK(-1); + (*env)->DeleteLocalRef(env, attr); + ERROR_CHECK(-1); + (*env)->DeleteLocalRef(env, outer_entry); + ERROR_CHECK(-1); + } + (void)client; + return 0; } static ssize_t -hyperdex_java_client_estimate_predicate_size(JNIEnv* env, jobject x) +hyperdex_java_client_estimate_predicate_size(JNIEnv *env, jobject x) { - jobject it; - jobject entry; - size_t sum = 0; - - if ((*env)->IsInstanceOf(env, x, _predicate) == JNI_TRUE) - { - sum = (*env)->CallLongMethod(env, x, _predicate_checksSize); - ERROR_CHECK(-1); - return sum; - } - else if ((*env)->IsInstanceOf(env, x, _list) == JNI_TRUE && - (*env)->IsInstanceOf(env, - (*env)->CallObjectMethod(env, x, _list_get, 0), _predicate) == JNI_TRUE) - { - it = (*env)->CallObjectMethod(env, x, _list_iterator); - ERROR_CHECK(-1); - - while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) - { - entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); - ERROR_CHECK(-1); - - if ((*env)->IsInstanceOf(env, entry, _predicate) != JNI_TRUE) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_WRONGTYPE, - "Cannot convert unknown type to a HyperDex predicate"); - return -1; - } - - ERROR_CHECK(-1); - sum += (*env)->CallLongMethod(env, x, _predicate_checksSize); - ERROR_CHECK(-1); - } - - return sum; - } - else - { - ERROR_CHECK(-1); - return 1; - } + jobject it; + jobject entry; + size_t sum = 0; + if ((*env)->IsInstanceOf(env, x, _predicate) == JNI_TRUE) + { + sum = (*env)->CallLongMethod(env, x, _predicate_checksSize); + ERROR_CHECK(-1); + return sum; + } + else if ((*env)->IsInstanceOf(env, x, _list) == JNI_TRUE && + (*env)->IsInstanceOf(env, + (*env)->CallObjectMethod(env, x, _list_get, 0), _predicate) == JNI_TRUE) + { + it = (*env)->CallObjectMethod(env, x, _list_iterator); + ERROR_CHECK(-1); + while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) + { + entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); + ERROR_CHECK(-1); + if ((*env)->IsInstanceOf(env, entry, _predicate) != JNI_TRUE) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_WRONGTYPE, + "Cannot convert unknown type to a HyperDex predicate"); + return -1; + } + ERROR_CHECK(-1); + sum += (*env)->CallLongMethod(env, x, _predicate_checksSize); + ERROR_CHECK(-1); + } + return sum; + } + else + { + ERROR_CHECK(-1); + return 1; + } } static ssize_t -hyperdex_java_client_convert_predicate(JNIEnv* env, - struct hyperdex_ds_arena* arena, - const char* attr, +hyperdex_java_client_convert_predicate(JNIEnv *env, + struct hyperdex_ds_arena *arena, + const char *attr, jobject x, - struct hyperdex_client_attribute_check* checks, + struct hyperdex_client_attribute_check *checks, size_t checks_idx) { - jobject it; - jobject entry; - jlong tmp; - ssize_t i; - - if ((*env)->IsInstanceOf(env, x, _predicate) == JNI_TRUE) - { - tmp = (*env)->CallLongMethod(env, x, _predicate_convertChecks, arena, checks, checks_idx); - ERROR_CHECK(-1); - - for (i = checks_idx; i < tmp; ++i) - { - checks[i].attr = attr; - } - - return tmp; - } - else if ((*env)->IsInstanceOf(env, x, _list) == JNI_TRUE && - (*env)->IsInstanceOf(env, - (*env)->CallObjectMethod(env, x, _list_get, 0), _predicate) == JNI_TRUE) - { - it = (*env)->CallObjectMethod(env, x, _list_iterator); - ERROR_CHECK(-1); - tmp = checks_idx; - - while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext)) - { - entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); - ERROR_CHECK(-1); - tmp = (*env)->CallLongMethod(env, entry, _predicate_convertChecks, arena, checks, tmp); - ERROR_CHECK(-1); - } - - for (i = checks_idx; i < tmp; ++i) - { - checks[i].attr = attr; - } - - return tmp; - } - else - { - checks[checks_idx].attr = attr; - checks[checks_idx].predicate = HYPERPREDICATE_EQUALS; - - if (hyperdex_java_client_convert_type(env, arena, x, - &checks[checks_idx].value, - &checks[checks_idx].value_sz, - &checks[checks_idx].datatype) < 0) - { - return -1; - } - - return checks_idx + 1; - } + jobject it; + jobject entry; + jlong tmp; + ssize_t i; + if ((*env)->IsInstanceOf(env, x, _predicate) == JNI_TRUE) + { + tmp = (*env)->CallLongMethod(env, x, _predicate_convertChecks, arena, checks, checks_idx); + ERROR_CHECK(-1); + for (i = checks_idx; i < tmp; ++i) + { + checks[i].attr = attr; + } + return tmp; + } + else if ((*env)->IsInstanceOf(env, x, _list) == JNI_TRUE && + (*env)->IsInstanceOf(env, + (*env)->CallObjectMethod(env, x, _list_get, 0), _predicate) == JNI_TRUE) + { + it = (*env)->CallObjectMethod(env, x, _list_iterator); + ERROR_CHECK(-1); + tmp = checks_idx; + while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext)) + { + entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); + ERROR_CHECK(-1); + tmp = (*env)->CallLongMethod(env, entry, _predicate_convertChecks, arena, checks, tmp); + ERROR_CHECK(-1); + } + for (i = checks_idx; i < tmp; ++i) + { + checks[i].attr = attr; + } + return tmp; + } + else + { + checks[checks_idx].attr = attr; + checks[checks_idx].predicate = HYPERPREDICATE_EQUALS; + if (hyperdex_java_client_convert_type(env, arena, x, + &checks[checks_idx].value, + &checks[checks_idx].value_sz, + &checks[checks_idx].datatype) < 0) + { + return -1; + } + return checks_idx + 1; + } } int -hyperdex_java_client_convert_predicates(JNIEnv* env, jobject client, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_predicates(JNIEnv *env, jobject client, + struct hyperdex_ds_arena *arena, jobject x, - const struct hyperdex_client_attribute_check** _checks, - size_t* _checks_sz) + const struct hyperdex_client_attribute_check **_checks, + size_t *_checks_sz) { - jobject set; - jobject it; - jobject entry; - jobject key; - jobject val; - const char* attr; - struct hyperdex_client_attribute_check* checks = NULL; - size_t checks_sz = 0; - size_t checks_idx = 0; - ssize_t these_checks = 0; - - set = (*env)->CallObjectMethod(env, x, _map_entrySet); - ERROR_CHECK(-1); - it = (*env)->CallObjectMethod(env, set, _set_iterator); - ERROR_CHECK(-1); - - while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) - { - entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); - ERROR_CHECK(-1); - val = (*env)->CallObjectMethod(env, entry, _map_entry_getValue); - ERROR_CHECK(-1); - these_checks = hyperdex_java_client_estimate_predicate_size(env, val); - - if (these_checks < 0) - { - return -1; - } - - checks_sz += these_checks; - } - - (*env)->DeleteLocalRef(env, it); - ERROR_CHECK(-1); - it = (*env)->CallObjectMethod(env, set, _set_iterator); - ERROR_CHECK(-1); - - checks = hyperdex_ds_allocate_attribute_check(arena, checks_sz); - - if (!checks) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - *_checks = checks; - *_checks_sz = checks_sz; - - while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) - { - entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); - ERROR_CHECK(-1); - key = (*env)->CallObjectMethod(env, entry, _map_entry_getKey); - ERROR_CHECK(-1); - val = (*env)->CallObjectMethod(env, entry, _map_entry_getValue); - ERROR_CHECK(-1); - attr = hyperdex_java_client_convert_cstring(env, arena, key); - - if (!attr) - { - return -1; - } - - checks_idx = hyperdex_java_client_convert_predicate(env, arena, attr, val, checks, checks_idx); - } - - (*env)->DeleteLocalRef(env, it); - ERROR_CHECK(-1); - (*env)->DeleteLocalRef(env, set); - ERROR_CHECK(-1); - (void)client; - return 0; + jobject set; + jobject it; + jobject entry; + jobject key; + jobject val; + const char *attr; + struct hyperdex_client_attribute_check *checks = NULL; + size_t checks_sz = 0; + size_t checks_idx = 0; + ssize_t these_checks = 0; + set = (*env)->CallObjectMethod(env, x, _map_entrySet); + ERROR_CHECK(-1); + it = (*env)->CallObjectMethod(env, set, _set_iterator); + ERROR_CHECK(-1); + while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) + { + entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); + ERROR_CHECK(-1); + val = (*env)->CallObjectMethod(env, entry, _map_entry_getValue); + ERROR_CHECK(-1); + these_checks = hyperdex_java_client_estimate_predicate_size(env, val); + if (these_checks < 0) + { + return -1; + } + checks_sz += these_checks; + } + (*env)->DeleteLocalRef(env, it); + ERROR_CHECK(-1); + it = (*env)->CallObjectMethod(env, set, _set_iterator); + ERROR_CHECK(-1); + checks = hyperdex_ds_allocate_attribute_check(arena, checks_sz); + if (!checks) + { + hyperdex_java_out_of_memory(env); + return -1; + } + *_checks = checks; + *_checks_sz = checks_sz; + while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) + { + entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); + ERROR_CHECK(-1); + key = (*env)->CallObjectMethod(env, entry, _map_entry_getKey); + ERROR_CHECK(-1); + val = (*env)->CallObjectMethod(env, entry, _map_entry_getValue); + ERROR_CHECK(-1); + attr = hyperdex_java_client_convert_cstring(env, arena, key); + if (!attr) + { + return -1; + } + checks_idx = hyperdex_java_client_convert_predicate(env, arena, attr, val, checks, checks_idx); + } + (*env)->DeleteLocalRef(env, it); + ERROR_CHECK(-1); + (*env)->DeleteLocalRef(env, set); + ERROR_CHECK(-1); + (void)client; + return 0; } static int -hyperdex_java_client_convert_attributenames(JNIEnv* env, jobject client, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_attributenames(JNIEnv *env, jobject client, + struct hyperdex_ds_arena *arena, jobject attrs, - const char*** names, size_t* names_sz) + const char *** names, size_t *names_sz) { - size_t idx = 0; - jobject entry; - jobject it = (*env)->CallObjectMethod(env, attrs, _list_iterator); - ERROR_CHECK(-1); - *names_sz = (*env)->CallIntMethod(env, attrs, _list_size); - ERROR_CHECK(-1); - *names = hyperdex_ds_malloc(arena, sizeof(char*) * (*names_sz)); - - if (!(*names)) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - idx = 0; - - while ((*env)->CallIntMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) - { - entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); - ERROR_CHECK(-1); - (*names)[idx] = hyperdex_java_client_convert_cstring(env, arena, entry); - - if (!(*names)[idx]) - { - return -1; - } - - (*env)->DeleteLocalRef(env, entry); - ++idx; - } - - (*env)->DeleteLocalRef(env, it); - (void) client; - return 0; + size_t idx = 0; + jobject entry; + jobject it = (*env)->CallObjectMethod(env, attrs, _list_iterator); + ERROR_CHECK(-1); + *names_sz = (*env)->CallIntMethod(env, attrs, _list_size); + ERROR_CHECK(-1); + *names = hyperdex_ds_malloc(arena, sizeof(char *) * (*names_sz)); + if (!(*names)) + { + hyperdex_java_out_of_memory(env); + return -1; + } + idx = 0; + while ((*env)->CallIntMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) + { + entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); + ERROR_CHECK(-1); + (*names)[idx] = hyperdex_java_client_convert_cstring(env, arena, entry); + if (!(*names)[idx]) + { + return -1; + } + (*env)->DeleteLocalRef(env, entry); + ++idx; + } + (*env)->DeleteLocalRef(env, it); + (void) client; + return 0; } static int -hyperdex_java_client_convert_sortby(JNIEnv* env, jobject client, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_sortby(JNIEnv *env, jobject client, + struct hyperdex_ds_arena *arena, jstring str, - const char** sortby) + const char **sortby) { - (void)client; - *sortby = hyperdex_java_client_convert_cstring(env, arena, str); - return *sortby != NULL ? 0 : -1; + (void)client; + *sortby = hyperdex_java_client_convert_cstring(env, arena, str); + return *sortby != NULL ? 0 : -1; } static int -hyperdex_java_client_convert_sum_key(JNIEnv* env, jobject client, - struct hyperdex_ds_arena* arena, - jstring str, - const char** sum_key) +hyperdex_java_client_convert_sum_key(JNIEnv *env, jobject client, + struct hyperdex_ds_arena *arena, + jstring str, + const char **sum_key) { - (void)client; - *sum_key = hyperdex_java_client_convert_cstring(env, arena, str); - return *sum_key != NULL ? 0 : -1; + (void)client; + *sum_key = hyperdex_java_client_convert_cstring(env, arena, str); + return *sum_key != NULL ? 0 : -1; } static int -hyperdex_java_client_convert_spacename(JNIEnv* env, jobject client, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_spacename(JNIEnv *env, jobject client, + struct hyperdex_ds_arena *arena, jstring str, - const char** spacename) + const char **spacename) { - (void)client; - *spacename = hyperdex_java_client_convert_cstring(env, arena, str); - return *spacename != NULL ? 0 : -1; + (void)client; + *spacename = hyperdex_java_client_convert_cstring(env, arena, str); + return *spacename != NULL ? 0 : -1; } /********************************** C -> Java *********************************/ #define BUILD_STRING(OUT, X, X_SZ) \ - do { \ - tmp_array = (*env)->NewByteArray(env, X_SZ); \ - ERROR_CHECK(0); \ - (*env)->SetByteArrayRegion(env, tmp_array, 0, X_SZ, (const jbyte*)X); \ - ERROR_CHECK(0); \ - OUT = (*env)->NewObject(env, _byte_string, _byte_string_init, tmp_array); \ - ERROR_CHECK(0); \ - } while (0) + do { \ + tmp_array = (*env)->NewByteArray(env, X_SZ); \ + ERROR_CHECK(0); \ + (*env)->SetByteArrayRegion(env, tmp_array, 0, X_SZ, (const jbyte*)X); \ + ERROR_CHECK(0); \ + OUT = (*env)->NewObject(env, _byte_string, _byte_string_init, tmp_array); \ + ERROR_CHECK(0); \ + } while (0) #define BUILD_INT(OUT, X) \ - do { \ - OUT = (*env)->NewObject(env, _long, _long_init, X); \ - ERROR_CHECK(0); \ - } while (0) + do { \ + OUT = (*env)->NewObject(env, _long, _long_init, X); \ + ERROR_CHECK(0); \ + } while (0) #define BUILD_FLOAT(OUT, X) \ - do { \ - OUT = (*env)->NewObject(env, _double, _double_init, X); \ - ERROR_CHECK(0); \ - } while (0) + do { \ + OUT = (*env)->NewObject(env, _double, _double_init, X); \ + ERROR_CHECK(0); \ + } while (0) static jobject -hyperdex_java_client_build_attribute(JNIEnv* env, - const struct hyperdex_client_attribute* attr) +hyperdex_java_client_build_attribute(JNIEnv *env, + const struct hyperdex_client_attribute *attr) { - struct hyperdex_ds_iterator iter; - jbyteArray tmp_array; - const char* tmp_str = NULL; - size_t tmp_str_sz = 0; - const char* tmp_str2 = NULL; - size_t tmp_str2_sz = 0; - int64_t tmp_i = 0; - int64_t tmp_i2 = 0; - double tmp_d = 0; - double tmp_d2 = 0; - int result = 0; - jobject ret = NULL; - jobject tmp = NULL; - jobject tmp2 = NULL; - - switch (attr->datatype) - { - case HYPERDATATYPE_STRING: - BUILD_STRING(tmp, attr->value, attr->value_sz); - return tmp; - case HYPERDATATYPE_INT64: - if (hyperdex_ds_unpack_int(attr->value, attr->value_sz, &tmp_i) < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed int"); - return 0; - } - - BUILD_INT(tmp, tmp_i); - return tmp; - case HYPERDATATYPE_FLOAT: - if (hyperdex_ds_unpack_float(attr->value, attr->value_sz, &tmp_d) < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed float"); - return 0; - } - - BUILD_FLOAT(tmp, tmp_d); - return tmp; - case HYPERDATATYPE_DOCUMENT: - BUILD_STRING(tmp, attr->value, attr->value_sz); - // Build document from string - return (*env)->NewObject(env, _document, _document_init, tmp); - case HYPERDATATYPE_LIST_STRING: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _array_list, _array_list_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_list_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) - { - BUILD_STRING(tmp, tmp_str, tmp_str_sz); - (*env)->CallBooleanMethod(env, ret, _array_list_add, tmp); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed list(string)"); - return 0; - } - - return ret; - case HYPERDATATYPE_LIST_INT64: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _array_list, _array_list_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_list_int_next(&iter, &tmp_i)) > 0) - { - BUILD_INT(tmp, tmp_i); - (*env)->CallBooleanMethod(env, ret, _array_list_add, tmp); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed list(int)"); - return 0; - } - - return ret; - case HYPERDATATYPE_LIST_FLOAT: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _array_list, _array_list_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_list_float_next(&iter, &tmp_d)) > 0) - { - BUILD_FLOAT(tmp, tmp_d); - (*env)->CallBooleanMethod(env, ret, _array_list_add, tmp); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed list(float)"); - return 0; - } - - return ret; - case HYPERDATATYPE_SET_STRING: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _hash_set, _hash_set_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_set_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) - { - BUILD_STRING(tmp, tmp_str, tmp_str_sz); - (*env)->CallBooleanMethod(env, ret, _hash_set_add, tmp); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed set(string)"); - return 0; - } - - return ret; - case HYPERDATATYPE_SET_INT64: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _hash_set, _hash_set_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_set_int_next(&iter, &tmp_i)) > 0) - { - BUILD_INT(tmp, tmp_i); - (*env)->CallObjectMethod(env, ret, _hash_set_add, tmp); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed set(int)"); - return 0; - } - - return ret; - case HYPERDATATYPE_SET_FLOAT: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _hash_set, _hash_set_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_set_float_next(&iter, &tmp_d)) > 0) - { - BUILD_FLOAT(tmp, tmp_d); - (*env)->CallObjectMethod(env, ret, _hash_set_add, tmp); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed set(float)"); - return 0; - } - - return ret; - case HYPERDATATYPE_MAP_STRING_STRING: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _hash_map, _hash_map_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_map_string_string_next(&iter, &tmp_str, &tmp_str_sz, &tmp_str2, &tmp_str2_sz)) > 0) - { - BUILD_STRING(tmp, tmp_str, tmp_str_sz); - BUILD_STRING(tmp2, tmp_str2, tmp_str2_sz); - (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(string, string)"); - return 0; - } - - return ret; - case HYPERDATATYPE_MAP_STRING_INT64: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _hash_map, _hash_map_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_map_string_int_next(&iter, &tmp_str, &tmp_str_sz, &tmp_i)) > 0) - { - BUILD_STRING(tmp, tmp_str, tmp_str_sz); - BUILD_INT(tmp2, tmp_i); - (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(string, int)"); - return 0; - } - - return ret; - case HYPERDATATYPE_MAP_STRING_FLOAT: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _hash_map, _hash_map_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_map_string_float_next(&iter, &tmp_str, &tmp_str_sz, &tmp_d)) > 0) - { - BUILD_STRING(tmp, tmp_str, tmp_str_sz); - BUILD_FLOAT(tmp2, tmp_d); - (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(string, float)"); - return 0; - } - - return ret; - case HYPERDATATYPE_MAP_INT64_STRING: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _hash_map, _hash_map_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_map_int_string_next(&iter, &tmp_i, &tmp_str, &tmp_str_sz)) > 0) - { - BUILD_INT(tmp, tmp_i); - BUILD_STRING(tmp2, tmp_str, tmp_str_sz); - (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(int, string)"); - return 0; - } - - return ret; - case HYPERDATATYPE_MAP_INT64_INT64: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _hash_map, _hash_map_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_map_int_int_next(&iter, &tmp_i, &tmp_i2)) > 0) - { - BUILD_INT(tmp, tmp_i); - BUILD_INT(tmp2, tmp_i2); - (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(int, int)"); - return 0; - } - - return ret; - case HYPERDATATYPE_MAP_INT64_FLOAT: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _hash_map, _hash_map_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_map_int_float_next(&iter, &tmp_i, &tmp_d)) > 0) - { - BUILD_INT(tmp, tmp_i); - BUILD_FLOAT(tmp2, tmp_d); - (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(int, float)"); - return 0; - } - - return ret; - case HYPERDATATYPE_MAP_FLOAT_STRING: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _hash_map, _hash_map_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_map_float_string_next(&iter, &tmp_d, &tmp_str, &tmp_str_sz)) > 0) - { - BUILD_FLOAT(tmp, tmp_d); - BUILD_STRING(tmp2, tmp_str, tmp_str_sz); - (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(float, string)"); - return 0; - } - - return ret; - case HYPERDATATYPE_MAP_FLOAT_INT64: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _hash_map, _hash_map_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_map_float_int_next(&iter, &tmp_d, &tmp_i)) > 0) - { - BUILD_FLOAT(tmp, tmp_d); - BUILD_INT(tmp2, tmp_i); - (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(float, int)"); - return 0; - } - - return ret; - case HYPERDATATYPE_MAP_FLOAT_FLOAT: - hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); - ret = (*env)->NewObject(env, _hash_map, _hash_map_init); - ERROR_CHECK(0); - - while ((result = hyperdex_ds_iterate_map_float_float_next(&iter, &tmp_d, &tmp_d2)) > 0) - { - BUILD_FLOAT(tmp, tmp_d); - BUILD_FLOAT(tmp2, tmp_d2); - (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); - ERROR_CHECK(0); - } - - if (result < 0) - { - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(float, float)"); - return 0; - } - - return ret; - case HYPERDATATYPE_GENERIC: - case HYPERDATATYPE_LIST_GENERIC: - case HYPERDATATYPE_SET_GENERIC: - case HYPERDATATYPE_MAP_GENERIC: - case HYPERDATATYPE_MAP_STRING_KEYONLY: - case HYPERDATATYPE_MAP_INT64_KEYONLY: - case HYPERDATATYPE_MAP_FLOAT_KEYONLY: - case HYPERDATATYPE_GARBAGE: - default: - hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed attributes"); - return 0; - } + struct hyperdex_ds_iterator iter; + jbyteArray tmp_array; + const char *tmp_str = NULL; + size_t tmp_str_sz = 0; + const char *tmp_str2 = NULL; + size_t tmp_str2_sz = 0; + int64_t tmp_i = 0; + int64_t tmp_i2 = 0; + double tmp_d = 0; + double tmp_d2 = 0; + int result = 0; + jobject ret = NULL; + jobject tmp = NULL; + jobject tmp2 = NULL; + switch (attr->datatype) + { + case HYPERDATATYPE_STRING: + BUILD_STRING(tmp, attr->value, attr->value_sz); + return tmp; + case HYPERDATATYPE_INT64: + if (hyperdex_ds_unpack_int(attr->value, attr->value_sz, &tmp_i) < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed int"); + return 0; + } + BUILD_INT(tmp, tmp_i); + return tmp; + case HYPERDATATYPE_FLOAT: + if (hyperdex_ds_unpack_float(attr->value, attr->value_sz, &tmp_d) < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed float"); + return 0; + } + BUILD_FLOAT(tmp, tmp_d); + return tmp; + case HYPERDATATYPE_DOCUMENT: + BUILD_STRING(tmp, attr->value, attr->value_sz); + // Build document from string + return (*env)->NewObject(env, _document, _document_init, tmp); + case HYPERDATATYPE_LIST_STRING: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _array_list, _array_list_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_list_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) + { + BUILD_STRING(tmp, tmp_str, tmp_str_sz); + (*env)->CallBooleanMethod(env, ret, _array_list_add, tmp); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed list(string)"); + return 0; + } + return ret; + case HYPERDATATYPE_LIST_INT64: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _array_list, _array_list_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_list_int_next(&iter, &tmp_i)) > 0) + { + BUILD_INT(tmp, tmp_i); + (*env)->CallBooleanMethod(env, ret, _array_list_add, tmp); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed list(int)"); + return 0; + } + return ret; + case HYPERDATATYPE_LIST_FLOAT: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _array_list, _array_list_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_list_float_next(&iter, &tmp_d)) > 0) + { + BUILD_FLOAT(tmp, tmp_d); + (*env)->CallBooleanMethod(env, ret, _array_list_add, tmp); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed list(float)"); + return 0; + } + return ret; + case HYPERDATATYPE_SET_STRING: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _hash_set, _hash_set_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_set_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) + { + BUILD_STRING(tmp, tmp_str, tmp_str_sz); + (*env)->CallBooleanMethod(env, ret, _hash_set_add, tmp); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed set(string)"); + return 0; + } + return ret; + case HYPERDATATYPE_SET_INT64: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _hash_set, _hash_set_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_set_int_next(&iter, &tmp_i)) > 0) + { + BUILD_INT(tmp, tmp_i); + (*env)->CallObjectMethod(env, ret, _hash_set_add, tmp); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed set(int)"); + return 0; + } + return ret; + case HYPERDATATYPE_SET_FLOAT: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _hash_set, _hash_set_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_set_float_next(&iter, &tmp_d)) > 0) + { + BUILD_FLOAT(tmp, tmp_d); + (*env)->CallObjectMethod(env, ret, _hash_set_add, tmp); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed set(float)"); + return 0; + } + return ret; + case HYPERDATATYPE_MAP_STRING_STRING: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _hash_map, _hash_map_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_map_string_string_next(&iter, &tmp_str, &tmp_str_sz, &tmp_str2, &tmp_str2_sz)) > 0) + { + BUILD_STRING(tmp, tmp_str, tmp_str_sz); + BUILD_STRING(tmp2, tmp_str2, tmp_str2_sz); + (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(string, string)"); + return 0; + } + return ret; + case HYPERDATATYPE_MAP_STRING_INT64: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _hash_map, _hash_map_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_map_string_int_next(&iter, &tmp_str, &tmp_str_sz, &tmp_i)) > 0) + { + BUILD_STRING(tmp, tmp_str, tmp_str_sz); + BUILD_INT(tmp2, tmp_i); + (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(string, int)"); + return 0; + } + return ret; + case HYPERDATATYPE_MAP_STRING_FLOAT: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _hash_map, _hash_map_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_map_string_float_next(&iter, &tmp_str, &tmp_str_sz, &tmp_d)) > 0) + { + BUILD_STRING(tmp, tmp_str, tmp_str_sz); + BUILD_FLOAT(tmp2, tmp_d); + (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(string, float)"); + return 0; + } + return ret; + case HYPERDATATYPE_MAP_INT64_STRING: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _hash_map, _hash_map_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_map_int_string_next(&iter, &tmp_i, &tmp_str, &tmp_str_sz)) > 0) + { + BUILD_INT(tmp, tmp_i); + BUILD_STRING(tmp2, tmp_str, tmp_str_sz); + (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(int, string)"); + return 0; + } + return ret; + case HYPERDATATYPE_MAP_INT64_INT64: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _hash_map, _hash_map_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_map_int_int_next(&iter, &tmp_i, &tmp_i2)) > 0) + { + BUILD_INT(tmp, tmp_i); + BUILD_INT(tmp2, tmp_i2); + (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(int, int)"); + return 0; + } + return ret; + case HYPERDATATYPE_MAP_INT64_FLOAT: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _hash_map, _hash_map_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_map_int_float_next(&iter, &tmp_i, &tmp_d)) > 0) + { + BUILD_INT(tmp, tmp_i); + BUILD_FLOAT(tmp2, tmp_d); + (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(int, float)"); + return 0; + } + return ret; + case HYPERDATATYPE_MAP_FLOAT_STRING: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _hash_map, _hash_map_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_map_float_string_next(&iter, &tmp_d, &tmp_str, &tmp_str_sz)) > 0) + { + BUILD_FLOAT(tmp, tmp_d); + BUILD_STRING(tmp2, tmp_str, tmp_str_sz); + (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(float, string)"); + return 0; + } + return ret; + case HYPERDATATYPE_MAP_FLOAT_INT64: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _hash_map, _hash_map_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_map_float_int_next(&iter, &tmp_d, &tmp_i)) > 0) + { + BUILD_FLOAT(tmp, tmp_d); + BUILD_INT(tmp2, tmp_i); + (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(float, int)"); + return 0; + } + return ret; + case HYPERDATATYPE_MAP_FLOAT_FLOAT: + hyperdex_ds_iterator_init(&iter, attr->datatype, attr->value, attr->value_sz); + ret = (*env)->NewObject(env, _hash_map, _hash_map_init); + ERROR_CHECK(0); + while ((result = hyperdex_ds_iterate_map_float_float_next(&iter, &tmp_d, &tmp_d2)) > 0) + { + BUILD_FLOAT(tmp, tmp_d); + BUILD_FLOAT(tmp2, tmp_d2); + (*env)->CallObjectMethod(env, ret, _hash_map_put, tmp, tmp2); + ERROR_CHECK(0); + } + if (result < 0) + { + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(float, float)"); + return 0; + } + return ret; + case HYPERDATATYPE_GENERIC: + case HYPERDATATYPE_LIST_GENERIC: + case HYPERDATATYPE_SET_GENERIC: + case HYPERDATATYPE_MAP_GENERIC: + case HYPERDATATYPE_MAP_STRING_KEYONLY: + case HYPERDATATYPE_MAP_INT64_KEYONLY: + case HYPERDATATYPE_MAP_FLOAT_KEYONLY: + case HYPERDATATYPE_GARBAGE: + default: + hyperdex_java_client_throw_exception(env, HYPERDEX_CLIENT_SERVERERROR, "server sent malformed attributes"); + return 0; + } } static jobject -hyperdex_java_client_build_attributes(JNIEnv* env, - const struct hyperdex_client_attribute* attrs, +hyperdex_java_client_build_attributes(JNIEnv *env, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) { - jobject ret; - jobject str; - jobject val; - size_t i = 0; - - ret = (*env)->NewObject(env, _hash_map, _hash_map_init); - ERROR_CHECK(0); - - for (i = 0; i < attrs_sz; ++i) - { - val = hyperdex_java_client_build_attribute(env, attrs + i); - - if (val == 0) - { - return 0; - } - - str = (*env)->NewStringUTF(env, attrs[i].attr); - ERROR_CHECK(0); - (*env)->CallObjectMethod(env, ret, _hash_map_put, str, val); - ERROR_CHECK(0); - } - - return ret; + jobject ret; + jobject str; + jobject val; + size_t i = 0; + ret = (*env)->NewObject(env, _hash_map, _hash_map_init); + ERROR_CHECK(0); + for (i = 0; i < attrs_sz; ++i) + { + val = hyperdex_java_client_build_attribute(env, attrs + i); + if (val == 0) + { + return 0; + } + str = (*env)->NewStringUTF(env, attrs[i].attr); + ERROR_CHECK(0); + (*env)->CallObjectMethod(env, ret, _hash_map_put, str, val); + ERROR_CHECK(0); + } + return ret; } /******************************* Deferred Class *******************************/ JNIEXPORT HYPERDEX_API void JNICALL -Java_org_hyperdex_client_Deferred__1create(JNIEnv* env, jobject deferred) +Java_org_hyperdex_client_Deferred__1create(JNIEnv *env, jobject deferred) { - struct hyperdex_java_client_deferred* ptr; - - ERROR_CHECK_VOID(); - ptr = malloc(sizeof(struct hyperdex_java_client_deferred)); - - if (!ptr) - { - hyperdex_java_out_of_memory(env); - return; - } - - memset(ptr, 0, sizeof(struct hyperdex_java_client_deferred)); - (*env)->SetLongField(env, deferred, _deferred_ptr, (long)ptr); - ERROR_CHECK_VOID(); - - ptr->arena = hyperdex_ds_arena_create(); - - if (!ptr->arena) - { - /* all other resources are caught by the finalizer? */ - hyperdex_java_out_of_memory(env); - return; - } - - ptr->reqid = -1; - ptr->status = HYPERDEX_CLIENT_GARBAGE; - ptr->attrs = NULL; - ptr->attrs_sz = 0; - ptr->description = NULL; - ptr->count = 0; - ptr->finished = 0; - ptr->encode_return = NULL; + struct hyperdex_java_client_deferred *ptr; + ERROR_CHECK_VOID(); + ptr = malloc(sizeof(struct hyperdex_java_client_deferred)); + if (!ptr) + { + hyperdex_java_out_of_memory(env); + return; + } + memset(ptr, 0, sizeof(struct hyperdex_java_client_deferred)); + (*env)->SetLongField(env, deferred, _deferred_ptr, (long)ptr); + ERROR_CHECK_VOID(); + ptr->arena = hyperdex_ds_arena_create(); + if (!ptr->arena) + { + /* all other resources are caught by the finalizer? */ + hyperdex_java_out_of_memory(env); + return; + } + ptr->reqid = -1; + ptr->status = HYPERDEX_CLIENT_GARBAGE; + ptr->attrs = NULL; + ptr->attrs_sz = 0; + ptr->description = NULL; + ptr->count = 0; + ptr->finished = 0; + ptr->encode_return = NULL; } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" JNIEXPORT HYPERDEX_API void JNICALL -Java_org_hyperdex_client_Deferred__1destroy(JNIEnv* env, jobject dfrd) +Java_org_hyperdex_client_Deferred__1destroy(JNIEnv *env, jobject dfrd) { - jlong lptr; - struct hyperdex_java_client_deferred* ptr; - - lptr = (*env)->GetLongField(env, dfrd, _deferred_ptr); - ERROR_CHECK_VOID(); - ptr = (struct hyperdex_java_client_deferred*)lptr; - - if (ptr) - { - if (ptr->arena) - { - hyperdex_ds_arena_destroy(ptr->arena); - } - - if (ptr->attrs) - { - hyperdex_client_destroy_attrs(ptr->attrs, ptr->attrs_sz); - } - - if (ptr->description) - { - free((void*)ptr->description); - } - - free(ptr); - } - - (*env)->SetLongField(env, dfrd, _deferred_ptr, 0); - ERROR_CHECK_VOID(); + jlong lptr; + struct hyperdex_java_client_deferred *ptr; + lptr = (*env)->GetLongField(env, dfrd, _deferred_ptr); + ERROR_CHECK_VOID(); + ptr = (struct hyperdex_java_client_deferred *)lptr; + if (ptr) + { + if (ptr->arena) + { + hyperdex_ds_arena_destroy(ptr->arena); + } + if (ptr->attrs) + { + hyperdex_client_destroy_attrs(ptr->attrs, ptr->attrs_sz); + } + if (ptr->description) + { + free((void *)ptr->description); + } + free(ptr); + } + (*env)->SetLongField(env, dfrd, _deferred_ptr, 0); + ERROR_CHECK_VOID(); } #pragma GCC diagnostic pop JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Deferred_waitForIt(JNIEnv* env, jobject obj) +Java_org_hyperdex_client_Deferred_waitForIt(JNIEnv *env, jobject obj) { - struct hyperdex_java_client_deferred* dfrd = NULL; - dfrd = hyperdex_get_deferred_ptr(env, obj); - ERROR_CHECK(0); - - while (!dfrd->finished && dfrd->reqid >= 0) - { - (*env)->CallObjectMethod(env, obj, _deferred_loop); - ERROR_CHECK(0); - } - - assert(dfrd->encode_return); - return dfrd->encode_return(env, obj, dfrd); + struct hyperdex_java_client_deferred *dfrd = NULL; + dfrd = hyperdex_get_deferred_ptr(env, obj); + ERROR_CHECK(0); + while (!dfrd->finished && dfrd->reqid >= 0) + { + (*env)->CallObjectMethod(env, obj, _deferred_loop); + ERROR_CHECK(0); + } + assert(dfrd->encode_return); + return dfrd->encode_return(env, obj, dfrd); } JNIEXPORT HYPERDEX_API void JNICALL -Java_org_hyperdex_client_Deferred_callback(JNIEnv* env, jobject obj) +Java_org_hyperdex_client_Deferred_callback(JNIEnv *env, jobject obj) { - jobject client_obj; - struct hyperdex_java_client_deferred* dfrd = NULL; - dfrd = hyperdex_get_deferred_ptr(env, obj); - ERROR_CHECK_VOID(); - dfrd->finished = 1; - client_obj = (*env)->GetObjectField(env, obj, _deferred_c); - (*env)->CallObjectMethod(env, client_obj, _client_remove_op, dfrd->reqid); - ERROR_CHECK_VOID(); + jobject client_obj; + struct hyperdex_java_client_deferred *dfrd = NULL; + dfrd = hyperdex_get_deferred_ptr(env, obj); + ERROR_CHECK_VOID(); + dfrd->finished = 1; + client_obj = (*env)->GetObjectField(env, obj, _deferred_c); + (*env)->CallObjectMethod(env, client_obj, _client_remove_op, dfrd->reqid); + ERROR_CHECK_VOID(); } jobject -hyperdex_java_client_deferred_encode_status(JNIEnv* env, jobject obj, struct hyperdex_java_client_deferred* d) +hyperdex_java_client_deferred_encode_status(JNIEnv *env, jobject obj, struct hyperdex_java_client_deferred *d) { - jobject ret; - jobject client_obj; - struct hyperdex_client* client; - - if (d->status == HYPERDEX_CLIENT_SUCCESS) - { - ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_TRUE); - ERROR_CHECK(0); - return ret; - } - else if (d->status == HYPERDEX_CLIENT_NOTFOUND) - { - return NULL; - } - else if (d->status == HYPERDEX_CLIENT_CMPFAIL) - { - ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_FALSE); - ERROR_CHECK(0); - return ret; - } - else - { - client_obj = (*env)->GetObjectField(env, obj, _deferred_c); - ERROR_CHECK(0); - client = hyperdex_get_client_ptr(env, client_obj); - hyperdex_java_client_throw_exception(env, d->status, hyperdex_client_error_message(client)); - return 0; - } + jobject ret; + jobject client_obj; + struct hyperdex_client *client; + if (d->status == HYPERDEX_CLIENT_SUCCESS) + { + ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_TRUE); + ERROR_CHECK(0); + return ret; + } + else if (d->status == HYPERDEX_CLIENT_NOTFOUND) + { + return NULL; + } + else if (d->status == HYPERDEX_CLIENT_CMPFAIL) + { + ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_FALSE); + ERROR_CHECK(0); + return ret; + } + else + { + client_obj = (*env)->GetObjectField(env, obj, _deferred_c); + ERROR_CHECK(0); + client = hyperdex_get_client_ptr(env, client_obj); + hyperdex_java_client_throw_exception(env, d->status, hyperdex_client_error_message(client)); + return 0; + } } static jobject -hyperdex_java_client_deferred_encode_status_attributes(JNIEnv* env, jobject obj, struct hyperdex_java_client_deferred* d) +hyperdex_java_client_deferred_encode_status_attributes(JNIEnv *env, jobject obj, struct hyperdex_java_client_deferred *d) { - jobject ret; - jobject client_obj; - struct hyperdex_client* client; - - if (d->status == HYPERDEX_CLIENT_SUCCESS) - { - ret = hyperdex_java_client_build_attributes(env, d->attrs, d->attrs_sz); - ERROR_CHECK(0); - return ret; - } - else if (d->status == HYPERDEX_CLIENT_NOTFOUND) - { - return NULL; - } - else if (d->status == HYPERDEX_CLIENT_CMPFAIL) - { - ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_FALSE); - ERROR_CHECK(0); - return ret; - } - else - { - client_obj = (*env)->GetObjectField(env, obj, _deferred_c); - client = hyperdex_get_client_ptr(env, client_obj); - hyperdex_java_client_throw_exception(env, d->status, hyperdex_client_error_message(client)); - return 0; - } + jobject ret; + jobject client_obj; + struct hyperdex_client *client; + if (d->status == HYPERDEX_CLIENT_SUCCESS) + { + ret = hyperdex_java_client_build_attributes(env, d->attrs, d->attrs_sz); + ERROR_CHECK(0); + return ret; + } + else if (d->status == HYPERDEX_CLIENT_NOTFOUND) + { + return NULL; + } + else if (d->status == HYPERDEX_CLIENT_CMPFAIL) + { + ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_FALSE); + ERROR_CHECK(0); + return ret; + } + else + { + client_obj = (*env)->GetObjectField(env, obj, _deferred_c); + client = hyperdex_get_client_ptr(env, client_obj); + hyperdex_java_client_throw_exception(env, d->status, hyperdex_client_error_message(client)); + return 0; + } } jobject -hyperdex_java_client_deferred_encode_status_count(JNIEnv* env, jobject obj, struct hyperdex_java_client_deferred* d) +hyperdex_java_client_deferred_encode_status_count(JNIEnv *env, jobject obj, struct hyperdex_java_client_deferred *d) { - jobject ret; - jobject client_obj; - struct hyperdex_client* client; - - if (d->status == HYPERDEX_CLIENT_SUCCESS) - { - ret = (*env)->NewObject(env, _long, _long_init, d->count); - ERROR_CHECK(0); - return ret; - } - else if (d->status == HYPERDEX_CLIENT_NOTFOUND) - { - return NULL; - } - else if (d->status == HYPERDEX_CLIENT_CMPFAIL) - { - ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_FALSE); - ERROR_CHECK(0); - return ret; - } - else - { - client_obj = (*env)->GetObjectField(env, obj, _deferred_c); - client = hyperdex_get_client_ptr(env, client_obj); - hyperdex_java_client_throw_exception(env, d->status, hyperdex_client_error_message(client)); - return 0; - } + jobject ret; + jobject client_obj; + struct hyperdex_client *client; + if (d->status == HYPERDEX_CLIENT_SUCCESS) + { + ret = (*env)->NewObject(env, _long, _long_init, d->count); + ERROR_CHECK(0); + return ret; + } + else if (d->status == HYPERDEX_CLIENT_NOTFOUND) + { + return NULL; + } + else if (d->status == HYPERDEX_CLIENT_CMPFAIL) + { + ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_FALSE); + ERROR_CHECK(0); + return ret; + } + else + { + client_obj = (*env)->GetObjectField(env, obj, _deferred_c); + client = hyperdex_get_client_ptr(env, client_obj); + hyperdex_java_client_throw_exception(env, d->status, hyperdex_client_error_message(client)); + return 0; + } } static jobject -hyperdex_java_client_deferred_encode_status_description(JNIEnv* env, jobject obj, struct hyperdex_java_client_deferred* d) +hyperdex_java_client_deferred_encode_status_description(JNIEnv *env, jobject obj, struct hyperdex_java_client_deferred *d) { - jobject ret; - jobject client_obj; - struct hyperdex_client* client; - - if (d->status == HYPERDEX_CLIENT_SUCCESS) - { - ret = (*env)->NewStringUTF(env, d->description); - ERROR_CHECK(0); - return ret; - } - else if (d->status == HYPERDEX_CLIENT_NOTFOUND) - { - ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_TRUE); - ERROR_CHECK(0); - return ret; - } - else if (d->status == HYPERDEX_CLIENT_CMPFAIL) - { - ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_FALSE); - ERROR_CHECK(0); - return ret; - } - else - { - client_obj = (*env)->GetObjectField(env, obj, _deferred_c); - client = hyperdex_get_client_ptr(env, client_obj); - hyperdex_java_client_throw_exception(env, d->status, hyperdex_client_error_message(client)); - return 0; - } + jobject ret; + jobject client_obj; + struct hyperdex_client *client; + if (d->status == HYPERDEX_CLIENT_SUCCESS) + { + ret = (*env)->NewStringUTF(env, d->description); + ERROR_CHECK(0); + return ret; + } + else if (d->status == HYPERDEX_CLIENT_NOTFOUND) + { + ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_TRUE); + ERROR_CHECK(0); + return ret; + } + else if (d->status == HYPERDEX_CLIENT_CMPFAIL) + { + ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_FALSE); + ERROR_CHECK(0); + return ret; + } + else + { + client_obj = (*env)->GetObjectField(env, obj, _deferred_c); + client = hyperdex_get_client_ptr(env, client_obj); + hyperdex_java_client_throw_exception(env, d->status, hyperdex_client_error_message(client)); + return 0; + } } /******************************* Iterator Class *******************************/ struct hyperdex_java_client_iterator { - struct hyperdex_ds_arena* arena; - int64_t reqid; - enum hyperdex_client_returncode status; - const struct hyperdex_client_attribute* attrs; - size_t attrs_sz; - int finished; - jobject (*encode_return)(JNIEnv* env, jobject obj, struct hyperdex_java_client_iterator* d); + struct hyperdex_ds_arena *arena; + int64_t reqid; + enum hyperdex_client_returncode status; + const struct hyperdex_client_attribute *attrs; + size_t attrs_sz; + int finished; + jobject (*encode_return)(JNIEnv *env, jobject obj, struct hyperdex_java_client_iterator *d); }; JNIEXPORT HYPERDEX_API void JNICALL -Java_org_hyperdex_client_Iterator__1create(JNIEnv* env, jobject iterator) +Java_org_hyperdex_client_Iterator__1create(JNIEnv *env, jobject iterator) { - jlong lptr; - struct hyperdex_java_client_iterator* ptr; - - lptr = (*env)->GetLongField(env, iterator, _iterator_ptr); - ERROR_CHECK_VOID(); - ptr = malloc(sizeof(struct hyperdex_java_client_iterator)); - - if (!ptr) - { - hyperdex_java_out_of_memory(env); - return; - } - - memset(ptr, 0, sizeof(struct hyperdex_java_client_iterator)); - lptr = (long) ptr; - (*env)->SetLongField(env, iterator, _iterator_ptr, lptr); - ERROR_CHECK_VOID(); - - ptr->arena = hyperdex_ds_arena_create(); - - if (!ptr->arena) - { - /* all other resources are caught by the finalizer? */ - hyperdex_java_out_of_memory(env); - return; - } - - ptr->reqid = -1; - ptr->status = HYPERDEX_CLIENT_GARBAGE; - ptr->attrs = NULL; - ptr->attrs_sz = 0; - ptr->finished = 0; - ptr->encode_return = NULL; + jlong lptr; + struct hyperdex_java_client_iterator *ptr; + lptr = (*env)->GetLongField(env, iterator, _iterator_ptr); + ERROR_CHECK_VOID(); + ptr = malloc(sizeof(struct hyperdex_java_client_iterator)); + if (!ptr) + { + hyperdex_java_out_of_memory(env); + return; + } + memset(ptr, 0, sizeof(struct hyperdex_java_client_iterator)); + lptr = (long) ptr; + (*env)->SetLongField(env, iterator, _iterator_ptr, lptr); + ERROR_CHECK_VOID(); + ptr->arena = hyperdex_ds_arena_create(); + if (!ptr->arena) + { + /* all other resources are caught by the finalizer? */ + hyperdex_java_out_of_memory(env); + return; + } + ptr->reqid = -1; + ptr->status = HYPERDEX_CLIENT_GARBAGE; + ptr->attrs = NULL; + ptr->attrs_sz = 0; + ptr->finished = 0; + ptr->encode_return = NULL; } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" JNIEXPORT HYPERDEX_API void JNICALL -Java_org_hyperdex_client_Iterator__1destroy(JNIEnv* env, jobject iter) +Java_org_hyperdex_client_Iterator__1destroy(JNIEnv *env, jobject iter) { - jlong lptr; - struct hyperdex_java_client_iterator* ptr; - - lptr = (*env)->GetLongField(env, iter, _iterator_ptr); - ERROR_CHECK_VOID(); - ptr = (struct hyperdex_java_client_iterator*)lptr; - - if (ptr) - { - if (ptr->arena) - { - hyperdex_ds_arena_destroy(ptr->arena); - } - - if (ptr->attrs) - { - hyperdex_client_destroy_attrs(ptr->attrs, ptr->attrs_sz); - } - - free(ptr); - } - - (*env)->SetLongField(env, iter, _iterator_ptr, 0); - ERROR_CHECK_VOID(); + jlong lptr; + struct hyperdex_java_client_iterator *ptr; + lptr = (*env)->GetLongField(env, iter, _iterator_ptr); + ERROR_CHECK_VOID(); + ptr = (struct hyperdex_java_client_iterator *)lptr; + if (ptr) + { + if (ptr->arena) + { + hyperdex_ds_arena_destroy(ptr->arena); + } + if (ptr->attrs) + { + hyperdex_client_destroy_attrs(ptr->attrs, ptr->attrs_sz); + } + free(ptr); + } + (*env)->SetLongField(env, iter, _iterator_ptr, 0); + ERROR_CHECK_VOID(); } JNIEXPORT HYPERDEX_API jboolean JNICALL -Java_org_hyperdex_client_Iterator_finished(JNIEnv* env, jobject obj) +Java_org_hyperdex_client_Iterator_finished(JNIEnv *env, jobject obj) { - struct hyperdex_java_client_iterator* iter = NULL; - iter = hyperdex_get_iterator_ptr(env, obj); - return iter->finished == 1 ? JNI_TRUE : JNI_FALSE; + struct hyperdex_java_client_iterator *iter = NULL; + iter = hyperdex_get_iterator_ptr(env, obj); + return iter->finished == 1 ? JNI_TRUE : JNI_FALSE; } JNIEXPORT HYPERDEX_API void JNICALL -Java_org_hyperdex_client_Iterator_callback(JNIEnv* env, jobject obj) +Java_org_hyperdex_client_Iterator_callback(JNIEnv *env, jobject obj) { - jobject tmp; - jobject client_obj; - struct hyperdex_client* client; - struct hyperdex_java_client_iterator* iter = NULL; - iter = hyperdex_get_iterator_ptr(env, obj); - ERROR_CHECK_VOID(); - client_obj = (*env)->GetObjectField(env, obj, _iterator_c); - ERROR_CHECK_VOID(); - - if (iter->status == HYPERDEX_CLIENT_SEARCHDONE) - { - iter->finished = 1; - (*env)->CallObjectMethod(env, client_obj, _client_remove_op, iter->reqid); - ERROR_CHECK_VOID(); - } - else if (iter->status == HYPERDEX_CLIENT_SUCCESS) - { - tmp = iter->encode_return(env, obj, iter); - - if (iter->attrs) - { - hyperdex_client_destroy_attrs(iter->attrs, iter->attrs_sz); - } - - iter->attrs = NULL; - iter->attrs_sz = 0; - (*env)->CallObjectMethod(env, obj, _iterator_appendBacklogged, tmp); - ERROR_CHECK_VOID(); - } - else - { - client_obj = (*env)->GetObjectField(env, obj, _iterator_c); - client = hyperdex_get_client_ptr(env, client_obj); - tmp = hyperdex_java_client_create_exception(env, iter->status, - hyperdex_client_error_message(client)); - (*env)->CallObjectMethod(env, obj, _iterator_appendBacklogged, tmp); - ERROR_CHECK_VOID(); - } + jobject tmp; + jobject client_obj; + struct hyperdex_client *client; + struct hyperdex_java_client_iterator *iter = NULL; + iter = hyperdex_get_iterator_ptr(env, obj); + ERROR_CHECK_VOID(); + client_obj = (*env)->GetObjectField(env, obj, _iterator_c); + ERROR_CHECK_VOID(); + if (iter->status == HYPERDEX_CLIENT_SEARCHDONE) + { + iter->finished = 1; + (*env)->CallObjectMethod(env, client_obj, _client_remove_op, iter->reqid); + ERROR_CHECK_VOID(); + } + else if (iter->status == HYPERDEX_CLIENT_SUCCESS) + { + tmp = iter->encode_return(env, obj, iter); + if (iter->attrs) + { + hyperdex_client_destroy_attrs(iter->attrs, iter->attrs_sz); + } + iter->attrs = NULL; + iter->attrs_sz = 0; + (*env)->CallObjectMethod(env, obj, _iterator_appendBacklogged, tmp); + ERROR_CHECK_VOID(); + } + else + { + client_obj = (*env)->GetObjectField(env, obj, _iterator_c); + client = hyperdex_get_client_ptr(env, client_obj); + tmp = hyperdex_java_client_create_exception(env, iter->status, + hyperdex_client_error_message(client)); + (*env)->CallObjectMethod(env, obj, _iterator_appendBacklogged, tmp); + ERROR_CHECK_VOID(); + } } static jobject -hyperdex_java_client_iterator_encode_status_attributes(JNIEnv* env, jobject obj, struct hyperdex_java_client_iterator* it) +hyperdex_java_client_iterator_encode_status_attributes(JNIEnv *env, jobject obj, struct hyperdex_java_client_iterator *it) { - jobject ret; - jobject client_obj; - struct hyperdex_client* client; - - if (it->status == HYPERDEX_CLIENT_SUCCESS) - { - ret = hyperdex_java_client_build_attributes(env, it->attrs, it->attrs_sz); - ERROR_CHECK(0); - return ret; - } - else if (it->status == HYPERDEX_CLIENT_NOTFOUND) - { - ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_TRUE); - ERROR_CHECK(0); - return ret; - } - else if (it->status == HYPERDEX_CLIENT_CMPFAIL) - { - ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_FALSE); - ERROR_CHECK(0); - return ret; - } - else - { - client_obj = (*env)->GetObjectField(env, obj, _deferred_c); - client = hyperdex_get_client_ptr(env, client_obj); - hyperdex_java_client_throw_exception(env, it->status, hyperdex_client_error_message(client)); - return 0; - } + jobject ret; + jobject client_obj; + struct hyperdex_client *client; + if (it->status == HYPERDEX_CLIENT_SUCCESS) + { + ret = hyperdex_java_client_build_attributes(env, it->attrs, it->attrs_sz); + ERROR_CHECK(0); + return ret; + } + else if (it->status == HYPERDEX_CLIENT_NOTFOUND) + { + ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_TRUE); + ERROR_CHECK(0); + return ret; + } + else if (it->status == HYPERDEX_CLIENT_CMPFAIL) + { + ret = (*env)->NewObject(env, _boolean, _boolean_init, JNI_FALSE); + ERROR_CHECK(0); + return ret; + } + else + { + client_obj = (*env)->GetObjectField(env, obj, _deferred_c); + client = hyperdex_get_client_ptr(env, client_obj); + hyperdex_java_client_throw_exception(env, it->status, hyperdex_client_error_message(client)); + return 0; + } } -const char* -hyperdex_java_client_convert_cstring(JNIEnv* env, - struct hyperdex_ds_arena* arena, +const char * +hyperdex_java_client_convert_cstring(JNIEnv *env, + struct hyperdex_ds_arena *arena, jobject str) { - const char* tmp = NULL; - const char* ret = NULL; - size_t ret_sz = 0; - enum hyperdex_ds_returncode rc; - int success; - tmp = (*env)->GetStringUTFChars(env, str, 0); - ERROR_CHECK(NULL); - success = hyperdex_ds_copy_string(arena, tmp, strlen(tmp) + 1, &rc, &ret, &ret_sz); - (*env)->ReleaseStringUTFChars(env, str, tmp); - ERROR_CHECK(NULL); - - if (success < 0) - { - hyperdex_java_out_of_memory(env); - return NULL; - } - - return ret; + const char *tmp = NULL; + const char *ret = NULL; + size_t ret_sz = 0; + enum hyperdex_ds_returncode rc; + int success; + tmp = (*env)->GetStringUTFChars(env, str, 0); + ERROR_CHECK(NULL); + success = hyperdex_ds_copy_string(arena, tmp, strlen(tmp) + 1, &rc, &ret, &ret_sz); + (*env)->ReleaseStringUTFChars(env, str, tmp); + ERROR_CHECK(NULL); + if (success < 0) + { + hyperdex_java_out_of_memory(env); + return NULL; + } + return ret; } int -hyperdex_java_client_convert_attributes(JNIEnv* env, jobject client, - struct hyperdex_ds_arena* arena, +hyperdex_java_client_convert_attributes(JNIEnv *env, jobject client, + struct hyperdex_ds_arena *arena, jobject x, - const struct hyperdex_client_attribute** _attrs, - size_t* _attrs_sz) + const struct hyperdex_client_attribute **_attrs, + size_t *_attrs_sz) { - jobject set; - jobject it; - jobject entry; - jobject key; - jobject val; - struct hyperdex_client_attribute* attrs = NULL; - size_t attrs_sz = 0; - size_t attrs_idx = 0; - - set = (*env)->CallObjectMethod(env, x, _map_entrySet); - ERROR_CHECK(-1); - it = (*env)->CallObjectMethod(env, set, _set_iterator); - ERROR_CHECK(-1); - attrs_sz = (*env)->CallIntMethod(env, x, _map_size); - ERROR_CHECK(-1); - attrs = hyperdex_ds_allocate_attribute(arena, attrs_sz); - - if (!attrs) - { - hyperdex_java_out_of_memory(env); - return -1; - } - - *_attrs = attrs; - *_attrs_sz = attrs_sz; - attrs_idx = 0; - - while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) - { - entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); - ERROR_CHECK(-1); - key = (*env)->CallObjectMethod(env, entry, _map_entry_getKey); - ERROR_CHECK(-1); - val = (*env)->CallObjectMethod(env, entry, _map_entry_getValue); - ERROR_CHECK(-1); - attrs[attrs_idx].attr = hyperdex_java_client_convert_cstring(env, arena, key); - - if (!attrs[attrs_idx].attr) - { - return -1; - } - - if (hyperdex_java_client_convert_type(env, arena, val, - &attrs[attrs_idx].value, - &attrs[attrs_idx].value_sz, - &attrs[attrs_idx].datatype) < 0) - { - return -1; - } - - (*env)->DeleteLocalRef(env, val); - (*env)->DeleteLocalRef(env, key); - (*env)->DeleteLocalRef(env, entry); - ++attrs_idx; - } - - (*env)->DeleteLocalRef(env, it); - (*env)->DeleteLocalRef(env, set); - (void)client; - return 0; + jobject set; + jobject it; + jobject entry; + jobject key; + jobject val; + struct hyperdex_client_attribute *attrs = NULL; + size_t attrs_sz = 0; + size_t attrs_idx = 0; + set = (*env)->CallObjectMethod(env, x, _map_entrySet); + ERROR_CHECK(-1); + it = (*env)->CallObjectMethod(env, set, _set_iterator); + ERROR_CHECK(-1); + attrs_sz = (*env)->CallIntMethod(env, x, _map_size); + ERROR_CHECK(-1); + attrs = hyperdex_ds_allocate_attribute(arena, attrs_sz); + if (!attrs) + { + hyperdex_java_out_of_memory(env); + return -1; + } + *_attrs = attrs; + *_attrs_sz = attrs_sz; + attrs_idx = 0; + while ((*env)->CallBooleanMethod(env, it, _java_iterator_hasNext) == JNI_TRUE) + { + entry = (*env)->CallObjectMethod(env, it, _java_iterator_next); + ERROR_CHECK(-1); + key = (*env)->CallObjectMethod(env, entry, _map_entry_getKey); + ERROR_CHECK(-1); + val = (*env)->CallObjectMethod(env, entry, _map_entry_getValue); + ERROR_CHECK(-1); + attrs[attrs_idx].attr = hyperdex_java_client_convert_cstring(env, arena, key); + if (!attrs[attrs_idx].attr) + { + return -1; + } + if (hyperdex_java_client_convert_type(env, arena, val, + &attrs[attrs_idx].value, + &attrs[attrs_idx].value_sz, + &attrs[attrs_idx].datatype) < 0) + { + return -1; + } + (*env)->DeleteLocalRef(env, val); + (*env)->DeleteLocalRef(env, key); + (*env)->DeleteLocalRef(env, entry); + ++attrs_idx; + } + (*env)->DeleteLocalRef(env, it); + (*env)->DeleteLocalRef(env, set); + (void)client; + return 0; } /********************************* Predicates *********************************/ #define SINGLE_OBJECT_PREDICATE(CamelCase, lower_case, PREDICATE) \ - JNIEXPORT HYPERDEX_API jlong JNICALL \ - Java_org_hyperdex_client_ ## CamelCase ## _checksSize(JNIEnv* env, jobject obj) \ - { \ - (void) env; \ - (void) obj; \ - return 1; \ - } \ - JNIEXPORT HYPERDEX_API jlong JNICALL \ - Java_org_hyperdex_client_ ## CamelCase ## _convertChecks(JNIEnv* env, jobject obj, jlong arena, \ - jlong _checks, jlong checks_sz) \ - { \ - struct hyperdex_client_attribute_check* checks = (struct hyperdex_client_attribute_check*) _checks; \ - jobject x = (*env)->GetObjectField(env, obj, _pred_ ## lower_case ## _x); \ - ERROR_CHECK(-1); \ - checks[checks_sz].predicate = HYPERPREDICATE_ ## PREDICATE; \ - if (hyperdex_java_client_convert_type(env, (struct hyperdex_ds_arena*)arena, x, \ - &checks[checks_sz].value, \ - &checks[checks_sz].value_sz, \ - &checks[checks_sz].datatype) < 0) \ - { \ - return -1; \ - } \ - ERROR_CHECK(-1); \ - return checks_sz + 1; \ - } + JNIEXPORT HYPERDEX_API jlong JNICALL \ + Java_org_hyperdex_client_ ## CamelCase ## _checksSize(JNIEnv* env, jobject obj) \ + { \ + (void) env; \ + (void) obj; \ + return 1; \ + } \ + JNIEXPORT HYPERDEX_API jlong JNICALL \ + Java_org_hyperdex_client_ ## CamelCase ## _convertChecks(JNIEnv* env, jobject obj, jlong arena, \ + jlong _checks, jlong checks_sz) \ + { \ + struct hyperdex_client_attribute_check* checks = (struct hyperdex_client_attribute_check*) _checks; \ + jobject x = (*env)->GetObjectField(env, obj, _pred_ ## lower_case ## _x); \ + ERROR_CHECK(-1); \ + checks[checks_sz].predicate = HYPERPREDICATE_ ## PREDICATE; \ + if (hyperdex_java_client_convert_type(env, (struct hyperdex_ds_arena*)arena, x, \ + &checks[checks_sz].value, \ + &checks[checks_sz].value_sz, \ + &checks[checks_sz].datatype) < 0) \ + { \ + return -1; \ + } \ + ERROR_CHECK(-1); \ + return checks_sz + 1; \ + } SINGLE_OBJECT_PREDICATE(LessEqual, less_equal, LESS_EQUAL) SINGLE_OBJECT_PREDICATE(GreaterEqual, greater_equal, GREATER_EQUAL) @@ -2279,44 +2085,41 @@ SINGLE_OBJECT_PREDICATE(LessThan, less_equal, LESS_THAN) SINGLE_OBJECT_PREDICATE(GreaterThan, greater_equal, GREATER_THAN) JNIEXPORT HYPERDEX_API jlong JNICALL -Java_org_hyperdex_client_Range_checksSize(JNIEnv* env, jobject obj) +Java_org_hyperdex_client_Range_checksSize(JNIEnv *env, jobject obj) { - (void) env; - (void) obj; - return 2; + (void) env; + (void) obj; + return 2; } JNIEXPORT HYPERDEX_API jlong JNICALL -Java_org_hyperdex_client_Range_convertChecks(JNIEnv* env, jobject obj, jlong arena, +Java_org_hyperdex_client_Range_convertChecks(JNIEnv *env, jobject obj, jlong arena, jlong _checks, jlong checks_sz) { - struct hyperdex_client_attribute_check* checks = (struct hyperdex_client_attribute_check*) _checks; - jobject x; - jobject y; - x = (*env)->GetObjectField(env, obj, _pred_range_x); - y = (*env)->GetObjectField(env, obj, _pred_range_y); - ERROR_CHECK(-1); - checks[checks_sz + 0].predicate = HYPERPREDICATE_GREATER_EQUAL; - checks[checks_sz + 1].predicate = HYPERPREDICATE_LESS_EQUAL; - - if (hyperdex_java_client_convert_type(env, (struct hyperdex_ds_arena*)arena, x, - &checks[checks_sz].value, - &checks[checks_sz].value_sz, - &checks[checks_sz].datatype) < 0) - { - return -1; - } - - if (hyperdex_java_client_convert_type(env, (struct hyperdex_ds_arena*)arena, y, - &checks[checks_sz + 1].value, - &checks[checks_sz + 1].value_sz, - &checks[checks_sz + 1].datatype) < 0) - { - return -1; - } - - ERROR_CHECK(-1); - return checks_sz + 2; + struct hyperdex_client_attribute_check *checks = (struct hyperdex_client_attribute_check *) _checks; + jobject x; + jobject y; + x = (*env)->GetObjectField(env, obj, _pred_range_x); + y = (*env)->GetObjectField(env, obj, _pred_range_y); + ERROR_CHECK(-1); + checks[checks_sz + 0].predicate = HYPERPREDICATE_GREATER_EQUAL; + checks[checks_sz + 1].predicate = HYPERPREDICATE_LESS_EQUAL; + if (hyperdex_java_client_convert_type(env, (struct hyperdex_ds_arena *)arena, x, + &checks[checks_sz].value, + &checks[checks_sz].value_sz, + &checks[checks_sz].datatype) < 0) + { + return -1; + } + if (hyperdex_java_client_convert_type(env, (struct hyperdex_ds_arena *)arena, y, + &checks[checks_sz + 1].value, + &checks[checks_sz + 1].value_sz, + &checks[checks_sz + 1].datatype) < 0) + { + return -1; + } + ERROR_CHECK(-1); + return checks_sz + 2; } SINGLE_OBJECT_PREDICATE(Regex, regex, REGEX) @@ -2327,71 +2130,62 @@ SINGLE_OBJECT_PREDICATE(LengthGreaterEqual, length_greater_equal, LENGTH_GREATER /******************************** Client Class ********************************/ JNIEXPORT HYPERDEX_API void JNICALL -Java_org_hyperdex_client_Client__1create(JNIEnv* env, jobject client, jstring _host, jint port) +Java_org_hyperdex_client_Client__1create(JNIEnv *env, jobject client, jstring _host, jint port) { - jlong lptr; - const char* host; - struct hyperdex_client* ptr; - - lptr = (*env)->GetLongField(env, client, _client_ptr); - ERROR_CHECK_VOID(); - host = (*env)->GetStringUTFChars(env, _host, NULL); - ERROR_CHECK_VOID(); - ptr = hyperdex_client_create(host, port); - (*env)->ReleaseStringUTFChars(env, _host, host); - - if (!ptr) - { - hyperdex_java_out_of_memory(env); - return; - } - - ERROR_CHECK_VOID(); - lptr = (long) ptr; - (*env)->SetLongField(env, client, _client_ptr, lptr); - ERROR_CHECK_VOID(); - assert(sizeof(long) >= sizeof(struct hyperdex_client*)); + jlong lptr; + const char *host; + struct hyperdex_client *ptr; + lptr = (*env)->GetLongField(env, client, _client_ptr); + ERROR_CHECK_VOID(); + host = (*env)->GetStringUTFChars(env, _host, NULL); + ERROR_CHECK_VOID(); + ptr = hyperdex_client_create(host, port); + (*env)->ReleaseStringUTFChars(env, _host, host); + if (!ptr) + { + hyperdex_java_out_of_memory(env); + return; + } + ERROR_CHECK_VOID(); + lptr = (long) ptr; + (*env)->SetLongField(env, client, _client_ptr, lptr); + ERROR_CHECK_VOID(); + assert(sizeof(long) >= sizeof(struct hyperdex_client *)); } JNIEXPORT HYPERDEX_API void JNICALL -Java_org_hyperdex_client_Client__1destroy(JNIEnv* env, jobject client) +Java_org_hyperdex_client_Client__1destroy(JNIEnv *env, jobject client) { - jlong lptr; - struct hyperdex_client* ptr; - - lptr = (*env)->GetLongField(env, client, _client_ptr); - ERROR_CHECK_VOID(); - ptr = (struct hyperdex_client*)lptr; - - if (ptr) - { - hyperdex_client_destroy(ptr); - } - - (*env)->SetLongField(env, client, _client_ptr, 0); - ERROR_CHECK_VOID(); + jlong lptr; + struct hyperdex_client *ptr; + lptr = (*env)->GetLongField(env, client, _client_ptr); + ERROR_CHECK_VOID(); + ptr = (struct hyperdex_client *)lptr; + if (ptr) + { + hyperdex_client_destroy(ptr); + } + (*env)->SetLongField(env, client, _client_ptr, 0); + ERROR_CHECK_VOID(); } JNIEXPORT HYPERDEX_API jlong JNICALL -Java_org_hyperdex_client_Client_inner_1loop(JNIEnv* env, jobject client) +Java_org_hyperdex_client_Client_inner_1loop(JNIEnv *env, jobject client) { - struct hyperdex_client* ptr; - int64_t x; - jlong y; - enum hyperdex_client_returncode rc; - - ptr = hyperdex_get_client_ptr(env, client); - x = hyperdex_client_loop(ptr, -1, &rc); - - if (x < 0) - { - hyperdex_java_client_throw_exception(env, rc, hyperdex_client_error_message(ptr)); - return -1; - } - - y = (jlong)x; - assert(x == y); - return y; + struct hyperdex_client *ptr; + int64_t x; + jlong y; + enum hyperdex_client_returncode rc; + ptr = hyperdex_get_client_ptr(env, client); + x = hyperdex_client_loop(ptr, -1, &rc); + if (x < 0) + { + hyperdex_java_client_throw_exception(env, rc, hyperdex_client_error_message(ptr)); + return -1; + } + y = (jlong)x; + assert(x == y); + return y; } #include "bindings/java/org_hyperdex_client_Client.definitions.c" diff --git a/bindings/java/org_hyperdex_client_Client.definitions.c b/bindings/java/org_hyperdex_client_Client.definitions.c index 8699a2f3c..a9f66639b 100644 --- a/bindings/java/org_hyperdex_client_Client.definitions.c +++ b/bindings/java/org_hyperdex_client_Client.definitions.c @@ -30,1301 +30,1271 @@ #include "visibility.h" JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key__status_attributes(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), jstring spacename, jobject key); - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key__status_attributes(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), jstring spacename, jobject key) -{ - const char* in_space; - const char* in_key; - size_t in_key_sz; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); - struct hyperdex_java_client_deferred* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_deferred_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_key, in_key_sz, &o->status, &o->attrs, &o->attrs_sz); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_deferred_encode_status_attributes; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; -} - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key_attributenames__status_attributes(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const char** attrnames, size_t attrnames_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), jstring spacename, jobject key, jobject attributenames); - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key_attributenames__status_attributes(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const char** attrnames, size_t attrnames_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), jstring spacename, jobject key, jobject attributenames) -{ - const char* in_space; - const char* in_key; - size_t in_key_sz; - const char** in_attrnames; - size_t in_attrnames_sz; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); - struct hyperdex_java_client_deferred* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_deferred_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); - if (success < 0) return 0; - success = hyperdex_java_client_convert_attributenames(env, obj, o->arena, attributenames, &in_attrnames, &in_attrnames_sz); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_key, in_key_sz, in_attrnames, in_attrnames_sz, &o->status, &o->attrs, &o->attrs_sz); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_deferred_encode_status_attributes; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; -} - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key_attributes__status(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status), jstring spacename, jobject key, jobject attributes); - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key_attributes__status(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status), jstring spacename, jobject key, jobject attributes) -{ - const char* in_space; - const char* in_key; - size_t in_key_sz; - const struct hyperdex_client_attribute* in_attrs; - size_t in_attrs_sz; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); - struct hyperdex_java_client_deferred* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_deferred_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); - if (success < 0) return 0; - success = hyperdex_java_client_convert_attributes(env, obj, o->arena, attributes, &in_attrs, &in_attrs_sz); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_key, in_key_sz, in_attrs, in_attrs_sz, &o->status); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_deferred_encode_status; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; -} - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status), jstring spacename, jobject key, jobject predicates, jobject attributes); - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status), jstring spacename, jobject key, jobject predicates, jobject attributes) -{ - const char* in_space; - const char* in_key; - size_t in_key_sz; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - const struct hyperdex_client_attribute* in_attrs; - size_t in_attrs_sz; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); - struct hyperdex_java_client_deferred* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_deferred_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); - if (success < 0) return 0; - success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); - if (success < 0) return 0; - success = hyperdex_java_client_convert_attributes(env, obj, o->arena, attributes, &in_attrs, &in_attrs_sz); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_key, in_key_sz, in_checks, in_checks_sz, in_attrs, in_attrs_sz, &o->status); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_deferred_encode_status; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; -} - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status, uint64_t* count), jstring spacename, jobject predicates, jobject attributes); - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status, uint64_t* count), jstring spacename, jobject predicates, jobject attributes) -{ - const char* in_space; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - const struct hyperdex_client_attribute* in_attrs; - size_t in_attrs_sz; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); - struct hyperdex_java_client_deferred* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_deferred_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); - if (success < 0) return 0; - success = hyperdex_java_client_convert_attributes(env, obj, o->arena, attributes, &in_attrs, &in_attrs_sz); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_checks, in_checks_sz, in_attrs, in_attrs_sz, &o->status, &o->count); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_deferred_encode_status_count; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; -} - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key__status(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, enum hyperdex_client_returncode* status), jstring spacename, jobject key); - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key__status(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, enum hyperdex_client_returncode* status), jstring spacename, jobject key) -{ - const char* in_space; - const char* in_key; - size_t in_key_sz; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); - struct hyperdex_java_client_deferred* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_deferred_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_key, in_key_sz, &o->status); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_deferred_encode_status; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; -} - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key_predicates__status(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status), jstring spacename, jobject key, jobject predicates); - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key_predicates__status(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status), jstring spacename, jobject key, jobject predicates) -{ - const char* in_space; - const char* in_key; - size_t in_key_sz; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); - struct hyperdex_java_client_deferred* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_deferred_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); - if (success < 0) return 0; - success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_key, in_key_sz, in_checks, in_checks_sz, &o->status); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_deferred_encode_status; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; -} - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_predicates__status_count(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, uint64_t* count), jstring spacename, jobject predicates); - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_predicates__status_count(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, uint64_t* count), jstring spacename, jobject predicates) -{ - const char* in_space; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); - struct hyperdex_java_client_deferred* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_deferred_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_checks, in_checks_sz, &o->status, &o->count); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_deferred_encode_status_count; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; -} - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_predicates__status_sum(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const char *sum_key, enum hyperdex_client_returncode* status, uint64_t* count), jstring spacename, jobject predicates, jstring key); - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_predicates__status_sum(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const char *sum_key, enum hyperdex_client_returncode* status, uint64_t* count), jstring spacename, jobject predicates, jstring key) -{ - const char* in_space; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - const char* in_sum_key; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); - struct hyperdex_java_client_deferred* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_deferred_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); - if (success < 0) return 0; - success = hyperdex_java_client_convert_sum_key(env, obj, o->arena, key, &in_sum_key); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_checks, in_checks_sz, in_sum_key, &o->status, &o->count); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_deferred_encode_status_count; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; -} - - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key_mapattributes__status(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status), jstring spacename, jobject key, jobject mapattributes); - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key_mapattributes__status(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status), jstring spacename, jobject key, jobject mapattributes) -{ - const char* in_space; - const char* in_key; - size_t in_key_sz; - const struct hyperdex_client_map_attribute* in_mapattrs; - size_t in_mapattrs_sz; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); - struct hyperdex_java_client_deferred* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_deferred_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); - if (success < 0) return 0; - success = hyperdex_java_client_convert_mapattributes(env, obj, o->arena, mapattributes, &in_mapattrs, &in_mapattrs_sz); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_key, in_key_sz, in_mapattrs, in_mapattrs_sz, &o->status); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_deferred_encode_status; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; -} - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status), jstring spacename, jobject key, jobject predicates, jobject mapattributes); - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status), jstring spacename, jobject key, jobject predicates, jobject mapattributes) -{ - const char* in_space; - const char* in_key; - size_t in_key_sz; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - const struct hyperdex_client_map_attribute* in_mapattrs; - size_t in_mapattrs_sz; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); - struct hyperdex_java_client_deferred* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_deferred_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); - if (success < 0) return 0; - success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); - if (success < 0) return 0; - success = hyperdex_java_client_convert_mapattributes(env, obj, o->arena, mapattributes, &in_mapattrs, &in_mapattrs_sz); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_key, in_key_sz, in_checks, in_checks_sz, in_mapattrs, in_mapattrs_sz, &o->status); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_deferred_encode_status; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; -} - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status, uint64_t* count), jstring spacename, jobject predicates, jobject mapattributes); - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status, uint64_t* count), jstring spacename, jobject predicates, jobject mapattributes) -{ - const char* in_space; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - const struct hyperdex_client_map_attribute* in_mapattrs; - size_t in_mapattrs_sz; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); - struct hyperdex_java_client_deferred* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_deferred_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); - if (success < 0) return 0; - success = hyperdex_java_client_convert_mapattributes(env, obj, o->arena, mapattributes, &in_mapattrs, &in_mapattrs_sz); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_checks, in_checks_sz, in_mapattrs, in_mapattrs_sz, &o->status, &o->count); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_deferred_encode_status_count; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; -} - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_iterator__spacename_predicates__status_attributes(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), jstring spacename, jobject predicates); - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_iterator__spacename_predicates__status_attributes(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), jstring spacename, jobject predicates) -{ - const char* in_space; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _iterator, _iterator_init, obj); - struct hyperdex_java_client_iterator* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_iterator_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_checks, in_checks_sz, &o->status, &o->attrs, &o->attrs_sz); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_iterator_encode_status_attributes; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; +hyperdex_java_client_asynccall__spacename_key__status_attributes(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), jstring spacename, jobject key); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key__status_attributes(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), jstring spacename, jobject key) +{ + const char *in_space; + const char *in_key; + size_t in_key_sz; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); + struct hyperdex_java_client_deferred *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_deferred_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_key, in_key_sz, &o->status, &o->attrs, &o->attrs_sz); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_deferred_encode_status_attributes; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; +} + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key_attributenames__status_attributes(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const char **attrnames, size_t attrnames_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), jstring spacename, jobject key, jobject attributenames); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key_attributenames__status_attributes(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const char **attrnames, size_t attrnames_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), jstring spacename, jobject key, jobject attributenames) +{ + const char *in_space; + const char *in_key; + size_t in_key_sz; + const char **in_attrnames; + size_t in_attrnames_sz; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); + struct hyperdex_java_client_deferred *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_deferred_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); + if (success < 0) return 0; + success = hyperdex_java_client_convert_attributenames(env, obj, o->arena, attributenames, &in_attrnames, &in_attrnames_sz); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_key, in_key_sz, in_attrnames, in_attrnames_sz, &o->status, &o->attrs, &o->attrs_sz); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_deferred_encode_status_attributes; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; +} + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key_attributes__status(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status), jstring spacename, jobject key, jobject attributes); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key_attributes__status(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status), jstring spacename, jobject key, jobject attributes) +{ + const char *in_space; + const char *in_key; + size_t in_key_sz; + const struct hyperdex_client_attribute *in_attrs; + size_t in_attrs_sz; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); + struct hyperdex_java_client_deferred *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_deferred_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); + if (success < 0) return 0; + success = hyperdex_java_client_convert_attributes(env, obj, o->arena, attributes, &in_attrs, &in_attrs_sz); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_key, in_key_sz, in_attrs, in_attrs_sz, &o->status); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_deferred_encode_status; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; +} + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status), jstring spacename, jobject key, jobject predicates, jobject attributes); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status), jstring spacename, jobject key, jobject predicates, jobject attributes) +{ + const char *in_space; + const char *in_key; + size_t in_key_sz; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + const struct hyperdex_client_attribute *in_attrs; + size_t in_attrs_sz; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); + struct hyperdex_java_client_deferred *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_deferred_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); + if (success < 0) return 0; + success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); + if (success < 0) return 0; + success = hyperdex_java_client_convert_attributes(env, obj, o->arena, attributes, &in_attrs, &in_attrs_sz); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_key, in_key_sz, in_checks, in_checks_sz, in_attrs, in_attrs_sz, &o->status); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_deferred_encode_status; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; +} + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status, uint64_t *count), jstring spacename, jobject predicates, jobject attributes); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status, uint64_t *count), jstring spacename, jobject predicates, jobject attributes) +{ + const char *in_space; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + const struct hyperdex_client_attribute *in_attrs; + size_t in_attrs_sz; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); + struct hyperdex_java_client_deferred *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_deferred_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); + if (success < 0) return 0; + success = hyperdex_java_client_convert_attributes(env, obj, o->arena, attributes, &in_attrs, &in_attrs_sz); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_checks, in_checks_sz, in_attrs, in_attrs_sz, &o->status, &o->count); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_deferred_encode_status_count; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; +} + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key__status(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, enum hyperdex_client_returncode *status), jstring spacename, jobject key); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key__status(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, enum hyperdex_client_returncode *status), jstring spacename, jobject key) +{ + const char *in_space; + const char *in_key; + size_t in_key_sz; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); + struct hyperdex_java_client_deferred *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_deferred_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_key, in_key_sz, &o->status); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_deferred_encode_status; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; +} + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key_predicates__status(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status), jstring spacename, jobject key, jobject predicates); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key_predicates__status(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status), jstring spacename, jobject key, jobject predicates) +{ + const char *in_space; + const char *in_key; + size_t in_key_sz; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); + struct hyperdex_java_client_deferred *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_deferred_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); + if (success < 0) return 0; + success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_key, in_key_sz, in_checks, in_checks_sz, &o->status); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_deferred_encode_status; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; +} + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_predicates__status_count(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, uint64_t *count), jstring spacename, jobject predicates); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_predicates__status_count(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, uint64_t *count), jstring spacename, jobject predicates) +{ + const char *in_space; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); + struct hyperdex_java_client_deferred *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_deferred_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_checks, in_checks_sz, &o->status, &o->count); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_deferred_encode_status_count; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; +} + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_predicates__status_sum(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const char *sum_key, enum hyperdex_client_returncode *status, uint64_t *count), jstring spacename, jobject predicates, jstring key); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_predicates__status_sum(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const char *sum_key, enum hyperdex_client_returncode *status, uint64_t *count), jstring spacename, jobject predicates, jstring key) +{ + const char *in_space; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + const char *in_sum_key; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); + struct hyperdex_java_client_deferred *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_deferred_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); + if (success < 0) return 0; + success = hyperdex_java_client_convert_sum_key(env, obj, o->arena, key, &in_sum_key); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_checks, in_checks_sz, in_sum_key, &o->status, &o->count); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_deferred_encode_status_count; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; +} + + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key_mapattributes__status(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status), jstring spacename, jobject key, jobject mapattributes); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key_mapattributes__status(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status), jstring spacename, jobject key, jobject mapattributes) +{ + const char *in_space; + const char *in_key; + size_t in_key_sz; + const struct hyperdex_client_map_attribute *in_mapattrs; + size_t in_mapattrs_sz; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); + struct hyperdex_java_client_deferred *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_deferred_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); + if (success < 0) return 0; + success = hyperdex_java_client_convert_mapattributes(env, obj, o->arena, mapattributes, &in_mapattrs, &in_mapattrs_sz); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_key, in_key_sz, in_mapattrs, in_mapattrs_sz, &o->status); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_deferred_encode_status; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; +} + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status), jstring spacename, jobject key, jobject predicates, jobject mapattributes); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status), jstring spacename, jobject key, jobject predicates, jobject mapattributes) +{ + const char *in_space; + const char *in_key; + size_t in_key_sz; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + const struct hyperdex_client_map_attribute *in_mapattrs; + size_t in_mapattrs_sz; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); + struct hyperdex_java_client_deferred *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_deferred_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_key(env, obj, o->arena, key, &in_key, &in_key_sz); + if (success < 0) return 0; + success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); + if (success < 0) return 0; + success = hyperdex_java_client_convert_mapattributes(env, obj, o->arena, mapattributes, &in_mapattrs, &in_mapattrs_sz); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_key, in_key_sz, in_checks, in_checks_sz, in_mapattrs, in_mapattrs_sz, &o->status); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_deferred_encode_status; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; +} + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status, uint64_t *count), jstring spacename, jobject predicates, jobject mapattributes); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status, uint64_t *count), jstring spacename, jobject predicates, jobject mapattributes) +{ + const char *in_space; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + const struct hyperdex_client_map_attribute *in_mapattrs; + size_t in_mapattrs_sz; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); + struct hyperdex_java_client_deferred *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_deferred_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); + if (success < 0) return 0; + success = hyperdex_java_client_convert_mapattributes(env, obj, o->arena, mapattributes, &in_mapattrs, &in_mapattrs_sz); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_checks, in_checks_sz, in_mapattrs, in_mapattrs_sz, &o->status, &o->count); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_deferred_encode_status_count; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; +} + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_iterator__spacename_predicates__status_attributes(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), jstring spacename, jobject predicates); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_iterator__spacename_predicates__status_attributes(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), jstring spacename, jobject predicates) +{ + const char *in_space; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _iterator, _iterator_init, obj); + struct hyperdex_java_client_iterator *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_iterator_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_checks, in_checks_sz, &o->status, &o->attrs, &o->attrs_sz); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_iterator_encode_status_attributes; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; +} + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_predicates__status_description(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, const char **description), jstring spacename, jobject predicates); + +JNIEXPORT HYPERDEX_API jobject JNICALL +hyperdex_java_client_asynccall__spacename_predicates__status_description(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, const char **description), jstring spacename, jobject predicates) +{ + const char *in_space; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); + struct hyperdex_java_client_deferred *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_deferred_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_checks, in_checks_sz, &o->status, &o->description); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_deferred_encode_status_description; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; } JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_predicates__status_description(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, const char** description), jstring spacename, jobject predicates); +hyperdex_java_client_iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const char *sort_by, uint64_t limit, int maxmin, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), jstring spacename, jobject predicates, jstring sortby, jint limit, jboolean maxmin); JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_asynccall__spacename_predicates__status_description(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, const char** description), jstring spacename, jobject predicates) +hyperdex_java_client_iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(JNIEnv *env, jobject obj, int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const char *sort_by, uint64_t limit, int maxmin, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), jstring spacename, jobject predicates, jstring sortby, jint limit, jboolean maxmin) { - const char* in_space; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, obj); - struct hyperdex_java_client_deferred* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_deferred_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_checks, in_checks_sz, &o->status, &o->description); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_deferred_encode_status_description; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; -} - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const char* sort_by, uint64_t limit, int maxmin, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), jstring spacename, jobject predicates, jstring sortby, jint limit, jboolean maxmin); - -JNIEXPORT HYPERDEX_API jobject JNICALL -hyperdex_java_client_iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(JNIEnv* env, jobject obj, int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const char* sort_by, uint64_t limit, int maxmin, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), jstring spacename, jobject predicates, jstring sortby, jint limit, jboolean maxmin) -{ - const char* in_space; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - const char* in_sort_by; - uint64_t in_limit; - int in_maxmin; - int success = 0; - struct hyperdex_client* client = hyperdex_get_client_ptr(env, obj); - jobject op = (*env)->NewObject(env, _iterator, _iterator_init, obj); - struct hyperdex_java_client_iterator* o = NULL; - ERROR_CHECK(0); - o = hyperdex_get_iterator_ptr(env, op); - ERROR_CHECK(0); - success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); - if (success < 0) return 0; - success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); - if (success < 0) return 0; - success = hyperdex_java_client_convert_sortby(env, obj, o->arena, sortby, &in_sort_by); - if (success < 0) return 0; - success = hyperdex_java_client_convert_limit(env, obj, o->arena, limit, &in_limit); - if (success < 0) return 0; - success = hyperdex_java_client_convert_maxmin(env, obj, o->arena, maxmin, &in_maxmin); - if (success < 0) return 0; - o->reqid = f(client, in_space, in_checks, in_checks_sz, in_sort_by, in_limit, in_maxmin, &o->status, &o->attrs, &o->attrs_sz); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); - return 0; - } - - o->encode_return = hyperdex_java_client_iterator_encode_status_attributes; - (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; + const char *in_space; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + const char *in_sort_by; + uint64_t in_limit; + int in_maxmin; + int success = 0; + struct hyperdex_client *client = hyperdex_get_client_ptr(env, obj); + jobject op = (*env)->NewObject(env, _iterator, _iterator_init, obj); + struct hyperdex_java_client_iterator *o = NULL; + ERROR_CHECK(0); + o = hyperdex_get_iterator_ptr(env, op); + ERROR_CHECK(0); + success = hyperdex_java_client_convert_spacename(env, obj, o->arena, spacename, &in_space); + if (success < 0) return 0; + success = hyperdex_java_client_convert_predicates(env, obj, o->arena, predicates, &in_checks, &in_checks_sz); + if (success < 0) return 0; + success = hyperdex_java_client_convert_sortby(env, obj, o->arena, sortby, &in_sort_by); + if (success < 0) return 0; + success = hyperdex_java_client_convert_limit(env, obj, o->arena, limit, &in_limit); + if (success < 0) return 0; + success = hyperdex_java_client_convert_maxmin(env, obj, o->arena, maxmin, &in_maxmin); + if (success < 0) return 0; + o->reqid = f(client, in_space, in_checks, in_checks_sz, in_sort_by, in_limit, in_maxmin, &o->status, &o->attrs, &o->attrs_sz); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client)); + return 0; + } + o->encode_return = hyperdex_java_client_iterator_encode_status_attributes; + (*env)->CallObjectMethod(env, obj, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1get(JNIEnv* env, jobject obj, jstring spacename, jobject key) +Java_org_hyperdex_client_Client_async_1get(JNIEnv *env, jobject obj, jstring spacename, jobject key) { - return hyperdex_java_client_asynccall__spacename_key__status_attributes(env, obj, hyperdex_client_get, spacename, key); + return hyperdex_java_client_asynccall__spacename_key__status_attributes(env, obj, hyperdex_client_get, spacename, key); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1get_1partial(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributenames) +Java_org_hyperdex_client_Client_async_1get_1partial(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributenames) { - return hyperdex_java_client_asynccall__spacename_key_attributenames__status_attributes(env, obj, hyperdex_client_get_partial, spacename, key, attributenames); + return hyperdex_java_client_asynccall__spacename_key_attributenames__status_attributes(env, obj, hyperdex_client_get_partial, spacename, key, attributenames); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1put(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1put(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_put, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_put, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1put(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1put(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_put, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_put, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1put_1or_1create(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1put_1or_1create(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_put_or_create, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_put_or_create, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1put(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1put(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_put, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_put, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1put_1if_1not_1exist(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1put_1if_1not_1exist(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_put_if_not_exist, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_put_if_not_exist, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1del(JNIEnv* env, jobject obj, jstring spacename, jobject key) +Java_org_hyperdex_client_Client_async_1del(JNIEnv *env, jobject obj, jstring spacename, jobject key) { - return hyperdex_java_client_asynccall__spacename_key__status(env, obj, hyperdex_client_del, spacename, key); + return hyperdex_java_client_asynccall__spacename_key__status(env, obj, hyperdex_client_del, spacename, key); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1del(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates) +Java_org_hyperdex_client_Client_async_1cond_1del(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates) { - return hyperdex_java_client_asynccall__spacename_key_predicates__status(env, obj, hyperdex_client_cond_del, spacename, key, predicates); + return hyperdex_java_client_asynccall__spacename_key_predicates__status(env, obj, hyperdex_client_cond_del, spacename, key, predicates); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1del(JNIEnv* env, jobject obj, jstring spacename, jobject predicates) +Java_org_hyperdex_client_Client_async_1group_1del(JNIEnv *env, jobject obj, jstring spacename, jobject predicates) { - return hyperdex_java_client_asynccall__spacename_predicates__status_count(env, obj, hyperdex_client_group_del, spacename, predicates); + return hyperdex_java_client_asynccall__spacename_predicates__status_count(env, obj, hyperdex_client_group_del, spacename, predicates); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1atomic_1add(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1atomic_1add(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_add, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_add, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1atomic_1add(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1atomic_1add(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_add, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_add, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1atomic_1add(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1atomic_1add(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_add, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_add, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1atomic_1sub(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1atomic_1sub(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_sub, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_sub, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1atomic_1sub(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1atomic_1sub(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_sub, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_sub, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1atomic_1sub(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1atomic_1sub(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_sub, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_sub, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1atomic_1mul(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1atomic_1mul(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_mul, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_mul, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1atomic_1mul(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1atomic_1mul(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_mul, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_mul, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1atomic_1mul(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1atomic_1mul(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_mul, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_mul, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1atomic_1div(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1atomic_1div(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_div, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_div, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1atomic_1div(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1atomic_1div(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_div, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_div, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1atomic_1div(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1atomic_1div(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_div, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_div, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1atomic_1mod(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1atomic_1mod(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_mod, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_mod, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1atomic_1mod(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1atomic_1mod(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_mod, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_mod, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1atomic_1mod(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1atomic_1mod(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_mod, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_mod, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1atomic_1and(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1atomic_1and(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_and, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_and, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1atomic_1and(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1atomic_1and(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_and, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_and, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1atomic_1and(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1atomic_1and(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_and, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_and, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1atomic_1or(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1atomic_1or(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_or, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_or, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1atomic_1or(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1atomic_1or(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_or, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_or, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1atomic_1or(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1atomic_1or(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_or, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_or, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1atomic_1xor(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1atomic_1xor(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_xor, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_xor, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1atomic_1xor(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1atomic_1xor(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_xor, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_xor, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1atomic_1xor(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1atomic_1xor(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_xor, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_xor, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1atomic_1min(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1atomic_1min(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_min, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_min, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1atomic_1min(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1atomic_1min(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_min, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_min, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1atomic_1min(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1atomic_1min(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_min, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_min, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1atomic_1max(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1atomic_1max(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_max, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_atomic_max, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1atomic_1max(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1atomic_1max(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_max, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_atomic_max, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1atomic_1max(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1atomic_1max(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_max, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_atomic_max, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1string_1prepend(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1string_1prepend(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_string_prepend, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_string_prepend, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1string_1prepend(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1string_1prepend(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_string_prepend, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_string_prepend, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1string_1prepend(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1string_1prepend(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_string_prepend, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_string_prepend, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1string_1append(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1string_1append(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_string_append, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_string_append, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1string_1append(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1string_1append(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_string_append, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_string_append, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1string_1append(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1string_1append(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_string_append, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_string_append, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1string_1ltrim(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1string_1ltrim(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_string_ltrim, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_string_ltrim, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1string_1ltrim(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1string_1ltrim(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_string_ltrim, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_string_ltrim, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1string_1ltrim(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1string_1ltrim(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_string_ltrim, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_string_ltrim, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1string_1rtrim(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1string_1rtrim(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_string_rtrim, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_string_rtrim, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1string_1rtrim(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1string_1rtrim(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_string_rtrim, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_string_rtrim, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1string_1rtrim(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1string_1rtrim(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_string_rtrim, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_string_rtrim, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1list_1lpush(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1list_1lpush(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_list_lpush, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_list_lpush, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1list_1lpush(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1list_1lpush(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_list_lpush, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_list_lpush, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1list_1lpush(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1list_1lpush(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_list_lpush, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_list_lpush, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1list_1rpush(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1list_1rpush(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_list_rpush, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_list_rpush, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1list_1rpush(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1list_1rpush(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_list_rpush, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_list_rpush, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1list_1rpush(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1list_1rpush(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_list_rpush, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_list_rpush, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1set_1add(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1set_1add(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_set_add, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_set_add, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1set_1add(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1set_1add(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_set_add, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_set_add, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1set_1add(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1set_1add(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_set_add, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_set_add, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1set_1remove(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1set_1remove(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_set_remove, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_set_remove, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1set_1remove(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1set_1remove(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_set_remove, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_set_remove, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1set_1remove(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1set_1remove(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_set_remove, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_set_remove, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1set_1intersect(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1set_1intersect(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_set_intersect, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_set_intersect, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1set_1intersect(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1set_1intersect(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_set_intersect, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_set_intersect, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1set_1intersect(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1set_1intersect(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_set_intersect, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_set_intersect, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1set_1union(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1set_1union(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_set_union, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_set_union, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1set_1union(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1set_1union(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_set_union, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_set_union, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1set_1union(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1set_1union(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_set_union, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_set_union, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1document_1rename(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1document_1rename(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_document_rename, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_document_rename, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1document_1rename(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1document_1rename(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_document_rename, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_document_rename, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1document_1rename(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1document_1rename(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_document_rename, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_document_rename, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1document_1unset(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1document_1unset(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_document_unset, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_document_unset, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1document_1unset(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1document_1unset(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_document_unset, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_document_unset, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1document_1unset(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1document_1unset(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_document_unset, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_document_unset, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1map_1add(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1map_1add(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_add, spacename, key, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_add, spacename, key, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1map_1add(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1cond_1map_1add(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_add, spacename, key, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_add, spacename, key, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1map_1add(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1group_1map_1add(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_add, spacename, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_add, spacename, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1map_1remove(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject attributes) +Java_org_hyperdex_client_Client_async_1map_1remove(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_map_remove, spacename, key, attributes); + return hyperdex_java_client_asynccall__spacename_key_attributes__status(env, obj, hyperdex_client_map_remove, spacename, key, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1map_1remove(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1cond_1map_1remove(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_map_remove, spacename, key, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_attributes__status(env, obj, hyperdex_client_cond_map_remove, spacename, key, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1map_1remove(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject attributes) +Java_org_hyperdex_client_Client_async_1group_1map_1remove(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject attributes) { - return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_map_remove, spacename, predicates, attributes); + return hyperdex_java_client_asynccall__spacename_predicates_attributes__status_count(env, obj, hyperdex_client_group_map_remove, spacename, predicates, attributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1map_1atomic_1add(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1map_1atomic_1add(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_add, spacename, key, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_add, spacename, key, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1add(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1add(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_add, spacename, key, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_add, spacename, key, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1add(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1add(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_add, spacename, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_add, spacename, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1map_1atomic_1sub(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1map_1atomic_1sub(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_sub, spacename, key, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_sub, spacename, key, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1sub(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1sub(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_sub, spacename, key, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_sub, spacename, key, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1sub(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1sub(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_sub, spacename, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_sub, spacename, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1map_1atomic_1mul(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1map_1atomic_1mul(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_mul, spacename, key, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_mul, spacename, key, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1mul(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1mul(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_mul, spacename, key, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_mul, spacename, key, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1mul(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1mul(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_mul, spacename, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_mul, spacename, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1map_1atomic_1div(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1map_1atomic_1div(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_div, spacename, key, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_div, spacename, key, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1div(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1div(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_div, spacename, key, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_div, spacename, key, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1div(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1div(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_div, spacename, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_div, spacename, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1map_1atomic_1mod(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1map_1atomic_1mod(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_mod, spacename, key, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_mod, spacename, key, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1mod(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1mod(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_mod, spacename, key, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_mod, spacename, key, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1mod(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1mod(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_mod, spacename, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_mod, spacename, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1map_1atomic_1and(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1map_1atomic_1and(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_and, spacename, key, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_and, spacename, key, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1and(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1and(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_and, spacename, key, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_and, spacename, key, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1and(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1and(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_and, spacename, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_and, spacename, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1map_1atomic_1or(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1map_1atomic_1or(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_or, spacename, key, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_or, spacename, key, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1or(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1or(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_or, spacename, key, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_or, spacename, key, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1or(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1or(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_or, spacename, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_or, spacename, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1map_1atomic_1xor(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1map_1atomic_1xor(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_xor, spacename, key, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_xor, spacename, key, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1xor(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1xor(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_xor, spacename, key, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_xor, spacename, key, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1xor(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1xor(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_xor, spacename, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_xor, spacename, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1map_1string_1prepend(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1map_1string_1prepend(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_string_prepend, spacename, key, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_string_prepend, spacename, key, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1map_1string_1prepend(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1cond_1map_1string_1prepend(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_string_prepend, spacename, key, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_string_prepend, spacename, key, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1map_1string_1prepend(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1group_1map_1string_1prepend(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_string_prepend, spacename, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_string_prepend, spacename, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1map_1string_1append(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1map_1string_1append(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_string_append, spacename, key, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_string_append, spacename, key, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1map_1string_1append(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1cond_1map_1string_1append(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_string_append, spacename, key, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_string_append, spacename, key, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1map_1string_1append(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1group_1map_1string_1append(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_string_append, spacename, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_string_append, spacename, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1map_1atomic_1min(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1map_1atomic_1min(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_min, spacename, key, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_min, spacename, key, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1min(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1min(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_min, spacename, key, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_min, spacename, key, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1min(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1min(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_min, spacename, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_min, spacename, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1map_1atomic_1max(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1map_1atomic_1max(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_max, spacename, key, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_mapattributes__status(env, obj, hyperdex_client_map_atomic_max, spacename, key, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1max(JNIEnv* env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1max(JNIEnv *env, jobject obj, jstring spacename, jobject key, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_max, spacename, key, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_key_predicates_mapattributes__status(env, obj, hyperdex_client_cond_map_atomic_max, spacename, key, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1max(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) +Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1max(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jobject mapattributes) { - return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_max, spacename, predicates, mapattributes); + return hyperdex_java_client_asynccall__spacename_predicates_mapattributes__status_count(env, obj, hyperdex_client_group_map_atomic_max, spacename, predicates, mapattributes); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_search(JNIEnv* env, jobject obj, jstring spacename, jobject predicates) +Java_org_hyperdex_client_Client_search(JNIEnv *env, jobject obj, jstring spacename, jobject predicates) { - return hyperdex_java_client_iterator__spacename_predicates__status_attributes(env, obj, hyperdex_client_search, spacename, predicates); + return hyperdex_java_client_iterator__spacename_predicates__status_attributes(env, obj, hyperdex_client_search, spacename, predicates); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1search_1describe(JNIEnv* env, jobject obj, jstring spacename, jobject predicates) +Java_org_hyperdex_client_Client_async_1search_1describe(JNIEnv *env, jobject obj, jstring spacename, jobject predicates) { - return hyperdex_java_client_asynccall__spacename_predicates__status_description(env, obj, hyperdex_client_search_describe, spacename, predicates); + return hyperdex_java_client_asynccall__spacename_predicates__status_description(env, obj, hyperdex_client_search_describe, spacename, predicates); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_sorted_1search(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jstring sortby, jint limit, jboolean maxmin) +Java_org_hyperdex_client_Client_sorted_1search(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jstring sortby, jint limit, jboolean maxmin) { - return hyperdex_java_client_iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(env, obj, hyperdex_client_sorted_search, spacename, predicates, sortby, limit, maxmin); + return hyperdex_java_client_iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(env, obj, hyperdex_client_sorted_search, spacename, predicates, sortby, limit, maxmin); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1count(JNIEnv* env, jobject obj, jstring spacename, jobject predicates) +Java_org_hyperdex_client_Client_async_1count(JNIEnv *env, jobject obj, jstring spacename, jobject predicates) { - return hyperdex_java_client_asynccall__spacename_predicates__status_count(env, obj, hyperdex_client_count, spacename, predicates); + return hyperdex_java_client_asynccall__spacename_predicates__status_count(env, obj, hyperdex_client_count, spacename, predicates); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Client_async_1sum(JNIEnv* env, jobject obj, jstring spacename, jobject predicates, jstring key) +Java_org_hyperdex_client_Client_async_1sum(JNIEnv *env, jobject obj, jstring spacename, jobject predicates, jstring key) { - return hyperdex_java_client_asynccall__spacename_predicates__status_sum(env, obj, hyperdex_client_sum, spacename, predicates, key); + return hyperdex_java_client_asynccall__spacename_predicates__status_sum(env, obj, hyperdex_client_sum, spacename, predicates, key); } diff --git a/bindings/java/org_hyperdex_client_Client.h b/bindings/java/org_hyperdex_client_Client.h index c2b1775ac..70f7e127e 100644 --- a/bindings/java/org_hyperdex_client_Client.h +++ b/bindings/java/org_hyperdex_client_Client.h @@ -13,7 +13,7 @@ extern "C" { * Signature: ()V */ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Client_initialize - (JNIEnv *, jclass); +(JNIEnv *, jclass); /* * Class: org_hyperdex_client_Client @@ -21,7 +21,7 @@ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Client_initialize * Signature: ()V */ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Client_terminate - (JNIEnv *, jclass); +(JNIEnv *, jclass); /* * Class: org_hyperdex_client_Client @@ -29,7 +29,7 @@ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Client_terminate * Signature: (Ljava/lang/String;I)V */ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Client__1create - (JNIEnv *, jobject, jstring, jint); +(JNIEnv *, jobject, jstring, jint); /* * Class: org_hyperdex_client_Client @@ -37,7 +37,7 @@ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Client__1create * Signature: ()V */ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Client__1destroy - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_Client @@ -45,7 +45,7 @@ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Client__1destroy * Signature: ()J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_Client_inner_1loop - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_Client @@ -53,7 +53,7 @@ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_Client_inner_1loop * Signature: (Ljava/lang/String;Ljava/lang/Object;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1get - (JNIEnv *, jobject, jstring, jobject); +(JNIEnv *, jobject, jstring, jobject); /* * Class: org_hyperdex_client_Client @@ -61,7 +61,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ge * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/List;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1get_1partial - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -69,7 +69,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ge * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1put - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -77,7 +77,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1pu * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1put - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -85,7 +85,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1put_1or_1create - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -93,7 +93,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1put - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -101,7 +101,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1put_1if_1not_1exist - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -109,7 +109,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1pu * Signature: (Ljava/lang/String;Ljava/lang/Object;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1del - (JNIEnv *, jobject, jstring, jobject); +(JNIEnv *, jobject, jstring, jobject); /* * Class: org_hyperdex_client_Client @@ -117,7 +117,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1de * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1del - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -125,7 +125,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1del - (JNIEnv *, jobject, jstring, jobject); +(JNIEnv *, jobject, jstring, jobject); /* * Class: org_hyperdex_client_Client @@ -133,7 +133,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1atomic_1add - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -141,7 +141,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1at * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1atomic_1add - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -149,7 +149,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1atomic_1add - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -157,7 +157,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1atomic_1sub - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -165,7 +165,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1at * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1atomic_1sub - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -173,7 +173,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1atomic_1sub - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -181,7 +181,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1atomic_1mul - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -189,7 +189,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1at * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1atomic_1mul - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -197,7 +197,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1atomic_1mul - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -205,7 +205,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1atomic_1div - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -213,7 +213,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1at * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1atomic_1div - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -221,7 +221,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1atomic_1div - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -229,7 +229,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1atomic_1mod - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -237,7 +237,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1at * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1atomic_1mod - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -245,7 +245,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1atomic_1mod - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -253,7 +253,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1atomic_1and - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -261,7 +261,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1at * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1atomic_1and - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -269,7 +269,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1atomic_1and - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -277,7 +277,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1atomic_1or - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -285,7 +285,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1at * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1atomic_1or - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -293,7 +293,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1atomic_1or - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -301,7 +301,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1atomic_1xor - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -309,7 +309,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1at * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1atomic_1xor - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -317,7 +317,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1atomic_1xor - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -325,7 +325,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1atomic_1min - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -333,7 +333,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1at * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1atomic_1min - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -341,7 +341,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1atomic_1min - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -349,7 +349,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1atomic_1max - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -357,7 +357,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1at * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1atomic_1max - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -365,7 +365,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1atomic_1max - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -373,7 +373,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1string_1prepend - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -381,7 +381,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1st * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1string_1prepend - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -389,7 +389,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1string_1prepend - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -397,7 +397,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1string_1append - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -405,7 +405,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1st * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1string_1append - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -413,7 +413,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1string_1append - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -421,7 +421,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1string_1ltrim - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -429,7 +429,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1st * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1string_1ltrim - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -437,7 +437,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1string_1ltrim - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -445,7 +445,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1string_1rtrim - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -453,7 +453,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1st * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1string_1rtrim - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -461,7 +461,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1string_1rtrim - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -469,7 +469,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1list_1lpush - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -477,7 +477,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1li * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1list_1lpush - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -485,7 +485,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1list_1lpush - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -493,7 +493,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1list_1rpush - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -501,7 +501,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1li * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1list_1rpush - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -509,7 +509,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1list_1rpush - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -517,7 +517,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1set_1add - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -525,7 +525,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1se * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1set_1add - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -533,7 +533,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1set_1add - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -541,7 +541,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1set_1remove - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -549,7 +549,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1se * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1set_1remove - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -557,7 +557,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1set_1remove - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -565,7 +565,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1set_1intersect - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -573,7 +573,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1se * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1set_1intersect - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -581,7 +581,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1set_1intersect - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -589,7 +589,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1set_1union - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -597,7 +597,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1se * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1set_1union - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -605,7 +605,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1set_1union - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -613,7 +613,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1document_1rename - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -621,7 +621,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1do * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1document_1rename - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -629,7 +629,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1document_1rename - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -637,7 +637,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1document_1unset - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -645,7 +645,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1do * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1document_1unset - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -653,7 +653,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1document_1unset - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -661,7 +661,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1map_1add - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -669,7 +669,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ma * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1map_1add - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -677,7 +677,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1map_1add - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -685,7 +685,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1map_1remove - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -693,7 +693,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ma * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1map_1remove - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -701,7 +701,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1map_1remove - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -709,7 +709,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1map_1atomic_1add - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -717,7 +717,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ma * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1add - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -725,7 +725,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1add - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -733,7 +733,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1map_1atomic_1sub - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -741,7 +741,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ma * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1sub - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -749,7 +749,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1sub - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -757,7 +757,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1map_1atomic_1mul - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -765,7 +765,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ma * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1mul - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -773,7 +773,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1mul - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -781,7 +781,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1map_1atomic_1div - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -789,7 +789,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ma * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1div - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -797,7 +797,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1div - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -805,7 +805,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1map_1atomic_1mod - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -813,7 +813,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ma * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1mod - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -821,7 +821,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1mod - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -829,7 +829,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1map_1atomic_1and - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -837,7 +837,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ma * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1and - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -845,7 +845,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1and - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -853,7 +853,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1map_1atomic_1or - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -861,7 +861,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ma * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1or - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -869,7 +869,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1or - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -877,7 +877,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1map_1atomic_1xor - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -885,7 +885,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ma * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1xor - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -893,7 +893,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1xor - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -901,7 +901,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1map_1string_1prepend - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -909,7 +909,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ma * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1map_1string_1prepend - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -917,7 +917,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1map_1string_1prepend - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -925,7 +925,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1map_1string_1append - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -933,7 +933,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ma * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1map_1string_1append - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -941,7 +941,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1map_1string_1append - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -949,7 +949,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1map_1atomic_1min - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -957,7 +957,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ma * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1min - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -965,7 +965,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1min - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -973,7 +973,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1map_1atomic_1max - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -981,7 +981,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1ma * Signature: (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1cond_1map_1atomic_1max - (JNIEnv *, jobject, jstring, jobject, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -989,7 +989,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1group_1map_1atomic_1max - (JNIEnv *, jobject, jstring, jobject, jobject); +(JNIEnv *, jobject, jstring, jobject, jobject); /* * Class: org_hyperdex_client_Client @@ -997,7 +997,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1gr * Signature: (Ljava/lang/String;Ljava/util/Map;)Lorg/hyperdex/client/Iterator; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_search - (JNIEnv *, jobject, jstring, jobject); +(JNIEnv *, jobject, jstring, jobject); /* * Class: org_hyperdex_client_Client @@ -1005,7 +1005,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_search * Signature: (Ljava/lang/String;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1search_1describe - (JNIEnv *, jobject, jstring, jobject); +(JNIEnv *, jobject, jstring, jobject); /* * Class: org_hyperdex_client_Client @@ -1013,7 +1013,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1se * Signature: (Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;IZ)Lorg/hyperdex/client/Iterator; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_sorted_1search - (JNIEnv *, jobject, jstring, jobject, jstring, jint, jboolean); +(JNIEnv *, jobject, jstring, jobject, jstring, jint, jboolean); /* * Class: org_hyperdex_client_Client @@ -1021,7 +1021,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_sorted_1s * Signature: (Ljava/lang/String;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1count - (JNIEnv *, jobject, jstring, jobject); +(JNIEnv *, jobject, jstring, jobject); /* * Class: org_hyperdex_client_Client @@ -1029,7 +1029,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1co * Signature: (Ljava/lang/String;Ljava/util/Map;)Lorg/hyperdex/client/Deferred; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Client_async_1sum - (JNIEnv *, jobject, jstring, jobject, jstring); +(JNIEnv *, jobject, jstring, jobject, jstring); #ifdef __cplusplus } diff --git a/bindings/java/org_hyperdex_client_Deferred.h b/bindings/java/org_hyperdex_client_Deferred.h index f00a7a699..52eebe22c 100644 --- a/bindings/java/org_hyperdex_client_Deferred.h +++ b/bindings/java/org_hyperdex_client_Deferred.h @@ -13,7 +13,7 @@ extern "C" { * Signature: ()V */ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Deferred__1create - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_Deferred @@ -21,7 +21,7 @@ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Deferred__1create * Signature: ()V */ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Deferred__1destroy - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_Deferred @@ -29,7 +29,7 @@ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Deferred__1destroy * Signature: ()Ljava/lang/Object; */ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Deferred_waitForIt - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_Deferred @@ -37,7 +37,7 @@ JNIEXPORT HYPERDEX_API jobject JNICALL Java_org_hyperdex_client_Deferred_waitFor * Signature: ()V */ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Deferred_callback - (JNIEnv *, jobject); +(JNIEnv *, jobject); #ifdef __cplusplus } diff --git a/bindings/java/org_hyperdex_client_GreaterEqual.h b/bindings/java/org_hyperdex_client_GreaterEqual.h index e2071398b..23666b98b 100644 --- a/bindings/java/org_hyperdex_client_GreaterEqual.h +++ b/bindings/java/org_hyperdex_client_GreaterEqual.h @@ -13,7 +13,7 @@ extern "C" { * Signature: ()J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_GreaterEqual_checksSize - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_GreaterEqual @@ -21,7 +21,7 @@ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_GreaterEqual_check * Signature: (JJJ)J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_GreaterEqual_convertChecks - (JNIEnv *, jobject, jlong, jlong, jlong); +(JNIEnv *, jobject, jlong, jlong, jlong); #ifdef __cplusplus } diff --git a/bindings/java/org_hyperdex_client_GreaterThan.h b/bindings/java/org_hyperdex_client_GreaterThan.h index f9ef32c60..88a5f3f7d 100644 --- a/bindings/java/org_hyperdex_client_GreaterThan.h +++ b/bindings/java/org_hyperdex_client_GreaterThan.h @@ -13,7 +13,7 @@ extern "C" { * Signature: ()J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_GreaterThan_checksSize - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_GreaterThan @@ -21,7 +21,7 @@ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_GreaterThan_checks * Signature: (JJJ)J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_GreaterThan_convertChecks - (JNIEnv *, jobject, jlong, jlong, jlong); +(JNIEnv *, jobject, jlong, jlong, jlong); #ifdef __cplusplus } diff --git a/bindings/java/org_hyperdex_client_Iterator.h b/bindings/java/org_hyperdex_client_Iterator.h index c40147c8a..9f617b1aa 100644 --- a/bindings/java/org_hyperdex_client_Iterator.h +++ b/bindings/java/org_hyperdex_client_Iterator.h @@ -13,7 +13,7 @@ extern "C" { * Signature: ()V */ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Iterator__1create - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_Iterator @@ -21,7 +21,7 @@ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Iterator__1create * Signature: ()V */ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Iterator__1destroy - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_Iterator @@ -29,7 +29,7 @@ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Iterator__1destroy * Signature: ()Z */ JNIEXPORT HYPERDEX_API jboolean JNICALL Java_org_hyperdex_client_Iterator_finished - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_Iterator @@ -37,7 +37,7 @@ JNIEXPORT HYPERDEX_API jboolean JNICALL Java_org_hyperdex_client_Iterator_finish * Signature: ()V */ JNIEXPORT HYPERDEX_API void JNICALL Java_org_hyperdex_client_Iterator_callback - (JNIEnv *, jobject); +(JNIEnv *, jobject); #ifdef __cplusplus } diff --git a/bindings/java/org_hyperdex_client_LengthEquals.h b/bindings/java/org_hyperdex_client_LengthEquals.h index ed29761c8..74568c6cb 100644 --- a/bindings/java/org_hyperdex_client_LengthEquals.h +++ b/bindings/java/org_hyperdex_client_LengthEquals.h @@ -13,7 +13,7 @@ extern "C" { * Signature: ()J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LengthEquals_checksSize - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_LengthEquals @@ -21,7 +21,7 @@ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LengthEquals_check * Signature: (JJJ)J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LengthEquals_convertChecks - (JNIEnv *, jobject, jlong, jlong, jlong); +(JNIEnv *, jobject, jlong, jlong, jlong); #ifdef __cplusplus } diff --git a/bindings/java/org_hyperdex_client_LengthGreaterEqual.h b/bindings/java/org_hyperdex_client_LengthGreaterEqual.h index c79ddaa18..55f344f9a 100644 --- a/bindings/java/org_hyperdex_client_LengthGreaterEqual.h +++ b/bindings/java/org_hyperdex_client_LengthGreaterEqual.h @@ -13,7 +13,7 @@ extern "C" { * Signature: ()J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LengthGreaterEqual_checksSize - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_LengthGreaterEqual @@ -21,7 +21,7 @@ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LengthGreaterEqual * Signature: (JJJ)J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LengthGreaterEqual_convertChecks - (JNIEnv *, jobject, jlong, jlong, jlong); +(JNIEnv *, jobject, jlong, jlong, jlong); #ifdef __cplusplus } diff --git a/bindings/java/org_hyperdex_client_LengthLessEqual.h b/bindings/java/org_hyperdex_client_LengthLessEqual.h index a9948b6e2..fdd87a350 100644 --- a/bindings/java/org_hyperdex_client_LengthLessEqual.h +++ b/bindings/java/org_hyperdex_client_LengthLessEqual.h @@ -13,7 +13,7 @@ extern "C" { * Signature: ()J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LengthLessEqual_checksSize - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_LengthLessEqual @@ -21,7 +21,7 @@ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LengthLessEqual_ch * Signature: (JJJ)J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LengthLessEqual_convertChecks - (JNIEnv *, jobject, jlong, jlong, jlong); +(JNIEnv *, jobject, jlong, jlong, jlong); #ifdef __cplusplus } diff --git a/bindings/java/org_hyperdex_client_LessEqual.h b/bindings/java/org_hyperdex_client_LessEqual.h index 344cc82b8..b5c3da4c4 100644 --- a/bindings/java/org_hyperdex_client_LessEqual.h +++ b/bindings/java/org_hyperdex_client_LessEqual.h @@ -13,7 +13,7 @@ extern "C" { * Signature: ()J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LessEqual_checksSize - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_LessEqual @@ -21,7 +21,7 @@ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LessEqual_checksSi * Signature: (JJJ)J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LessEqual_convertChecks - (JNIEnv *, jobject, jlong, jlong, jlong); +(JNIEnv *, jobject, jlong, jlong, jlong); #ifdef __cplusplus } diff --git a/bindings/java/org_hyperdex_client_LessThan.h b/bindings/java/org_hyperdex_client_LessThan.h index 886a97933..fc4b52c47 100644 --- a/bindings/java/org_hyperdex_client_LessThan.h +++ b/bindings/java/org_hyperdex_client_LessThan.h @@ -13,7 +13,7 @@ extern "C" { * Signature: ()J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LessThan_checksSize - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_LessThan @@ -21,7 +21,7 @@ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LessThan_checksSiz * Signature: (JJJ)J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_LessThan_convertChecks - (JNIEnv *, jobject, jlong, jlong, jlong); +(JNIEnv *, jobject, jlong, jlong, jlong); #ifdef __cplusplus } diff --git a/bindings/java/org_hyperdex_client_Microtransaction.c b/bindings/java/org_hyperdex_client_Microtransaction.c index e34371c9b..946d268d8 100644 --- a/bindings/java/org_hyperdex_client_Microtransaction.c +++ b/bindings/java/org_hyperdex_client_Microtransaction.c @@ -45,9 +45,9 @@ #define ERROR_CHECK_VOID() if ((*env)->ExceptionCheck(env) == JNI_TRUE) return #define REF(NAME, DEF) \ - tmp_cls = (DEF); \ - NAME = (jclass) (*env)->NewGlobalRef(env, tmp_cls); \ - (*env)->DeleteLocalRef(env, tmp_cls); + tmp_cls = (DEF); \ + NAME = (jclass) (*env)->NewGlobalRef(env, tmp_cls); \ + (*env)->DeleteLocalRef(env, tmp_cls); static jclass _uxact; static jfieldID _uxact_client; @@ -68,239 +68,220 @@ static jclass _boolean; static jmethodID _boolean_init; JNIEXPORT HYPERDEX_API void JNICALL -Java_org_hyperdex_client_Microtransaction_initialize(JNIEnv* env, jclass client) +Java_org_hyperdex_client_Microtransaction_initialize(JNIEnv *env, jclass client) { - jclass tmp_cls; - - /* cache class Client */ - REF(_uxact, (*env)->FindClass(env, "org/hyperdex/client/Microtransaction")); - _uxact_client = (*env)->GetFieldID(env, _uxact, "client", "Lorg/hyperdex/client/Client;"); - _uxact_uxact_ptr = (*env)->GetFieldID(env, _uxact, "uxact_ptr", "J"); - _uxact_deferred_ptr = (*env)->GetFieldID(env, _uxact, "deferred_ptr", "J"); - REF(_client, (*env)->FindClass(env, "org/hyperdex/client/Client")); - _client_ptr = (*env)->GetFieldID(env, _client, "ptr", "J"); - _client_add_op = (*env)->GetMethodID(env, _client, "add_op", "(JLorg/hyperdex/client/Operation;)V"); - _client_remove_op = (*env)->GetMethodID(env, _client, "remove_op", "(J)V"); - REF(_deferred, (*env)->FindClass(env, "org/hyperdex/client/Deferred")); - _deferred_ptr = (*env)->GetFieldID(env, _deferred, "ptr", "J"); - _deferred_init = (*env)->GetMethodID(env, _deferred, "", "(Lorg/hyperdex/client/Client;)V"); - _deferred_c = (*env)->GetFieldID(env, _deferred, "c", "Lorg/hyperdex/client/Client;"); - REF(_boolean, (*env)->FindClass(env, "java/lang/Boolean")); - _boolean_init = (*env)->GetMethodID(env, _boolean, "", "(Z)V"); - - CHECK_CACHE(_uxact); - CHECK_CACHE(_uxact_client); - CHECK_CACHE(_uxact_uxact_ptr); - CHECK_CACHE(_uxact_deferred_ptr); - CHECK_CACHE(_client); - CHECK_CACHE(_client_ptr); - CHECK_CACHE(_client_add_op); - CHECK_CACHE(_client_remove_op); - CHECK_CACHE(_boolean); - CHECK_CACHE(_boolean_init); - CHECK_CACHE(_deferred); - CHECK_CACHE(_deferred_init); - CHECK_CACHE(_deferred_c); - CHECK_CACHE(_deferred_ptr); - - ERROR_CHECK_VOID(); + jclass tmp_cls; + /* cache class Client */ + REF(_uxact, (*env)->FindClass(env, "org/hyperdex/client/Microtransaction")); + _uxact_client = (*env)->GetFieldID(env, _uxact, "client", "Lorg/hyperdex/client/Client;"); + _uxact_uxact_ptr = (*env)->GetFieldID(env, _uxact, "uxact_ptr", "J"); + _uxact_deferred_ptr = (*env)->GetFieldID(env, _uxact, "deferred_ptr", "J"); + REF(_client, (*env)->FindClass(env, "org/hyperdex/client/Client")); + _client_ptr = (*env)->GetFieldID(env, _client, "ptr", "J"); + _client_add_op = (*env)->GetMethodID(env, _client, "add_op", "(JLorg/hyperdex/client/Operation;)V"); + _client_remove_op = (*env)->GetMethodID(env, _client, "remove_op", "(J)V"); + REF(_deferred, (*env)->FindClass(env, "org/hyperdex/client/Deferred")); + _deferred_ptr = (*env)->GetFieldID(env, _deferred, "ptr", "J"); + _deferred_init = (*env)->GetMethodID(env, _deferred, "", "(Lorg/hyperdex/client/Client;)V"); + _deferred_c = (*env)->GetFieldID(env, _deferred, "c", "Lorg/hyperdex/client/Client;"); + REF(_boolean, (*env)->FindClass(env, "java/lang/Boolean")); + _boolean_init = (*env)->GetMethodID(env, _boolean, "", "(Z)V"); + CHECK_CACHE(_uxact); + CHECK_CACHE(_uxact_client); + CHECK_CACHE(_uxact_uxact_ptr); + CHECK_CACHE(_uxact_deferred_ptr); + CHECK_CACHE(_client); + CHECK_CACHE(_client_ptr); + CHECK_CACHE(_client_add_op); + CHECK_CACHE(_client_remove_op); + CHECK_CACHE(_boolean); + CHECK_CACHE(_boolean_init); + CHECK_CACHE(_deferred); + CHECK_CACHE(_deferred_init); + CHECK_CACHE(_deferred_c); + CHECK_CACHE(_deferred_ptr); + ERROR_CHECK_VOID(); } static jobject -hyperdex_uxact_get_client(JNIEnv* env, jobject obj) +hyperdex_uxact_get_client(JNIEnv *env, jobject obj) { - jobject c; - c = (*env)->GetObjectField(env, obj, _uxact_client); - assert(c); - return c; + jobject c; + c = (*env)->GetObjectField(env, obj, _uxact_client); + assert(c); + return c; } -static struct hyperdex_client* -hyperdex_uxact_get_client_ptr(JNIEnv* env, jobject obj) +static struct hyperdex_client * +hyperdex_uxact_get_client_ptr(JNIEnv *env, jobject obj) { - jobject c; - struct hyperdex_client* x; - c = hyperdex_uxact_get_client(env, obj); - x = (struct hyperdex_client*) (*env)->GetLongField(env, c, _client_ptr); - assert(x); - return x; + jobject c; + struct hyperdex_client *x; + c = hyperdex_uxact_get_client(env, obj); + x = (struct hyperdex_client *) (*env)->GetLongField(env, c, _client_ptr); + assert(x); + return x; } -static struct hyperdex_client* -hyperdex_client_get_client_ptr(JNIEnv* env, jobject obj) +static struct hyperdex_client * +hyperdex_client_get_client_ptr(JNIEnv *env, jobject obj) { - struct hyperdex_client* x; - x = (struct hyperdex_client*) (*env)->GetLongField(env, obj, _client_ptr); - assert(x); - return x; + struct hyperdex_client *x; + x = (struct hyperdex_client *) (*env)->GetLongField(env, obj, _client_ptr); + assert(x); + return x; } -static struct hyperdex_java_client_deferred* -hyperdex_uxact_get_deferred_ptr(JNIEnv* env, jobject obj) +static struct hyperdex_java_client_deferred * +hyperdex_uxact_get_deferred_ptr(JNIEnv *env, jobject obj) { - struct hyperdex_java_client_deferred* x; - x = (struct hyperdex_java_client_deferred*) (*env)->GetLongField(env, obj, _uxact_deferred_ptr); - assert(x); - return x; + struct hyperdex_java_client_deferred *x; + x = (struct hyperdex_java_client_deferred *) (*env)->GetLongField(env, obj, _uxact_deferred_ptr); + assert(x); + return x; } -static struct hyperdex_java_client_deferred* -hyperdex_get_deferred_ptr(JNIEnv* env, jobject obj) +static struct hyperdex_java_client_deferred * +hyperdex_get_deferred_ptr(JNIEnv *env, jobject obj) { - struct hyperdex_java_client_deferred* x; - x = (struct hyperdex_java_client_deferred*) (*env)->GetLongField(env, obj, _deferred_ptr); - assert(x); - return x; + struct hyperdex_java_client_deferred *x; + x = (struct hyperdex_java_client_deferred *) (*env)->GetLongField(env, obj, _deferred_ptr); + assert(x); + return x; } -static struct hyperdex_ds_arena* -hyperdex_uxact_get_arena_ptr(JNIEnv* env, jobject obj) +static struct hyperdex_ds_arena * +hyperdex_uxact_get_arena_ptr(JNIEnv *env, jobject obj) { - struct hyperdex_java_client_deferred* x; - x = (struct hyperdex_java_client_deferred*) (*env)->GetLongField(env, obj, _uxact_deferred_ptr); - assert(x); - return x->arena; + struct hyperdex_java_client_deferred *x; + x = (struct hyperdex_java_client_deferred *) (*env)->GetLongField(env, obj, _uxact_deferred_ptr); + assert(x); + return x->arena; } -static struct hyperdex_client_microtransaction* -hyperdex_uxact_get_uxact_ptr(JNIEnv* env, jobject obj) +static struct hyperdex_client_microtransaction * +hyperdex_uxact_get_uxact_ptr(JNIEnv *env, jobject obj) { - struct hyperdex_client_microtransaction* x; - x = (struct hyperdex_client_microtransaction*) (*env)->GetLongField(env, obj, _uxact_uxact_ptr); - assert(x); - return x; + struct hyperdex_client_microtransaction *x; + x = (struct hyperdex_client_microtransaction *) (*env)->GetLongField(env, obj, _uxact_uxact_ptr); + assert(x); + return x; } JNIEXPORT HYPERDEX_API void JNICALL -Java_org_hyperdex_client_Microtransaction__1create(JNIEnv* env, jobject uxact, jstring _space) +Java_org_hyperdex_client_Microtransaction__1create(JNIEnv *env, jobject uxact, jstring _space) { - struct hyperdex_client *client; - struct hyperdex_client_microtransaction *uxact_ptr; - const char *space; - struct hyperdex_java_client_deferred *deferred; - - deferred = (struct hyperdex_java_client_deferred*)malloc(sizeof(struct hyperdex_java_client_deferred)); - memset(deferred, 0, sizeof(struct hyperdex_java_client_deferred)); - - deferred->arena = hyperdex_ds_arena_create(); - - if (!deferred->arena) - { - /* all other resources are caught by the finalizer? */ - hyperdex_java_out_of_memory(env); - return; - } - - deferred->status = HYPERDEX_CLIENT_GARBAGE; - - space = (*env)->GetStringUTFChars(env, _space, NULL); - - client = hyperdex_uxact_get_client_ptr(env, uxact); - uxact_ptr = hyperdex_client_uxact_init(client, space, &deferred->status); - - (*env)->SetLongField(env, uxact, _uxact_uxact_ptr, (long)uxact_ptr); - (*env)->SetLongField(env, uxact, _uxact_deferred_ptr, (long)deferred); + struct hyperdex_client *client; + struct hyperdex_client_microtransaction *uxact_ptr; + const char *space; + struct hyperdex_java_client_deferred *deferred; + deferred = (struct hyperdex_java_client_deferred *)malloc(sizeof(struct hyperdex_java_client_deferred)); + memset(deferred, 0, sizeof(struct hyperdex_java_client_deferred)); + deferred->arena = hyperdex_ds_arena_create(); + if (!deferred->arena) + { + /* all other resources are caught by the finalizer? */ + hyperdex_java_out_of_memory(env); + return; + } + deferred->status = HYPERDEX_CLIENT_GARBAGE; + space = (*env)->GetStringUTFChars(env, _space, NULL); + client = hyperdex_uxact_get_client_ptr(env, uxact); + uxact_ptr = hyperdex_client_uxact_init(client, space, &deferred->status); + (*env)->SetLongField(env, uxact, _uxact_uxact_ptr, (long)uxact_ptr); + (*env)->SetLongField(env, uxact, _uxact_deferred_ptr, (long)deferred); } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Microtransaction_async_1cond_1commit(JNIEnv* env, jobject uxact, jstring jkey, jobject checks) +Java_org_hyperdex_client_Microtransaction_async_1cond_1commit(JNIEnv *env, jobject uxact, jstring jkey, jobject checks) { - const char* key; - size_t key_sz; - const struct hyperdex_client_attribute_check *chks; - size_t chks_sz; - struct hyperdex_client* client_ptr = hyperdex_uxact_get_client_ptr(env, uxact); - struct hyperdex_client_microtransaction *uxact_ptr = hyperdex_uxact_get_uxact_ptr(env, uxact); - jobject client = hyperdex_uxact_get_client(env, uxact); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, client); - struct hyperdex_java_client_deferred* o = hyperdex_uxact_get_deferred_ptr(env, uxact); - ERROR_CHECK(0); - - hyperdex_java_client_convert_key(env, client, o->arena, jkey, &key, &key_sz); - hyperdex_java_client_convert_predicates(env, client, o->arena, checks, &chks, &chks_sz); - o->encode_return = hyperdex_java_client_deferred_encode_status; - o->reqid = hyperdex_client_uxact_cond_commit(client_ptr, uxact_ptr, key, key_sz, chks, chks_sz); - - (*env)->SetLongField(env, op, _deferred_ptr, (long)o); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client_ptr)); - return NULL; - } - (*env)->CallObjectMethod(env, client, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; + const char *key; + size_t key_sz; + const struct hyperdex_client_attribute_check *chks; + size_t chks_sz; + struct hyperdex_client *client_ptr = hyperdex_uxact_get_client_ptr(env, uxact); + struct hyperdex_client_microtransaction *uxact_ptr = hyperdex_uxact_get_uxact_ptr(env, uxact); + jobject client = hyperdex_uxact_get_client(env, uxact); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, client); + struct hyperdex_java_client_deferred *o = hyperdex_uxact_get_deferred_ptr(env, uxact); + ERROR_CHECK(0); + hyperdex_java_client_convert_key(env, client, o->arena, jkey, &key, &key_sz); + hyperdex_java_client_convert_predicates(env, client, o->arena, checks, &chks, &chks_sz); + o->encode_return = hyperdex_java_client_deferred_encode_status; + o->reqid = hyperdex_client_uxact_cond_commit(client_ptr, uxact_ptr, key, key_sz, chks, chks_sz); + (*env)->SetLongField(env, op, _deferred_ptr, (long)o); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client_ptr)); + return NULL; + } + (*env)->CallObjectMethod(env, client, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Microtransaction_async_1group_1commit(JNIEnv* env, jobject uxact, jobject checks) +Java_org_hyperdex_client_Microtransaction_async_1group_1commit(JNIEnv *env, jobject uxact, jobject checks) { - const struct hyperdex_client_attribute_check *chks; - size_t chks_sz; - struct hyperdex_client* client_ptr = hyperdex_uxact_get_client_ptr(env, uxact); - struct hyperdex_client_microtransaction *uxact_ptr = hyperdex_uxact_get_uxact_ptr(env, uxact); - jobject client = hyperdex_uxact_get_client(env, uxact); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, client); - struct hyperdex_java_client_deferred* o = hyperdex_uxact_get_deferred_ptr(env, uxact); - ERROR_CHECK(0); - - hyperdex_java_client_convert_predicates(env, client, o->arena, checks, &chks, &chks_sz); - o->encode_return = hyperdex_java_client_deferred_encode_status_count; - o->reqid = hyperdex_client_uxact_group_commit(client_ptr, uxact_ptr, chks, chks_sz, &o->count); - - (*env)->SetLongField(env, op, _deferred_ptr, (long)o); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client_ptr)); - return NULL; - } - (*env)->CallObjectMethod(env, client, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; + const struct hyperdex_client_attribute_check *chks; + size_t chks_sz; + struct hyperdex_client *client_ptr = hyperdex_uxact_get_client_ptr(env, uxact); + struct hyperdex_client_microtransaction *uxact_ptr = hyperdex_uxact_get_uxact_ptr(env, uxact); + jobject client = hyperdex_uxact_get_client(env, uxact); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, client); + struct hyperdex_java_client_deferred *o = hyperdex_uxact_get_deferred_ptr(env, uxact); + ERROR_CHECK(0); + hyperdex_java_client_convert_predicates(env, client, o->arena, checks, &chks, &chks_sz); + o->encode_return = hyperdex_java_client_deferred_encode_status_count; + o->reqid = hyperdex_client_uxact_group_commit(client_ptr, uxact_ptr, chks, chks_sz, &o->count); + (*env)->SetLongField(env, op, _deferred_ptr, (long)o); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client_ptr)); + return NULL; + } + (*env)->CallObjectMethod(env, client, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; } JNIEXPORT HYPERDEX_API jobject JNICALL -Java_org_hyperdex_client_Microtransaction_async_1commit(JNIEnv* env, jobject uxact, jstring key) +Java_org_hyperdex_client_Microtransaction_async_1commit(JNIEnv *env, jobject uxact, jstring key) { - const char* in_key; - size_t in_key_sz; - struct hyperdex_client* client_ptr = hyperdex_uxact_get_client_ptr(env, uxact); - struct hyperdex_client_microtransaction *uxact_ptr = hyperdex_uxact_get_uxact_ptr(env, uxact); - jobject client = hyperdex_uxact_get_client(env, uxact); - jobject op = (*env)->NewObject(env, _deferred, _deferred_init, client); - struct hyperdex_java_client_deferred* o = hyperdex_uxact_get_deferred_ptr(env, uxact); - ERROR_CHECK(0); - - hyperdex_java_client_convert_key(env, client, o->arena, key, &in_key, &in_key_sz); - o->encode_return = hyperdex_java_client_deferred_encode_status; - o->reqid = hyperdex_client_uxact_commit(client_ptr, uxact_ptr, in_key, in_key_sz); - - (*env)->SetLongField(env, op, _deferred_ptr, (long)o); - - if (o->reqid < 0) - { - hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client_ptr)); - return NULL; - } - (*env)->CallObjectMethod(env, client, _client_add_op, o->reqid, op); - ERROR_CHECK(0); - return op; + const char *in_key; + size_t in_key_sz; + struct hyperdex_client *client_ptr = hyperdex_uxact_get_client_ptr(env, uxact); + struct hyperdex_client_microtransaction *uxact_ptr = hyperdex_uxact_get_uxact_ptr(env, uxact); + jobject client = hyperdex_uxact_get_client(env, uxact); + jobject op = (*env)->NewObject(env, _deferred, _deferred_init, client); + struct hyperdex_java_client_deferred *o = hyperdex_uxact_get_deferred_ptr(env, uxact); + ERROR_CHECK(0); + hyperdex_java_client_convert_key(env, client, o->arena, key, &in_key, &in_key_sz); + o->encode_return = hyperdex_java_client_deferred_encode_status; + o->reqid = hyperdex_client_uxact_commit(client_ptr, uxact_ptr, in_key, in_key_sz); + (*env)->SetLongField(env, op, _deferred_ptr, (long)o); + if (o->reqid < 0) + { + hyperdex_java_client_throw_exception(env, o->status, hyperdex_client_error_message(client_ptr)); + return NULL; + } + (*env)->CallObjectMethod(env, client, _client_add_op, o->reqid, op); + ERROR_CHECK(0); + return op; } JNIEXPORT HYPERDEX_API void JNICALL -Java_org_hyperdex_client_Microtransaction__1destroy(JNIEnv* env, jclass uxact) +Java_org_hyperdex_client_Microtransaction__1destroy(JNIEnv *env, jclass uxact) { - ERROR_CHECK_VOID(); + ERROR_CHECK_VOID(); } JNIEXPORT HYPERDEX_API void JNICALL -Java_org_hyperdex_client_Microtransaction_terminate(JNIEnv* env, jclass uxact) +Java_org_hyperdex_client_Microtransaction_terminate(JNIEnv *env, jclass uxact) { - (*env)->DeleteGlobalRef(env, _uxact); - (*env)->DeleteGlobalRef(env, _client); - (void) uxact; + (*env)->DeleteGlobalRef(env, _uxact); + (*env)->DeleteGlobalRef(env, _client); + (void) uxact; } #include "bindings/java/org_hyperdex_client_Microtransaction.definitions.c" diff --git a/bindings/java/org_hyperdex_client_Range.h b/bindings/java/org_hyperdex_client_Range.h index 7c9737629..96c2ca8c5 100644 --- a/bindings/java/org_hyperdex_client_Range.h +++ b/bindings/java/org_hyperdex_client_Range.h @@ -13,7 +13,7 @@ extern "C" { * Signature: ()J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_Range_checksSize - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_Range @@ -21,7 +21,7 @@ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_Range_checksSize * Signature: (JJJ)J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_Range_convertChecks - (JNIEnv *, jobject, jlong, jlong, jlong); +(JNIEnv *, jobject, jlong, jlong, jlong); #ifdef __cplusplus } diff --git a/bindings/java/org_hyperdex_client_Regex.h b/bindings/java/org_hyperdex_client_Regex.h index cf245786a..637506e57 100644 --- a/bindings/java/org_hyperdex_client_Regex.h +++ b/bindings/java/org_hyperdex_client_Regex.h @@ -13,7 +13,7 @@ extern "C" { * Signature: ()J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_Regex_checksSize - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: org_hyperdex_client_Regex @@ -21,7 +21,7 @@ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_Regex_checksSize * Signature: (JJJ)J */ JNIEXPORT HYPERDEX_API jlong JNICALL Java_org_hyperdex_client_Regex_convertChecks - (JNIEnv *, jobject, jlong, jlong, jlong); +(JNIEnv *, jobject, jlong, jlong, jlong); #ifdef __cplusplus } diff --git a/bindings/node.js/client.cc b/bindings/node.js/client.cc index 37d09b325..02a47f84f 100644 --- a/bindings/node.js/client.cc +++ b/bindings/node.js/client.cc @@ -57,286 +57,286 @@ class Operation; class HyperDexClient : public node::ObjectWrap { - public: - static v8::Persistent ctor; - static v8::Persistent global_err; - static v8::Persistent type_hint; - static v8::Persistent predicate; - static void Init(v8::Handle exports); - static v8::Handle New(const v8::Arguments& args); - - public: - HyperDexClient(const char* host, uint16_t port); - ~HyperDexClient() throw (); - - public: - static v8::Handle asInt(const v8::Arguments& args); - static v8::Handle asFloat(const v8::Arguments& args); - static v8::Handle asList(const v8::Arguments& args); - static v8::Handle asSet(const v8::Arguments& args); - static v8::Handle asMap(const v8::Arguments& args); - static v8::Handle loop(const v8::Arguments& args); - static v8::Handle loop_error(const v8::Arguments& args); - - static v8::Handle Equals(const v8::Arguments& args); - static v8::Handle LessThan(const v8::Arguments& args); - static v8::Handle LessEqual(const v8::Arguments& args); - static v8::Handle GreaterEqual(const v8::Arguments& args); - static v8::Handle GreaterThan(const v8::Arguments& args); - static v8::Handle Regex(const v8::Arguments& args); - static v8::Handle LengthEquals(const v8::Arguments& args); - static v8::Handle LengthLessEqual(const v8::Arguments& args); - static v8::Handle LengthGreaterEqual(const v8::Arguments& args); - static v8::Handle Contains(const v8::Arguments& args); +public: + static v8::Persistent ctor; + static v8::Persistent global_err; + static v8::Persistent type_hint; + static v8::Persistent predicate; + static void Init(v8::Handle exports); + static v8::Handle New(const v8::Arguments &args); + +public: + HyperDexClient(const char *host, uint16_t port); + ~HyperDexClient() throw (); + +public: + static v8::Handle asInt(const v8::Arguments &args); + static v8::Handle asFloat(const v8::Arguments &args); + static v8::Handle asList(const v8::Arguments &args); + static v8::Handle asSet(const v8::Arguments &args); + static v8::Handle asMap(const v8::Arguments &args); + static v8::Handle loop(const v8::Arguments &args); + static v8::Handle loop_error(const v8::Arguments &args); + + static v8::Handle Equals(const v8::Arguments &args); + static v8::Handle LessThan(const v8::Arguments &args); + static v8::Handle LessEqual(const v8::Arguments &args); + static v8::Handle GreaterEqual(const v8::Arguments &args); + static v8::Handle GreaterThan(const v8::Arguments &args); + static v8::Handle Regex(const v8::Arguments &args); + static v8::Handle LengthEquals(const v8::Arguments &args); + static v8::Handle LengthLessEqual(const v8::Arguments &args); + static v8::Handle LengthGreaterEqual(const v8::Arguments &args); + static v8::Handle Contains(const v8::Arguments &args); #include "client.declarations.cc" - public: - hyperdex_client* client() { return m_cl; } - void add(int64_t reqid, e::intrusive_ptr op); - void loop(int timeout); - void poll_start(); - void poll_stop(); - - public: - static void poll_callback(uv_poll_t* watcher, int status, int revents); - static void poll_cleanup(uv_handle_t* handle); - - private: - hyperdex_client* m_cl; - std::map > m_ops; - v8::Persistent m_callback; - uv_poll_t* m_poll; - bool m_poll_active; +public: + hyperdex_client *client() { return m_cl; } + void add(int64_t reqid, e::intrusive_ptr op); + void loop(int timeout); + void poll_start(); + void poll_stop(); + +public: + static void poll_callback(uv_poll_t *watcher, int status, int revents); + static void poll_cleanup(uv_handle_t *handle); + +private: + hyperdex_client *m_cl; + std::map > m_ops; + v8::Persistent m_callback; + uv_poll_t *m_poll; + bool m_poll_active; }; -typedef int (*elem_string_fptr)(void*, const char*, size_t, enum hyperdex_ds_returncode*); -typedef int (*elem_int_fptr)(void*, int64_t, enum hyperdex_ds_returncode*); -typedef int (*elem_float_fptr)(void*, double, enum hyperdex_ds_returncode*); +typedef int (*elem_string_fptr)(void *, const char *, size_t, enum hyperdex_ds_returncode *); +typedef int (*elem_int_fptr)(void *, int64_t, enum hyperdex_ds_returncode *); +typedef int (*elem_float_fptr)(void *, double, enum hyperdex_ds_returncode *); class Operation { - public: - Operation(v8::Handle& c1, HyperDexClient* c2); - ~Operation() throw (); - - public: - typedef bool (Operation::*type_converter)(v8::Handle&, const char**, size_t*, hyperdatatype*); - - bool set_callback(v8::Handle& func); - bool set_callback(v8::Handle& func, - v8::Handle& done); - bool convert_error(v8::Handle& _value, - const char** value, size_t* value_sz, - hyperdatatype* datatype); - bool convert_int(v8::Handle& _value, - const char** value, size_t* value_sz, - hyperdatatype* datatype); - bool convert_float(v8::Handle& _value, - const char** value, size_t* value_sz, - hyperdatatype* datatype); - bool convert_elem(v8::Handle& value, void* x, - elem_string_fptr f_string, - elem_int_fptr f_int, - elem_float_fptr f_float); - bool convert_list(v8::Handle& _value, - const char** value, size_t* value_sz, - hyperdatatype* datatype); - bool convert_set(v8::Handle& _value, - const char** value, size_t* value_sz, - hyperdatatype* datatype); - bool convert_map(v8::Handle& _value, - const char** value, size_t* value_sz, - hyperdatatype* datatype); - bool convert_type(v8::Handle& _value, - const char** value, size_t* value_sz, - hyperdatatype* datatype, - bool make_callback_on_error, - bool may_default_to_json); - bool convert_cstring(v8::Handle& _cstring, - const char** cstring); - - bool convert_spacename(v8::Handle& _spacename, - const char** spacename); - bool convert_key(v8::Handle& _key, - const char** key, size_t* key_sz); - bool convert_attributes(v8::Handle& _attributes, - const hyperdex_client_attribute** attrs, - size_t* attrs_sz); - bool convert_document_predicates(const std::string& s, - v8::Handle& v, - std::vector* checks); - bool convert_predicates(v8::Handle& _predicates, - const hyperdex_client_attribute_check** checks, - size_t* checks_sz); - bool convert_mapattributes(v8::Handle& _predicates, - const hyperdex_client_map_attribute** checks, - size_t* checks_sz); - bool convert_attributenames(v8::Handle& _attributenames, - const char*** attributenames, - size_t* attributenames_sz); - bool convert_sortby(v8::Handle& _sortby, - const char** sortby); - bool convert_limit(v8::Handle& _limit, - uint64_t* limit); - bool convert_maxmin(v8::Handle& _maxmin, - int* maximize); - - // 20 Sept 2015 - William Whitacre - // Patch against 1.8.1: Enable macaroon authorization. - - // Convert a v8 array of strings to a character pointer array. - bool convert_auth_context(v8::Handle &_value, - const char ***p_auth, size_t *p_auth_sz); - - // Set and clear the auth context using the hyperdex_client API. - bool set_auth_context(v8::Handle &_value); - bool clear_auth_context(); - - bool build_string(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_int(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_float(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_document(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_list_string(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_list_int(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_list_float(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_set_string(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_set_int(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_set_float(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_map_string_string(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_map_string_int(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_map_string_float(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_map_int_string(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_map_int_int(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_map_int_float(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_map_float_string(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_map_float_int(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_map_float_float(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error); - bool build_attribute(const hyperdex_client_attribute* attr, - v8::Local& retval, - v8::Local& error); - void build_attributes(v8::Local& retval, - v8::Local& error); - - void encode_asynccall_status(); - void encode_asynccall_status_attributes(); - void encode_asynccall_status_count(); - void encode_asynccall_status_description(); - void encode_iterator_status_attributes(); - - public: - void make_callback(v8::Handle& first, - v8::Handle& second); - void make_callback_done(); - static v8::Local error_from_status(hyperdex_client* client, - hyperdex_client_returncode status); - v8::Local error_from_status(); - v8::Local error_message(const char* msg); - v8::Local error_out_of_memory(); - void callback_error(v8::Handle& err); - void callback_error_from_status(); - void callback_error_message(const char* msg); - void callback_error_out_of_memory(); - - public: - HyperDexClient* client; - int64_t reqid; - enum hyperdex_client_returncode status; - const struct hyperdex_client_attribute* attrs; - size_t attrs_sz; - const char* description; - uint64_t count; - bool finished; - void (Operation::*encode_return)(); - const char **m_auth; - - private: - void inc() { ++m_ref; } - void dec() { if (--m_ref == 0) delete this; } - friend class e::intrusive_ptr; - - private: - size_t m_ref; - hyperdex_ds_arena* m_arena; - v8::Persistent m_client; - v8::Persistent m_callback; - v8::Persistent m_callback_done; - bool m_has_callback_done; +public: + Operation(v8::Handle &c1, HyperDexClient *c2); + ~Operation() throw (); + +public: + typedef bool (Operation::*type_converter)(v8::Handle &, const char **, size_t *, hyperdatatype *); + + bool set_callback(v8::Handle &func); + bool set_callback(v8::Handle &func, + v8::Handle &done); + bool convert_error(v8::Handle &_value, + const char **value, size_t *value_sz, + hyperdatatype *datatype); + bool convert_int(v8::Handle &_value, + const char **value, size_t *value_sz, + hyperdatatype *datatype); + bool convert_float(v8::Handle &_value, + const char **value, size_t *value_sz, + hyperdatatype *datatype); + bool convert_elem(v8::Handle &value, void *x, + elem_string_fptr f_string, + elem_int_fptr f_int, + elem_float_fptr f_float); + bool convert_list(v8::Handle &_value, + const char **value, size_t *value_sz, + hyperdatatype *datatype); + bool convert_set(v8::Handle &_value, + const char **value, size_t *value_sz, + hyperdatatype *datatype); + bool convert_map(v8::Handle &_value, + const char **value, size_t *value_sz, + hyperdatatype *datatype); + bool convert_type(v8::Handle &_value, + const char **value, size_t *value_sz, + hyperdatatype *datatype, + bool make_callback_on_error, + bool may_default_to_json); + bool convert_cstring(v8::Handle &_cstring, + const char **cstring); + + bool convert_spacename(v8::Handle &_spacename, + const char **spacename); + bool convert_key(v8::Handle &_key, + const char **key, size_t *key_sz); + bool convert_attributes(v8::Handle &_attributes, + const hyperdex_client_attribute **attrs, + size_t *attrs_sz); + bool convert_document_predicates(const std::string &s, + v8::Handle &v, + std::vector *checks); + bool convert_predicates(v8::Handle &_predicates, + const hyperdex_client_attribute_check **checks, + size_t *checks_sz); + bool convert_mapattributes(v8::Handle &_predicates, + const hyperdex_client_map_attribute **checks, + size_t *checks_sz); + bool convert_attributenames(v8::Handle &_attributenames, + const char *** attributenames, + size_t *attributenames_sz); + bool convert_sortby(v8::Handle &_sortby, + const char **sortby); + bool convert_limit(v8::Handle &_limit, + uint64_t *limit); + bool convert_maxmin(v8::Handle &_maxmin, + int *maximize); + + // 20 Sept 2015 - William Whitacre + // Patch against 1.8.1: Enable macaroon authorization. + + // Convert a v8 array of strings to a character pointer array. + bool convert_auth_context(v8::Handle &_value, + const char ***p_auth, size_t *p_auth_sz); + + // Set and clear the auth context using the hyperdex_client API. + bool set_auth_context(v8::Handle &_value); + bool clear_auth_context(); + + bool build_string(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_int(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_float(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_document(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_list_string(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_list_int(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_list_float(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_set_string(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_set_int(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_set_float(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_map_string_string(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_map_string_int(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_map_string_float(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_map_int_string(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_map_int_int(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_map_int_float(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_map_float_string(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_map_float_int(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_map_float_float(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error); + bool build_attribute(const hyperdex_client_attribute *attr, + v8::Local &retval, + v8::Local &error); + void build_attributes(v8::Local &retval, + v8::Local &error); + + void encode_asynccall_status(); + void encode_asynccall_status_attributes(); + void encode_asynccall_status_count(); + void encode_asynccall_status_description(); + void encode_iterator_status_attributes(); + +public: + void make_callback(v8::Handle &first, + v8::Handle &second); + void make_callback_done(); + static v8::Local error_from_status(hyperdex_client *client, + hyperdex_client_returncode status); + v8::Local error_from_status(); + v8::Local error_message(const char *msg); + v8::Local error_out_of_memory(); + void callback_error(v8::Handle &err); + void callback_error_from_status(); + void callback_error_message(const char *msg); + void callback_error_out_of_memory(); + +public: + HyperDexClient *client; + int64_t reqid; + enum hyperdex_client_returncode status; + const struct hyperdex_client_attribute *attrs; + size_t attrs_sz; + const char *description; + uint64_t count; + bool finished; + void (Operation::*encode_return)(); + const char **m_auth; + +private: + void inc() { ++m_ref; } + void dec() { if (--m_ref == 0) delete this; } + friend class e::intrusive_ptr; + +private: + size_t m_ref; + hyperdex_ds_arena *m_arena; + v8::Persistent m_client; + v8::Persistent m_callback; + v8::Persistent m_callback_done; + bool m_has_callback_done; }; class TypeHint : public node::ObjectWrap { - public: - static v8::Handle New(const v8::Arguments& args); +public: + static v8::Handle New(const v8::Arguments &args); - public: - TypeHint(hyperdatatype t, v8::Local& o); - ~TypeHint() throw (); +public: + TypeHint(hyperdatatype t, v8::Local &o); + ~TypeHint() throw (); - public: - Operation::type_converter get_converter(); - v8::Handle value(); - hyperdatatype get_type(); +public: + Operation::type_converter get_converter(); + v8::Handle value(); + hyperdatatype get_type(); - private: - hyperdatatype m_type; - v8::Persistent m_obj; +private: + hyperdatatype m_type; + v8::Persistent m_obj; }; class Predicate : public node::ObjectWrap { - public: - static v8::Handle New(const v8::Arguments& args); +public: + static v8::Handle New(const v8::Arguments &args); - public: - Predicate(hyperpredicate p, v8::Local& v); - ~Predicate() throw (); +public: + Predicate(hyperpredicate p, v8::Local &v); + ~Predicate() throw (); - public: - v8::Handle value(); - hyperpredicate get_pred(); +public: + v8::Handle value(); + hyperpredicate get_pred(); - private: - hyperpredicate m_pred; - v8::Persistent m_obj; +private: + hyperpredicate m_pred; + v8::Persistent m_obj; }; v8::Persistent HyperDexClient::ctor; @@ -347,337 +347,300 @@ v8::Persistent HyperDexClient::predicate; void HyperDexClient :: Init(v8::Handle target) { - v8::Local tpl - = v8::FunctionTemplate::New(HyperDexClient::New); - tpl->SetClassName(v8::String::NewSymbol("Client")); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - NODE_SET_PROTOTYPE_METHOD(tpl, "asInt", HyperDexClient::asInt); - NODE_SET_PROTOTYPE_METHOD(tpl, "asInt", HyperDexClient::asInt); - NODE_SET_PROTOTYPE_METHOD(tpl, "asFloat", HyperDexClient::asFloat); - NODE_SET_PROTOTYPE_METHOD(tpl, "asList", HyperDexClient::asList); - NODE_SET_PROTOTYPE_METHOD(tpl, "asSet", HyperDexClient::asSet); - NODE_SET_PROTOTYPE_METHOD(tpl, "asMap", HyperDexClient::asMap); - - NODE_SET_PROTOTYPE_METHOD(tpl, "Equals", HyperDexClient::Equals); - NODE_SET_PROTOTYPE_METHOD(tpl, "LessThan", HyperDexClient::LessThan); - NODE_SET_PROTOTYPE_METHOD(tpl, "LessEqual", HyperDexClient::LessEqual); - NODE_SET_PROTOTYPE_METHOD(tpl, "GreaterEqual", HyperDexClient::GreaterEqual); - NODE_SET_PROTOTYPE_METHOD(tpl, "GreaterThan", HyperDexClient::GreaterThan); - NODE_SET_PROTOTYPE_METHOD(tpl, "Regex", HyperDexClient::Regex); - NODE_SET_PROTOTYPE_METHOD(tpl, "LengthEquals", HyperDexClient::LengthEquals); - NODE_SET_PROTOTYPE_METHOD(tpl, "LengthLessEqual", HyperDexClient::LengthLessEqual); - NODE_SET_PROTOTYPE_METHOD(tpl, "LengthGreaterEqual", HyperDexClient::LengthGreaterEqual); - NODE_SET_PROTOTYPE_METHOD(tpl, "Contains", HyperDexClient::Contains); - - NODE_SET_PROTOTYPE_METHOD(tpl, "loop", HyperDexClient::loop); + v8::Local tpl + = v8::FunctionTemplate::New(HyperDexClient::New); + tpl->SetClassName(v8::String::NewSymbol("Client")); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + NODE_SET_PROTOTYPE_METHOD(tpl, "asInt", HyperDexClient::asInt); + NODE_SET_PROTOTYPE_METHOD(tpl, "asInt", HyperDexClient::asInt); + NODE_SET_PROTOTYPE_METHOD(tpl, "asFloat", HyperDexClient::asFloat); + NODE_SET_PROTOTYPE_METHOD(tpl, "asList", HyperDexClient::asList); + NODE_SET_PROTOTYPE_METHOD(tpl, "asSet", HyperDexClient::asSet); + NODE_SET_PROTOTYPE_METHOD(tpl, "asMap", HyperDexClient::asMap); + NODE_SET_PROTOTYPE_METHOD(tpl, "Equals", HyperDexClient::Equals); + NODE_SET_PROTOTYPE_METHOD(tpl, "LessThan", HyperDexClient::LessThan); + NODE_SET_PROTOTYPE_METHOD(tpl, "LessEqual", HyperDexClient::LessEqual); + NODE_SET_PROTOTYPE_METHOD(tpl, "GreaterEqual", HyperDexClient::GreaterEqual); + NODE_SET_PROTOTYPE_METHOD(tpl, "GreaterThan", HyperDexClient::GreaterThan); + NODE_SET_PROTOTYPE_METHOD(tpl, "Regex", HyperDexClient::Regex); + NODE_SET_PROTOTYPE_METHOD(tpl, "LengthEquals", HyperDexClient::LengthEquals); + NODE_SET_PROTOTYPE_METHOD(tpl, "LengthLessEqual", HyperDexClient::LengthLessEqual); + NODE_SET_PROTOTYPE_METHOD(tpl, "LengthGreaterEqual", HyperDexClient::LengthGreaterEqual); + NODE_SET_PROTOTYPE_METHOD(tpl, "Contains", HyperDexClient::Contains); + NODE_SET_PROTOTYPE_METHOD(tpl, "loop", HyperDexClient::loop); #include "client.prototypes.cc" - - ctor = v8::Persistent::New(tpl->GetFunction()); - target->Set(v8::String::NewSymbol("Client"), ctor); - - v8::Local tpl_err - = v8::FunctionTemplate::New(HyperDexClient::loop_error); - global_err = v8::Persistent::New(tpl_err->GetFunction()); - - v8::Local tpl_type - = v8::FunctionTemplate::New(TypeHint::New); - tpl_type->SetClassName(v8::String::NewSymbol("TypeHint")); - tpl_type->InstanceTemplate()->SetInternalFieldCount(1); - type_hint = v8::Persistent::New(tpl_type->GetFunction()); - - v8::Local tpl_pred - = v8::FunctionTemplate::New(Predicate::New); - tpl_pred->SetClassName(v8::String::NewSymbol("Predicate")); - tpl_pred->InstanceTemplate()->SetInternalFieldCount(2); - predicate = v8::Persistent::New(tpl_pred->GetFunction()); + ctor = v8::Persistent::New(tpl->GetFunction()); + target->Set(v8::String::NewSymbol("Client"), ctor); + v8::Local tpl_err + = v8::FunctionTemplate::New(HyperDexClient::loop_error); + global_err = v8::Persistent::New(tpl_err->GetFunction()); + v8::Local tpl_type + = v8::FunctionTemplate::New(TypeHint::New); + tpl_type->SetClassName(v8::String::NewSymbol("TypeHint")); + tpl_type->InstanceTemplate()->SetInternalFieldCount(1); + type_hint = v8::Persistent::New(tpl_type->GetFunction()); + v8::Local tpl_pred + = v8::FunctionTemplate::New(Predicate::New); + tpl_pred->SetClassName(v8::String::NewSymbol("Predicate")); + tpl_pred->InstanceTemplate()->SetInternalFieldCount(2); + predicate = v8::Persistent::New(tpl_pred->GetFunction()); } v8::Handle -HyperDexClient :: New(const v8::Arguments& args) -{ - v8::HandleScope scope; - - if (!args.IsConstructCall()) - { - return v8::ThrowException(v8::String::New("client must be constructed with \"new\"")); - } - - if (args.Length() != 2) - { - return v8::ThrowException(v8::String::New("constructor requires (host, port) arguments")); - } - - if (args[0].IsEmpty() || !args[0]->IsString()) - { - return v8::ThrowException(v8::String::New("constructor requires that the \"host\" argument be a string")); - } - - if (args[1].IsEmpty() || !args[1]->IsNumber()) - { - return v8::ThrowException(v8::String::New("constructor requires that the \"port\" argument be a number")); - } - - v8::Local _host = args[0].As(); - v8::Local _port = args[1].As(); - v8::String::AsciiValue s(_host); - - const char* host = *s; - uint16_t port = _port->Value(); - - HyperDexClient* c = new HyperDexClient(host, port); - c->Wrap(args.This()); - return scope.Close(args.This()); -} - -HyperDexClient :: HyperDexClient(const char* host, uint16_t port) - : m_cl(hyperdex_client_create(host, port)) - , m_poll(NULL) - , m_poll_active(false) -{ - if (m_cl) - { - m_poll = new uv_poll_t; - uv_poll_init_socket(uv_default_loop(), m_poll, hyperdex_client_poll_fd(m_cl)); - m_poll->data = this; - } - - v8::Local func(v8::Local::New(global_err)); - v8::Local cbobj = v8::Object::New(); - cbobj->Set(v8::String::NewSymbol("callback"), func); - m_callback = v8::Persistent::New(cbobj); +HyperDexClient :: New(const v8::Arguments &args) +{ + v8::HandleScope scope; + if (!args.IsConstructCall()) + { + return v8::ThrowException(v8::String::New("client must be constructed with \"new\"")); + } + if (args.Length() != 2) + { + return v8::ThrowException(v8::String::New("constructor requires (host, port) arguments")); + } + if (args[0].IsEmpty() || !args[0]->IsString()) + { + return v8::ThrowException(v8::String::New("constructor requires that the \"host\" argument be a string")); + } + if (args[1].IsEmpty() || !args[1]->IsNumber()) + { + return v8::ThrowException(v8::String::New("constructor requires that the \"port\" argument be a number")); + } + v8::Local _host = args[0].As(); + v8::Local _port = args[1].As(); + v8::String::AsciiValue s(_host); + const char *host = *s; + uint16_t port = _port->Value(); + HyperDexClient *c = new HyperDexClient(host, port); + c->Wrap(args.This()); + return scope.Close(args.This()); +} + +HyperDexClient :: HyperDexClient(const char *host, uint16_t port) + : m_cl(hyperdex_client_create(host, port)) + , m_poll(NULL) + , m_poll_active(false) +{ + if (m_cl) + { + m_poll = new uv_poll_t; + uv_poll_init_socket(uv_default_loop(), m_poll, hyperdex_client_poll_fd(m_cl)); + m_poll->data = this; + } + v8::Local func(v8::Local::New(global_err)); + v8::Local cbobj = v8::Object::New(); + cbobj->Set(v8::String::NewSymbol("callback"), func); + m_callback = v8::Persistent::New(cbobj); } HyperDexClient :: ~HyperDexClient() throw () { - if (m_cl) - { - hyperdex_client_destroy(m_cl); - } - - if (m_poll) - { - m_poll->data = NULL; - poll_stop(); - uv_close(reinterpret_cast(m_poll), poll_cleanup); - } - - if (!m_callback.IsEmpty()) - { - m_callback.Dispose(); - m_callback.Clear(); - } + if (m_cl) + { + hyperdex_client_destroy(m_cl); + } + if (m_poll) + { + m_poll->data = NULL; + poll_stop(); + uv_close(reinterpret_cast(m_poll), poll_cleanup); + } + if (!m_callback.IsEmpty()) + { + m_callback.Dispose(); + m_callback.Clear(); + } } void HyperDexClient :: add(int64_t reqid, e::intrusive_ptr op) { - m_ops[reqid] = op; - poll_start(); + m_ops[reqid] = op; + poll_start(); } void HyperDexClient :: loop(int timeout) { - enum hyperdex_client_returncode rc; - int64_t ret = hyperdex_client_loop(m_cl, timeout, &rc); - - if (ret < 0 && timeout == 0 && rc == HYPERDEX_CLIENT_TIMEOUT) - { - return; - } - - if (ret < 0) - { - v8::Local obj = v8::Local::New(m_callback); - v8::Local callback - = obj->Get(v8::String::NewSymbol("callback")).As(); - v8::Local err = Operation::error_from_status(m_cl, rc); - v8::Handle argv[] = { err }; - node::MakeCallback(v8::Context::GetCurrent()->Global(), callback, 1, argv); - return; - } - - std::map >::iterator it; - it = m_ops.find(ret); - assert(it != m_ops.end()); - (*it->second.*it->second->encode_return)(); - - if (it->second->finished) - { - m_ops.erase(it); - } - - if (m_ops.empty()) - { - poll_stop(); - } + enum hyperdex_client_returncode rc; + int64_t ret = hyperdex_client_loop(m_cl, timeout, &rc); + if (ret < 0 && timeout == 0 && rc == HYPERDEX_CLIENT_TIMEOUT) + { + return; + } + if (ret < 0) + { + v8::Local obj = v8::Local::New(m_callback); + v8::Local callback + = obj->Get(v8::String::NewSymbol("callback")).As(); + v8::Local err = Operation::error_from_status(m_cl, rc); + v8::Handle argv[] = { err }; + node::MakeCallback(v8::Context::GetCurrent()->Global(), callback, 1, argv); + return; + } + std::map >::iterator it; + it = m_ops.find(ret); + assert(it != m_ops.end()); + (*it->second.*it->second->encode_return)(); + if (it->second->finished) + { + m_ops.erase(it); + } + if (m_ops.empty()) + { + poll_stop(); + } } void HyperDexClient :: poll_start() { - if (m_poll_active || !m_poll) - { - return; - } - - m_poll_active = true; - uv_poll_start(m_poll, UV_READABLE, poll_callback); + if (m_poll_active || !m_poll) + { + return; + } + m_poll_active = true; + uv_poll_start(m_poll, UV_READABLE, poll_callback); } void HyperDexClient :: poll_stop() { - if (!m_poll_active || !m_poll) - { - return; - } - - uv_poll_stop(m_poll); - m_poll_active = false; + if (!m_poll_active || !m_poll) + { + return; + } + uv_poll_stop(m_poll); + m_poll_active = false; } void -HyperDexClient :: poll_callback(uv_poll_t* watcher, int status, int revents) +HyperDexClient :: poll_callback(uv_poll_t *watcher, int status, int revents) { - HyperDexClient* cl = reinterpret_cast(watcher->data); - - if (cl) - { - cl->loop(0); - } + HyperDexClient *cl = reinterpret_cast(watcher->data); + if (cl) + { + cl->loop(0); + } } void -HyperDexClient :: poll_cleanup(uv_handle_t* handle) +HyperDexClient :: poll_cleanup(uv_handle_t *handle) { - uv_poll_t* poll = reinterpret_cast(handle); - - if (handle) - { - delete poll; - } + uv_poll_t *poll = reinterpret_cast(handle); + if (handle) + { + delete poll; + } } v8::Handle -HyperDexClient :: loop(const v8::Arguments& args) +HyperDexClient :: loop(const v8::Arguments &args) { - v8::HandleScope scope; - int timeout = -1; - - if (args.Length() > 0 && args[0]->IsNumber()) - { - timeout = args[0]->IntegerValue(); - } - - HyperDexClient* client = node::ObjectWrap::Unwrap(args.This()); - client->loop(timeout); - return scope.Close(v8::Undefined()); + v8::HandleScope scope; + int timeout = -1; + if (args.Length() > 0 && args[0]->IsNumber()) + { + timeout = args[0]->IntegerValue(); + } + HyperDexClient *client = node::ObjectWrap::Unwrap(args.This()); + client->loop(timeout); + return scope.Close(v8::Undefined()); } v8::Handle -HyperDexClient :: loop_error(const v8::Arguments& args) +HyperDexClient :: loop_error(const v8::Arguments &args) { - v8::HandleScope scope; - - if (args.Length() > 0) - { - v8::ThrowException(args[0]); - } - - return scope.Close(v8::Undefined()); + v8::HandleScope scope; + if (args.Length() > 0) + { + v8::ThrowException(args[0]); + } + return scope.Close(v8::Undefined()); } v8::Handle -TypeHint :: New(const v8::Arguments& args) -{ - v8::HandleScope scope; - - if (!args.IsConstructCall()) - { - return v8::ThrowException(v8::String::New("client must be constructed with \"new\"")); - } - - if (args.Length() != 2) - { - return v8::ThrowException(v8::String::New("type hint requires (type, obj) arguments")); - } - - if (args[0].IsEmpty() || !args[0]->IsString()) - { - return v8::ThrowException(v8::String::New("type hint requires that the \"type\" argument be a string")); - } - - if (args[1].IsEmpty()) - { - return v8::ThrowException(v8::String::New("type hint requires something to cast")); - } - - v8::Local _type = args[0].As(); - v8::String::AsciiValue s(_type); - hyperdatatype t = HYPERDATATYPE_GARBAGE; - - if (strcmp("int", *s) == 0 || - strcmp("int64", *s) == 0) - { - t = HYPERDATATYPE_INT64; - } - else if (strcmp("float", *s) == 0) - { - t = HYPERDATATYPE_FLOAT; - } - else if (strcmp("list", *s) == 0) - { - t = HYPERDATATYPE_LIST_GENERIC; - } - else if (strcmp("set", *s) == 0) - { - t = HYPERDATATYPE_SET_GENERIC; - } - else if (strcmp("map", *s) == 0) - { - t = HYPERDATATYPE_MAP_GENERIC; - } - else - { - return v8::ThrowException(v8::String::New("cannot cast unknown type")); - } - - v8::Local obj = v8::Local::New(args[1]); - TypeHint* th = new TypeHint(t, obj); - th->Wrap(args.This()); - return scope.Close(args.This()); -} - -TypeHint :: TypeHint(hyperdatatype t, v8::Local& o) - : m_type(t) - , m_obj() -{ - if (!o.IsEmpty()) - { - m_obj = v8::Persistent::New(o); - } +TypeHint :: New(const v8::Arguments &args) +{ + v8::HandleScope scope; + if (!args.IsConstructCall()) + { + return v8::ThrowException(v8::String::New("client must be constructed with \"new\"")); + } + if (args.Length() != 2) + { + return v8::ThrowException(v8::String::New("type hint requires (type, obj) arguments")); + } + if (args[0].IsEmpty() || !args[0]->IsString()) + { + return v8::ThrowException(v8::String::New("type hint requires that the \"type\" argument be a string")); + } + if (args[1].IsEmpty()) + { + return v8::ThrowException(v8::String::New("type hint requires something to cast")); + } + v8::Local _type = args[0].As(); + v8::String::AsciiValue s(_type); + hyperdatatype t = HYPERDATATYPE_GARBAGE; + if (strcmp("int", *s) == 0 || + strcmp("int64", *s) == 0) + { + t = HYPERDATATYPE_INT64; + } + else if (strcmp("float", *s) == 0) + { + t = HYPERDATATYPE_FLOAT; + } + else if (strcmp("list", *s) == 0) + { + t = HYPERDATATYPE_LIST_GENERIC; + } + else if (strcmp("set", *s) == 0) + { + t = HYPERDATATYPE_SET_GENERIC; + } + else if (strcmp("map", *s) == 0) + { + t = HYPERDATATYPE_MAP_GENERIC; + } + else + { + return v8::ThrowException(v8::String::New("cannot cast unknown type")); + } + v8::Local obj = v8::Local::New(args[1]); + TypeHint *th = new TypeHint(t, obj); + th->Wrap(args.This()); + return scope.Close(args.This()); +} + +TypeHint :: TypeHint(hyperdatatype t, v8::Local &o) + : m_type(t) + , m_obj() +{ + if (!o.IsEmpty()) + { + m_obj = v8::Persistent::New(o); + } } TypeHint :: ~TypeHint() throw () { - if (!m_obj.IsEmpty()) - { - m_obj.Dispose(); - m_obj.Clear(); - } + if (!m_obj.IsEmpty()) + { + m_obj.Dispose(); + m_obj.Clear(); + } } #define HYPERDEX_TYPE_CAST(X, Y) \ - v8::Handle \ - HyperDexClient :: X(const v8::Arguments& args) \ - { \ - v8::Local th = v8::Local::New(type_hint); \ - v8::Local t(v8::String::New(Y)); \ - v8::Handle argv[] = {t, args[0]}; \ - return th->NewInstance(2, argv); \ - } + v8::Handle \ + HyperDexClient :: X(const v8::Arguments& args) \ + { \ + v8::Local th = v8::Local::New(type_hint); \ + v8::Local t(v8::String::New(Y)); \ + v8::Handle argv[] = {t, args[0]}; \ + return th->NewInstance(2, argv); \ + } HYPERDEX_TYPE_CAST(asInt, "int"); HYPERDEX_TYPE_CAST(asFloat, "float"); @@ -688,138 +651,131 @@ HYPERDEX_TYPE_CAST(asMap, "map"); Operation::type_converter TypeHint :: get_converter() { - switch (m_type) - { - case HYPERDATATYPE_INT64: - return &Operation::convert_int; - case HYPERDATATYPE_FLOAT: - return &Operation::convert_float; - case HYPERDATATYPE_LIST_GENERIC: - return &Operation::convert_list; - case HYPERDATATYPE_SET_GENERIC: - return &Operation::convert_set; - case HYPERDATATYPE_MAP_GENERIC: - return &Operation::convert_map; - case HYPERDATATYPE_GENERIC: - case HYPERDATATYPE_STRING: - case HYPERDATATYPE_LIST_STRING: - case HYPERDATATYPE_LIST_INT64: - case HYPERDATATYPE_LIST_FLOAT: - case HYPERDATATYPE_SET_STRING: - case HYPERDATATYPE_SET_INT64: - case HYPERDATATYPE_SET_FLOAT: - case HYPERDATATYPE_MAP_STRING_KEYONLY: - case HYPERDATATYPE_MAP_STRING_STRING: - case HYPERDATATYPE_MAP_STRING_INT64: - case HYPERDATATYPE_MAP_STRING_FLOAT: - case HYPERDATATYPE_MAP_INT64_KEYONLY: - case HYPERDATATYPE_MAP_INT64_STRING: - case HYPERDATATYPE_MAP_INT64_INT64: - case HYPERDATATYPE_MAP_INT64_FLOAT: - case HYPERDATATYPE_MAP_FLOAT_KEYONLY: - case HYPERDATATYPE_MAP_FLOAT_STRING: - case HYPERDATATYPE_MAP_FLOAT_INT64: - case HYPERDATATYPE_MAP_FLOAT_FLOAT: - case HYPERDATATYPE_GARBAGE: - default: - return &Operation::convert_error; - } + switch (m_type) + { + case HYPERDATATYPE_INT64: + return &Operation::convert_int; + case HYPERDATATYPE_FLOAT: + return &Operation::convert_float; + case HYPERDATATYPE_LIST_GENERIC: + return &Operation::convert_list; + case HYPERDATATYPE_SET_GENERIC: + return &Operation::convert_set; + case HYPERDATATYPE_MAP_GENERIC: + return &Operation::convert_map; + case HYPERDATATYPE_GENERIC: + case HYPERDATATYPE_STRING: + case HYPERDATATYPE_LIST_STRING: + case HYPERDATATYPE_LIST_INT64: + case HYPERDATATYPE_LIST_FLOAT: + case HYPERDATATYPE_SET_STRING: + case HYPERDATATYPE_SET_INT64: + case HYPERDATATYPE_SET_FLOAT: + case HYPERDATATYPE_MAP_STRING_KEYONLY: + case HYPERDATATYPE_MAP_STRING_STRING: + case HYPERDATATYPE_MAP_STRING_INT64: + case HYPERDATATYPE_MAP_STRING_FLOAT: + case HYPERDATATYPE_MAP_INT64_KEYONLY: + case HYPERDATATYPE_MAP_INT64_STRING: + case HYPERDATATYPE_MAP_INT64_INT64: + case HYPERDATATYPE_MAP_INT64_FLOAT: + case HYPERDATATYPE_MAP_FLOAT_KEYONLY: + case HYPERDATATYPE_MAP_FLOAT_STRING: + case HYPERDATATYPE_MAP_FLOAT_INT64: + case HYPERDATATYPE_MAP_FLOAT_FLOAT: + case HYPERDATATYPE_GARBAGE: + default: + return &Operation::convert_error; + } } v8::Handle TypeHint :: value() { - v8::HandleScope scope; - return scope.Close(v8::Local::New(m_obj)); + v8::HandleScope scope; + return scope.Close(v8::Local::New(m_obj)); } hyperdatatype TypeHint :: get_type() { - return m_type; + return m_type; } v8::Handle -Predicate :: New(const v8::Arguments& args) -{ - v8::HandleScope scope; - - if (!args.IsConstructCall()) - { - return v8::ThrowException(v8::String::New("client must be constructed with \"new\"")); - } - - if (args.Length() != 2) - { - return v8::ThrowException(v8::String::New("predicate requires (predicate, obj) arguments")); - } - - if (args[0].IsEmpty() || !args[0]->IsNumber()) - { - return v8::ThrowException(v8::String::New("predicate requires that the \"predicate\" argument be a number")); - } - - if (args[1].IsEmpty()) - { - return v8::ThrowException(v8::String::New("predicate requires something to cast")); - } - - int _p = args[0].As()->Value(); - hyperpredicate p = static_cast(_p); - - switch (p) - { - case HYPERPREDICATE_FAIL: - case HYPERPREDICATE_EQUALS: - case HYPERPREDICATE_LESS_THAN: - case HYPERPREDICATE_LESS_EQUAL: - case HYPERPREDICATE_GREATER_EQUAL: - case HYPERPREDICATE_GREATER_THAN: - case HYPERPREDICATE_CONTAINS_LESS_THAN: - case HYPERPREDICATE_REGEX: - case HYPERPREDICATE_LENGTH_EQUALS: - case HYPERPREDICATE_LENGTH_LESS_EQUAL: - case HYPERPREDICATE_LENGTH_GREATER_EQUAL: - case HYPERPREDICATE_CONTAINS: - break; - default: - abort(); - } - - v8::Local obj = v8::Local::New(args[1]); - Predicate* pred = new Predicate(p, obj); - pred->Wrap(args.This()); - return scope.Close(args.This()); -} - -Predicate :: Predicate(hyperpredicate p, v8::Local& o) - : m_pred(p) - , m_obj() -{ - if (!o.IsEmpty()) - { - m_obj = v8::Persistent::New(o); - } +Predicate :: New(const v8::Arguments &args) +{ + v8::HandleScope scope; + if (!args.IsConstructCall()) + { + return v8::ThrowException(v8::String::New("client must be constructed with \"new\"")); + } + if (args.Length() != 2) + { + return v8::ThrowException(v8::String::New("predicate requires (predicate, obj) arguments")); + } + if (args[0].IsEmpty() || !args[0]->IsNumber()) + { + return v8::ThrowException(v8::String::New("predicate requires that the \"predicate\" argument be a number")); + } + if (args[1].IsEmpty()) + { + return v8::ThrowException(v8::String::New("predicate requires something to cast")); + } + int _p = args[0].As()->Value(); + hyperpredicate p = static_cast(_p); + switch (p) + { + case HYPERPREDICATE_FAIL: + case HYPERPREDICATE_EQUALS: + case HYPERPREDICATE_LESS_THAN: + case HYPERPREDICATE_LESS_EQUAL: + case HYPERPREDICATE_GREATER_EQUAL: + case HYPERPREDICATE_GREATER_THAN: + case HYPERPREDICATE_CONTAINS_LESS_THAN: + case HYPERPREDICATE_REGEX: + case HYPERPREDICATE_LENGTH_EQUALS: + case HYPERPREDICATE_LENGTH_LESS_EQUAL: + case HYPERPREDICATE_LENGTH_GREATER_EQUAL: + case HYPERPREDICATE_CONTAINS: + break; + default: + abort(); + } + v8::Local obj = v8::Local::New(args[1]); + Predicate *pred = new Predicate(p, obj); + pred->Wrap(args.This()); + return scope.Close(args.This()); +} + +Predicate :: Predicate(hyperpredicate p, v8::Local &o) + : m_pred(p) + , m_obj() +{ + if (!o.IsEmpty()) + { + m_obj = v8::Persistent::New(o); + } } Predicate :: ~Predicate() throw () { - if (!m_obj.IsEmpty()) - { - m_obj.Dispose(); - m_obj.Clear(); - } + if (!m_obj.IsEmpty()) + { + m_obj.Dispose(); + m_obj.Clear(); + } } #define HYPERDEX_PRED_CAST(X, Y) \ - v8::Handle \ - HyperDexClient :: X(const v8::Arguments& args) \ - { \ - v8::Local pred = v8::Local::New(predicate); \ - v8::Local p(v8::Integer::New(Y)); \ - v8::Handle argv[] = {p, args[0]}; \ - return pred->NewInstance(2, argv); \ - } + v8::Handle \ + HyperDexClient :: X(const v8::Arguments& args) \ + { \ + v8::Local pred = v8::Local::New(predicate); \ + v8::Local p(v8::Integer::New(Y)); \ + v8::Handle argv[] = {p, args[0]}; \ + return pred->NewInstance(2, argv); \ + } HYPERDEX_PRED_CAST(Equals, HYPERPREDICATE_EQUALS) HYPERDEX_PRED_CAST(LessThan, HYPERPREDICATE_LESS_THAN) @@ -835,849 +791,736 @@ HYPERDEX_PRED_CAST(Contains, HYPERPREDICATE_CONTAINS) v8::Handle Predicate :: value() { - v8::HandleScope scope; - return scope.Close(v8::Local::New(m_obj)); + v8::HandleScope scope; + return scope.Close(v8::Local::New(m_obj)); } hyperpredicate Predicate :: get_pred() { - return m_pred; + return m_pred; } #include "client.definitions.cc" -Operation :: Operation(v8::Handle& c1, HyperDexClient* c2) - : client(c2) - , reqid(-1) - , status(HYPERDEX_CLIENT_GARBAGE) - , attrs(NULL) - , attrs_sz(0) - , description(NULL) - , count(0) - , finished(false) - , encode_return() - , m_auth(NULL) - , m_ref(0) - , m_arena(hyperdex_ds_arena_create()) - , m_client() - , m_callback() - , m_callback_done() - , m_has_callback_done(false) -{ - m_client = v8::Persistent::New(c1); - v8::Local cbobj1 = v8::Object::New(); - m_callback = v8::Persistent::New(cbobj1); - v8::Local cbobj2 = v8::Object::New(); - m_callback_done = v8::Persistent::New(cbobj2); +Operation :: Operation(v8::Handle &c1, HyperDexClient *c2) + : client(c2) + , reqid(-1) + , status(HYPERDEX_CLIENT_GARBAGE) + , attrs(NULL) + , attrs_sz(0) + , description(NULL) + , count(0) + , finished(false) + , encode_return() + , m_auth(NULL) + , m_ref(0) + , m_arena(hyperdex_ds_arena_create()) + , m_client() + , m_callback() + , m_callback_done() + , m_has_callback_done(false) +{ + m_client = v8::Persistent::New(c1); + v8::Local cbobj1 = v8::Object::New(); + m_callback = v8::Persistent::New(cbobj1); + v8::Local cbobj2 = v8::Object::New(); + m_callback_done = v8::Persistent::New(cbobj2); } Operation :: ~Operation() throw () { - if (m_arena) - { - hyperdex_ds_arena_destroy(m_arena); - } - - if (attrs) - { - hyperdex_client_destroy_attrs(attrs, attrs_sz); - } - - if (m_auth) - { - free((void *)m_auth); - } - - if (description) - { - free((void*)description); - } - - if (!m_client.IsEmpty()) - { - m_client.Dispose(); - m_client.Clear(); - } - - if (!m_callback.IsEmpty()) - { - m_callback.Dispose(); - m_callback.Clear(); - } + if (m_arena) + { + hyperdex_ds_arena_destroy(m_arena); + } + if (attrs) + { + hyperdex_client_destroy_attrs(attrs, attrs_sz); + } + if (m_auth) + { + free((void *)m_auth); + } + if (description) + { + free((void *)description); + } + if (!m_client.IsEmpty()) + { + m_client.Dispose(); + m_client.Clear(); + } + if (!m_callback.IsEmpty()) + { + m_callback.Dispose(); + m_callback.Clear(); + } } bool -Operation :: set_callback(v8::Handle& func) +Operation :: set_callback(v8::Handle &func) { - v8::Local::New(m_callback)->Set(v8::String::NewSymbol("callback"), func); - m_has_callback_done = false; - return true; + v8::Local::New(m_callback)->Set(v8::String::NewSymbol("callback"), func); + m_has_callback_done = false; + return true; } bool -Operation :: set_callback(v8::Handle& func, v8::Handle& done) +Operation :: set_callback(v8::Handle &func, v8::Handle &done) { - v8::Local::New(m_callback)->Set(v8::String::NewSymbol("callback"), func); - v8::Local::New(m_callback_done)->Set(v8::String::NewSymbol("callback"), done); - m_has_callback_done = true; - return true; + v8::Local::New(m_callback)->Set(v8::String::NewSymbol("callback"), func); + v8::Local::New(m_callback_done)->Set(v8::String::NewSymbol("callback"), done); + m_has_callback_done = true; + return true; } bool -Operation :: convert_error(v8::Handle& _value, - const char** value, size_t* value_sz, - hyperdatatype* datatype) +Operation :: convert_error(v8::Handle &_value, + const char **value, size_t *value_sz, + hyperdatatype *datatype) { - this->callback_error_message("cannot convert to HyperDex type"); - return false; + this->callback_error_message("cannot convert to HyperDex type"); + return false; } bool -Operation :: convert_int(v8::Handle& _value, - const char** value, size_t* value_sz, - hyperdatatype* datatype) -{ - if (_value->IsNumber()) - { - double _num = _value.As()->Value(); - int64_t num = _num; - hyperdex_ds_returncode error; - - if (hyperdex_ds_copy_int(m_arena, num, &error, value, value_sz) < 0) - { - this->callback_error_out_of_memory(); - return false; - } - - *datatype = HYPERDATATYPE_INT64; - return true; - } - else - { - this->callback_error_message("cannot convert to an int"); - return false; - } +Operation :: convert_int(v8::Handle &_value, + const char **value, size_t *value_sz, + hyperdatatype *datatype) +{ + if (_value->IsNumber()) + { + double _num = _value.As()->Value(); + int64_t num = _num; + hyperdex_ds_returncode error; + if (hyperdex_ds_copy_int(m_arena, num, &error, value, value_sz) < 0) + { + this->callback_error_out_of_memory(); + return false; + } + *datatype = HYPERDATATYPE_INT64; + return true; + } + else + { + this->callback_error_message("cannot convert to an int"); + return false; + } } bool -Operation :: convert_float(v8::Handle& _value, - const char** value, size_t* value_sz, - hyperdatatype* datatype) -{ - if (_value->IsNumber()) - { - double num = _value.As()->Value(); - hyperdex_ds_returncode error; - - if (hyperdex_ds_copy_float(m_arena, num, &error, value, value_sz) < 0) - { - this->callback_error_out_of_memory(); - return false; - } - - *datatype = HYPERDATATYPE_FLOAT; - return true; - } - else - { - this->callback_error_message("cannot convert to a float"); - return false; - } +Operation :: convert_float(v8::Handle &_value, + const char **value, size_t *value_sz, + hyperdatatype *datatype) +{ + if (_value->IsNumber()) + { + double num = _value.As()->Value(); + hyperdex_ds_returncode error; + if (hyperdex_ds_copy_float(m_arena, num, &error, value, value_sz) < 0) + { + this->callback_error_out_of_memory(); + return false; + } + *datatype = HYPERDATATYPE_FLOAT; + return true; + } + else + { + this->callback_error_message("cannot convert to a float"); + return false; + } } #define HDJS_HANDLE_ELEM_ERROR(X, TYPE) \ - switch (X) \ - { \ - case HYPERDEX_DS_NOMEM: \ - this->callback_error_out_of_memory(); \ - return false; \ - case HYPERDEX_DS_MIXED_TYPES: \ - this->callback_error_message("Cannot add " TYPE " to a heterogenous container"); \ - return false; \ - case HYPERDEX_DS_SUCCESS: \ - case HYPERDEX_DS_STRING_TOO_LONG: \ - case HYPERDEX_DS_WRONG_STATE: \ - default: \ - this->callback_error_message("Cannot convert " TYPE " to a HyperDex type"); \ - return false; \ - } + switch (X) \ + { \ + case HYPERDEX_DS_NOMEM: \ + this->callback_error_out_of_memory(); \ + return false; \ + case HYPERDEX_DS_MIXED_TYPES: \ + this->callback_error_message("Cannot add " TYPE " to a heterogenous container"); \ + return false; \ + case HYPERDEX_DS_SUCCESS: \ + case HYPERDEX_DS_STRING_TOO_LONG: \ + case HYPERDEX_DS_WRONG_STATE: \ + default: \ + this->callback_error_message("Cannot convert " TYPE " to a HyperDex type"); \ + return false; \ + } bool -Operation :: convert_elem(v8::Handle& value, void* x, +Operation :: convert_elem(v8::Handle &value, void *x, elem_string_fptr f_string, elem_int_fptr f_int, elem_float_fptr f_float) { - if (value.IsEmpty()) - { - this->callback_error_message("cannot convert undefined to HyperDex type"); - return false; - } - - if (value->IsObject() && - value->ToObject()->GetConstructor()->StrictEquals(HyperDexClient::type_hint)) - { - TypeHint* hint = node::ObjectWrap::Unwrap(value.As()); - assert(hint); - - if (hint->get_type() == HYPERDATATYPE_INT64) - { - double _num = hint->value().As()->Value(); - int64_t num = _num; - hyperdex_ds_returncode error; - - if (f_int(x, num, &error) < 0) - { - HDJS_HANDLE_ELEM_ERROR(error, "int"); - } - - return true; - } - else if (hint->get_type() == HYPERDATATYPE_FLOAT) - { - double num = hint->value().As()->Value(); - hyperdex_ds_returncode error; - - if (f_float(x, num, &error) < 0) - { - HDJS_HANDLE_ELEM_ERROR(error, "float"); - } - - return true; - } - else - { - this->callback_error_message("cannot convert to HyperDex type"); - return false; - } - } - - if (value->IsNumber()) - { - double _num = value.As()->Value(); - int64_t num = _num; - hyperdex_ds_returncode error; - - if (f_int(x, num, &error) < 0) - { - HDJS_HANDLE_ELEM_ERROR(error, "int"); - } - - return true; - } - - if (node::Buffer::HasInstance(value->ToObject())) - { - size_t sz = node::Buffer::Length(value->ToObject()); - char* data = node::Buffer::Data(value->ToObject()); - hyperdex_ds_returncode error; - - if (f_string(x, data, sz, &error) < 0) - { - HDJS_HANDLE_ELEM_ERROR(error, "string"); - } - - return true; - } - - if (value->IsString()) - { - hyperdex_ds_returncode error; - v8::String::Utf8Value s(value); - - if (s.length() == 0 && *s == NULL) - { - this->callback_error_message("cannot convert object to string"); - return false; - } - - if (f_string(x, *s, s.length(), &error) < 0) - { - HDJS_HANDLE_ELEM_ERROR(error, "string"); - } - - return true; - } - - this->callback_error_message("cannot convert to HyperDex type"); - return false; + if (value.IsEmpty()) + { + this->callback_error_message("cannot convert undefined to HyperDex type"); + return false; + } + if (value->IsObject() && + value->ToObject()->GetConstructor()->StrictEquals(HyperDexClient::type_hint)) + { + TypeHint *hint = node::ObjectWrap::Unwrap(value.As()); + assert(hint); + if (hint->get_type() == HYPERDATATYPE_INT64) + { + double _num = hint->value().As()->Value(); + int64_t num = _num; + hyperdex_ds_returncode error; + if (f_int(x, num, &error) < 0) + { + HDJS_HANDLE_ELEM_ERROR(error, "int"); + } + return true; + } + else if (hint->get_type() == HYPERDATATYPE_FLOAT) + { + double num = hint->value().As()->Value(); + hyperdex_ds_returncode error; + if (f_float(x, num, &error) < 0) + { + HDJS_HANDLE_ELEM_ERROR(error, "float"); + } + return true; + } + else + { + this->callback_error_message("cannot convert to HyperDex type"); + return false; + } + } + if (value->IsNumber()) + { + double _num = value.As()->Value(); + int64_t num = _num; + hyperdex_ds_returncode error; + if (f_int(x, num, &error) < 0) + { + HDJS_HANDLE_ELEM_ERROR(error, "int"); + } + return true; + } + if (node::Buffer::HasInstance(value->ToObject())) + { + size_t sz = node::Buffer::Length(value->ToObject()); + char *data = node::Buffer::Data(value->ToObject()); + hyperdex_ds_returncode error; + if (f_string(x, data, sz, &error) < 0) + { + HDJS_HANDLE_ELEM_ERROR(error, "string"); + } + return true; + } + if (value->IsString()) + { + hyperdex_ds_returncode error; + v8::String::Utf8Value s(value); + if (s.length() == 0 && *s == NULL) + { + this->callback_error_message("cannot convert object to string"); + return false; + } + if (f_string(x, *s, s.length(), &error) < 0) + { + HDJS_HANDLE_ELEM_ERROR(error, "string"); + } + return true; + } + this->callback_error_message("cannot convert to HyperDex type"); + return false; } bool -Operation :: convert_list(v8::Handle& _value, - const char** value, size_t* value_sz, - hyperdatatype* datatype) -{ - if (!_value->IsArray()) - { - this->callback_error_message("lists must be specified as arrays"); - return false; - } - - struct hyperdex_ds_list* list; - enum hyperdex_ds_returncode error; - list = hyperdex_ds_allocate_list(m_arena); - - if (!list) - { - this->callback_error_out_of_memory(); - return false; - } - - v8::Local arr = v8::Local::New(_value.As()); - - for (size_t i = 0; i < arr->Length(); ++i) - { - v8::Local entry = arr->Get(i); - - if (!this->convert_elem(entry, list, - (elem_string_fptr) hyperdex_ds_list_append_string, - (elem_int_fptr) hyperdex_ds_list_append_int, - (elem_float_fptr) hyperdex_ds_list_append_float)) - { - return false; - } - } - - if (hyperdex_ds_list_finalize(list, &error, value, value_sz, datatype) < 0) - { - this->callback_error_out_of_memory(); - return false; - } - - return true; +Operation :: convert_list(v8::Handle &_value, + const char **value, size_t *value_sz, + hyperdatatype *datatype) +{ + if (!_value->IsArray()) + { + this->callback_error_message("lists must be specified as arrays"); + return false; + } + struct hyperdex_ds_list *list; + enum hyperdex_ds_returncode error; + list = hyperdex_ds_allocate_list(m_arena); + if (!list) + { + this->callback_error_out_of_memory(); + return false; + } + v8::Local arr = v8::Local::New(_value.As()); + for (size_t i = 0; i < arr->Length(); ++i) + { + v8::Local entry = arr->Get(i); + if (!this->convert_elem(entry, list, + (elem_string_fptr) hyperdex_ds_list_append_string, + (elem_int_fptr) hyperdex_ds_list_append_int, + (elem_float_fptr) hyperdex_ds_list_append_float)) + { + return false; + } + } + if (hyperdex_ds_list_finalize(list, &error, value, value_sz, datatype) < 0) + { + this->callback_error_out_of_memory(); + return false; + } + return true; } bool -Operation :: convert_set(v8::Handle& _value, - const char** value, size_t* value_sz, - hyperdatatype* datatype) -{ - if (!_value->IsArray()) - { - this->callback_error_message("sets must be specified as arrays"); - return false; - } - - struct hyperdex_ds_set* set; - enum hyperdex_ds_returncode error; - set = hyperdex_ds_allocate_set(m_arena); - - if (!set) - { - this->callback_error_out_of_memory(); - return false; - } - - v8::Local arr = v8::Local::New(_value.As()); - - for (size_t i = 0; i < arr->Length(); ++i) - { - v8::Local entry = arr->Get(i); - - if (!this->convert_elem(entry, set, - (elem_string_fptr) hyperdex_ds_set_insert_string, - (elem_int_fptr) hyperdex_ds_set_insert_int, - (elem_float_fptr) hyperdex_ds_set_insert_float)) - { - return false; - } - } - - if (hyperdex_ds_set_finalize(set, &error, value, value_sz, datatype) < 0) - { - this->callback_error_out_of_memory(); - return false; - } - - return true; +Operation :: convert_set(v8::Handle &_value, + const char **value, size_t *value_sz, + hyperdatatype *datatype) +{ + if (!_value->IsArray()) + { + this->callback_error_message("sets must be specified as arrays"); + return false; + } + struct hyperdex_ds_set *set; + enum hyperdex_ds_returncode error; + set = hyperdex_ds_allocate_set(m_arena); + if (!set) + { + this->callback_error_out_of_memory(); + return false; + } + v8::Local arr = v8::Local::New(_value.As()); + for (size_t i = 0; i < arr->Length(); ++i) + { + v8::Local entry = arr->Get(i); + if (!this->convert_elem(entry, set, + (elem_string_fptr) hyperdex_ds_set_insert_string, + (elem_int_fptr) hyperdex_ds_set_insert_int, + (elem_float_fptr) hyperdex_ds_set_insert_float)) + { + return false; + } + } + if (hyperdex_ds_set_finalize(set, &error, value, value_sz, datatype) < 0) + { + this->callback_error_out_of_memory(); + return false; + } + return true; } bool -Operation :: convert_map(v8::Handle& _value, - const char** value, size_t* value_sz, - hyperdatatype* datatype) -{ - if (!_value->IsArray()) - { - this->callback_error_message("maps must be specified as arrays"); - return false; - } - - struct hyperdex_ds_map* map; - enum hyperdex_ds_returncode error; - map = hyperdex_ds_allocate_map(m_arena); - - if (!map) - { - this->callback_error_out_of_memory(); - return false; - } - - v8::Local arr = v8::Local::New(_value.As()); - - for (size_t i = 0; i < arr->Length(); ++i) - { - v8::Local _pair = arr->Get(i); - - if (!_pair->IsArray()) - { - this->callback_error_message("map pairs must be specified as arrays"); - return false; - } - - v8::Local pair = _pair.As(); - - if (pair->Length() != 2) - { - this->callback_error_message("map pairs must be of length 2"); - return false; - } - - v8::Local key = pair->Get(0); - v8::Local val = pair->Get(1); - - if (!this->convert_elem(key, map, - (elem_string_fptr) hyperdex_ds_map_insert_key_string, - (elem_int_fptr) hyperdex_ds_map_insert_key_int, - (elem_float_fptr) hyperdex_ds_map_insert_key_float) || - !this->convert_elem(val, map, - (elem_string_fptr) hyperdex_ds_map_insert_val_string, - (elem_int_fptr) hyperdex_ds_map_insert_val_int, - (elem_float_fptr) hyperdex_ds_map_insert_val_float)) - { - return false; - } - } - - if (hyperdex_ds_map_finalize(map, &error, value, value_sz, datatype) < 0) - { - this->callback_error_out_of_memory(); - return false; - } - - return true; +Operation :: convert_map(v8::Handle &_value, + const char **value, size_t *value_sz, + hyperdatatype *datatype) +{ + if (!_value->IsArray()) + { + this->callback_error_message("maps must be specified as arrays"); + return false; + } + struct hyperdex_ds_map *map; + enum hyperdex_ds_returncode error; + map = hyperdex_ds_allocate_map(m_arena); + if (!map) + { + this->callback_error_out_of_memory(); + return false; + } + v8::Local arr = v8::Local::New(_value.As()); + for (size_t i = 0; i < arr->Length(); ++i) + { + v8::Local _pair = arr->Get(i); + if (!_pair->IsArray()) + { + this->callback_error_message("map pairs must be specified as arrays"); + return false; + } + v8::Local pair = _pair.As(); + if (pair->Length() != 2) + { + this->callback_error_message("map pairs must be of length 2"); + return false; + } + v8::Local key = pair->Get(0); + v8::Local val = pair->Get(1); + if (!this->convert_elem(key, map, + (elem_string_fptr) hyperdex_ds_map_insert_key_string, + (elem_int_fptr) hyperdex_ds_map_insert_key_int, + (elem_float_fptr) hyperdex_ds_map_insert_key_float) || + !this->convert_elem(val, map, + (elem_string_fptr) hyperdex_ds_map_insert_val_string, + (elem_int_fptr) hyperdex_ds_map_insert_val_int, + (elem_float_fptr) hyperdex_ds_map_insert_val_float)) + { + return false; + } + } + if (hyperdex_ds_map_finalize(map, &error, value, value_sz, datatype) < 0) + { + this->callback_error_out_of_memory(); + return false; + } + return true; } bool -Operation :: convert_cstring(v8::Handle& _cstring, - const char** cstring) -{ - v8::String::Utf8Value s(_cstring); - - if (s.length() == 0 && *s == NULL) - { - this->callback_error_message("cannot convert object to string"); - return false; - } - - hyperdex_ds_returncode error; - size_t sz; - - if (hyperdex_ds_copy_string(m_arena, *s, s.length() + 1, &error, cstring, &sz) < 0) - { - this->callback_error_out_of_memory(); - return false; - } - - return true; +Operation :: convert_cstring(v8::Handle &_cstring, + const char **cstring) +{ + v8::String::Utf8Value s(_cstring); + if (s.length() == 0 && *s == NULL) + { + this->callback_error_message("cannot convert object to string"); + return false; + } + hyperdex_ds_returncode error; + size_t sz; + if (hyperdex_ds_copy_string(m_arena, *s, s.length() + 1, &error, cstring, &sz) < 0) + { + this->callback_error_out_of_memory(); + return false; + } + return true; } bool -Operation :: convert_type(v8::Handle& _value, - const char** value, size_t* value_sz, - hyperdatatype* datatype, +Operation :: convert_type(v8::Handle &_value, + const char **value, size_t *value_sz, + hyperdatatype *datatype, bool make_callback_on_error, bool may_default_to_json) { - if (_value.IsEmpty()) - { - if (make_callback_on_error) - { - this->callback_error_message("cannot convert undefined to HyperDex type"); - } - - return false; - } - - if (_value->IsObject() && - _value->ToObject()->GetConstructor()->StrictEquals(HyperDexClient::type_hint)) - { - TypeHint* hint = node::ObjectWrap::Unwrap(_value.As()); - assert(hint); - Operation::type_converter conv = hint->get_converter(); - v8::Local inner = v8::Local::New(hint->value()); - return (this->*conv)(inner, value, value_sz, datatype); - } - - if (_value->IsNumber()) - { - double _num = _value.As()->Value(); - int64_t num = _num; - hyperdex_ds_returncode error; - - if (hyperdex_ds_copy_int(m_arena, num, &error, value, value_sz) < 0) - { - if (make_callback_on_error) - { - this->callback_error_out_of_memory(); - } - - return false; - } - - *datatype = HYPERDATATYPE_INT64; - return true; - } - - if (node::Buffer::HasInstance(_value->ToObject())) - { - size_t sz = node::Buffer::Length(_value->ToObject()); - char* data = node::Buffer::Data(_value->ToObject()); - hyperdex_ds_returncode error; - - if (hyperdex_ds_copy_string(m_arena, data, sz, &error, value, value_sz) < 0) - { - if (make_callback_on_error) - { - this->callback_error_out_of_memory(); - } - - return false; - } - - *datatype = HYPERDATATYPE_STRING; - return true; - } - - if (_value->IsString()) - { - v8::String::Utf8Value s(_value); - - if (s.length() == 0 && *s == NULL) - { - if (make_callback_on_error) - { - this->callback_error_message("cannot convert object to string"); - } - - return false; - } - - hyperdex_ds_returncode error; - - if (hyperdex_ds_copy_string(m_arena, *s, s.length(), &error, value, value_sz) < 0) - { - if (make_callback_on_error) - { - this->callback_error_out_of_memory(); - } - - return false; - } - - *datatype = HYPERDATATYPE_STRING; - return true; - } - - if (may_default_to_json) - { - v8::Local global = v8::Context::GetCurrent()->Global(); - v8::Local JSON = global->Get(v8::String::New("JSON"))->ToObject(); - v8::Handle parse = v8::Handle::Cast(JSON->Get(v8::String::New("stringify"))); - v8::Handle argv[1] = { _value }; - v8::Local str = v8::Local::New(parse->Call(JSON, 1, argv)); - v8::String::Utf8Value s(str); - - if (s.length() == 0 && *s == NULL) - { - if (make_callback_on_error) - { - this->callback_error_message("cannot convert object to JSON"); - } - - return false; - } - - hyperdex_ds_returncode error; - - if (hyperdex_ds_copy_string(m_arena, *s, s.length(), &error, value, value_sz) < 0) - { - if (make_callback_on_error) - { - this->callback_error_out_of_memory(); - } - - return false; - } - - *datatype = HYPERDATATYPE_DOCUMENT; - return true; - } - - if (make_callback_on_error) - { - this->callback_error_message("cannot convert to HyperDex type"); - } - - return false; + if (_value.IsEmpty()) + { + if (make_callback_on_error) + { + this->callback_error_message("cannot convert undefined to HyperDex type"); + } + return false; + } + if (_value->IsObject() && + _value->ToObject()->GetConstructor()->StrictEquals(HyperDexClient::type_hint)) + { + TypeHint *hint = node::ObjectWrap::Unwrap(_value.As()); + assert(hint); + Operation::type_converter conv = hint->get_converter(); + v8::Local inner = v8::Local::New(hint->value()); + return (this->*conv)(inner, value, value_sz, datatype); + } + if (_value->IsNumber()) + { + double _num = _value.As()->Value(); + int64_t num = _num; + hyperdex_ds_returncode error; + if (hyperdex_ds_copy_int(m_arena, num, &error, value, value_sz) < 0) + { + if (make_callback_on_error) + { + this->callback_error_out_of_memory(); + } + return false; + } + *datatype = HYPERDATATYPE_INT64; + return true; + } + if (node::Buffer::HasInstance(_value->ToObject())) + { + size_t sz = node::Buffer::Length(_value->ToObject()); + char *data = node::Buffer::Data(_value->ToObject()); + hyperdex_ds_returncode error; + if (hyperdex_ds_copy_string(m_arena, data, sz, &error, value, value_sz) < 0) + { + if (make_callback_on_error) + { + this->callback_error_out_of_memory(); + } + return false; + } + *datatype = HYPERDATATYPE_STRING; + return true; + } + if (_value->IsString()) + { + v8::String::Utf8Value s(_value); + if (s.length() == 0 && *s == NULL) + { + if (make_callback_on_error) + { + this->callback_error_message("cannot convert object to string"); + } + return false; + } + hyperdex_ds_returncode error; + if (hyperdex_ds_copy_string(m_arena, *s, s.length(), &error, value, value_sz) < 0) + { + if (make_callback_on_error) + { + this->callback_error_out_of_memory(); + } + return false; + } + *datatype = HYPERDATATYPE_STRING; + return true; + } + if (may_default_to_json) + { + v8::Local global = v8::Context::GetCurrent()->Global(); + v8::Local JSON = global->Get(v8::String::New("JSON"))->ToObject(); + v8::Handle parse = v8::Handle::Cast(JSON->Get(v8::String::New("stringify"))); + v8::Handle argv[1] = { _value }; + v8::Local str = v8::Local::New(parse->Call(JSON, 1, argv)); + v8::String::Utf8Value s(str); + if (s.length() == 0 && *s == NULL) + { + if (make_callback_on_error) + { + this->callback_error_message("cannot convert object to JSON"); + } + return false; + } + hyperdex_ds_returncode error; + if (hyperdex_ds_copy_string(m_arena, *s, s.length(), &error, value, value_sz) < 0) + { + if (make_callback_on_error) + { + this->callback_error_out_of_memory(); + } + return false; + } + *datatype = HYPERDATATYPE_DOCUMENT; + return true; + } + if (make_callback_on_error) + { + this->callback_error_message("cannot convert to HyperDex type"); + } + return false; } bool -Operation :: convert_spacename(v8::Handle& _spacename, - const char** spacename) +Operation :: convert_spacename(v8::Handle &_spacename, + const char **spacename) { - return convert_cstring(_spacename, spacename); + return convert_cstring(_spacename, spacename); } bool -Operation :: convert_key(v8::Handle& _key, - const char** key, size_t* key_sz) +Operation :: convert_key(v8::Handle &_key, + const char **key, size_t *key_sz) { - hyperdatatype datatype; - return convert_type(_key, key, key_sz, &datatype, true, false); + hyperdatatype datatype; + return convert_type(_key, key, key_sz, &datatype, true, false); } bool -Operation :: convert_attributes(v8::Handle& x, - const hyperdex_client_attribute** _attrs, - size_t* _attrs_sz) -{ - if (!x->IsObject()) - { - this->callback_error_message("attributes must be an object"); - return false; - } - - v8::Local attributes = x->ToObject(); - v8::Local arr = attributes->GetPropertyNames(); - size_t ret_attrs_sz = arr->Length(); - struct hyperdex_client_attribute* ret_attrs; - ret_attrs = hyperdex_ds_allocate_attribute(m_arena, ret_attrs_sz); - - if (!ret_attrs) - { - this->callback_error_out_of_memory(); - return false; - } - - *_attrs = ret_attrs; - *_attrs_sz = ret_attrs_sz; - - for (size_t i = 0; i < arr->Length(); ++i) - { - v8::Local key = arr->Get(i); - v8::Local val = attributes->Get(key); - - if (!convert_cstring(key, &ret_attrs[i].attr) || - !convert_type(val, &ret_attrs[i].value, - &ret_attrs[i].value_sz, - &ret_attrs[i].datatype, true, true)) - { - return false; - } - } - - return true; +Operation :: convert_attributes(v8::Handle &x, + const hyperdex_client_attribute **_attrs, + size_t *_attrs_sz) +{ + if (!x->IsObject()) + { + this->callback_error_message("attributes must be an object"); + return false; + } + v8::Local attributes = x->ToObject(); + v8::Local arr = attributes->GetPropertyNames(); + size_t ret_attrs_sz = arr->Length(); + struct hyperdex_client_attribute *ret_attrs; + ret_attrs = hyperdex_ds_allocate_attribute(m_arena, ret_attrs_sz); + if (!ret_attrs) + { + this->callback_error_out_of_memory(); + return false; + } + *_attrs = ret_attrs; + *_attrs_sz = ret_attrs_sz; + for (size_t i = 0; i < arr->Length(); ++i) + { + v8::Local key = arr->Get(i); + v8::Local val = attributes->Get(key); + if (!convert_cstring(key, &ret_attrs[i].attr) || + !convert_type(val, &ret_attrs[i].value, + &ret_attrs[i].value_sz, + &ret_attrs[i].datatype, true, true)) + { + return false; + } + } + return true; } bool -Operation :: convert_document_predicates(const std::string& prefix, - v8::Handle& x, - std::vector* checks) -{ - v8::Local arr = x->GetPropertyNames(); - - for (size_t i = 0; i < arr->Length(); ++i) - { - hyperdex_client_attribute_check check; - v8::Local key = arr->Get(i); - v8::Local val = x->Get(key); - hyperdex_ds_returncode error; - size_t sz; - - if (convert_type(val, &check.value, - &check.value_sz, - &check.datatype, false, false)) - { - if (!convert_cstring(key, &check.attr)) - { - return false; - } - - std::string attr = prefix + check.attr; - - if (hyperdex_ds_copy_string(m_arena, attr.c_str(), attr.size() + 1, &error, &check.attr, &sz) < 0) - { - this->callback_error_out_of_memory(); - return false; - } - - check.predicate = HYPERPREDICATE_EQUALS; - checks->push_back(check); - } - else if (val->IsObject() && - val->ToObject()->GetConstructor()->StrictEquals(HyperDexClient::predicate)) - { - Predicate* pred = node::ObjectWrap::Unwrap(val.As()); - v8::Local v = v8::Local::New(pred->value()); - - if (!convert_cstring(key, &check.attr) || - !convert_type(v, &check.value, - &check.value_sz, - &check.datatype, true, false)) - { - return false; - } - - std::string attr = prefix + check.attr; - - if (hyperdex_ds_copy_string(m_arena, attr.c_str(), attr.size() + 1, &error, &check.attr, &sz) < 0) - { - this->callback_error_out_of_memory(); - return false; - } - - check.predicate = pred->get_pred(); - checks->push_back(check); - } - else if (val->IsObject()) - { - v8::String::Utf8Value s(key); - - if (s.length() == 0 && *s == NULL) - { - this->callback_error_message("cannot convert object to string"); - return false; - } - - std::string ss(prefix); - ss.append(*s, s.length()); - ss.append(".", 1); - v8::Local ps = val->ToObject(); - - if (!convert_document_predicates(ss, ps, checks)) - { - return false; - } - } - } - - return true; +Operation :: convert_document_predicates(const std::string &prefix, + v8::Handle &x, + std::vector *checks) +{ + v8::Local arr = x->GetPropertyNames(); + for (size_t i = 0; i < arr->Length(); ++i) + { + hyperdex_client_attribute_check check; + v8::Local key = arr->Get(i); + v8::Local val = x->Get(key); + hyperdex_ds_returncode error; + size_t sz; + if (convert_type(val, &check.value, + &check.value_sz, + &check.datatype, false, false)) + { + if (!convert_cstring(key, &check.attr)) + { + return false; + } + std::string attr = prefix + check.attr; + if (hyperdex_ds_copy_string(m_arena, attr.c_str(), attr.size() + 1, &error, &check.attr, &sz) < 0) + { + this->callback_error_out_of_memory(); + return false; + } + check.predicate = HYPERPREDICATE_EQUALS; + checks->push_back(check); + } + else if (val->IsObject() && + val->ToObject()->GetConstructor()->StrictEquals(HyperDexClient::predicate)) + { + Predicate *pred = node::ObjectWrap::Unwrap(val.As()); + v8::Local v = v8::Local::New(pred->value()); + if (!convert_cstring(key, &check.attr) || + !convert_type(v, &check.value, + &check.value_sz, + &check.datatype, true, false)) + { + return false; + } + std::string attr = prefix + check.attr; + if (hyperdex_ds_copy_string(m_arena, attr.c_str(), attr.size() + 1, &error, &check.attr, &sz) < 0) + { + this->callback_error_out_of_memory(); + return false; + } + check.predicate = pred->get_pred(); + checks->push_back(check); + } + else if (val->IsObject()) + { + v8::String::Utf8Value s(key); + if (s.length() == 0 && *s == NULL) + { + this->callback_error_message("cannot convert object to string"); + return false; + } + std::string ss(prefix); + ss.append(*s, s.length()); + ss.append(".", 1); + v8::Local ps = val->ToObject(); + if (!convert_document_predicates(ss, ps, checks)) + { + return false; + } + } + } + return true; } bool -Operation :: convert_predicates(v8::Handle& x, - const hyperdex_client_attribute_check** _checks, - size_t* _checks_sz) -{ - if (!x->IsObject()) - { - this->callback_error_message("predicates must be an object"); - return false; - } - - v8::Local predicates = x->ToObject(); - std::vector checks; - - if (!convert_document_predicates("", predicates, &checks)) - { - return false; - } - - hyperdex_client_attribute_check* cs; - *_checks = cs = hyperdex_ds_allocate_attribute_check(m_arena, checks.size()); - *_checks_sz = checks.size(); - - if (!*_checks) - { - this->callback_error_out_of_memory(); - return false; - } - - for (size_t i = 0; i < checks.size(); ++i) - { - cs[i] = checks[i]; - } - - return true; +Operation :: convert_predicates(v8::Handle &x, + const hyperdex_client_attribute_check **_checks, + size_t *_checks_sz) +{ + if (!x->IsObject()) + { + this->callback_error_message("predicates must be an object"); + return false; + } + v8::Local predicates = x->ToObject(); + std::vector checks; + if (!convert_document_predicates("", predicates, &checks)) + { + return false; + } + hyperdex_client_attribute_check *cs; + *_checks = cs = hyperdex_ds_allocate_attribute_check(m_arena, checks.size()); + *_checks_sz = checks.size(); + if (!*_checks) + { + this->callback_error_out_of_memory(); + return false; + } + for (size_t i = 0; i < checks.size(); ++i) + { + cs[i] = checks[i]; + } + return true; } bool -Operation :: convert_mapattributes(v8::Handle& _predicates, - const hyperdex_client_map_attribute** _mapattrs, - size_t* _mapattrs_sz) +Operation :: convert_mapattributes(v8::Handle &_predicates, + const hyperdex_client_map_attribute **_mapattrs, + size_t *_mapattrs_sz) { - v8::ThrowException(v8::String::New("mapattributes not yet supported")); // XXX - *_mapattrs = NULL; - *_mapattrs_sz = 0; - return false; + v8::ThrowException(v8::String::New("mapattributes not yet supported")); // XXX + *_mapattrs = NULL; + *_mapattrs_sz = 0; + return false; } bool -Operation :: convert_attributenames(v8::Handle& x, - const char*** attributenames, - size_t* attributenames_sz) -{ - if (!x->IsArray()) - { - this->callback_error_message("attribute names must be an array"); - return false; - } - - v8::Handle arr = v8::Handle::Cast(x); - *attributenames_sz = arr->Length(); - const char** ret = static_cast(hyperdex_ds_malloc(m_arena, sizeof(char*) * *attributenames_sz)); - - if (!ret) - { - this->callback_error_out_of_memory(); - return false; - } - - *attributenames = ret; - - for (size_t i = 0; i < arr->Length(); ++i) - { - v8::Local key = arr->Get(i); - - if (!convert_cstring(key, &ret[i])) - { - return false; - } - } - - return true; +Operation :: convert_attributenames(v8::Handle &x, + const char *** attributenames, + size_t *attributenames_sz) +{ + if (!x->IsArray()) + { + this->callback_error_message("attribute names must be an array"); + return false; + } + v8::Handle arr = v8::Handle::Cast(x); + *attributenames_sz = arr->Length(); + const char **ret = static_cast(hyperdex_ds_malloc(m_arena, sizeof(char *) * *attributenames_sz)); + if (!ret) + { + this->callback_error_out_of_memory(); + return false; + } + *attributenames = ret; + for (size_t i = 0; i < arr->Length(); ++i) + { + v8::Local key = arr->Get(i); + if (!convert_cstring(key, &ret[i])) + { + return false; + } + } + return true; } bool -Operation :: convert_sortby(v8::Handle& _sortby, - const char** sortby) +Operation :: convert_sortby(v8::Handle &_sortby, + const char **sortby) { - return convert_cstring(_sortby, sortby); + return convert_cstring(_sortby, sortby); } bool -Operation :: convert_limit(v8::Handle& _limit, - uint64_t* limit) +Operation :: convert_limit(v8::Handle &_limit, + uint64_t *limit) { - if (!_limit->IsNumber()) - { - this->callback_error_message("limit must be numeric"); - return false; - } - - *limit = _limit->IntegerValue(); - return true; + if (!_limit->IsNumber()) + { + this->callback_error_message("limit must be numeric"); + return false; + } + *limit = _limit->IntegerValue(); + return true; } bool -Operation :: convert_maxmin(v8::Handle& _maxmin, - int* maximize) +Operation :: convert_maxmin(v8::Handle &_maxmin, + int *maximize) { - *maximize = _maxmin->IsTrue() ? 1 : 0; - return true; + *maximize = _maxmin->IsTrue() ? 1 : 0; + return true; } // 20 Sept 2015 - William Whitacre @@ -1686,1136 +1529,1019 @@ bool Operation :: convert_auth_context(v8::Handle &_value, const char ***p_auth, size_t *p_auth_sz) { - // Make sure this is an array we've been passed. - if (!_value->IsArray()) - { - this->callback_error_message("auth must be specified as an array"); - return false; - } - - // Reference it as an array. - v8::Local arr = - v8::Local::New(_value.As()); - - // Allocate the pointer array for storing the authorization chain. - const size_t auth_sz = arr->Length(); - const char **auth = reinterpret_cast(malloc(auth_sz * sizeof(const char *))); - - // Loop through the array elements. - for (size_t i = 0; i < auth_sz; ++i) - { - // Retrieve array element at index i. - v8::Local _M = arr->Get(i); - - // Make sure it's actually a string and use the convert_cstring member - // function to copy the string. - if (_M.IsEmpty() || - !(_M->IsString() && this->convert_cstring(_M, &auth[i]))) - { - this->callback_error_message("auth must be an array of strings"); - return false; - } - } - - // Copy the resulting pointers to the return arguments. - *p_auth_sz = auth_sz; - *p_auth = auth; - - // Everything worked ok. - return true; + // Make sure this is an array we've been passed. + if (!_value->IsArray()) + { + this->callback_error_message("auth must be specified as an array"); + return false; + } + // Reference it as an array. + v8::Local arr = + v8::Local::New(_value.As()); + // Allocate the pointer array for storing the authorization chain. + const size_t auth_sz = arr->Length(); + const char **auth = reinterpret_cast(malloc(auth_sz * sizeof(const char *))); + // Loop through the array elements. + for (size_t i = 0; i < auth_sz; ++i) + { + // Retrieve array element at index i. + v8::Local _M = arr->Get(i); + // Make sure it's actually a string and use the convert_cstring member + // function to copy the string. + if (_M.IsEmpty() || + !(_M->IsString() && this->convert_cstring(_M, &auth[i]))) + { + this->callback_error_message("auth must be an array of strings"); + return false; + } + } + // Copy the resulting pointers to the return arguments. + *p_auth_sz = auth_sz; + *p_auth = auth; + // Everything worked ok. + return true; } bool Operation :: set_auth_context(v8::Handle &_value) { - // Clear the authorization context if it's already been set (wierd). - this->clear_auth_context(); - size_t auth_sz; - - // Convert the authorization context object to an array of character - // pointers. - if (this->convert_auth_context(_value, &this->m_auth, &auth_sz)) - { - // Call hyperdex client to set the authorization context. - hyperdex_client_set_auth_context( - this->client->client(), - this->m_auth, auth_sz - ); - return true; - } - else - { - // Something went wrong during conversion! - return false; - } + // Clear the authorization context if it's already been set (wierd). + this->clear_auth_context(); + size_t auth_sz; + // Convert the authorization context object to an array of character + // pointers. + if (this->convert_auth_context(_value, &this->m_auth, &auth_sz)) + { + // Call hyperdex client to set the authorization context. + hyperdex_client_set_auth_context( + this->client->client(), + this->m_auth, auth_sz + ); + return true; + } + else + { + // Something went wrong during conversion! + return false; + } } bool Operation :: clear_auth_context() { - // Make sure the authorization context has been set. - if (this->m_auth != NULL) - { - // Call hyperdex client to clear the authorization context. - hyperdex_client_clear_auth_context(this->client->client()); - - // Free the array. - free((void *)this->m_auth); - this->m_auth = NULL; - } - - // this->m_auth is always null at this point, and if an array was there - // it was freed. - return true; + // Make sure the authorization context has been set. + if (this->m_auth != NULL) + { + // Call hyperdex client to clear the authorization context. + hyperdex_client_clear_auth_context(this->client->client()); + // Free the array. + free((void *)this->m_auth); + this->m_auth = NULL; + } + // this->m_auth is always null at this point, and if an array was there + // it was freed. + return true; } bool -Operation :: build_string(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - node::Buffer* buf = node::Buffer::New(value_sz); - memmove(node::Buffer::Data(buf), value, value_sz); - v8::Local global = v8::Context::GetCurrent()->Global(); - v8::Local buf_ctor - = v8::Local::Cast(global->Get(v8::String::NewSymbol("Buffer"))); - v8::Local A(v8::Integer::New(value_sz)); - v8::Local B(v8::Integer::New(0)); - v8::Handle argv[3] = { buf->handle_, A, B }; - v8::Local jsbuf = buf_ctor->NewInstance(3, argv); - retval = jsbuf; - return true; +Operation :: build_string(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + node::Buffer *buf = node::Buffer::New(value_sz); + memmove(node::Buffer::Data(buf), value, value_sz); + v8::Local global = v8::Context::GetCurrent()->Global(); + v8::Local buf_ctor + = v8::Local::Cast(global->Get(v8::String::NewSymbol("Buffer"))); + v8::Local A(v8::Integer::New(value_sz)); + v8::Local B(v8::Integer::New(0)); + v8::Handle argv[3] = { buf->handle_, A, B }; + v8::Local jsbuf = buf_ctor->NewInstance(3, argv); + retval = jsbuf; + return true; } bool -Operation :: build_int(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) +Operation :: build_int(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) { - int64_t tmp; - - if (hyperdex_ds_unpack_int(value, value_sz, &tmp) < 0) - { - return false; - } - - retval = v8::Integer::New(tmp); - return true; + int64_t tmp; + if (hyperdex_ds_unpack_int(value, value_sz, &tmp) < 0) + { + return false; + } + retval = v8::Integer::New(tmp); + return true; } bool -Operation :: build_float(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) +Operation :: build_float(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) { - double tmp; - - if (hyperdex_ds_unpack_float(value, value_sz, &tmp) < 0) - { - return false; - } - - retval = v8::Number::New(tmp); - return true; + double tmp; + if (hyperdex_ds_unpack_float(value, value_sz, &tmp) < 0) + { + return false; + } + retval = v8::Number::New(tmp); + return true; } bool -Operation :: build_document(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) +Operation :: build_document(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) { - v8::Local global = v8::Context::GetCurrent()->Global(); - v8::Local JSON = global->Get(v8::String::New("JSON"))->ToObject(); - v8::Handle parse = v8::Handle::Cast(JSON->Get(v8::String::New("parse"))); - v8::Local str(v8::String::New(value, value_sz)); - v8::Handle argv[1] = { str }; - retval = v8::Local::New(parse->Call(JSON, 1, argv)); - return true; + v8::Local global = v8::Context::GetCurrent()->Global(); + v8::Local JSON = global->Get(v8::String::New("JSON"))->ToObject(); + v8::Handle parse = v8::Handle::Cast(JSON->Get(v8::String::New("parse"))); + v8::Local str(v8::String::New(value, value_sz)); + v8::Handle argv[1] = { str }; + retval = v8::Local::New(parse->Call(JSON, 1, argv)); + return true; } bool -Operation :: build_list_string(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_STRING, value, value_sz); - const char* tmp_str = NULL; - size_t tmp_str_sz = 0; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_list_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed list(string)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_STRING, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_list_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) - { - v8::Local elem; - - if (!build_string(tmp_str, tmp_str_sz, elem, error)) - { - return false; - } - - arr->Set(idx, elem); - ++idx; - } - - retval = arr; - return true; +Operation :: build_list_string(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_STRING, value, value_sz); + const char *tmp_str = NULL; + size_t tmp_str_sz = 0; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_list_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed list(string)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_STRING, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_list_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) + { + v8::Local elem; + if (!build_string(tmp_str, tmp_str_sz, elem, error)) + { + return false; + } + arr->Set(idx, elem); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_list_int(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_INT64, value, value_sz); - int64_t tmp; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_list_int_next(&iter, &tmp)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed list(int)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_INT64, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_list_int_next(&iter, &tmp)) > 0) - { - v8::Local elem(v8::Integer::New(tmp)); - arr->Set(idx, elem); - ++idx; - } - - retval = arr; - return true; +Operation :: build_list_int(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_INT64, value, value_sz); + int64_t tmp; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_list_int_next(&iter, &tmp)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed list(int)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_INT64, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_list_int_next(&iter, &tmp)) > 0) + { + v8::Local elem(v8::Integer::New(tmp)); + arr->Set(idx, elem); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_list_float(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_FLOAT, value, value_sz); - double tmp; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_list_float_next(&iter, &tmp)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed list(float)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_FLOAT, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_list_float_next(&iter, &tmp)) > 0) - { - v8::Local elem(v8::Number::New(tmp)); - arr->Set(idx, elem); - ++idx; - } - - retval = arr; - return true; +Operation :: build_list_float(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_FLOAT, value, value_sz); + double tmp; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_list_float_next(&iter, &tmp)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed list(float)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_FLOAT, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_list_float_next(&iter, &tmp)) > 0) + { + v8::Local elem(v8::Number::New(tmp)); + arr->Set(idx, elem); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_set_string(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_STRING, value, value_sz); - const char* tmp_str = NULL; - size_t tmp_str_sz = 0; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_set_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed set(string)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_STRING, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_set_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) - { - v8::Local elem; - - if (!build_string(tmp_str, tmp_str_sz, elem, error)) - { - return false; - } - - arr->Set(idx, elem); - ++idx; - } - - retval = arr; - return true; +Operation :: build_set_string(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_STRING, value, value_sz); + const char *tmp_str = NULL; + size_t tmp_str_sz = 0; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_set_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed set(string)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_STRING, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_set_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) + { + v8::Local elem; + if (!build_string(tmp_str, tmp_str_sz, elem, error)) + { + return false; + } + arr->Set(idx, elem); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_set_int(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_INT64, value, value_sz); - int64_t tmp; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_set_int_next(&iter, &tmp)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed set(int)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_INT64, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_set_int_next(&iter, &tmp)) > 0) - { - v8::Local elem(v8::Integer::New(tmp)); - arr->Set(idx, elem); - ++idx; - } - - retval = arr; - return true; +Operation :: build_set_int(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_INT64, value, value_sz); + int64_t tmp; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_set_int_next(&iter, &tmp)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed set(int)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_INT64, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_set_int_next(&iter, &tmp)) > 0) + { + v8::Local elem(v8::Integer::New(tmp)); + arr->Set(idx, elem); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_set_float(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_FLOAT, value, value_sz); - double tmp; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_set_float_next(&iter, &tmp)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed set(float)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_FLOAT, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_set_float_next(&iter, &tmp)) > 0) - { - v8::Local elem(v8::Number::New(tmp)); - arr->Set(idx, elem); - ++idx; - } - - retval = arr; - return true; +Operation :: build_set_float(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_FLOAT, value, value_sz); + double tmp; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_set_float_next(&iter, &tmp)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed set(float)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_FLOAT, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_set_float_next(&iter, &tmp)) > 0) + { + v8::Local elem(v8::Number::New(tmp)); + arr->Set(idx, elem); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_map_string_string(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_STRING, value, value_sz); - const char* k = NULL; - const char* v = NULL; - size_t k_sz = 0; - size_t v_sz = 0; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_map_string_string_next(&iter, &k, &k_sz, &v, &v_sz)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed map(string, string)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_STRING, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_map_string_string_next(&iter, &k, &k_sz, &v, &v_sz)) > 0) - { - v8::Local key; - v8::Local val; - - if (!build_string(k, k_sz, key, error) || - !build_string(v, v_sz, val, error)) - { - return false; - } - - v8::Local pair(v8::Array::New(2)); - pair->Set(0, key); - pair->Set(1, val); - arr->Set(idx, pair); - ++idx; - } - - retval = arr; - return true; +Operation :: build_map_string_string(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_STRING, value, value_sz); + const char *k = NULL; + const char *v = NULL; + size_t k_sz = 0; + size_t v_sz = 0; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_map_string_string_next(&iter, &k, &k_sz, &v, &v_sz)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed map(string, string)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_STRING, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_map_string_string_next(&iter, &k, &k_sz, &v, &v_sz)) > 0) + { + v8::Local key; + v8::Local val; + if (!build_string(k, k_sz, key, error) || + !build_string(v, v_sz, val, error)) + { + return false; + } + v8::Local pair(v8::Array::New(2)); + pair->Set(0, key); + pair->Set(1, val); + arr->Set(idx, pair); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_map_string_int(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_INT64, value, value_sz); - const char* k = NULL; - size_t k_sz = 0; - int64_t v; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_map_string_int_next(&iter, &k, &k_sz, &v)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed map(string, int)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_INT64, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_map_string_int_next(&iter, &k, &k_sz, &v)) > 0) - { - v8::Local key; - v8::Local val(v8::Integer::New(v)); - - if (!build_string(k, k_sz, key, error)) - { - return false; - } - - v8::Local pair(v8::Array::New(2)); - pair->Set(0, key); - pair->Set(1, val); - arr->Set(idx, pair); - ++idx; - } - - retval = arr; - return true; +Operation :: build_map_string_int(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_INT64, value, value_sz); + const char *k = NULL; + size_t k_sz = 0; + int64_t v; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_map_string_int_next(&iter, &k, &k_sz, &v)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed map(string, int)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_INT64, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_map_string_int_next(&iter, &k, &k_sz, &v)) > 0) + { + v8::Local key; + v8::Local val(v8::Integer::New(v)); + if (!build_string(k, k_sz, key, error)) + { + return false; + } + v8::Local pair(v8::Array::New(2)); + pair->Set(0, key); + pair->Set(1, val); + arr->Set(idx, pair); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_map_string_float(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_FLOAT, value, value_sz); - const char* k = NULL; - size_t k_sz = 0; - double v; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_map_string_float_next(&iter, &k, &k_sz, &v)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed map(string, float)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_FLOAT, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_map_string_float_next(&iter, &k, &k_sz, &v)) > 0) - { - v8::Local key; - v8::Local val(v8::Number::New(v)); - - if (!build_string(k, k_sz, key, error)) - { - return false; - } - - v8::Local pair(v8::Array::New(2)); - pair->Set(0, key); - pair->Set(1, val); - arr->Set(idx, pair); - ++idx; - } - - retval = arr; - return true; +Operation :: build_map_string_float(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_FLOAT, value, value_sz); + const char *k = NULL; + size_t k_sz = 0; + double v; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_map_string_float_next(&iter, &k, &k_sz, &v)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed map(string, float)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_FLOAT, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_map_string_float_next(&iter, &k, &k_sz, &v)) > 0) + { + v8::Local key; + v8::Local val(v8::Number::New(v)); + if (!build_string(k, k_sz, key, error)) + { + return false; + } + v8::Local pair(v8::Array::New(2)); + pair->Set(0, key); + pair->Set(1, val); + arr->Set(idx, pair); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_map_int_string(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_INT64_STRING, value, value_sz); - int64_t k; - const char* v = NULL; - size_t v_sz = 0; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_map_int_string_next(&iter, &k, &v, &v_sz)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed map(int, string)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_INT64_STRING, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_map_int_string_next(&iter, &k, &v, &v_sz)) > 0) - { - v8::Local key(v8::Integer::New(k)); - v8::Local val; - - if (!build_string(v, v_sz, val, error)) - { - return false; - } - - v8::Local pair(v8::Array::New(2)); - pair->Set(0, key); - pair->Set(1, val); - arr->Set(idx, pair); - ++idx; - } - - retval = arr; - return true; +Operation :: build_map_int_string(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_INT64_STRING, value, value_sz); + int64_t k; + const char *v = NULL; + size_t v_sz = 0; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_map_int_string_next(&iter, &k, &v, &v_sz)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed map(int, string)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_INT64_STRING, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_map_int_string_next(&iter, &k, &v, &v_sz)) > 0) + { + v8::Local key(v8::Integer::New(k)); + v8::Local val; + if (!build_string(v, v_sz, val, error)) + { + return false; + } + v8::Local pair(v8::Array::New(2)); + pair->Set(0, key); + pair->Set(1, val); + arr->Set(idx, pair); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_map_int_int(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_INT64_INT64, value, value_sz); - int64_t k; - int64_t v; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_map_int_int_next(&iter, &k, &v)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed map(int, int)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_INT64_INT64, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_map_int_int_next(&iter, &k, &v)) > 0) - { - v8::Local key(v8::Integer::New(k)); - v8::Local val(v8::Integer::New(v)); - v8::Local pair(v8::Array::New(2)); - pair->Set(0, key); - pair->Set(1, val); - arr->Set(idx, pair); - ++idx; - } - - retval = arr; - return true; +Operation :: build_map_int_int(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_INT64_INT64, value, value_sz); + int64_t k; + int64_t v; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_map_int_int_next(&iter, &k, &v)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed map(int, int)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_INT64_INT64, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_map_int_int_next(&iter, &k, &v)) > 0) + { + v8::Local key(v8::Integer::New(k)); + v8::Local val(v8::Integer::New(v)); + v8::Local pair(v8::Array::New(2)); + pair->Set(0, key); + pair->Set(1, val); + arr->Set(idx, pair); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_map_int_float(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_INT64_FLOAT, value, value_sz); - int64_t k; - double v; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_map_int_float_next(&iter, &k, &v)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed map(int, float)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_INT64_FLOAT, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_map_int_float_next(&iter, &k, &v)) > 0) - { - v8::Local key(v8::Integer::New(k)); - v8::Local val(v8::Number::New(v)); - v8::Local pair(v8::Array::New(2)); - pair->Set(0, key); - pair->Set(1, val); - arr->Set(idx, pair); - ++idx; - } - - retval = arr; - return true; +Operation :: build_map_int_float(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_INT64_FLOAT, value, value_sz); + int64_t k; + double v; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_map_int_float_next(&iter, &k, &v)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed map(int, float)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_INT64_FLOAT, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_map_int_float_next(&iter, &k, &v)) > 0) + { + v8::Local key(v8::Integer::New(k)); + v8::Local val(v8::Number::New(v)); + v8::Local pair(v8::Array::New(2)); + pair->Set(0, key); + pair->Set(1, val); + arr->Set(idx, pair); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_map_float_string(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_FLOAT_STRING, value, value_sz); - double k; - const char* v = NULL; - size_t v_sz = 0; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_map_float_string_next(&iter, &k, &v, &v_sz)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed map(float, string)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_FLOAT_STRING, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_map_float_string_next(&iter, &k, &v, &v_sz)) > 0) - { - v8::Local key(v8::Number::New(k)); - v8::Local val; - - if (!build_string(v, v_sz, val, error)) - { - return false; - } - - v8::Local pair(v8::Array::New(2)); - pair->Set(0, key); - pair->Set(1, val); - arr->Set(idx, pair); - ++idx; - } - - retval = arr; - return true; +Operation :: build_map_float_string(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_FLOAT_STRING, value, value_sz); + double k; + const char *v = NULL; + size_t v_sz = 0; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_map_float_string_next(&iter, &k, &v, &v_sz)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed map(float, string)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_FLOAT_STRING, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_map_float_string_next(&iter, &k, &v, &v_sz)) > 0) + { + v8::Local key(v8::Number::New(k)); + v8::Local val; + if (!build_string(v, v_sz, val, error)) + { + return false; + } + v8::Local pair(v8::Array::New(2)); + pair->Set(0, key); + pair->Set(1, val); + arr->Set(idx, pair); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_map_float_int(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_FLOAT_INT64, value, value_sz); - double k; - int64_t v; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_map_float_int_next(&iter, &k, &v)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed map(float, int)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_FLOAT_INT64, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_map_float_int_next(&iter, &k, &v)) > 0) - { - v8::Local key(v8::Number::New(k)); - v8::Local val(v8::Integer::New(v)); - v8::Local pair(v8::Array::New(2)); - pair->Set(0, key); - pair->Set(1, val); - arr->Set(idx, pair); - ++idx; - } - - retval = arr; - return true; +Operation :: build_map_float_int(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_FLOAT_INT64, value, value_sz); + double k; + int64_t v; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_map_float_int_next(&iter, &k, &v)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed map(float, int)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_FLOAT_INT64, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_map_float_int_next(&iter, &k, &v)) > 0) + { + v8::Local key(v8::Number::New(k)); + v8::Local val(v8::Integer::New(v)); + v8::Local pair(v8::Array::New(2)); + pair->Set(0, key); + pair->Set(1, val); + arr->Set(idx, pair); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_map_float_float(const char* value, size_t value_sz, - v8::Local& retval, - v8::Local& error) -{ - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_FLOAT_FLOAT, value, value_sz); - double k; - double v; - size_t len = 0; - int result = 0; - - while ((result = hyperdex_ds_iterate_map_float_float_next(&iter, &k, &v)) > 0) - { - ++len; - } - - if (result < 0) - { - error = error_message("server sent malformed map(float, float)"); - return false; - } - - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_FLOAT_FLOAT, value, value_sz); - v8::Local arr(v8::Array::New(len)); - size_t idx = 0; - - while ((result = hyperdex_ds_iterate_map_float_float_next(&iter, &k, &v)) > 0) - { - v8::Local key(v8::Number::New(k)); - v8::Local val(v8::Number::New(v)); - v8::Local pair(v8::Array::New(2)); - pair->Set(0, key); - pair->Set(1, val); - arr->Set(idx, pair); - ++idx; - } - - retval = arr; - return true; +Operation :: build_map_float_float(const char *value, size_t value_sz, + v8::Local &retval, + v8::Local &error) +{ + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_FLOAT_FLOAT, value, value_sz); + double k; + double v; + size_t len = 0; + int result = 0; + while ((result = hyperdex_ds_iterate_map_float_float_next(&iter, &k, &v)) > 0) + { + ++len; + } + if (result < 0) + { + error = error_message("server sent malformed map(float, float)"); + return false; + } + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_FLOAT_FLOAT, value, value_sz); + v8::Local arr(v8::Array::New(len)); + size_t idx = 0; + while ((result = hyperdex_ds_iterate_map_float_float_next(&iter, &k, &v)) > 0) + { + v8::Local key(v8::Number::New(k)); + v8::Local val(v8::Number::New(v)); + v8::Local pair(v8::Array::New(2)); + pair->Set(0, key); + pair->Set(1, val); + arr->Set(idx, pair); + ++idx; + } + retval = arr; + return true; } bool -Operation :: build_attribute(const hyperdex_client_attribute* attr, - v8::Local& retval, - v8::Local& error) -{ - switch (attr->datatype) - { - case HYPERDATATYPE_STRING: - return build_string(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_INT64: - return build_int(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_FLOAT: - return build_float(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_DOCUMENT: - return build_document(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_LIST_STRING: - return build_list_string(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_LIST_INT64: - return build_list_int(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_LIST_FLOAT: - return build_list_float(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_SET_STRING: - return build_set_string(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_SET_INT64: - return build_set_int(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_SET_FLOAT: - return build_set_float(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_MAP_STRING_STRING: - return build_map_string_string(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_MAP_STRING_INT64: - return build_map_string_int(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_MAP_STRING_FLOAT: - return build_map_string_float(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_MAP_INT64_STRING: - return build_map_int_string(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_MAP_INT64_INT64: - return build_map_int_int(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_MAP_INT64_FLOAT: - return build_map_int_float(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_MAP_FLOAT_STRING: - return build_map_float_string(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_MAP_FLOAT_INT64: - return build_map_float_int(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_MAP_FLOAT_FLOAT: - return build_map_float_float(attr->value, attr->value_sz, retval, error); - case HYPERDATATYPE_GENERIC: - case HYPERDATATYPE_LIST_GENERIC: - case HYPERDATATYPE_SET_GENERIC: - case HYPERDATATYPE_MAP_GENERIC: - case HYPERDATATYPE_MAP_STRING_KEYONLY: - case HYPERDATATYPE_MAP_INT64_KEYONLY: - case HYPERDATATYPE_MAP_FLOAT_KEYONLY: - case HYPERDATATYPE_GARBAGE: - default: - error = this->error_message("server sent malformed attributes"); - return false; - } +Operation :: build_attribute(const hyperdex_client_attribute *attr, + v8::Local &retval, + v8::Local &error) +{ + switch (attr->datatype) + { + case HYPERDATATYPE_STRING: + return build_string(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_INT64: + return build_int(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_FLOAT: + return build_float(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_DOCUMENT: + return build_document(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_LIST_STRING: + return build_list_string(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_LIST_INT64: + return build_list_int(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_LIST_FLOAT: + return build_list_float(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_SET_STRING: + return build_set_string(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_SET_INT64: + return build_set_int(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_SET_FLOAT: + return build_set_float(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_MAP_STRING_STRING: + return build_map_string_string(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_MAP_STRING_INT64: + return build_map_string_int(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_MAP_STRING_FLOAT: + return build_map_string_float(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_MAP_INT64_STRING: + return build_map_int_string(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_MAP_INT64_INT64: + return build_map_int_int(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_MAP_INT64_FLOAT: + return build_map_int_float(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_MAP_FLOAT_STRING: + return build_map_float_string(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_MAP_FLOAT_INT64: + return build_map_float_int(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_MAP_FLOAT_FLOAT: + return build_map_float_float(attr->value, attr->value_sz, retval, error); + case HYPERDATATYPE_GENERIC: + case HYPERDATATYPE_LIST_GENERIC: + case HYPERDATATYPE_SET_GENERIC: + case HYPERDATATYPE_MAP_GENERIC: + case HYPERDATATYPE_MAP_STRING_KEYONLY: + case HYPERDATATYPE_MAP_INT64_KEYONLY: + case HYPERDATATYPE_MAP_FLOAT_KEYONLY: + case HYPERDATATYPE_GARBAGE: + default: + error = this->error_message("server sent malformed attributes"); + return false; + } } void -Operation :: build_attributes(v8::Local& retval, - v8::Local& error) -{ - v8::Local obj(v8::Object::New()); - - for (size_t i = 0; i < attrs_sz; ++i) - { - v8::Local val; - - if (!build_attribute(attrs + i, val, error)) - { - retval = v8::Local::New(v8::Undefined()); - return; - } - - obj->Set(v8::String::New(attrs[i].attr), val); - } - - if (attrs) - { - hyperdex_client_destroy_attrs(attrs, attrs_sz); - attrs = NULL; - attrs_sz = 0; - } - - retval = obj; - error = v8::Local::New(v8::Undefined()); +Operation :: build_attributes(v8::Local &retval, + v8::Local &error) +{ + v8::Local obj(v8::Object::New()); + for (size_t i = 0; i < attrs_sz; ++i) + { + v8::Local val; + if (!build_attribute(attrs + i, val, error)) + { + retval = v8::Local::New(v8::Undefined()); + return; + } + obj->Set(v8::String::New(attrs[i].attr), val); + } + if (attrs) + { + hyperdex_client_destroy_attrs(attrs, attrs_sz); + attrs = NULL; + attrs_sz = 0; + } + retval = obj; + error = v8::Local::New(v8::Undefined()); } void Operation :: encode_asynccall_status() { - v8::Local retval; - v8::Local error; - - if (status == HYPERDEX_CLIENT_SUCCESS) - { - retval = v8::Local::New(v8::True()); - error = v8::Local::New(v8::Undefined()); - } - else if (status == HYPERDEX_CLIENT_NOTFOUND) - { - retval = v8::Local::New(v8::Null()); - error = v8::Local::New(v8::Undefined()); - } - else if (status == HYPERDEX_CLIENT_CMPFAIL) - { - retval = v8::Local::New(v8::False()); - error = v8::Local::New(v8::Undefined()); - } - else - { - retval = v8::Local::New(v8::Undefined()); - error = v8::Local::New(this->error_from_status()); - } - - finished = true; - this->make_callback(error, retval); + v8::Local retval; + v8::Local error; + if (status == HYPERDEX_CLIENT_SUCCESS) + { + retval = v8::Local::New(v8::True()); + error = v8::Local::New(v8::Undefined()); + } + else if (status == HYPERDEX_CLIENT_NOTFOUND) + { + retval = v8::Local::New(v8::Null()); + error = v8::Local::New(v8::Undefined()); + } + else if (status == HYPERDEX_CLIENT_CMPFAIL) + { + retval = v8::Local::New(v8::False()); + error = v8::Local::New(v8::Undefined()); + } + else + { + retval = v8::Local::New(v8::Undefined()); + error = v8::Local::New(this->error_from_status()); + } + finished = true; + this->make_callback(error, retval); } void Operation :: encode_asynccall_status_attributes() { - v8::Local retval; - v8::Local error; - - if (status == HYPERDEX_CLIENT_SUCCESS) - { - this->build_attributes(retval, error); - } - else if (status == HYPERDEX_CLIENT_NOTFOUND) - { - retval = v8::Local::New(v8::Null()); - error = v8::Local::New(v8::Undefined()); - } - else if (status == HYPERDEX_CLIENT_CMPFAIL) - { - retval = v8::Local::New(v8::False()); - error = v8::Local::New(v8::Undefined()); - } - else - { - retval = v8::Local::New(v8::Undefined()); - error = v8::Local::New(this->error_from_status()); - } - - finished = true; - this->make_callback(error, retval); + v8::Local retval; + v8::Local error; + if (status == HYPERDEX_CLIENT_SUCCESS) + { + this->build_attributes(retval, error); + } + else if (status == HYPERDEX_CLIENT_NOTFOUND) + { + retval = v8::Local::New(v8::Null()); + error = v8::Local::New(v8::Undefined()); + } + else if (status == HYPERDEX_CLIENT_CMPFAIL) + { + retval = v8::Local::New(v8::False()); + error = v8::Local::New(v8::Undefined()); + } + else + { + retval = v8::Local::New(v8::Undefined()); + error = v8::Local::New(this->error_from_status()); + } + finished = true; + this->make_callback(error, retval); } void Operation :: encode_asynccall_status_count() { - v8::Local retval; - v8::Local error; - - if (status == HYPERDEX_CLIENT_SUCCESS) - { - retval = v8::Local::New(v8::Integer::New(count)); - error = v8::Local::New(v8::Undefined()); - } - else if (status == HYPERDEX_CLIENT_NOTFOUND) - { - retval = v8::Local::New(v8::Null()); - error = v8::Local::New(v8::Undefined()); - } - else if (status == HYPERDEX_CLIENT_CMPFAIL) - { - retval = v8::Local::New(v8::False()); - error = v8::Local::New(v8::Undefined()); - } - else - { - retval = v8::Local::New(v8::Undefined()); - error = v8::Local::New(this->error_from_status()); - } - - finished = true; - this->make_callback(error, retval); + v8::Local retval; + v8::Local error; + if (status == HYPERDEX_CLIENT_SUCCESS) + { + retval = v8::Local::New(v8::Integer::New(count)); + error = v8::Local::New(v8::Undefined()); + } + else if (status == HYPERDEX_CLIENT_NOTFOUND) + { + retval = v8::Local::New(v8::Null()); + error = v8::Local::New(v8::Undefined()); + } + else if (status == HYPERDEX_CLIENT_CMPFAIL) + { + retval = v8::Local::New(v8::False()); + error = v8::Local::New(v8::Undefined()); + } + else + { + retval = v8::Local::New(v8::Undefined()); + error = v8::Local::New(this->error_from_status()); + } + finished = true; + this->make_callback(error, retval); } void Operation :: encode_asynccall_status_description() { - v8::Local retval; - v8::Local error; - - if (status == HYPERDEX_CLIENT_SUCCESS) - { - retval = v8::Local::New(v8::String::New(description)); - error = v8::Local::New(v8::Undefined()); - } - else if (status == HYPERDEX_CLIENT_NOTFOUND) - { - retval = v8::Local::New(v8::Null()); - error = v8::Local::New(v8::Undefined()); - } - else if (status == HYPERDEX_CLIENT_CMPFAIL) - { - retval = v8::Local::New(v8::False()); - error = v8::Local::New(v8::Undefined()); - } - else - { - retval = v8::Local::New(v8::Undefined()); - error = v8::Local::New(this->error_from_status()); - } - - finished = true; - this->make_callback(error, retval); + v8::Local retval; + v8::Local error; + if (status == HYPERDEX_CLIENT_SUCCESS) + { + retval = v8::Local::New(v8::String::New(description)); + error = v8::Local::New(v8::Undefined()); + } + else if (status == HYPERDEX_CLIENT_NOTFOUND) + { + retval = v8::Local::New(v8::Null()); + error = v8::Local::New(v8::Undefined()); + } + else if (status == HYPERDEX_CLIENT_CMPFAIL) + { + retval = v8::Local::New(v8::False()); + error = v8::Local::New(v8::Undefined()); + } + else + { + retval = v8::Local::New(v8::Undefined()); + error = v8::Local::New(this->error_from_status()); + } + finished = true; + this->make_callback(error, retval); } void Operation :: encode_iterator_status_attributes() { - v8::Local retval; - v8::Local error; - - if (status == HYPERDEX_CLIENT_SEARCHDONE) - { - finished = true; - this->make_callback_done(); - return; - } - else if (status == HYPERDEX_CLIENT_SUCCESS) - { - this->build_attributes(retval, error); - } - else if (status == HYPERDEX_CLIENT_NOTFOUND) - { - retval = v8::Local::New(v8::Null()); - error = v8::Local::New(v8::Undefined()); - } - else if (status == HYPERDEX_CLIENT_CMPFAIL) - { - retval = v8::Local::New(v8::False()); - error = v8::Local::New(v8::Undefined()); - } - else - { - retval = v8::Local::New(v8::Undefined()); - error = v8::Local::New(this->error_from_status()); - } - - this->make_callback(error, retval); + v8::Local retval; + v8::Local error; + if (status == HYPERDEX_CLIENT_SEARCHDONE) + { + finished = true; + this->make_callback_done(); + return; + } + else if (status == HYPERDEX_CLIENT_SUCCESS) + { + this->build_attributes(retval, error); + } + else if (status == HYPERDEX_CLIENT_NOTFOUND) + { + retval = v8::Local::New(v8::Null()); + error = v8::Local::New(v8::Undefined()); + } + else if (status == HYPERDEX_CLIENT_CMPFAIL) + { + retval = v8::Local::New(v8::False()); + error = v8::Local::New(v8::Undefined()); + } + else + { + retval = v8::Local::New(v8::Undefined()); + error = v8::Local::New(this->error_from_status()); + } + this->make_callback(error, retval); } void -Operation :: make_callback(v8::Handle& first, - v8::Handle& second) +Operation :: make_callback(v8::Handle &first, + v8::Handle &second) { - v8::Local callback = v8::Local::New(m_callback)->Get(v8::String::NewSymbol("callback")).As(); - v8::Handle argv[] = { first, second }; - node::MakeCallback(v8::Context::GetCurrent()->Global(), callback, 2, argv); + v8::Local callback = v8::Local::New(m_callback)->Get(v8::String::NewSymbol("callback")).As(); + v8::Handle argv[] = { first, second }; + node::MakeCallback(v8::Context::GetCurrent()->Global(), callback, 2, argv); } void Operation :: make_callback_done() { - assert(m_has_callback_done); - v8::Local callback = v8::Local::New(m_callback_done)->Get(v8::String::NewSymbol("callback")).As(); - v8::Handle argv[] = {}; - node::MakeCallback(v8::Context::GetCurrent()->Global(), callback, 0, argv); + assert(m_has_callback_done); + v8::Local callback = v8::Local::New(m_callback_done)->Get(v8::String::NewSymbol("callback")).As(); + v8::Handle argv[] = {}; + node::MakeCallback(v8::Context::GetCurrent()->Global(), callback, 0, argv); } v8::Local -Operation :: error_from_status(hyperdex_client* client, +Operation :: error_from_status(hyperdex_client *client, hyperdex_client_returncode status) { - v8::Local obj(v8::Object::New()); - obj->Set(v8::String::New("msg"), - v8::String::New(hyperdex_client_error_message(client))); - obj->Set(v8::String::New("sym"), - v8::String::New(hyperdex_client_returncode_to_string(status))); - return obj; + v8::Local obj(v8::Object::New()); + obj->Set(v8::String::New("msg"), + v8::String::New(hyperdex_client_error_message(client))); + obj->Set(v8::String::New("sym"), + v8::String::New(hyperdex_client_returncode_to_string(status))); + return obj; } v8::Local Operation :: error_from_status() { - return Operation::error_from_status(client->client(), status); + return Operation::error_from_status(client->client(), status); } v8::Local -Operation :: error_message(const char* msg) +Operation :: error_message(const char *msg) { - v8::Local obj(v8::Object::New()); - obj->Set(v8::String::New("msg"), v8::String::New(msg)); - return obj; + v8::Local obj(v8::Object::New()); + obj->Set(v8::String::New("msg"), v8::String::New(msg)); + return obj; } v8::Local Operation :: error_out_of_memory() { - return error_message("out of memory"); + return error_message("out of memory"); } void -Operation :: callback_error(v8::Handle& err) +Operation :: callback_error(v8::Handle &err) { - v8::Local X(v8::Local::New(v8::Undefined())); - make_callback(err, X); + v8::Local X(v8::Local::New(v8::Undefined())); + make_callback(err, X); } void Operation :: callback_error_from_status() { - v8::Local err - = v8::Local::New(this->error_from_status()); - callback_error(err); + v8::Local err + = v8::Local::New(this->error_from_status()); + callback_error(err); } void -Operation :: callback_error_message(const char* msg) +Operation :: callback_error_message(const char *msg) { - v8::Local err - = v8::Local::New(this->error_message(msg)); - callback_error(err); + v8::Local err + = v8::Local::New(this->error_message(msg)); + callback_error(err); } void Operation :: callback_error_out_of_memory() { - v8::Local err - = v8::Local::New(this->error_out_of_memory()); - callback_error(err); + v8::Local err + = v8::Local::New(this->error_out_of_memory()); + callback_error(err); } void Init(v8::Handle target) { - HyperDexClient::Init(target); + HyperDexClient::Init(target); } } // namespace nodejs diff --git a/bindings/node.js/client.declarations.cc b/bindings/node.js/client.declarations.cc index 4585bdfb0..3073b5067 100644 --- a/bindings/node.js/client.declarations.cc +++ b/bindings/node.js/client.declarations.cc @@ -28,142 +28,142 @@ #ifdef HYPERDEX_NODE_INCLUDED_CLIENT_CC -static v8::Handle asynccall__spacename_key__status_attributes(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), const v8::Arguments& args); -static v8::Handle asynccall__spacename_key_attributenames__status_attributes(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const char** attrnames, size_t attrnames_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), const v8::Arguments& args); -static v8::Handle asynccall__spacename_key_attributes__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status), const v8::Arguments& args); -static v8::Handle asynccall__spacename_key_predicates_attributes__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status), const v8::Arguments& args); -static v8::Handle asynccall__spacename_predicates_attributes__status_count(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status, uint64_t* count), const v8::Arguments& args); -static v8::Handle asynccall__spacename_key__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, enum hyperdex_client_returncode* status), const v8::Arguments& args); -static v8::Handle asynccall__spacename_key_predicates__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status), const v8::Arguments& args); -static v8::Handle asynccall__spacename_predicates__status_count(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, uint64_t* count), const v8::Arguments& args); -static v8::Handle asynccall__spacename_key_mapattributes__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status), const v8::Arguments& args); -static v8::Handle asynccall__spacename_key_predicates_mapattributes__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status), const v8::Arguments& args); -static v8::Handle asynccall__spacename_predicates_mapattributes__status_count(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status, uint64_t* count), const v8::Arguments& args); -static v8::Handle iterator__spacename_predicates__status_attributes(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), const v8::Arguments& args); -static v8::Handle asynccall__spacename_predicates__status_description(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, const char** description), const v8::Arguments& args); -static v8::Handle iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const char* sort_by, uint64_t limit, int maxmin, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), const v8::Arguments& args); +static v8::Handle asynccall__spacename_key__status_attributes(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), const v8::Arguments &args); +static v8::Handle asynccall__spacename_key_attributenames__status_attributes(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const char **attrnames, size_t attrnames_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), const v8::Arguments &args); +static v8::Handle asynccall__spacename_key_attributes__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status), const v8::Arguments &args); +static v8::Handle asynccall__spacename_key_predicates_attributes__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status), const v8::Arguments &args); +static v8::Handle asynccall__spacename_predicates_attributes__status_count(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status, uint64_t *count), const v8::Arguments &args); +static v8::Handle asynccall__spacename_key__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, enum hyperdex_client_returncode *status), const v8::Arguments &args); +static v8::Handle asynccall__spacename_key_predicates__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status), const v8::Arguments &args); +static v8::Handle asynccall__spacename_predicates__status_count(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, uint64_t *count), const v8::Arguments &args); +static v8::Handle asynccall__spacename_key_mapattributes__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status), const v8::Arguments &args); +static v8::Handle asynccall__spacename_key_predicates_mapattributes__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status), const v8::Arguments &args); +static v8::Handle asynccall__spacename_predicates_mapattributes__status_count(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status, uint64_t *count), const v8::Arguments &args); +static v8::Handle iterator__spacename_predicates__status_attributes(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), const v8::Arguments &args); +static v8::Handle asynccall__spacename_predicates__status_description(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, const char **description), const v8::Arguments &args); +static v8::Handle iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const char *sort_by, uint64_t limit, int maxmin, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), const v8::Arguments &args); -static v8::Handle get(const v8::Arguments& args); -static v8::Handle get_partial(const v8::Arguments& args); -static v8::Handle put(const v8::Arguments& args); -static v8::Handle cond_put(const v8::Arguments& args); -static v8::Handle cond_put_or_create(const v8::Arguments& args); -static v8::Handle group_put(const v8::Arguments& args); -static v8::Handle put_if_not_exist(const v8::Arguments& args); -static v8::Handle del(const v8::Arguments& args); -static v8::Handle cond_del(const v8::Arguments& args); -static v8::Handle group_del(const v8::Arguments& args); -static v8::Handle atomic_add(const v8::Arguments& args); -static v8::Handle cond_atomic_add(const v8::Arguments& args); -static v8::Handle group_atomic_add(const v8::Arguments& args); -static v8::Handle atomic_sub(const v8::Arguments& args); -static v8::Handle cond_atomic_sub(const v8::Arguments& args); -static v8::Handle group_atomic_sub(const v8::Arguments& args); -static v8::Handle atomic_mul(const v8::Arguments& args); -static v8::Handle cond_atomic_mul(const v8::Arguments& args); -static v8::Handle group_atomic_mul(const v8::Arguments& args); -static v8::Handle atomic_div(const v8::Arguments& args); -static v8::Handle cond_atomic_div(const v8::Arguments& args); -static v8::Handle group_atomic_div(const v8::Arguments& args); -static v8::Handle atomic_mod(const v8::Arguments& args); -static v8::Handle cond_atomic_mod(const v8::Arguments& args); -static v8::Handle group_atomic_mod(const v8::Arguments& args); -static v8::Handle atomic_and(const v8::Arguments& args); -static v8::Handle cond_atomic_and(const v8::Arguments& args); -static v8::Handle group_atomic_and(const v8::Arguments& args); -static v8::Handle atomic_or(const v8::Arguments& args); -static v8::Handle cond_atomic_or(const v8::Arguments& args); -static v8::Handle group_atomic_or(const v8::Arguments& args); -static v8::Handle atomic_xor(const v8::Arguments& args); -static v8::Handle cond_atomic_xor(const v8::Arguments& args); -static v8::Handle group_atomic_xor(const v8::Arguments& args); -static v8::Handle atomic_min(const v8::Arguments& args); -static v8::Handle cond_atomic_min(const v8::Arguments& args); -static v8::Handle group_atomic_min(const v8::Arguments& args); -static v8::Handle atomic_max(const v8::Arguments& args); -static v8::Handle cond_atomic_max(const v8::Arguments& args); -static v8::Handle group_atomic_max(const v8::Arguments& args); -static v8::Handle string_prepend(const v8::Arguments& args); -static v8::Handle cond_string_prepend(const v8::Arguments& args); -static v8::Handle group_string_prepend(const v8::Arguments& args); -static v8::Handle string_append(const v8::Arguments& args); -static v8::Handle cond_string_append(const v8::Arguments& args); -static v8::Handle group_string_append(const v8::Arguments& args); -static v8::Handle string_ltrim(const v8::Arguments& args); -static v8::Handle cond_string_ltrim(const v8::Arguments& args); -static v8::Handle group_string_ltrim(const v8::Arguments& args); -static v8::Handle string_rtrim(const v8::Arguments& args); -static v8::Handle cond_string_rtrim(const v8::Arguments& args); -static v8::Handle group_string_rtrim(const v8::Arguments& args); -static v8::Handle list_lpush(const v8::Arguments& args); -static v8::Handle cond_list_lpush(const v8::Arguments& args); -static v8::Handle group_list_lpush(const v8::Arguments& args); -static v8::Handle list_rpush(const v8::Arguments& args); -static v8::Handle cond_list_rpush(const v8::Arguments& args); -static v8::Handle group_list_rpush(const v8::Arguments& args); -static v8::Handle set_add(const v8::Arguments& args); -static v8::Handle cond_set_add(const v8::Arguments& args); -static v8::Handle group_set_add(const v8::Arguments& args); -static v8::Handle set_remove(const v8::Arguments& args); -static v8::Handle cond_set_remove(const v8::Arguments& args); -static v8::Handle group_set_remove(const v8::Arguments& args); -static v8::Handle set_intersect(const v8::Arguments& args); -static v8::Handle cond_set_intersect(const v8::Arguments& args); -static v8::Handle group_set_intersect(const v8::Arguments& args); -static v8::Handle set_union(const v8::Arguments& args); -static v8::Handle cond_set_union(const v8::Arguments& args); -static v8::Handle group_set_union(const v8::Arguments& args); -static v8::Handle document_rename(const v8::Arguments& args); -static v8::Handle cond_document_rename(const v8::Arguments& args); -static v8::Handle group_document_rename(const v8::Arguments& args); -static v8::Handle document_unset(const v8::Arguments& args); -static v8::Handle cond_document_unset(const v8::Arguments& args); -static v8::Handle group_document_unset(const v8::Arguments& args); -static v8::Handle map_add(const v8::Arguments& args); -static v8::Handle cond_map_add(const v8::Arguments& args); -static v8::Handle group_map_add(const v8::Arguments& args); -static v8::Handle map_remove(const v8::Arguments& args); -static v8::Handle cond_map_remove(const v8::Arguments& args); -static v8::Handle group_map_remove(const v8::Arguments& args); -static v8::Handle map_atomic_add(const v8::Arguments& args); -static v8::Handle cond_map_atomic_add(const v8::Arguments& args); -static v8::Handle group_map_atomic_add(const v8::Arguments& args); -static v8::Handle map_atomic_sub(const v8::Arguments& args); -static v8::Handle cond_map_atomic_sub(const v8::Arguments& args); -static v8::Handle group_map_atomic_sub(const v8::Arguments& args); -static v8::Handle map_atomic_mul(const v8::Arguments& args); -static v8::Handle cond_map_atomic_mul(const v8::Arguments& args); -static v8::Handle group_map_atomic_mul(const v8::Arguments& args); -static v8::Handle map_atomic_div(const v8::Arguments& args); -static v8::Handle cond_map_atomic_div(const v8::Arguments& args); -static v8::Handle group_map_atomic_div(const v8::Arguments& args); -static v8::Handle map_atomic_mod(const v8::Arguments& args); -static v8::Handle cond_map_atomic_mod(const v8::Arguments& args); -static v8::Handle group_map_atomic_mod(const v8::Arguments& args); -static v8::Handle map_atomic_and(const v8::Arguments& args); -static v8::Handle cond_map_atomic_and(const v8::Arguments& args); -static v8::Handle group_map_atomic_and(const v8::Arguments& args); -static v8::Handle map_atomic_or(const v8::Arguments& args); -static v8::Handle cond_map_atomic_or(const v8::Arguments& args); -static v8::Handle group_map_atomic_or(const v8::Arguments& args); -static v8::Handle map_atomic_xor(const v8::Arguments& args); -static v8::Handle cond_map_atomic_xor(const v8::Arguments& args); -static v8::Handle group_map_atomic_xor(const v8::Arguments& args); -static v8::Handle map_string_prepend(const v8::Arguments& args); -static v8::Handle cond_map_string_prepend(const v8::Arguments& args); -static v8::Handle group_map_string_prepend(const v8::Arguments& args); -static v8::Handle map_string_append(const v8::Arguments& args); -static v8::Handle cond_map_string_append(const v8::Arguments& args); -static v8::Handle group_map_string_append(const v8::Arguments& args); -static v8::Handle map_atomic_min(const v8::Arguments& args); -static v8::Handle cond_map_atomic_min(const v8::Arguments& args); -static v8::Handle group_map_atomic_min(const v8::Arguments& args); -static v8::Handle map_atomic_max(const v8::Arguments& args); -static v8::Handle cond_map_atomic_max(const v8::Arguments& args); -static v8::Handle group_map_atomic_max(const v8::Arguments& args); -static v8::Handle search(const v8::Arguments& args); -static v8::Handle search_describe(const v8::Arguments& args); -static v8::Handle sorted_search(const v8::Arguments& args); -static v8::Handle count(const v8::Arguments& args); +static v8::Handle get(const v8::Arguments &args); +static v8::Handle get_partial(const v8::Arguments &args); +static v8::Handle put(const v8::Arguments &args); +static v8::Handle cond_put(const v8::Arguments &args); +static v8::Handle cond_put_or_create(const v8::Arguments &args); +static v8::Handle group_put(const v8::Arguments &args); +static v8::Handle put_if_not_exist(const v8::Arguments &args); +static v8::Handle del(const v8::Arguments &args); +static v8::Handle cond_del(const v8::Arguments &args); +static v8::Handle group_del(const v8::Arguments &args); +static v8::Handle atomic_add(const v8::Arguments &args); +static v8::Handle cond_atomic_add(const v8::Arguments &args); +static v8::Handle group_atomic_add(const v8::Arguments &args); +static v8::Handle atomic_sub(const v8::Arguments &args); +static v8::Handle cond_atomic_sub(const v8::Arguments &args); +static v8::Handle group_atomic_sub(const v8::Arguments &args); +static v8::Handle atomic_mul(const v8::Arguments &args); +static v8::Handle cond_atomic_mul(const v8::Arguments &args); +static v8::Handle group_atomic_mul(const v8::Arguments &args); +static v8::Handle atomic_div(const v8::Arguments &args); +static v8::Handle cond_atomic_div(const v8::Arguments &args); +static v8::Handle group_atomic_div(const v8::Arguments &args); +static v8::Handle atomic_mod(const v8::Arguments &args); +static v8::Handle cond_atomic_mod(const v8::Arguments &args); +static v8::Handle group_atomic_mod(const v8::Arguments &args); +static v8::Handle atomic_and(const v8::Arguments &args); +static v8::Handle cond_atomic_and(const v8::Arguments &args); +static v8::Handle group_atomic_and(const v8::Arguments &args); +static v8::Handle atomic_or(const v8::Arguments &args); +static v8::Handle cond_atomic_or(const v8::Arguments &args); +static v8::Handle group_atomic_or(const v8::Arguments &args); +static v8::Handle atomic_xor(const v8::Arguments &args); +static v8::Handle cond_atomic_xor(const v8::Arguments &args); +static v8::Handle group_atomic_xor(const v8::Arguments &args); +static v8::Handle atomic_min(const v8::Arguments &args); +static v8::Handle cond_atomic_min(const v8::Arguments &args); +static v8::Handle group_atomic_min(const v8::Arguments &args); +static v8::Handle atomic_max(const v8::Arguments &args); +static v8::Handle cond_atomic_max(const v8::Arguments &args); +static v8::Handle group_atomic_max(const v8::Arguments &args); +static v8::Handle string_prepend(const v8::Arguments &args); +static v8::Handle cond_string_prepend(const v8::Arguments &args); +static v8::Handle group_string_prepend(const v8::Arguments &args); +static v8::Handle string_append(const v8::Arguments &args); +static v8::Handle cond_string_append(const v8::Arguments &args); +static v8::Handle group_string_append(const v8::Arguments &args); +static v8::Handle string_ltrim(const v8::Arguments &args); +static v8::Handle cond_string_ltrim(const v8::Arguments &args); +static v8::Handle group_string_ltrim(const v8::Arguments &args); +static v8::Handle string_rtrim(const v8::Arguments &args); +static v8::Handle cond_string_rtrim(const v8::Arguments &args); +static v8::Handle group_string_rtrim(const v8::Arguments &args); +static v8::Handle list_lpush(const v8::Arguments &args); +static v8::Handle cond_list_lpush(const v8::Arguments &args); +static v8::Handle group_list_lpush(const v8::Arguments &args); +static v8::Handle list_rpush(const v8::Arguments &args); +static v8::Handle cond_list_rpush(const v8::Arguments &args); +static v8::Handle group_list_rpush(const v8::Arguments &args); +static v8::Handle set_add(const v8::Arguments &args); +static v8::Handle cond_set_add(const v8::Arguments &args); +static v8::Handle group_set_add(const v8::Arguments &args); +static v8::Handle set_remove(const v8::Arguments &args); +static v8::Handle cond_set_remove(const v8::Arguments &args); +static v8::Handle group_set_remove(const v8::Arguments &args); +static v8::Handle set_intersect(const v8::Arguments &args); +static v8::Handle cond_set_intersect(const v8::Arguments &args); +static v8::Handle group_set_intersect(const v8::Arguments &args); +static v8::Handle set_union(const v8::Arguments &args); +static v8::Handle cond_set_union(const v8::Arguments &args); +static v8::Handle group_set_union(const v8::Arguments &args); +static v8::Handle document_rename(const v8::Arguments &args); +static v8::Handle cond_document_rename(const v8::Arguments &args); +static v8::Handle group_document_rename(const v8::Arguments &args); +static v8::Handle document_unset(const v8::Arguments &args); +static v8::Handle cond_document_unset(const v8::Arguments &args); +static v8::Handle group_document_unset(const v8::Arguments &args); +static v8::Handle map_add(const v8::Arguments &args); +static v8::Handle cond_map_add(const v8::Arguments &args); +static v8::Handle group_map_add(const v8::Arguments &args); +static v8::Handle map_remove(const v8::Arguments &args); +static v8::Handle cond_map_remove(const v8::Arguments &args); +static v8::Handle group_map_remove(const v8::Arguments &args); +static v8::Handle map_atomic_add(const v8::Arguments &args); +static v8::Handle cond_map_atomic_add(const v8::Arguments &args); +static v8::Handle group_map_atomic_add(const v8::Arguments &args); +static v8::Handle map_atomic_sub(const v8::Arguments &args); +static v8::Handle cond_map_atomic_sub(const v8::Arguments &args); +static v8::Handle group_map_atomic_sub(const v8::Arguments &args); +static v8::Handle map_atomic_mul(const v8::Arguments &args); +static v8::Handle cond_map_atomic_mul(const v8::Arguments &args); +static v8::Handle group_map_atomic_mul(const v8::Arguments &args); +static v8::Handle map_atomic_div(const v8::Arguments &args); +static v8::Handle cond_map_atomic_div(const v8::Arguments &args); +static v8::Handle group_map_atomic_div(const v8::Arguments &args); +static v8::Handle map_atomic_mod(const v8::Arguments &args); +static v8::Handle cond_map_atomic_mod(const v8::Arguments &args); +static v8::Handle group_map_atomic_mod(const v8::Arguments &args); +static v8::Handle map_atomic_and(const v8::Arguments &args); +static v8::Handle cond_map_atomic_and(const v8::Arguments &args); +static v8::Handle group_map_atomic_and(const v8::Arguments &args); +static v8::Handle map_atomic_or(const v8::Arguments &args); +static v8::Handle cond_map_atomic_or(const v8::Arguments &args); +static v8::Handle group_map_atomic_or(const v8::Arguments &args); +static v8::Handle map_atomic_xor(const v8::Arguments &args); +static v8::Handle cond_map_atomic_xor(const v8::Arguments &args); +static v8::Handle group_map_atomic_xor(const v8::Arguments &args); +static v8::Handle map_string_prepend(const v8::Arguments &args); +static v8::Handle cond_map_string_prepend(const v8::Arguments &args); +static v8::Handle group_map_string_prepend(const v8::Arguments &args); +static v8::Handle map_string_append(const v8::Arguments &args); +static v8::Handle cond_map_string_append(const v8::Arguments &args); +static v8::Handle group_map_string_append(const v8::Arguments &args); +static v8::Handle map_atomic_min(const v8::Arguments &args); +static v8::Handle cond_map_atomic_min(const v8::Arguments &args); +static v8::Handle group_map_atomic_min(const v8::Arguments &args); +static v8::Handle map_atomic_max(const v8::Arguments &args); +static v8::Handle cond_map_atomic_max(const v8::Arguments &args); +static v8::Handle group_map_atomic_max(const v8::Arguments &args); +static v8::Handle search(const v8::Arguments &args); +static v8::Handle search_describe(const v8::Arguments &args); +static v8::Handle sorted_search(const v8::Arguments &args); +static v8::Handle count(const v8::Arguments &args); #endif // HYPERDEX_NODE_INCLUDED_CLIENT_CC diff --git a/bindings/node.js/client.definitions.cc b/bindings/node.js/client.definitions.cc index 92dd1e602..1e9f0e34f 100644 --- a/bindings/node.js/client.definitions.cc +++ b/bindings/node.js/client.definitions.cc @@ -29,1437 +29,1353 @@ #ifdef HYPERDEX_NODE_INCLUDED_CLIENT_CC v8::Handle -HyperDexClient :: asynccall__spacename_key__status_attributes(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), const v8::Arguments& args) -{ - v8::HandleScope scope; - v8::Local client_obj = args.This(); - HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); - e::intrusive_ptr op(new Operation(client_obj, client)); - const size_t base_args_sz = 2; - const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); - const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; - v8::Local func = args[i_Func].As(); - - if (func.IsEmpty() || !func->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } - - const char* in_space; - v8::Local spacename = args[0]; - if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); - const char* in_key; - size_t in_key_sz; - v8::Local key = args[1]; - if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); - if (bDoAuth) - { - v8::Handle M = args[base_args_sz]; - if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } - } - - op->reqid = f(client->client(), in_space, in_key, in_key_sz, &op->status, &op->attrs, &op->attrs_sz); - - if (bDoAuth) op->clear_auth_context(); - if (op->reqid < 0) - { - op->callback_error_from_status(); - return scope.Close(v8::Undefined()); - } - - op->encode_return = &Operation::encode_asynccall_status_attributes; - client->add(op->reqid, op); - return scope.Close(v8::Undefined()); -} - -v8::Handle -HyperDexClient :: asynccall__spacename_key_attributenames__status_attributes(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const char** attrnames, size_t attrnames_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), const v8::Arguments& args) -{ - v8::HandleScope scope; - v8::Local client_obj = args.This(); - HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); - e::intrusive_ptr op(new Operation(client_obj, client)); - const size_t base_args_sz = 3; - const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); - const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; - v8::Local func = args[i_Func].As(); - - if (func.IsEmpty() || !func->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } - - const char* in_space; - v8::Local spacename = args[0]; - if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); - const char* in_key; - size_t in_key_sz; - v8::Local key = args[1]; - if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); - const char** in_attrnames; - size_t in_attrnames_sz; - v8::Local attributenames = args[2]; - if (!op->convert_attributenames(attributenames, &in_attrnames, &in_attrnames_sz)) return scope.Close(v8::Undefined()); - if (bDoAuth) - { - v8::Handle M = args[base_args_sz]; - if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } - } - - op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_attrnames, in_attrnames_sz, &op->status, &op->attrs, &op->attrs_sz); - - if (bDoAuth) op->clear_auth_context(); - if (op->reqid < 0) - { - op->callback_error_from_status(); - return scope.Close(v8::Undefined()); - } - - op->encode_return = &Operation::encode_asynccall_status_attributes; - client->add(op->reqid, op); - return scope.Close(v8::Undefined()); -} - -v8::Handle -HyperDexClient :: asynccall__spacename_key_attributes__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status), const v8::Arguments& args) -{ - v8::HandleScope scope; - v8::Local client_obj = args.This(); - HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); - e::intrusive_ptr op(new Operation(client_obj, client)); - const size_t base_args_sz = 3; - const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); - const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; - v8::Local func = args[i_Func].As(); - - if (func.IsEmpty() || !func->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } - - const char* in_space; - v8::Local spacename = args[0]; - if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); - const char* in_key; - size_t in_key_sz; - v8::Local key = args[1]; - if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_attribute* in_attrs; - size_t in_attrs_sz; - v8::Local attributes = args[2]; - if (!op->convert_attributes(attributes, &in_attrs, &in_attrs_sz)) return scope.Close(v8::Undefined()); - if (bDoAuth) - { - v8::Handle M = args[base_args_sz]; - if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } - } - - op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_attrs, in_attrs_sz, &op->status); - - if (bDoAuth) op->clear_auth_context(); - if (op->reqid < 0) - { - op->callback_error_from_status(); - return scope.Close(v8::Undefined()); - } - - op->encode_return = &Operation::encode_asynccall_status; - client->add(op->reqid, op); - return scope.Close(v8::Undefined()); -} - -v8::Handle -HyperDexClient :: asynccall__spacename_key_predicates_attributes__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status), const v8::Arguments& args) -{ - v8::HandleScope scope; - v8::Local client_obj = args.This(); - HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); - e::intrusive_ptr op(new Operation(client_obj, client)); - const size_t base_args_sz = 4; - const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); - const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; - v8::Local func = args[i_Func].As(); - - if (func.IsEmpty() || !func->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } - - const char* in_space; - v8::Local spacename = args[0]; - if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); - const char* in_key; - size_t in_key_sz; - v8::Local key = args[1]; - if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - v8::Local predicates = args[2]; - if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_attribute* in_attrs; - size_t in_attrs_sz; - v8::Local attributes = args[3]; - if (!op->convert_attributes(attributes, &in_attrs, &in_attrs_sz)) return scope.Close(v8::Undefined()); - if (bDoAuth) - { - v8::Handle M = args[base_args_sz]; - if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } - } - - op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_checks, in_checks_sz, in_attrs, in_attrs_sz, &op->status); - - if (bDoAuth) op->clear_auth_context(); - if (op->reqid < 0) - { - op->callback_error_from_status(); - return scope.Close(v8::Undefined()); - } - - op->encode_return = &Operation::encode_asynccall_status; - client->add(op->reqid, op); - return scope.Close(v8::Undefined()); -} - -v8::Handle -HyperDexClient :: asynccall__spacename_predicates_attributes__status_count(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status, uint64_t* count), const v8::Arguments& args) -{ - v8::HandleScope scope; - v8::Local client_obj = args.This(); - HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); - e::intrusive_ptr op(new Operation(client_obj, client)); - const size_t base_args_sz = 3; - const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); - const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; - v8::Local func = args[i_Func].As(); - - if (func.IsEmpty() || !func->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } - - const char* in_space; - v8::Local spacename = args[0]; - if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - v8::Local predicates = args[1]; - if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_attribute* in_attrs; - size_t in_attrs_sz; - v8::Local attributes = args[2]; - if (!op->convert_attributes(attributes, &in_attrs, &in_attrs_sz)) return scope.Close(v8::Undefined()); - if (bDoAuth) - { - v8::Handle M = args[base_args_sz]; - if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } - } - - op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, in_attrs, in_attrs_sz, &op->status, &op->count); - - if (bDoAuth) op->clear_auth_context(); - if (op->reqid < 0) - { - op->callback_error_from_status(); - return scope.Close(v8::Undefined()); - } - - op->encode_return = &Operation::encode_asynccall_status_count; - client->add(op->reqid, op); - return scope.Close(v8::Undefined()); -} - -v8::Handle -HyperDexClient :: asynccall__spacename_key__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, enum hyperdex_client_returncode* status), const v8::Arguments& args) -{ - v8::HandleScope scope; - v8::Local client_obj = args.This(); - HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); - e::intrusive_ptr op(new Operation(client_obj, client)); - const size_t base_args_sz = 2; - const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); - const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; - v8::Local func = args[i_Func].As(); - - if (func.IsEmpty() || !func->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } - - const char* in_space; - v8::Local spacename = args[0]; - if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); - const char* in_key; - size_t in_key_sz; - v8::Local key = args[1]; - if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); - if (bDoAuth) - { - v8::Handle M = args[base_args_sz]; - if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } - } - - op->reqid = f(client->client(), in_space, in_key, in_key_sz, &op->status); - - if (bDoAuth) op->clear_auth_context(); - if (op->reqid < 0) - { - op->callback_error_from_status(); - return scope.Close(v8::Undefined()); - } - - op->encode_return = &Operation::encode_asynccall_status; - client->add(op->reqid, op); - return scope.Close(v8::Undefined()); -} - -v8::Handle -HyperDexClient :: asynccall__spacename_key_predicates__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status), const v8::Arguments& args) -{ - v8::HandleScope scope; - v8::Local client_obj = args.This(); - HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); - e::intrusive_ptr op(new Operation(client_obj, client)); - const size_t base_args_sz = 3; - const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); - const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; - v8::Local func = args[i_Func].As(); - - if (func.IsEmpty() || !func->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } - - const char* in_space; - v8::Local spacename = args[0]; - if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); - const char* in_key; - size_t in_key_sz; - v8::Local key = args[1]; - if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - v8::Local predicates = args[2]; - if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); - if (bDoAuth) - { - v8::Handle M = args[base_args_sz]; - if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } - } - - op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_checks, in_checks_sz, &op->status); - - if (bDoAuth) op->clear_auth_context(); - if (op->reqid < 0) - { - op->callback_error_from_status(); - return scope.Close(v8::Undefined()); - } - - op->encode_return = &Operation::encode_asynccall_status; - client->add(op->reqid, op); - return scope.Close(v8::Undefined()); -} - -v8::Handle -HyperDexClient :: asynccall__spacename_predicates__status_count(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, uint64_t* count), const v8::Arguments& args) -{ - v8::HandleScope scope; - v8::Local client_obj = args.This(); - HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); - e::intrusive_ptr op(new Operation(client_obj, client)); - const size_t base_args_sz = 2; - const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); - const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; - v8::Local func = args[i_Func].As(); - - if (func.IsEmpty() || !func->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } - - const char* in_space; - v8::Local spacename = args[0]; - if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - v8::Local predicates = args[1]; - if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); - if (bDoAuth) - { - v8::Handle M = args[base_args_sz]; - if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } - } - - op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, &op->status, &op->count); - - if (bDoAuth) op->clear_auth_context(); - if (op->reqid < 0) - { - op->callback_error_from_status(); - return scope.Close(v8::Undefined()); - } - - op->encode_return = &Operation::encode_asynccall_status_count; - client->add(op->reqid, op); - return scope.Close(v8::Undefined()); -} - -v8::Handle -HyperDexClient :: asynccall__spacename_key_mapattributes__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status), const v8::Arguments& args) -{ - v8::HandleScope scope; - v8::Local client_obj = args.This(); - HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); - e::intrusive_ptr op(new Operation(client_obj, client)); - const size_t base_args_sz = 3; - const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); - const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; - v8::Local func = args[i_Func].As(); - - if (func.IsEmpty() || !func->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } - - const char* in_space; - v8::Local spacename = args[0]; - if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); - const char* in_key; - size_t in_key_sz; - v8::Local key = args[1]; - if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_map_attribute* in_mapattrs; - size_t in_mapattrs_sz; - v8::Local mapattributes = args[2]; - if (!op->convert_mapattributes(mapattributes, &in_mapattrs, &in_mapattrs_sz)) return scope.Close(v8::Undefined()); - if (bDoAuth) - { - v8::Handle M = args[base_args_sz]; - if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } - } - - op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_mapattrs, in_mapattrs_sz, &op->status); - - if (bDoAuth) op->clear_auth_context(); - if (op->reqid < 0) - { - op->callback_error_from_status(); - return scope.Close(v8::Undefined()); - } - - op->encode_return = &Operation::encode_asynccall_status; - client->add(op->reqid, op); - return scope.Close(v8::Undefined()); -} - -v8::Handle -HyperDexClient :: asynccall__spacename_key_predicates_mapattributes__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status), const v8::Arguments& args) -{ - v8::HandleScope scope; - v8::Local client_obj = args.This(); - HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); - e::intrusive_ptr op(new Operation(client_obj, client)); - const size_t base_args_sz = 4; - const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); - const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; - v8::Local func = args[i_Func].As(); - - if (func.IsEmpty() || !func->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } - - const char* in_space; - v8::Local spacename = args[0]; - if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); - const char* in_key; - size_t in_key_sz; - v8::Local key = args[1]; - if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - v8::Local predicates = args[2]; - if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_map_attribute* in_mapattrs; - size_t in_mapattrs_sz; - v8::Local mapattributes = args[3]; - if (!op->convert_mapattributes(mapattributes, &in_mapattrs, &in_mapattrs_sz)) return scope.Close(v8::Undefined()); - if (bDoAuth) - { - v8::Handle M = args[base_args_sz]; - if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } - } - - op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_checks, in_checks_sz, in_mapattrs, in_mapattrs_sz, &op->status); - - if (bDoAuth) op->clear_auth_context(); - if (op->reqid < 0) - { - op->callback_error_from_status(); - return scope.Close(v8::Undefined()); - } - - op->encode_return = &Operation::encode_asynccall_status; - client->add(op->reqid, op); - return scope.Close(v8::Undefined()); -} - -v8::Handle -HyperDexClient :: asynccall__spacename_predicates_mapattributes__status_count(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status, uint64_t* count), const v8::Arguments& args) -{ - v8::HandleScope scope; - v8::Local client_obj = args.This(); - HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); - e::intrusive_ptr op(new Operation(client_obj, client)); - const size_t base_args_sz = 3; - const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); - const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; - v8::Local func = args[i_Func].As(); - - if (func.IsEmpty() || !func->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } - - const char* in_space; - v8::Local spacename = args[0]; - if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - v8::Local predicates = args[1]; - if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_map_attribute* in_mapattrs; - size_t in_mapattrs_sz; - v8::Local mapattributes = args[2]; - if (!op->convert_mapattributes(mapattributes, &in_mapattrs, &in_mapattrs_sz)) return scope.Close(v8::Undefined()); - if (bDoAuth) - { - v8::Handle M = args[base_args_sz]; - if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } - } - - op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, in_mapattrs, in_mapattrs_sz, &op->status, &op->count); - - if (bDoAuth) op->clear_auth_context(); - if (op->reqid < 0) - { - op->callback_error_from_status(); - return scope.Close(v8::Undefined()); - } - - op->encode_return = &Operation::encode_asynccall_status_count; - client->add(op->reqid, op); - return scope.Close(v8::Undefined()); -} - -v8::Handle -HyperDexClient :: iterator__spacename_predicates__status_attributes(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), const v8::Arguments& args) -{ - v8::HandleScope scope; - v8::Local client_obj = args.This(); - HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); - e::intrusive_ptr op(new Operation(client_obj, client)); - v8::Local func = args[2].As(); - - if (func.IsEmpty() || !func->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - v8::Local done = args[3].As(); - - if (done.IsEmpty() || !done->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - if (!op->set_callback(func, done)) { return scope.Close(v8::Undefined()); } - const char* in_space; - v8::Local spacename = args[0]; - if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - v8::Local predicates = args[1]; - if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); - op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, &op->status, &op->attrs, &op->attrs_sz); - - if (op->reqid < 0) - { - op->callback_error_from_status(); - return scope.Close(v8::Undefined()); - } - - op->encode_return = &Operation::encode_iterator_status_attributes; - client->add(op->reqid, op); - return scope.Close(v8::Undefined()); -} - -v8::Handle -HyperDexClient :: asynccall__spacename_predicates__status_description(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, const char** description), const v8::Arguments& args) -{ - v8::HandleScope scope; - v8::Local client_obj = args.This(); - HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); - e::intrusive_ptr op(new Operation(client_obj, client)); - const size_t base_args_sz = 2; - const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); - const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; - v8::Local func = args[i_Func].As(); - - if (func.IsEmpty() || !func->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } - - const char* in_space; - v8::Local spacename = args[0]; - if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - v8::Local predicates = args[1]; - if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); - if (bDoAuth) - { - v8::Handle M = args[base_args_sz]; - if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } - } - - op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, &op->status, &op->description); - - if (bDoAuth) op->clear_auth_context(); - if (op->reqid < 0) - { - op->callback_error_from_status(); - return scope.Close(v8::Undefined()); - } - - op->encode_return = &Operation::encode_asynccall_status_description; - client->add(op->reqid, op); - return scope.Close(v8::Undefined()); -} - +HyperDexClient :: asynccall__spacename_key__status_attributes(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), const v8::Arguments &args) +{ + v8::HandleScope scope; + v8::Local client_obj = args.This(); + HyperDexClient *client = node::ObjectWrap::Unwrap(client_obj); + e::intrusive_ptr op(new Operation(client_obj, client)); + const size_t base_args_sz = 2; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); + if (func.IsEmpty() || !func->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char *in_space; + v8::Local spacename = args[0]; + if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); + const char *in_key; + size_t in_key_sz; + v8::Local key = args[1]; + if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, &op->status, &op->attrs, &op->attrs_sz); + if (bDoAuth) op->clear_auth_context(); + if (op->reqid < 0) + { + op->callback_error_from_status(); + return scope.Close(v8::Undefined()); + } + op->encode_return = &Operation::encode_asynccall_status_attributes; + client->add(op->reqid, op); + return scope.Close(v8::Undefined()); +} + +v8::Handle +HyperDexClient :: asynccall__spacename_key_attributenames__status_attributes(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const char **attrnames, size_t attrnames_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), const v8::Arguments &args) +{ + v8::HandleScope scope; + v8::Local client_obj = args.This(); + HyperDexClient *client = node::ObjectWrap::Unwrap(client_obj); + e::intrusive_ptr op(new Operation(client_obj, client)); + const size_t base_args_sz = 3; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); + if (func.IsEmpty() || !func->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char *in_space; + v8::Local spacename = args[0]; + if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); + const char *in_key; + size_t in_key_sz; + v8::Local key = args[1]; + if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); + const char **in_attrnames; + size_t in_attrnames_sz; + v8::Local attributenames = args[2]; + if (!op->convert_attributenames(attributenames, &in_attrnames, &in_attrnames_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_attrnames, in_attrnames_sz, &op->status, &op->attrs, &op->attrs_sz); + if (bDoAuth) op->clear_auth_context(); + if (op->reqid < 0) + { + op->callback_error_from_status(); + return scope.Close(v8::Undefined()); + } + op->encode_return = &Operation::encode_asynccall_status_attributes; + client->add(op->reqid, op); + return scope.Close(v8::Undefined()); +} + +v8::Handle +HyperDexClient :: asynccall__spacename_key_attributes__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status), const v8::Arguments &args) +{ + v8::HandleScope scope; + v8::Local client_obj = args.This(); + HyperDexClient *client = node::ObjectWrap::Unwrap(client_obj); + e::intrusive_ptr op(new Operation(client_obj, client)); + const size_t base_args_sz = 3; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); + if (func.IsEmpty() || !func->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char *in_space; + v8::Local spacename = args[0]; + if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); + const char *in_key; + size_t in_key_sz; + v8::Local key = args[1]; + if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_attribute *in_attrs; + size_t in_attrs_sz; + v8::Local attributes = args[2]; + if (!op->convert_attributes(attributes, &in_attrs, &in_attrs_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_attrs, in_attrs_sz, &op->status); + if (bDoAuth) op->clear_auth_context(); + if (op->reqid < 0) + { + op->callback_error_from_status(); + return scope.Close(v8::Undefined()); + } + op->encode_return = &Operation::encode_asynccall_status; + client->add(op->reqid, op); + return scope.Close(v8::Undefined()); +} + +v8::Handle +HyperDexClient :: asynccall__spacename_key_predicates_attributes__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status), const v8::Arguments &args) +{ + v8::HandleScope scope; + v8::Local client_obj = args.This(); + HyperDexClient *client = node::ObjectWrap::Unwrap(client_obj); + e::intrusive_ptr op(new Operation(client_obj, client)); + const size_t base_args_sz = 4; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); + if (func.IsEmpty() || !func->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char *in_space; + v8::Local spacename = args[0]; + if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); + const char *in_key; + size_t in_key_sz; + v8::Local key = args[1]; + if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + v8::Local predicates = args[2]; + if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_attribute *in_attrs; + size_t in_attrs_sz; + v8::Local attributes = args[3]; + if (!op->convert_attributes(attributes, &in_attrs, &in_attrs_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_checks, in_checks_sz, in_attrs, in_attrs_sz, &op->status); + if (bDoAuth) op->clear_auth_context(); + if (op->reqid < 0) + { + op->callback_error_from_status(); + return scope.Close(v8::Undefined()); + } + op->encode_return = &Operation::encode_asynccall_status; + client->add(op->reqid, op); + return scope.Close(v8::Undefined()); +} + +v8::Handle +HyperDexClient :: asynccall__spacename_predicates_attributes__status_count(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status, uint64_t *count), const v8::Arguments &args) +{ + v8::HandleScope scope; + v8::Local client_obj = args.This(); + HyperDexClient *client = node::ObjectWrap::Unwrap(client_obj); + e::intrusive_ptr op(new Operation(client_obj, client)); + const size_t base_args_sz = 3; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); + if (func.IsEmpty() || !func->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char *in_space; + v8::Local spacename = args[0]; + if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + v8::Local predicates = args[1]; + if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_attribute *in_attrs; + size_t in_attrs_sz; + v8::Local attributes = args[2]; + if (!op->convert_attributes(attributes, &in_attrs, &in_attrs_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, in_attrs, in_attrs_sz, &op->status, &op->count); + if (bDoAuth) op->clear_auth_context(); + if (op->reqid < 0) + { + op->callback_error_from_status(); + return scope.Close(v8::Undefined()); + } + op->encode_return = &Operation::encode_asynccall_status_count; + client->add(op->reqid, op); + return scope.Close(v8::Undefined()); +} + +v8::Handle +HyperDexClient :: asynccall__spacename_key__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, enum hyperdex_client_returncode *status), const v8::Arguments &args) +{ + v8::HandleScope scope; + v8::Local client_obj = args.This(); + HyperDexClient *client = node::ObjectWrap::Unwrap(client_obj); + e::intrusive_ptr op(new Operation(client_obj, client)); + const size_t base_args_sz = 2; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); + if (func.IsEmpty() || !func->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char *in_space; + v8::Local spacename = args[0]; + if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); + const char *in_key; + size_t in_key_sz; + v8::Local key = args[1]; + if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, &op->status); + if (bDoAuth) op->clear_auth_context(); + if (op->reqid < 0) + { + op->callback_error_from_status(); + return scope.Close(v8::Undefined()); + } + op->encode_return = &Operation::encode_asynccall_status; + client->add(op->reqid, op); + return scope.Close(v8::Undefined()); +} + +v8::Handle +HyperDexClient :: asynccall__spacename_key_predicates__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status), const v8::Arguments &args) +{ + v8::HandleScope scope; + v8::Local client_obj = args.This(); + HyperDexClient *client = node::ObjectWrap::Unwrap(client_obj); + e::intrusive_ptr op(new Operation(client_obj, client)); + const size_t base_args_sz = 3; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); + if (func.IsEmpty() || !func->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char *in_space; + v8::Local spacename = args[0]; + if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); + const char *in_key; + size_t in_key_sz; + v8::Local key = args[1]; + if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + v8::Local predicates = args[2]; + if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_checks, in_checks_sz, &op->status); + if (bDoAuth) op->clear_auth_context(); + if (op->reqid < 0) + { + op->callback_error_from_status(); + return scope.Close(v8::Undefined()); + } + op->encode_return = &Operation::encode_asynccall_status; + client->add(op->reqid, op); + return scope.Close(v8::Undefined()); +} + +v8::Handle +HyperDexClient :: asynccall__spacename_predicates__status_count(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, uint64_t *count), const v8::Arguments &args) +{ + v8::HandleScope scope; + v8::Local client_obj = args.This(); + HyperDexClient *client = node::ObjectWrap::Unwrap(client_obj); + e::intrusive_ptr op(new Operation(client_obj, client)); + const size_t base_args_sz = 2; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); + if (func.IsEmpty() || !func->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char *in_space; + v8::Local spacename = args[0]; + if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + v8::Local predicates = args[1]; + if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, &op->status, &op->count); + if (bDoAuth) op->clear_auth_context(); + if (op->reqid < 0) + { + op->callback_error_from_status(); + return scope.Close(v8::Undefined()); + } + op->encode_return = &Operation::encode_asynccall_status_count; + client->add(op->reqid, op); + return scope.Close(v8::Undefined()); +} + +v8::Handle +HyperDexClient :: asynccall__spacename_key_mapattributes__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status), const v8::Arguments &args) +{ + v8::HandleScope scope; + v8::Local client_obj = args.This(); + HyperDexClient *client = node::ObjectWrap::Unwrap(client_obj); + e::intrusive_ptr op(new Operation(client_obj, client)); + const size_t base_args_sz = 3; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); + if (func.IsEmpty() || !func->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char *in_space; + v8::Local spacename = args[0]; + if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); + const char *in_key; + size_t in_key_sz; + v8::Local key = args[1]; + if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_map_attribute *in_mapattrs; + size_t in_mapattrs_sz; + v8::Local mapattributes = args[2]; + if (!op->convert_mapattributes(mapattributes, &in_mapattrs, &in_mapattrs_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_mapattrs, in_mapattrs_sz, &op->status); + if (bDoAuth) op->clear_auth_context(); + if (op->reqid < 0) + { + op->callback_error_from_status(); + return scope.Close(v8::Undefined()); + } + op->encode_return = &Operation::encode_asynccall_status; + client->add(op->reqid, op); + return scope.Close(v8::Undefined()); +} + +v8::Handle +HyperDexClient :: asynccall__spacename_key_predicates_mapattributes__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status), const v8::Arguments &args) +{ + v8::HandleScope scope; + v8::Local client_obj = args.This(); + HyperDexClient *client = node::ObjectWrap::Unwrap(client_obj); + e::intrusive_ptr op(new Operation(client_obj, client)); + const size_t base_args_sz = 4; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); + if (func.IsEmpty() || !func->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char *in_space; + v8::Local spacename = args[0]; + if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); + const char *in_key; + size_t in_key_sz; + v8::Local key = args[1]; + if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + v8::Local predicates = args[2]; + if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_map_attribute *in_mapattrs; + size_t in_mapattrs_sz; + v8::Local mapattributes = args[3]; + if (!op->convert_mapattributes(mapattributes, &in_mapattrs, &in_mapattrs_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_checks, in_checks_sz, in_mapattrs, in_mapattrs_sz, &op->status); + if (bDoAuth) op->clear_auth_context(); + if (op->reqid < 0) + { + op->callback_error_from_status(); + return scope.Close(v8::Undefined()); + } + op->encode_return = &Operation::encode_asynccall_status; + client->add(op->reqid, op); + return scope.Close(v8::Undefined()); +} + +v8::Handle +HyperDexClient :: asynccall__spacename_predicates_mapattributes__status_count(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status, uint64_t *count), const v8::Arguments &args) +{ + v8::HandleScope scope; + v8::Local client_obj = args.This(); + HyperDexClient *client = node::ObjectWrap::Unwrap(client_obj); + e::intrusive_ptr op(new Operation(client_obj, client)); + const size_t base_args_sz = 3; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); + if (func.IsEmpty() || !func->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char *in_space; + v8::Local spacename = args[0]; + if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + v8::Local predicates = args[1]; + if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_map_attribute *in_mapattrs; + size_t in_mapattrs_sz; + v8::Local mapattributes = args[2]; + if (!op->convert_mapattributes(mapattributes, &in_mapattrs, &in_mapattrs_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, in_mapattrs, in_mapattrs_sz, &op->status, &op->count); + if (bDoAuth) op->clear_auth_context(); + if (op->reqid < 0) + { + op->callback_error_from_status(); + return scope.Close(v8::Undefined()); + } + op->encode_return = &Operation::encode_asynccall_status_count; + client->add(op->reqid, op); + return scope.Close(v8::Undefined()); +} + +v8::Handle +HyperDexClient :: iterator__spacename_predicates__status_attributes(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), const v8::Arguments &args) +{ + v8::HandleScope scope; + v8::Local client_obj = args.This(); + HyperDexClient *client = node::ObjectWrap::Unwrap(client_obj); + e::intrusive_ptr op(new Operation(client_obj, client)); + v8::Local func = args[2].As(); + if (func.IsEmpty() || !func->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + v8::Local done = args[3].As(); + if (done.IsEmpty() || !done->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + if (!op->set_callback(func, done)) { return scope.Close(v8::Undefined()); } + const char *in_space; + v8::Local spacename = args[0]; + if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + v8::Local predicates = args[1]; + if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); + op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, &op->status, &op->attrs, &op->attrs_sz); + if (op->reqid < 0) + { + op->callback_error_from_status(); + return scope.Close(v8::Undefined()); + } + op->encode_return = &Operation::encode_iterator_status_attributes; + client->add(op->reqid, op); + return scope.Close(v8::Undefined()); +} + +v8::Handle +HyperDexClient :: asynccall__spacename_predicates__status_description(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, const char **description), const v8::Arguments &args) +{ + v8::HandleScope scope; + v8::Local client_obj = args.This(); + HyperDexClient *client = node::ObjectWrap::Unwrap(client_obj); + e::intrusive_ptr op(new Operation(client_obj, client)); + const size_t base_args_sz = 2; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); + if (func.IsEmpty() || !func->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char *in_space; + v8::Local spacename = args[0]; + if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + v8::Local predicates = args[1]; + if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, &op->status, &op->description); + if (bDoAuth) op->clear_auth_context(); + if (op->reqid < 0) + { + op->callback_error_from_status(); + return scope.Close(v8::Undefined()); + } + op->encode_return = &Operation::encode_asynccall_status_description; + client->add(op->reqid, op); + return scope.Close(v8::Undefined()); +} + v8::Handle -HyperDexClient :: iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const char* sort_by, uint64_t limit, int maxmin, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), const v8::Arguments& args) +HyperDexClient :: iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const char *sort_by, uint64_t limit, int maxmin, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), const v8::Arguments &args) { - v8::HandleScope scope; - v8::Local client_obj = args.This(); - HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); - e::intrusive_ptr op(new Operation(client_obj, client)); - v8::Local func = args[5].As(); - - if (func.IsEmpty() || !func->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - v8::Local done = args[6].As(); - - if (done.IsEmpty() || !done->IsFunction()) - { - v8::ThrowException(v8::String::New("Callback must be a function")); - return scope.Close(v8::Undefined()); - } - - if (!op->set_callback(func, done)) { return scope.Close(v8::Undefined()); } - const char* in_space; - v8::Local spacename = args[0]; - if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - v8::Local predicates = args[1]; - if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); - const char* in_sort_by; - v8::Local sortby = args[2]; - if (!op->convert_sortby(sortby, &in_sort_by)) return scope.Close(v8::Undefined()); - uint64_t in_limit; - v8::Local limit = args[3]; - if (!op->convert_limit(limit, &in_limit)) return scope.Close(v8::Undefined()); - int in_maxmin; - v8::Local maxmin = args[4]; - if (!op->convert_maxmin(maxmin, &in_maxmin)) return scope.Close(v8::Undefined()); - op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, in_sort_by, in_limit, in_maxmin, &op->status, &op->attrs, &op->attrs_sz); - - if (op->reqid < 0) - { - op->callback_error_from_status(); - return scope.Close(v8::Undefined()); - } - - op->encode_return = &Operation::encode_iterator_status_attributes; - client->add(op->reqid, op); - return scope.Close(v8::Undefined()); + v8::HandleScope scope; + v8::Local client_obj = args.This(); + HyperDexClient *client = node::ObjectWrap::Unwrap(client_obj); + e::intrusive_ptr op(new Operation(client_obj, client)); + v8::Local func = args[5].As(); + if (func.IsEmpty() || !func->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + v8::Local done = args[6].As(); + if (done.IsEmpty() || !done->IsFunction()) + { + v8::ThrowException(v8::String::New("Callback must be a function")); + return scope.Close(v8::Undefined()); + } + if (!op->set_callback(func, done)) { return scope.Close(v8::Undefined()); } + const char *in_space; + v8::Local spacename = args[0]; + if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + v8::Local predicates = args[1]; + if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); + const char *in_sort_by; + v8::Local sortby = args[2]; + if (!op->convert_sortby(sortby, &in_sort_by)) return scope.Close(v8::Undefined()); + uint64_t in_limit; + v8::Local limit = args[3]; + if (!op->convert_limit(limit, &in_limit)) return scope.Close(v8::Undefined()); + int in_maxmin; + v8::Local maxmin = args[4]; + if (!op->convert_maxmin(maxmin, &in_maxmin)) return scope.Close(v8::Undefined()); + op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, in_sort_by, in_limit, in_maxmin, &op->status, &op->attrs, &op->attrs_sz); + if (op->reqid < 0) + { + op->callback_error_from_status(); + return scope.Close(v8::Undefined()); + } + op->encode_return = &Operation::encode_iterator_status_attributes; + client->add(op->reqid, op); + return scope.Close(v8::Undefined()); } v8::Handle -HyperDexClient :: get(const v8::Arguments& args) +HyperDexClient :: get(const v8::Arguments &args) { - return asynccall__spacename_key__status_attributes(hyperdex_client_get, args); + return asynccall__spacename_key__status_attributes(hyperdex_client_get, args); } v8::Handle -HyperDexClient :: get_partial(const v8::Arguments& args) +HyperDexClient :: get_partial(const v8::Arguments &args) { - return asynccall__spacename_key_attributenames__status_attributes(hyperdex_client_get_partial, args); + return asynccall__spacename_key_attributenames__status_attributes(hyperdex_client_get_partial, args); } v8::Handle -HyperDexClient :: put(const v8::Arguments& args) +HyperDexClient :: put(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_put, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_put, args); } v8::Handle -HyperDexClient :: cond_put(const v8::Arguments& args) +HyperDexClient :: cond_put(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_put, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_put, args); } v8::Handle -HyperDexClient :: cond_put_or_create(const v8::Arguments& args) +HyperDexClient :: cond_put_or_create(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_put_or_create, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_put_or_create, args); } v8::Handle -HyperDexClient :: group_put(const v8::Arguments& args) +HyperDexClient :: group_put(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_put, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_put, args); } v8::Handle -HyperDexClient :: put_if_not_exist(const v8::Arguments& args) +HyperDexClient :: put_if_not_exist(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_put_if_not_exist, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_put_if_not_exist, args); } v8::Handle -HyperDexClient :: del(const v8::Arguments& args) +HyperDexClient :: del(const v8::Arguments &args) { - return asynccall__spacename_key__status(hyperdex_client_del, args); + return asynccall__spacename_key__status(hyperdex_client_del, args); } v8::Handle -HyperDexClient :: cond_del(const v8::Arguments& args) +HyperDexClient :: cond_del(const v8::Arguments &args) { - return asynccall__spacename_key_predicates__status(hyperdex_client_cond_del, args); + return asynccall__spacename_key_predicates__status(hyperdex_client_cond_del, args); } v8::Handle -HyperDexClient :: group_del(const v8::Arguments& args) +HyperDexClient :: group_del(const v8::Arguments &args) { - return asynccall__spacename_predicates__status_count(hyperdex_client_group_del, args); + return asynccall__spacename_predicates__status_count(hyperdex_client_group_del, args); } v8::Handle -HyperDexClient :: atomic_add(const v8::Arguments& args) +HyperDexClient :: atomic_add(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_add, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_add, args); } v8::Handle -HyperDexClient :: cond_atomic_add(const v8::Arguments& args) +HyperDexClient :: cond_atomic_add(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_add, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_add, args); } v8::Handle -HyperDexClient :: group_atomic_add(const v8::Arguments& args) +HyperDexClient :: group_atomic_add(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_add, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_add, args); } v8::Handle -HyperDexClient :: atomic_sub(const v8::Arguments& args) +HyperDexClient :: atomic_sub(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_sub, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_sub, args); } v8::Handle -HyperDexClient :: cond_atomic_sub(const v8::Arguments& args) +HyperDexClient :: cond_atomic_sub(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_sub, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_sub, args); } v8::Handle -HyperDexClient :: group_atomic_sub(const v8::Arguments& args) +HyperDexClient :: group_atomic_sub(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_sub, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_sub, args); } v8::Handle -HyperDexClient :: atomic_mul(const v8::Arguments& args) +HyperDexClient :: atomic_mul(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_mul, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_mul, args); } v8::Handle -HyperDexClient :: cond_atomic_mul(const v8::Arguments& args) +HyperDexClient :: cond_atomic_mul(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_mul, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_mul, args); } v8::Handle -HyperDexClient :: group_atomic_mul(const v8::Arguments& args) +HyperDexClient :: group_atomic_mul(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_mul, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_mul, args); } v8::Handle -HyperDexClient :: atomic_div(const v8::Arguments& args) +HyperDexClient :: atomic_div(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_div, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_div, args); } v8::Handle -HyperDexClient :: cond_atomic_div(const v8::Arguments& args) +HyperDexClient :: cond_atomic_div(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_div, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_div, args); } v8::Handle -HyperDexClient :: group_atomic_div(const v8::Arguments& args) +HyperDexClient :: group_atomic_div(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_div, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_div, args); } v8::Handle -HyperDexClient :: atomic_mod(const v8::Arguments& args) +HyperDexClient :: atomic_mod(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_mod, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_mod, args); } v8::Handle -HyperDexClient :: cond_atomic_mod(const v8::Arguments& args) +HyperDexClient :: cond_atomic_mod(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_mod, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_mod, args); } v8::Handle -HyperDexClient :: group_atomic_mod(const v8::Arguments& args) +HyperDexClient :: group_atomic_mod(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_mod, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_mod, args); } v8::Handle -HyperDexClient :: atomic_and(const v8::Arguments& args) +HyperDexClient :: atomic_and(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_and, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_and, args); } v8::Handle -HyperDexClient :: cond_atomic_and(const v8::Arguments& args) +HyperDexClient :: cond_atomic_and(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_and, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_and, args); } v8::Handle -HyperDexClient :: group_atomic_and(const v8::Arguments& args) +HyperDexClient :: group_atomic_and(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_and, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_and, args); } v8::Handle -HyperDexClient :: atomic_or(const v8::Arguments& args) +HyperDexClient :: atomic_or(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_or, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_or, args); } v8::Handle -HyperDexClient :: cond_atomic_or(const v8::Arguments& args) +HyperDexClient :: cond_atomic_or(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_or, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_or, args); } v8::Handle -HyperDexClient :: group_atomic_or(const v8::Arguments& args) +HyperDexClient :: group_atomic_or(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_or, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_or, args); } v8::Handle -HyperDexClient :: atomic_xor(const v8::Arguments& args) +HyperDexClient :: atomic_xor(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_xor, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_xor, args); } v8::Handle -HyperDexClient :: cond_atomic_xor(const v8::Arguments& args) +HyperDexClient :: cond_atomic_xor(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_xor, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_xor, args); } v8::Handle -HyperDexClient :: group_atomic_xor(const v8::Arguments& args) +HyperDexClient :: group_atomic_xor(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_xor, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_xor, args); } v8::Handle -HyperDexClient :: atomic_min(const v8::Arguments& args) +HyperDexClient :: atomic_min(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_min, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_min, args); } v8::Handle -HyperDexClient :: cond_atomic_min(const v8::Arguments& args) +HyperDexClient :: cond_atomic_min(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_min, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_min, args); } v8::Handle -HyperDexClient :: group_atomic_min(const v8::Arguments& args) +HyperDexClient :: group_atomic_min(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_min, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_min, args); } v8::Handle -HyperDexClient :: atomic_max(const v8::Arguments& args) +HyperDexClient :: atomic_max(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_max, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_atomic_max, args); } v8::Handle -HyperDexClient :: cond_atomic_max(const v8::Arguments& args) +HyperDexClient :: cond_atomic_max(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_max, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_max, args); } v8::Handle -HyperDexClient :: group_atomic_max(const v8::Arguments& args) +HyperDexClient :: group_atomic_max(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_max, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_max, args); } v8::Handle -HyperDexClient :: string_prepend(const v8::Arguments& args) +HyperDexClient :: string_prepend(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_string_prepend, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_string_prepend, args); } v8::Handle -HyperDexClient :: cond_string_prepend(const v8::Arguments& args) +HyperDexClient :: cond_string_prepend(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_prepend, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_prepend, args); } v8::Handle -HyperDexClient :: group_string_prepend(const v8::Arguments& args) +HyperDexClient :: group_string_prepend(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_prepend, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_prepend, args); } v8::Handle -HyperDexClient :: string_append(const v8::Arguments& args) +HyperDexClient :: string_append(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_string_append, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_string_append, args); } v8::Handle -HyperDexClient :: cond_string_append(const v8::Arguments& args) +HyperDexClient :: cond_string_append(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_append, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_append, args); } v8::Handle -HyperDexClient :: group_string_append(const v8::Arguments& args) +HyperDexClient :: group_string_append(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_append, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_append, args); } v8::Handle -HyperDexClient :: string_ltrim(const v8::Arguments& args) +HyperDexClient :: string_ltrim(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_string_ltrim, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_string_ltrim, args); } v8::Handle -HyperDexClient :: cond_string_ltrim(const v8::Arguments& args) +HyperDexClient :: cond_string_ltrim(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_ltrim, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_ltrim, args); } v8::Handle -HyperDexClient :: group_string_ltrim(const v8::Arguments& args) +HyperDexClient :: group_string_ltrim(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_ltrim, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_ltrim, args); } v8::Handle -HyperDexClient :: string_rtrim(const v8::Arguments& args) +HyperDexClient :: string_rtrim(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_string_rtrim, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_string_rtrim, args); } v8::Handle -HyperDexClient :: cond_string_rtrim(const v8::Arguments& args) +HyperDexClient :: cond_string_rtrim(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_rtrim, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_rtrim, args); } v8::Handle -HyperDexClient :: group_string_rtrim(const v8::Arguments& args) +HyperDexClient :: group_string_rtrim(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_rtrim, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_rtrim, args); } v8::Handle -HyperDexClient :: list_lpush(const v8::Arguments& args) +HyperDexClient :: list_lpush(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_list_lpush, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_list_lpush, args); } v8::Handle -HyperDexClient :: cond_list_lpush(const v8::Arguments& args) +HyperDexClient :: cond_list_lpush(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_list_lpush, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_list_lpush, args); } v8::Handle -HyperDexClient :: group_list_lpush(const v8::Arguments& args) +HyperDexClient :: group_list_lpush(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_list_lpush, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_list_lpush, args); } v8::Handle -HyperDexClient :: list_rpush(const v8::Arguments& args) +HyperDexClient :: list_rpush(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_list_rpush, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_list_rpush, args); } v8::Handle -HyperDexClient :: cond_list_rpush(const v8::Arguments& args) +HyperDexClient :: cond_list_rpush(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_list_rpush, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_list_rpush, args); } v8::Handle -HyperDexClient :: group_list_rpush(const v8::Arguments& args) +HyperDexClient :: group_list_rpush(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_list_rpush, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_list_rpush, args); } v8::Handle -HyperDexClient :: set_add(const v8::Arguments& args) +HyperDexClient :: set_add(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_set_add, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_set_add, args); } v8::Handle -HyperDexClient :: cond_set_add(const v8::Arguments& args) +HyperDexClient :: cond_set_add(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_add, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_add, args); } v8::Handle -HyperDexClient :: group_set_add(const v8::Arguments& args) +HyperDexClient :: group_set_add(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_add, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_add, args); } v8::Handle -HyperDexClient :: set_remove(const v8::Arguments& args) +HyperDexClient :: set_remove(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_set_remove, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_set_remove, args); } v8::Handle -HyperDexClient :: cond_set_remove(const v8::Arguments& args) +HyperDexClient :: cond_set_remove(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_remove, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_remove, args); } v8::Handle -HyperDexClient :: group_set_remove(const v8::Arguments& args) +HyperDexClient :: group_set_remove(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_remove, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_remove, args); } v8::Handle -HyperDexClient :: set_intersect(const v8::Arguments& args) +HyperDexClient :: set_intersect(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_set_intersect, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_set_intersect, args); } v8::Handle -HyperDexClient :: cond_set_intersect(const v8::Arguments& args) +HyperDexClient :: cond_set_intersect(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_intersect, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_intersect, args); } v8::Handle -HyperDexClient :: group_set_intersect(const v8::Arguments& args) +HyperDexClient :: group_set_intersect(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_intersect, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_intersect, args); } v8::Handle -HyperDexClient :: set_union(const v8::Arguments& args) +HyperDexClient :: set_union(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_set_union, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_set_union, args); } v8::Handle -HyperDexClient :: cond_set_union(const v8::Arguments& args) +HyperDexClient :: cond_set_union(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_union, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_union, args); } v8::Handle -HyperDexClient :: group_set_union(const v8::Arguments& args) +HyperDexClient :: group_set_union(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_union, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_union, args); } v8::Handle -HyperDexClient :: document_rename(const v8::Arguments& args) +HyperDexClient :: document_rename(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_document_rename, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_document_rename, args); } v8::Handle -HyperDexClient :: cond_document_rename(const v8::Arguments& args) +HyperDexClient :: cond_document_rename(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_document_rename, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_document_rename, args); } v8::Handle -HyperDexClient :: group_document_rename(const v8::Arguments& args) +HyperDexClient :: group_document_rename(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_document_rename, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_document_rename, args); } v8::Handle -HyperDexClient :: document_unset(const v8::Arguments& args) +HyperDexClient :: document_unset(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_document_unset, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_document_unset, args); } v8::Handle -HyperDexClient :: cond_document_unset(const v8::Arguments& args) +HyperDexClient :: cond_document_unset(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_document_unset, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_document_unset, args); } v8::Handle -HyperDexClient :: group_document_unset(const v8::Arguments& args) +HyperDexClient :: group_document_unset(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_document_unset, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_document_unset, args); } v8::Handle -HyperDexClient :: map_add(const v8::Arguments& args) +HyperDexClient :: map_add(const v8::Arguments &args) { - return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_add, args); + return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_add, args); } v8::Handle -HyperDexClient :: cond_map_add(const v8::Arguments& args) +HyperDexClient :: cond_map_add(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_add, args); + return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_add, args); } v8::Handle -HyperDexClient :: group_map_add(const v8::Arguments& args) +HyperDexClient :: group_map_add(const v8::Arguments &args) { - return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_add, args); + return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_add, args); } v8::Handle -HyperDexClient :: map_remove(const v8::Arguments& args) +HyperDexClient :: map_remove(const v8::Arguments &args) { - return asynccall__spacename_key_attributes__status(hyperdex_client_map_remove, args); + return asynccall__spacename_key_attributes__status(hyperdex_client_map_remove, args); } v8::Handle -HyperDexClient :: cond_map_remove(const v8::Arguments& args) +HyperDexClient :: cond_map_remove(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_map_remove, args); + return asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_map_remove, args); } v8::Handle -HyperDexClient :: group_map_remove(const v8::Arguments& args) +HyperDexClient :: group_map_remove(const v8::Arguments &args) { - return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_map_remove, args); + return asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_map_remove, args); } v8::Handle -HyperDexClient :: map_atomic_add(const v8::Arguments& args) +HyperDexClient :: map_atomic_add(const v8::Arguments &args) { - return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_add, args); + return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_add, args); } v8::Handle -HyperDexClient :: cond_map_atomic_add(const v8::Arguments& args) +HyperDexClient :: cond_map_atomic_add(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_add, args); + return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_add, args); } v8::Handle -HyperDexClient :: group_map_atomic_add(const v8::Arguments& args) +HyperDexClient :: group_map_atomic_add(const v8::Arguments &args) { - return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_add, args); + return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_add, args); } v8::Handle -HyperDexClient :: map_atomic_sub(const v8::Arguments& args) +HyperDexClient :: map_atomic_sub(const v8::Arguments &args) { - return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_sub, args); + return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_sub, args); } v8::Handle -HyperDexClient :: cond_map_atomic_sub(const v8::Arguments& args) +HyperDexClient :: cond_map_atomic_sub(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_sub, args); + return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_sub, args); } v8::Handle -HyperDexClient :: group_map_atomic_sub(const v8::Arguments& args) +HyperDexClient :: group_map_atomic_sub(const v8::Arguments &args) { - return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_sub, args); + return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_sub, args); } v8::Handle -HyperDexClient :: map_atomic_mul(const v8::Arguments& args) +HyperDexClient :: map_atomic_mul(const v8::Arguments &args) { - return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_mul, args); + return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_mul, args); } v8::Handle -HyperDexClient :: cond_map_atomic_mul(const v8::Arguments& args) +HyperDexClient :: cond_map_atomic_mul(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_mul, args); + return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_mul, args); } v8::Handle -HyperDexClient :: group_map_atomic_mul(const v8::Arguments& args) +HyperDexClient :: group_map_atomic_mul(const v8::Arguments &args) { - return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_mul, args); + return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_mul, args); } v8::Handle -HyperDexClient :: map_atomic_div(const v8::Arguments& args) +HyperDexClient :: map_atomic_div(const v8::Arguments &args) { - return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_div, args); + return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_div, args); } v8::Handle -HyperDexClient :: cond_map_atomic_div(const v8::Arguments& args) +HyperDexClient :: cond_map_atomic_div(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_div, args); + return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_div, args); } v8::Handle -HyperDexClient :: group_map_atomic_div(const v8::Arguments& args) +HyperDexClient :: group_map_atomic_div(const v8::Arguments &args) { - return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_div, args); + return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_div, args); } v8::Handle -HyperDexClient :: map_atomic_mod(const v8::Arguments& args) +HyperDexClient :: map_atomic_mod(const v8::Arguments &args) { - return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_mod, args); + return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_mod, args); } v8::Handle -HyperDexClient :: cond_map_atomic_mod(const v8::Arguments& args) +HyperDexClient :: cond_map_atomic_mod(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_mod, args); + return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_mod, args); } v8::Handle -HyperDexClient :: group_map_atomic_mod(const v8::Arguments& args) +HyperDexClient :: group_map_atomic_mod(const v8::Arguments &args) { - return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_mod, args); + return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_mod, args); } v8::Handle -HyperDexClient :: map_atomic_and(const v8::Arguments& args) +HyperDexClient :: map_atomic_and(const v8::Arguments &args) { - return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_and, args); + return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_and, args); } v8::Handle -HyperDexClient :: cond_map_atomic_and(const v8::Arguments& args) +HyperDexClient :: cond_map_atomic_and(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_and, args); + return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_and, args); } v8::Handle -HyperDexClient :: group_map_atomic_and(const v8::Arguments& args) +HyperDexClient :: group_map_atomic_and(const v8::Arguments &args) { - return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_and, args); + return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_and, args); } v8::Handle -HyperDexClient :: map_atomic_or(const v8::Arguments& args) +HyperDexClient :: map_atomic_or(const v8::Arguments &args) { - return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_or, args); + return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_or, args); } v8::Handle -HyperDexClient :: cond_map_atomic_or(const v8::Arguments& args) +HyperDexClient :: cond_map_atomic_or(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_or, args); + return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_or, args); } v8::Handle -HyperDexClient :: group_map_atomic_or(const v8::Arguments& args) +HyperDexClient :: group_map_atomic_or(const v8::Arguments &args) { - return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_or, args); + return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_or, args); } v8::Handle -HyperDexClient :: map_atomic_xor(const v8::Arguments& args) +HyperDexClient :: map_atomic_xor(const v8::Arguments &args) { - return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_xor, args); + return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_xor, args); } v8::Handle -HyperDexClient :: cond_map_atomic_xor(const v8::Arguments& args) +HyperDexClient :: cond_map_atomic_xor(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_xor, args); + return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_xor, args); } v8::Handle -HyperDexClient :: group_map_atomic_xor(const v8::Arguments& args) +HyperDexClient :: group_map_atomic_xor(const v8::Arguments &args) { - return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_xor, args); + return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_xor, args); } v8::Handle -HyperDexClient :: map_string_prepend(const v8::Arguments& args) +HyperDexClient :: map_string_prepend(const v8::Arguments &args) { - return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_string_prepend, args); + return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_string_prepend, args); } v8::Handle -HyperDexClient :: cond_map_string_prepend(const v8::Arguments& args) +HyperDexClient :: cond_map_string_prepend(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_string_prepend, args); + return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_string_prepend, args); } v8::Handle -HyperDexClient :: group_map_string_prepend(const v8::Arguments& args) +HyperDexClient :: group_map_string_prepend(const v8::Arguments &args) { - return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_string_prepend, args); + return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_string_prepend, args); } v8::Handle -HyperDexClient :: map_string_append(const v8::Arguments& args) +HyperDexClient :: map_string_append(const v8::Arguments &args) { - return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_string_append, args); + return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_string_append, args); } v8::Handle -HyperDexClient :: cond_map_string_append(const v8::Arguments& args) +HyperDexClient :: cond_map_string_append(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_string_append, args); + return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_string_append, args); } v8::Handle -HyperDexClient :: group_map_string_append(const v8::Arguments& args) +HyperDexClient :: group_map_string_append(const v8::Arguments &args) { - return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_string_append, args); + return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_string_append, args); } v8::Handle -HyperDexClient :: map_atomic_min(const v8::Arguments& args) +HyperDexClient :: map_atomic_min(const v8::Arguments &args) { - return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_min, args); + return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_min, args); } v8::Handle -HyperDexClient :: cond_map_atomic_min(const v8::Arguments& args) +HyperDexClient :: cond_map_atomic_min(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_min, args); + return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_min, args); } v8::Handle -HyperDexClient :: group_map_atomic_min(const v8::Arguments& args) +HyperDexClient :: group_map_atomic_min(const v8::Arguments &args) { - return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_min, args); + return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_min, args); } v8::Handle -HyperDexClient :: map_atomic_max(const v8::Arguments& args) +HyperDexClient :: map_atomic_max(const v8::Arguments &args) { - return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_max, args); + return asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_max, args); } v8::Handle -HyperDexClient :: cond_map_atomic_max(const v8::Arguments& args) +HyperDexClient :: cond_map_atomic_max(const v8::Arguments &args) { - return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_max, args); + return asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_max, args); } v8::Handle -HyperDexClient :: group_map_atomic_max(const v8::Arguments& args) +HyperDexClient :: group_map_atomic_max(const v8::Arguments &args) { - return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_max, args); + return asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_max, args); } v8::Handle -HyperDexClient :: search(const v8::Arguments& args) +HyperDexClient :: search(const v8::Arguments &args) { - return iterator__spacename_predicates__status_attributes(hyperdex_client_search, args); + return iterator__spacename_predicates__status_attributes(hyperdex_client_search, args); } v8::Handle -HyperDexClient :: search_describe(const v8::Arguments& args) +HyperDexClient :: search_describe(const v8::Arguments &args) { - return asynccall__spacename_predicates__status_description(hyperdex_client_search_describe, args); + return asynccall__spacename_predicates__status_description(hyperdex_client_search_describe, args); } v8::Handle -HyperDexClient :: sorted_search(const v8::Arguments& args) +HyperDexClient :: sorted_search(const v8::Arguments &args) { - return iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(hyperdex_client_sorted_search, args); + return iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(hyperdex_client_sorted_search, args); } v8::Handle -HyperDexClient :: count(const v8::Arguments& args) +HyperDexClient :: count(const v8::Arguments &args) { - return asynccall__spacename_predicates__status_count(hyperdex_client_count, args); + return asynccall__spacename_predicates__status_count(hyperdex_client_count, args); } #endif // HYPERDEX_NODE_INCLUDED_CLIENT_CC diff --git a/bindings/ruby/client.c b/bindings/ruby/client.c index 7cfe02bee..1c49fec74 100644 --- a/bindings/ruby/client.c +++ b/bindings/ruby/client.c @@ -63,1369 +63,1238 @@ static VALUE class_contains; void hyperdex_ruby_out_of_memory() { - rb_raise(rb_eNoMemError, "failed to allocate memory"); + rb_raise(rb_eNoMemError, "failed to allocate memory"); } static VALUE hyperdex_ruby_client_create_exception(enum hyperdex_client_returncode status, - const char* error_message) + const char *error_message) { - const char* symbol = hyperdex_client_returncode_to_string(status); - VALUE exception; - exception = rb_exc_new2(class_exception, error_message); - rb_iv_set(exception, "@status", rb_uint_new(status)); - rb_iv_set(exception, "@symbol", rb_str_new2(symbol)); - return exception; + const char *symbol = hyperdex_client_returncode_to_string(status); + VALUE exception; + exception = rb_exc_new2(class_exception, error_message); + rb_iv_set(exception, "@status", rb_uint_new(status)); + rb_iv_set(exception, "@symbol", rb_str_new2(symbol)); + return exception; } void hyperdex_ruby_client_throw_exception(enum hyperdex_client_returncode status, - const char* error_message) + const char *error_message) { - VALUE exception = hyperdex_ruby_client_create_exception(status, error_message); - rb_exc_raise(exception); - abort(); /* unreachable? */ + VALUE exception = hyperdex_ruby_client_create_exception(status, error_message); + rb_exc_raise(exception); + abort(); /* unreachable? */ } /******************************* Predicate class ******************************/ struct hyperdex_ruby_client_predicate_inner { - VALUE v; - enum hyperpredicate predicate; + VALUE v; + enum hyperpredicate predicate; }; struct hyperdex_ruby_client_predicate { - size_t num_checks; - struct hyperdex_ruby_client_predicate_inner checks[1]; + size_t num_checks; + struct hyperdex_ruby_client_predicate_inner checks[1]; }; /********************************** Ruby -> C *********************************/ -static const char* -hyperdex_ruby_client_convert_cstring(VALUE x, const char* error_message) +static const char * +hyperdex_ruby_client_convert_cstring(VALUE x, const char *error_message) { - if (TYPE(x) == T_SYMBOL) - { - return rb_id2name(SYM2ID(x)); - } - else if (TYPE(x) == T_STRING) - { - return StringValueCStr(x); - } - else - { - rb_exc_raise(rb_exc_new2(rb_eTypeError, error_message)); - abort(); /* unreachable? */ - } + if (TYPE(x) == T_SYMBOL) + { + return rb_id2name(SYM2ID(x)); + } + else if (TYPE(x) == T_STRING) + { + return StringValueCStr(x); + } + else + { + rb_exc_raise(rb_exc_new2(rb_eTypeError, error_message)); + abort(); /* unreachable? */ + } } -typedef int (*elem_string_fptr)(void*, const char*, size_t, enum hyperdex_ds_returncode*); -typedef int (*elem_int_fptr)(void*, int64_t, enum hyperdex_ds_returncode*); -typedef int (*elem_float_fptr)(void*, double, enum hyperdex_ds_returncode*); +typedef int (*elem_string_fptr)(void *, const char *, size_t, enum hyperdex_ds_returncode *); +typedef int (*elem_int_fptr)(void *, int64_t, enum hyperdex_ds_returncode *); +typedef int (*elem_float_fptr)(void *, double, enum hyperdex_ds_returncode *); #define HDRB_HANDLE_ELEM_ERROR(X, TYPE) \ - switch (X) \ - { \ - case HYPERDEX_DS_NOMEM: \ - hyperdex_ruby_out_of_memory(); \ - case HYPERDEX_DS_MIXED_TYPES: \ - rb_raise(rb_eTypeError, "Cannot add " TYPE " to a heterogenous container"); \ - case HYPERDEX_DS_SUCCESS: \ - case HYPERDEX_DS_STRING_TOO_LONG: \ - case HYPERDEX_DS_WRONG_STATE: \ - default: \ - rb_raise(rb_eTypeError, "Cannot convert " TYPE " to a HyperDex type"); \ - } + switch (X) \ + { \ + case HYPERDEX_DS_NOMEM: \ + hyperdex_ruby_out_of_memory(); \ + case HYPERDEX_DS_MIXED_TYPES: \ + rb_raise(rb_eTypeError, "Cannot add " TYPE " to a heterogenous container"); \ + case HYPERDEX_DS_SUCCESS: \ + case HYPERDEX_DS_STRING_TOO_LONG: \ + case HYPERDEX_DS_WRONG_STATE: \ + default: \ + rb_raise(rb_eTypeError, "Cannot convert " TYPE " to a HyperDex type"); \ + } static void hyperdex_ruby_client_convert_elem(VALUE e, - void* x, + void *x, elem_string_fptr f_string, elem_int_fptr f_int, elem_float_fptr f_float) { - enum hyperdex_ds_returncode error; - const char* tmp_str; - size_t tmp_str_sz; - int64_t tmp_i; - double tmp_d; - - switch (TYPE(e)) - { - case T_SYMBOL: - tmp_str = rb_id2name(SYM2ID(e)); - tmp_str_sz = strlen(tmp_str); - if (f_string(x, tmp_str, tmp_str_sz, &error) < 0) - { - HDRB_HANDLE_ELEM_ERROR(error, "string"); - } - break; - case T_STRING: - tmp_str = StringValuePtr(e); - tmp_str_sz = RSTRING_LEN(e); - if (f_string(x, tmp_str, tmp_str_sz, &error) < 0) - { - HDRB_HANDLE_ELEM_ERROR(error, "string"); - } - break; - case T_FIXNUM: - case T_BIGNUM: - tmp_i = NUM2LL(e); - if (f_int(x, tmp_i, &error) < 0) - { - HDRB_HANDLE_ELEM_ERROR(error, "integer"); - } - break; - case T_FLOAT: - tmp_d = NUM2DBL(e); - if (f_float(x, tmp_d, &error) < 0) - { - HDRB_HANDLE_ELEM_ERROR(error, "float"); - } - break; - default: - rb_raise(rb_eTypeError, "Cannot convert object to a HyperDex container element"); - break; - } + enum hyperdex_ds_returncode error; + const char *tmp_str; + size_t tmp_str_sz; + int64_t tmp_i; + double tmp_d; + switch (TYPE(e)) + { + case T_SYMBOL: + tmp_str = rb_id2name(SYM2ID(e)); + tmp_str_sz = strlen(tmp_str); + if (f_string(x, tmp_str, tmp_str_sz, &error) < 0) + { + HDRB_HANDLE_ELEM_ERROR(error, "string"); + } + break; + case T_STRING: + tmp_str = StringValuePtr(e); + tmp_str_sz = RSTRING_LEN(e); + if (f_string(x, tmp_str, tmp_str_sz, &error) < 0) + { + HDRB_HANDLE_ELEM_ERROR(error, "string"); + } + break; + case T_FIXNUM: + case T_BIGNUM: + tmp_i = NUM2LL(e); + if (f_int(x, tmp_i, &error) < 0) + { + HDRB_HANDLE_ELEM_ERROR(error, "integer"); + } + break; + case T_FLOAT: + tmp_d = NUM2DBL(e); + if (f_float(x, tmp_d, &error) < 0) + { + HDRB_HANDLE_ELEM_ERROR(error, "float"); + } + break; + default: + rb_raise(rb_eTypeError, "Cannot convert object to a HyperDex container element"); + break; + } } static void -hyperdex_ruby_client_convert_list(struct hyperdex_ds_arena* arena, +hyperdex_ruby_client_convert_list(struct hyperdex_ds_arena *arena, VALUE x, - const char** value, - size_t* value_sz, - enum hyperdatatype* datatype) + const char **value, + size_t *value_sz, + enum hyperdatatype *datatype) { - struct hyperdex_ds_list* list; - enum hyperdex_ds_returncode error; - VALUE entry; - ssize_t i = 0; - - list = hyperdex_ds_allocate_list(arena); - - if (!list) - { - hyperdex_ruby_out_of_memory(); - } - - for (i = 0; i < RARRAY_LEN(x); ++i) - { - entry = rb_ary_entry(x, i); - hyperdex_ruby_client_convert_elem(entry, list, - (elem_string_fptr) hyperdex_ds_list_append_string, - (elem_int_fptr) hyperdex_ds_list_append_int, - (elem_float_fptr) hyperdex_ds_list_append_float); - } - - if (hyperdex_ds_list_finalize(list, &error, value, value_sz, datatype) < 0) - { - hyperdex_ruby_out_of_memory(); - } + struct hyperdex_ds_list *list; + enum hyperdex_ds_returncode error; + VALUE entry; + ssize_t i = 0; + list = hyperdex_ds_allocate_list(arena); + if (!list) + { + hyperdex_ruby_out_of_memory(); + } + for (i = 0; i < RARRAY_LEN(x); ++i) + { + entry = rb_ary_entry(x, i); + hyperdex_ruby_client_convert_elem(entry, list, + (elem_string_fptr) hyperdex_ds_list_append_string, + (elem_int_fptr) hyperdex_ds_list_append_int, + (elem_float_fptr) hyperdex_ds_list_append_float); + } + if (hyperdex_ds_list_finalize(list, &error, value, value_sz, datatype) < 0) + { + hyperdex_ruby_out_of_memory(); + } } static void -hyperdex_ruby_client_convert_set(struct hyperdex_ds_arena* arena, +hyperdex_ruby_client_convert_set(struct hyperdex_ds_arena *arena, VALUE _x, - const char** value, - size_t* value_sz, - enum hyperdatatype* datatype) + const char **value, + size_t *value_sz, + enum hyperdatatype *datatype) { - struct hyperdex_ds_set* set; - enum hyperdex_ds_returncode error; - VALUE entry; - ssize_t i = 0; - VALUE x = rb_funcall(_x, rb_intern("to_a"), 0); - - set = hyperdex_ds_allocate_set(arena); - - if (!set) - { - hyperdex_ruby_out_of_memory(); - } - - for (i = 0; i < RARRAY_LEN(x); ++i) - { - entry = rb_ary_entry(x, i); - hyperdex_ruby_client_convert_elem(entry, set, - (elem_string_fptr) hyperdex_ds_set_insert_string, - (elem_int_fptr) hyperdex_ds_set_insert_int, - (elem_float_fptr) hyperdex_ds_set_insert_float); - } - - if (hyperdex_ds_set_finalize(set, &error, value, value_sz, datatype) < 0) - { - hyperdex_ruby_out_of_memory(); - } + struct hyperdex_ds_set *set; + enum hyperdex_ds_returncode error; + VALUE entry; + ssize_t i = 0; + VALUE x = rb_funcall(_x, rb_intern("to_a"), 0); + set = hyperdex_ds_allocate_set(arena); + if (!set) + { + hyperdex_ruby_out_of_memory(); + } + for (i = 0; i < RARRAY_LEN(x); ++i) + { + entry = rb_ary_entry(x, i); + hyperdex_ruby_client_convert_elem(entry, set, + (elem_string_fptr) hyperdex_ds_set_insert_string, + (elem_int_fptr) hyperdex_ds_set_insert_int, + (elem_float_fptr) hyperdex_ds_set_insert_float); + } + if (hyperdex_ds_set_finalize(set, &error, value, value_sz, datatype) < 0) + { + hyperdex_ruby_out_of_memory(); + } } static void -hyperdex_ruby_client_convert_map(struct hyperdex_ds_arena* arena, +hyperdex_ruby_client_convert_map(struct hyperdex_ds_arena *arena, VALUE _x, - const char** value, - size_t* value_sz, - enum hyperdatatype* datatype) + const char **value, + size_t *value_sz, + enum hyperdatatype *datatype) { - struct hyperdex_ds_map* map; - enum hyperdex_ds_returncode error; - VALUE entry; - VALUE key; - VALUE val; - ssize_t i = 0; - VALUE x = rb_funcall(_x, rb_intern("to_a"), 0); - - map = hyperdex_ds_allocate_map(arena); - - if (!map) - { - hyperdex_ruby_out_of_memory(); - } - - for (i = 0; i < RARRAY_LEN(x); ++i) - { - entry = rb_ary_entry(x, i); - key = rb_ary_entry(entry, 0); - val = rb_ary_entry(entry, 1); - hyperdex_ruby_client_convert_elem(key, map, - (elem_string_fptr) hyperdex_ds_map_insert_key_string, - (elem_int_fptr) hyperdex_ds_map_insert_key_int, - (elem_float_fptr) hyperdex_ds_map_insert_key_float); - hyperdex_ruby_client_convert_elem(val, map, - (elem_string_fptr) hyperdex_ds_map_insert_val_string, - (elem_int_fptr) hyperdex_ds_map_insert_val_int, - (elem_float_fptr) hyperdex_ds_map_insert_val_float); - } - - if (hyperdex_ds_map_finalize(map, &error, value, value_sz, datatype) < 0) - { - hyperdex_ruby_out_of_memory(); - } + struct hyperdex_ds_map *map; + enum hyperdex_ds_returncode error; + VALUE entry; + VALUE key; + VALUE val; + ssize_t i = 0; + VALUE x = rb_funcall(_x, rb_intern("to_a"), 0); + map = hyperdex_ds_allocate_map(arena); + if (!map) + { + hyperdex_ruby_out_of_memory(); + } + for (i = 0; i < RARRAY_LEN(x); ++i) + { + entry = rb_ary_entry(x, i); + key = rb_ary_entry(entry, 0); + val = rb_ary_entry(entry, 1); + hyperdex_ruby_client_convert_elem(key, map, + (elem_string_fptr) hyperdex_ds_map_insert_key_string, + (elem_int_fptr) hyperdex_ds_map_insert_key_int, + (elem_float_fptr) hyperdex_ds_map_insert_key_float); + hyperdex_ruby_client_convert_elem(val, map, + (elem_string_fptr) hyperdex_ds_map_insert_val_string, + (elem_int_fptr) hyperdex_ds_map_insert_val_int, + (elem_float_fptr) hyperdex_ds_map_insert_val_float); + } + if (hyperdex_ds_map_finalize(map, &error, value, value_sz, datatype) < 0) + { + hyperdex_ruby_out_of_memory(); + } } static void -hyperdex_ruby_client_convert_type(struct hyperdex_ds_arena* arena, +hyperdex_ruby_client_convert_type(struct hyperdex_ds_arena *arena, VALUE x, - const char** value, - size_t* value_sz, - enum hyperdatatype* datatype) + const char **value, + size_t *value_sz, + enum hyperdatatype *datatype) { - enum hyperdex_ds_returncode error; - const char* tmp_str; - size_t tmp_str_sz; - int64_t tmp_i; - double tmp_d; - - switch (TYPE(x)) - { - case T_SYMBOL: - tmp_str = rb_id2name(SYM2ID(x)); - tmp_str_sz = strlen(tmp_str); - - if (hyperdex_ds_copy_string(arena, tmp_str, tmp_str_sz, - &error, value, value_sz) < 0) - { - hyperdex_ruby_out_of_memory(); - } - - *datatype = HYPERDATATYPE_STRING; - break; - case T_STRING: - tmp_str = StringValuePtr(x); - tmp_str_sz = RSTRING_LEN(x); - - if (hyperdex_ds_copy_string(arena, tmp_str, tmp_str_sz, - &error, value, value_sz) < 0) - { - hyperdex_ruby_out_of_memory(); - } - - *datatype = HYPERDATATYPE_STRING; - break; - case T_FIXNUM: - case T_BIGNUM: - tmp_i = NUM2LL(x); - - if (hyperdex_ds_copy_int(arena, tmp_i, - &error, value, value_sz) < 0) - { - hyperdex_ruby_out_of_memory(); - } - - *datatype = HYPERDATATYPE_INT64; - break; - case T_FLOAT: - tmp_d = NUM2DBL(x); - - if (hyperdex_ds_copy_float(arena, tmp_d, - &error, value, value_sz) < 0) - { - hyperdex_ruby_out_of_memory(); - } - - *datatype = HYPERDATATYPE_FLOAT; - break; - case T_ARRAY: - hyperdex_ruby_client_convert_list(arena, x, value, value_sz, datatype); - break; - case T_HASH: - hyperdex_ruby_client_convert_map(arena, x, value, value_sz, datatype); - break; - case T_OBJECT: - if (!rb_obj_is_kind_of(x, Set) == Qtrue) - { - rb_raise(rb_eTypeError, "Cannot convert object to a HyperDex type"); - break; - } - - hyperdex_ruby_client_convert_set(arena, x, value, value_sz, datatype); - break; - default: - rb_raise(rb_eTypeError, "Cannot convert object to a HyperDex type"); - break; - } + enum hyperdex_ds_returncode error; + const char *tmp_str; + size_t tmp_str_sz; + int64_t tmp_i; + double tmp_d; + switch (TYPE(x)) + { + case T_SYMBOL: + tmp_str = rb_id2name(SYM2ID(x)); + tmp_str_sz = strlen(tmp_str); + if (hyperdex_ds_copy_string(arena, tmp_str, tmp_str_sz, + &error, value, value_sz) < 0) + { + hyperdex_ruby_out_of_memory(); + } + *datatype = HYPERDATATYPE_STRING; + break; + case T_STRING: + tmp_str = StringValuePtr(x); + tmp_str_sz = RSTRING_LEN(x); + if (hyperdex_ds_copy_string(arena, tmp_str, tmp_str_sz, + &error, value, value_sz) < 0) + { + hyperdex_ruby_out_of_memory(); + } + *datatype = HYPERDATATYPE_STRING; + break; + case T_FIXNUM: + case T_BIGNUM: + tmp_i = NUM2LL(x); + if (hyperdex_ds_copy_int(arena, tmp_i, + &error, value, value_sz) < 0) + { + hyperdex_ruby_out_of_memory(); + } + *datatype = HYPERDATATYPE_INT64; + break; + case T_FLOAT: + tmp_d = NUM2DBL(x); + if (hyperdex_ds_copy_float(arena, tmp_d, + &error, value, value_sz) < 0) + { + hyperdex_ruby_out_of_memory(); + } + *datatype = HYPERDATATYPE_FLOAT; + break; + case T_ARRAY: + hyperdex_ruby_client_convert_list(arena, x, value, value_sz, datatype); + break; + case T_HASH: + hyperdex_ruby_client_convert_map(arena, x, value, value_sz, datatype); + break; + case T_OBJECT: + if (!rb_obj_is_kind_of(x, Set) == Qtrue) + { + rb_raise(rb_eTypeError, "Cannot convert object to a HyperDex type"); + break; + } + hyperdex_ruby_client_convert_set(arena, x, value, value_sz, datatype); + break; + default: + rb_raise(rb_eTypeError, "Cannot convert object to a HyperDex type"); + break; + } } static void -hyperdex_ruby_client_convert_attributes(struct hyperdex_ds_arena* arena, +hyperdex_ruby_client_convert_attributes(struct hyperdex_ds_arena *arena, VALUE x, - const struct hyperdex_client_attribute** _attrs, - size_t* _attrs_sz) + const struct hyperdex_client_attribute **_attrs, + size_t *_attrs_sz) { - VALUE hash_pairs = Qnil; - VALUE hash_pair = Qnil; - VALUE key = Qnil; - VALUE val = Qnil; - struct hyperdex_client_attribute* attrs; - size_t attrs_sz; - ssize_t i; - - if (TYPE(x) != T_HASH) - { - rb_exc_raise(rb_exc_new2(rb_eTypeError, "Attributes must be specified as a hash")); - abort(); /* unreachable? */ - } - - hash_pairs = rb_funcall(x, rb_intern("to_a"), 0); - attrs_sz = RARRAY_LEN(hash_pairs); - attrs = hyperdex_ds_allocate_attribute(arena, attrs_sz); - - if (!attrs) - { - hyperdex_ruby_out_of_memory(); - } - - *_attrs = attrs; - *_attrs_sz = attrs_sz; - - for (i = 0; i < RARRAY_LEN(hash_pairs); ++i) - { - hash_pair = rb_ary_entry(hash_pairs, i); - key = rb_ary_entry(hash_pair, 0); - val = rb_ary_entry(hash_pair, 1); - - attrs[i].attr = hyperdex_ruby_client_convert_cstring(key, "Attribute name must be a string or symbol"); - hyperdex_ruby_client_convert_type(arena, val, &attrs[i].value, &attrs[i].value_sz, &attrs[i].datatype); - } + VALUE hash_pairs = Qnil; + VALUE hash_pair = Qnil; + VALUE key = Qnil; + VALUE val = Qnil; + struct hyperdex_client_attribute *attrs; + size_t attrs_sz; + ssize_t i; + if (TYPE(x) != T_HASH) + { + rb_exc_raise(rb_exc_new2(rb_eTypeError, "Attributes must be specified as a hash")); + abort(); /* unreachable? */ + } + hash_pairs = rb_funcall(x, rb_intern("to_a"), 0); + attrs_sz = RARRAY_LEN(hash_pairs); + attrs = hyperdex_ds_allocate_attribute(arena, attrs_sz); + if (!attrs) + { + hyperdex_ruby_out_of_memory(); + } + *_attrs = attrs; + *_attrs_sz = attrs_sz; + for (i = 0; i < RARRAY_LEN(hash_pairs); ++i) + { + hash_pair = rb_ary_entry(hash_pairs, i); + key = rb_ary_entry(hash_pair, 0); + val = rb_ary_entry(hash_pair, 1); + attrs[i].attr = hyperdex_ruby_client_convert_cstring(key, "Attribute name must be a string or symbol"); + hyperdex_ruby_client_convert_type(arena, val, &attrs[i].value, &attrs[i].value_sz, &attrs[i].datatype); + } } static void -hyperdex_ruby_client_convert_key(struct hyperdex_ds_arena* arena, +hyperdex_ruby_client_convert_key(struct hyperdex_ds_arena *arena, VALUE x, - const char** key, - size_t* key_sz) + const char **key, + size_t *key_sz) { - enum hyperdatatype datatype; - hyperdex_ruby_client_convert_type(arena, x, key, key_sz, &datatype); + enum hyperdatatype datatype; + hyperdex_ruby_client_convert_type(arena, x, key, key_sz, &datatype); } static void -hyperdex_ruby_client_convert_limit(struct hyperdex_ds_arena* arena, +hyperdex_ruby_client_convert_limit(struct hyperdex_ds_arena *arena, VALUE x, - uint64_t* limit) + uint64_t *limit) { - *limit = rb_num2ulong(x); - (void) arena; + *limit = rb_num2ulong(x); + (void) arena; } static void -hyperdex_ruby_client_convert_mapattributes(struct hyperdex_ds_arena* arena, +hyperdex_ruby_client_convert_mapattributes(struct hyperdex_ds_arena *arena, VALUE x, - const struct hyperdex_client_map_attribute** _mapattrs, - size_t* _mapattrs_sz) + const struct hyperdex_client_map_attribute **_mapattrs, + size_t *_mapattrs_sz) { - VALUE outer_pairs = Qnil; - VALUE outer_pair = Qnil; - VALUE inner_pairs = Qnil; - VALUE inner_pair = Qnil; - VALUE attr = Qnil; - VALUE key = Qnil; - VALUE val = Qnil; - struct hyperdex_client_map_attribute* mapattrs = NULL; - size_t mapattrs_sz = 0; - size_t mapattrs_idx = 0; - ssize_t i = 0; - size_t j = 0; - - if (TYPE(x) != T_HASH) - { - rb_exc_raise(rb_exc_new2(rb_eTypeError, "Map attributes must be specified as a hash")); - abort(); /* unreachable? */ - } - - outer_pairs = rb_funcall(x, rb_intern("to_a"), 0); - - for (i = 0; i < RARRAY_LEN(outer_pairs); ++i) - { - outer_pair = rb_ary_entry(outer_pairs, i); - inner_pairs = rb_ary_entry(outer_pair, 1); - - if (TYPE(inner_pairs) != T_HASH) - { - rb_exc_raise(rb_exc_new2(rb_eTypeError, "Map attributes must be specified as a hash")); - abort(); /* unreachable? */ - } - - mapattrs_sz += RHASH_SIZE(inner_pairs); - } - - mapattrs = hyperdex_ds_allocate_map_attribute(arena, mapattrs_sz); - - if (!mapattrs) - { - hyperdex_ruby_out_of_memory(); - } - - *_mapattrs = mapattrs; - *_mapattrs_sz = mapattrs_sz; - - for (i = 0; i < RARRAY_LEN(outer_pairs); ++i) - { - outer_pair = rb_ary_entry(outer_pairs, i); - attr = rb_ary_entry(outer_pair, 0); - inner_pairs = rb_ary_entry(outer_pair, 1); - inner_pairs = rb_funcall(inner_pairs, rb_intern("to_a"), 0); - - for (j = 0; RARRAY_LEN(inner_pairs); ++j) - { - inner_pair = rb_ary_entry(inner_pairs, j); - key = rb_ary_entry(inner_pair, 0); - val = rb_ary_entry(inner_pair, 1); - mapattrs[mapattrs_idx].attr = hyperdex_ruby_client_convert_cstring(attr, "Attribute name must be a string or symbol"); - hyperdex_ruby_client_convert_type(arena, key, - &mapattrs[mapattrs_idx].map_key, - &mapattrs[mapattrs_idx].map_key_sz, - &mapattrs[mapattrs_idx].map_key_datatype); - hyperdex_ruby_client_convert_type(arena, val, - &mapattrs[mapattrs_idx].value, - &mapattrs[mapattrs_idx].value_sz, - &mapattrs[mapattrs_idx].value_datatype); - ++mapattrs_idx; - } - } + VALUE outer_pairs = Qnil; + VALUE outer_pair = Qnil; + VALUE inner_pairs = Qnil; + VALUE inner_pair = Qnil; + VALUE attr = Qnil; + VALUE key = Qnil; + VALUE val = Qnil; + struct hyperdex_client_map_attribute *mapattrs = NULL; + size_t mapattrs_sz = 0; + size_t mapattrs_idx = 0; + ssize_t i = 0; + size_t j = 0; + if (TYPE(x) != T_HASH) + { + rb_exc_raise(rb_exc_new2(rb_eTypeError, "Map attributes must be specified as a hash")); + abort(); /* unreachable? */ + } + outer_pairs = rb_funcall(x, rb_intern("to_a"), 0); + for (i = 0; i < RARRAY_LEN(outer_pairs); ++i) + { + outer_pair = rb_ary_entry(outer_pairs, i); + inner_pairs = rb_ary_entry(outer_pair, 1); + if (TYPE(inner_pairs) != T_HASH) + { + rb_exc_raise(rb_exc_new2(rb_eTypeError, "Map attributes must be specified as a hash")); + abort(); /* unreachable? */ + } + mapattrs_sz += RHASH_SIZE(inner_pairs); + } + mapattrs = hyperdex_ds_allocate_map_attribute(arena, mapattrs_sz); + if (!mapattrs) + { + hyperdex_ruby_out_of_memory(); + } + *_mapattrs = mapattrs; + *_mapattrs_sz = mapattrs_sz; + for (i = 0; i < RARRAY_LEN(outer_pairs); ++i) + { + outer_pair = rb_ary_entry(outer_pairs, i); + attr = rb_ary_entry(outer_pair, 0); + inner_pairs = rb_ary_entry(outer_pair, 1); + inner_pairs = rb_funcall(inner_pairs, rb_intern("to_a"), 0); + for (j = 0; RARRAY_LEN(inner_pairs); ++j) + { + inner_pair = rb_ary_entry(inner_pairs, j); + key = rb_ary_entry(inner_pair, 0); + val = rb_ary_entry(inner_pair, 1); + mapattrs[mapattrs_idx].attr = hyperdex_ruby_client_convert_cstring(attr, "Attribute name must be a string or symbol"); + hyperdex_ruby_client_convert_type(arena, key, + &mapattrs[mapattrs_idx].map_key, + &mapattrs[mapattrs_idx].map_key_sz, + &mapattrs[mapattrs_idx].map_key_datatype); + hyperdex_ruby_client_convert_type(arena, val, + &mapattrs[mapattrs_idx].value, + &mapattrs[mapattrs_idx].value_sz, + &mapattrs[mapattrs_idx].value_datatype); + ++mapattrs_idx; + } + } } static void -hyperdex_ruby_client_convert_maxmin(struct hyperdex_ds_arena* arena, +hyperdex_ruby_client_convert_maxmin(struct hyperdex_ds_arena *arena, VALUE x, - int* maxmin) + int *maxmin) { - *maxmin = x == Qtrue ? 1: 0; - (void) arena; + *maxmin = x == Qtrue ? 1 : 0; + (void) arena; } static size_t hyperdex_ruby_client_estimate_predicate_size(VALUE x) { - VALUE pred = Qnil; - struct hyperdex_ruby_client_predicate* p = NULL; - ssize_t i = 0; - size_t sum = 0; - - if (TYPE(x) == T_DATA && - rb_obj_is_kind_of(x, class_predicate) == Qtrue) - { - Data_Get_Struct(x, struct hyperdex_ruby_client_predicate, p); - return p->num_checks; - } - else if (TYPE(x) == T_ARRAY && - RARRAY_LEN(x) > 0 && - rb_obj_is_kind_of(rb_ary_entry(x, 0), class_predicate) == Qtrue) - { - for (i = 0; i < RARRAY_LEN(x); ++i) - { - pred = rb_ary_entry(x, i); - - if (TYPE(pred) != T_DATA || - rb_obj_is_kind_of(pred, class_predicate) != Qtrue) - { - rb_raise(rb_eTypeError, "Cannot convert predicate to a HyperDex type"); - return 0; - } - - Data_Get_Struct(pred, struct hyperdex_ruby_client_predicate, p); - sum += p->num_checks; - } - - return sum; - } - else - { - return 1; - } + VALUE pred = Qnil; + struct hyperdex_ruby_client_predicate *p = NULL; + ssize_t i = 0; + size_t sum = 0; + if (TYPE(x) == T_DATA && + rb_obj_is_kind_of(x, class_predicate) == Qtrue) + { + Data_Get_Struct(x, struct hyperdex_ruby_client_predicate, p); + return p->num_checks; + } + else if (TYPE(x) == T_ARRAY && + RARRAY_LEN(x) > 0 && + rb_obj_is_kind_of(rb_ary_entry(x, 0), class_predicate) == Qtrue) + { + for (i = 0; i < RARRAY_LEN(x); ++i) + { + pred = rb_ary_entry(x, i); + if (TYPE(pred) != T_DATA || + rb_obj_is_kind_of(pred, class_predicate) != Qtrue) + { + rb_raise(rb_eTypeError, "Cannot convert predicate to a HyperDex type"); + return 0; + } + Data_Get_Struct(pred, struct hyperdex_ruby_client_predicate, p); + sum += p->num_checks; + } + return sum; + } + else + { + return 1; + } } static size_t -hyperdex_ruby_client_convert_predicate(struct hyperdex_ds_arena* arena, - const char* attr, +hyperdex_ruby_client_convert_predicate(struct hyperdex_ds_arena *arena, + const char *attr, VALUE x, - struct hyperdex_client_attribute_check* checks, + struct hyperdex_client_attribute_check *checks, size_t checks_idx) { - VALUE pred = Qnil; - struct hyperdex_ruby_client_predicate* p = NULL; - size_t i = 0; - - if (TYPE(x) == T_DATA && - rb_obj_is_kind_of(x, class_predicate) == Qtrue) - { - Data_Get_Struct(x, struct hyperdex_ruby_client_predicate, p); - - for (i = 0; i < p->num_checks; ++i) - { - checks[checks_idx + i].attr = attr; - checks[checks_idx + i].predicate = p->checks[i].predicate; - hyperdex_ruby_client_convert_type(arena, p->checks[i].v, - &checks[checks_idx + i].value, - &checks[checks_idx + i].value_sz, - &checks[checks_idx + i].datatype); - } - - return checks_idx + p->num_checks; - } - else if (TYPE(x) == T_ARRAY && - RARRAY_LEN(x) > 0 && - rb_obj_is_kind_of(rb_ary_entry(x, 0), class_predicate) == Qtrue) - { - for (i = 0; i < (size_t)RARRAY_LEN(x); ++i) - { - pred = rb_ary_entry(x, i); - assert(TYPE(pred) == T_DATA); - assert(rb_obj_is_kind_of(pred, class_predicate) == Qtrue); - checks_idx = hyperdex_ruby_client_convert_predicate(arena, attr, pred, checks, checks_idx); - } - - return checks_idx; - } - else - { - checks[checks_idx].attr = attr; - checks[checks_idx].predicate = HYPERPREDICATE_EQUALS, - hyperdex_ruby_client_convert_type(arena, x, - &checks[checks_idx].value, - &checks[checks_idx].value_sz, - &checks[checks_idx].datatype); - return checks_idx + 1; - } + VALUE pred = Qnil; + struct hyperdex_ruby_client_predicate *p = NULL; + size_t i = 0; + if (TYPE(x) == T_DATA && + rb_obj_is_kind_of(x, class_predicate) == Qtrue) + { + Data_Get_Struct(x, struct hyperdex_ruby_client_predicate, p); + for (i = 0; i < p->num_checks; ++i) + { + checks[checks_idx + i].attr = attr; + checks[checks_idx + i].predicate = p->checks[i].predicate; + hyperdex_ruby_client_convert_type(arena, p->checks[i].v, + &checks[checks_idx + i].value, + &checks[checks_idx + i].value_sz, + &checks[checks_idx + i].datatype); + } + return checks_idx + p->num_checks; + } + else if (TYPE(x) == T_ARRAY && + RARRAY_LEN(x) > 0 && + rb_obj_is_kind_of(rb_ary_entry(x, 0), class_predicate) == Qtrue) + { + for (i = 0; i < (size_t)RARRAY_LEN(x); ++i) + { + pred = rb_ary_entry(x, i); + assert(TYPE(pred) == T_DATA); + assert(rb_obj_is_kind_of(pred, class_predicate) == Qtrue); + checks_idx = hyperdex_ruby_client_convert_predicate(arena, attr, pred, checks, checks_idx); + } + return checks_idx; + } + else + { + checks[checks_idx].attr = attr; + checks[checks_idx].predicate = HYPERPREDICATE_EQUALS, + hyperdex_ruby_client_convert_type(arena, x, + &checks[checks_idx].value, + &checks[checks_idx].value_sz, + &checks[checks_idx].datatype); + return checks_idx + 1; + } } static void -hyperdex_ruby_client_convert_predicates(struct hyperdex_ds_arena* arena, +hyperdex_ruby_client_convert_predicates(struct hyperdex_ds_arena *arena, VALUE x, - const struct hyperdex_client_attribute_check** _checks, - size_t* _checks_sz) + const struct hyperdex_client_attribute_check **_checks, + size_t *_checks_sz) { - VALUE hash_pairs = Qnil; - VALUE hash_pair = Qnil; - VALUE key = Qnil; - VALUE val = Qnil; - struct hyperdex_client_attribute_check* checks = NULL; - size_t checks_sz = 0; - size_t checks_idx = 0; - ssize_t i = 0; - const char* attr; - - if (TYPE(x) != T_HASH) - { - rb_exc_raise(rb_exc_new2(rb_eTypeError, "Predicates must be specified as a hash")); - abort(); /* unreachable? */ - } - - hash_pairs = rb_funcall(x, rb_intern("to_a"), 0); - - /* figure out how many checks to allocate */ - for (i = 0; i < RARRAY_LEN(hash_pairs); ++i) - { - hash_pair = rb_ary_entry(hash_pairs, i); - val = rb_ary_entry(hash_pair, 1); - checks_sz += hyperdex_ruby_client_estimate_predicate_size(val); - } - - checks = hyperdex_ds_allocate_attribute_check(arena, checks_sz); - - if (!checks) - { - hyperdex_ruby_out_of_memory(); - } - - *_checks = checks; - *_checks_sz = checks_sz; - checks_idx = 0; - - /* turn the predicate into checks */ - for (i = 0; i < RARRAY_LEN(hash_pairs); ++i) - { - hash_pair = rb_ary_entry(hash_pairs, i); - key = rb_ary_entry(hash_pair, 0); - val = rb_ary_entry(hash_pair, 1); - - attr = hyperdex_ruby_client_convert_cstring(key, "Attribute name must be a string or symbol"); - checks_idx = hyperdex_ruby_client_convert_predicate(arena, attr, val, checks, checks_idx); - } + VALUE hash_pairs = Qnil; + VALUE hash_pair = Qnil; + VALUE key = Qnil; + VALUE val = Qnil; + struct hyperdex_client_attribute_check *checks = NULL; + size_t checks_sz = 0; + size_t checks_idx = 0; + ssize_t i = 0; + const char *attr; + if (TYPE(x) != T_HASH) + { + rb_exc_raise(rb_exc_new2(rb_eTypeError, "Predicates must be specified as a hash")); + abort(); /* unreachable? */ + } + hash_pairs = rb_funcall(x, rb_intern("to_a"), 0); + /* figure out how many checks to allocate */ + for (i = 0; i < RARRAY_LEN(hash_pairs); ++i) + { + hash_pair = rb_ary_entry(hash_pairs, i); + val = rb_ary_entry(hash_pair, 1); + checks_sz += hyperdex_ruby_client_estimate_predicate_size(val); + } + checks = hyperdex_ds_allocate_attribute_check(arena, checks_sz); + if (!checks) + { + hyperdex_ruby_out_of_memory(); + } + *_checks = checks; + *_checks_sz = checks_sz; + checks_idx = 0; + /* turn the predicate into checks */ + for (i = 0; i < RARRAY_LEN(hash_pairs); ++i) + { + hash_pair = rb_ary_entry(hash_pairs, i); + key = rb_ary_entry(hash_pair, 0); + val = rb_ary_entry(hash_pair, 1); + attr = hyperdex_ruby_client_convert_cstring(key, "Attribute name must be a string or symbol"); + checks_idx = hyperdex_ruby_client_convert_predicate(arena, attr, val, checks, checks_idx); + } } static void -hyperdex_ruby_client_convert_attributenames(struct hyperdex_ds_arena* arena, +hyperdex_ruby_client_convert_attributenames(struct hyperdex_ds_arena *arena, VALUE x, - const char*** names, size_t* names_sz) + const char *** names, size_t *names_sz) { - size_t i = 0; - *names_sz = RARRAY_LEN(x); - *names = hyperdex_ds_malloc(arena, sizeof(char*) * (*names_sz)); - - if (!(*names)) - { - hyperdex_ruby_out_of_memory(); - } - - for (i = 0; i < *names_sz; ++i) - { - (*names)[i] = hyperdex_ruby_client_convert_cstring(rb_ary_entry(x, i), - "Attribute name must be a string or symbol"); - } + size_t i = 0; + *names_sz = RARRAY_LEN(x); + *names = hyperdex_ds_malloc(arena, sizeof(char *) * (*names_sz)); + if (!(*names)) + { + hyperdex_ruby_out_of_memory(); + } + for (i = 0; i < *names_sz; ++i) + { + (*names)[i] = hyperdex_ruby_client_convert_cstring(rb_ary_entry(x, i), + "Attribute name must be a string or symbol"); + } } static void -hyperdex_ruby_client_convert_sortby(struct hyperdex_ds_arena* arena, +hyperdex_ruby_client_convert_sortby(struct hyperdex_ds_arena *arena, VALUE x, - const char** sortby) + const char **sortby) { - *sortby = hyperdex_ruby_client_convert_cstring(x, "sortby must be a string or symbol"); - (void) arena; + *sortby = hyperdex_ruby_client_convert_cstring(x, "sortby must be a string or symbol"); + (void) arena; } static void -hyperdex_ruby_client_convert_spacename(struct hyperdex_ds_arena* arena, +hyperdex_ruby_client_convert_spacename(struct hyperdex_ds_arena *arena, VALUE x, - const char** spacename) + const char **spacename) { - *spacename = hyperdex_ruby_client_convert_cstring(x, "spacename must be a string or symbol"); - (void) arena; + *spacename = hyperdex_ruby_client_convert_cstring(x, "spacename must be a string or symbol"); + (void) arena; } /********************************** C -> Ruby *********************************/ static VALUE -hyperdex_ruby_client_build_attribute(const struct hyperdex_client_attribute* attrs) +hyperdex_ruby_client_build_attribute(const struct hyperdex_client_attribute *attrs) { - struct hyperdex_ds_iterator iter; - const char* tmp_str = NULL; - size_t tmp_str_sz = 0; - const char* tmp_str2 = NULL; - size_t tmp_str2_sz = 0; - int64_t tmp_i = 0; - int64_t tmp_i2 = 0; - double tmp_d = 0; - double tmp_d2 = 0; - int result = 0; - VALUE ret = Qnil; - VALUE tmp = Qnil; - VALUE tmp2 = Qnil; - - switch (attrs->datatype) - { - case HYPERDATATYPE_STRING: - return rb_str_new(attrs->value, attrs->value_sz); - case HYPERDATATYPE_INT64: - if (hyperdex_ds_unpack_int(attrs->value, attrs->value_sz, &tmp_i) < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed int"); - } - - return LL2NUM(tmp_i); - case HYPERDATATYPE_FLOAT: - if (hyperdex_ds_unpack_float(attrs->value, attrs->value_sz, &tmp_d) < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed float"); - } - - return rb_float_new(tmp_d); - case HYPERDATATYPE_DOCUMENT: - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_WRONGTYPE, "Ruby bindings do not support JSON objects"); - case HYPERDATATYPE_LIST_STRING: - ret = rb_ary_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_list_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) - { - tmp = rb_str_new(tmp_str, tmp_str_sz); - rb_ary_push(ret, tmp); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed list(string)"); - } - - return ret; - case HYPERDATATYPE_LIST_INT64: - ret = rb_ary_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_list_int_next(&iter, &tmp_i)) > 0) - { - tmp = LL2NUM(tmp_i); - rb_ary_push(ret, tmp); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed list(int)"); - } - - return ret; - case HYPERDATATYPE_LIST_FLOAT: - ret = rb_ary_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_list_float_next(&iter, &tmp_d)) > 0) - { - tmp = rb_float_new(tmp_d); - rb_ary_push(ret, tmp); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed list(float)"); - } - - return ret; - case HYPERDATATYPE_SET_STRING: - ret = rb_ary_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_set_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) - { - tmp = rb_str_new(tmp_str, tmp_str_sz); - rb_ary_push(ret, tmp); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed set(string)"); - } - - return rb_class_new_instance(1, &ret, Set); - case HYPERDATATYPE_SET_INT64: - ret = rb_ary_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_set_int_next(&iter, &tmp_i)) > 0) - { - tmp = LL2NUM(tmp_i); - rb_ary_push(ret, tmp); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed set(int)"); - } - - return rb_class_new_instance(1, &ret, Set); - case HYPERDATATYPE_SET_FLOAT: - ret = rb_ary_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_set_float_next(&iter, &tmp_d)) > 0) - { - tmp = rb_float_new(tmp_d); - rb_ary_push(ret, tmp); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed set(float)"); - } - - return rb_class_new_instance(1, &ret, Set); - case HYPERDATATYPE_MAP_STRING_STRING: - ret = rb_hash_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_map_string_string_next(&iter, &tmp_str, &tmp_str_sz, &tmp_str2, &tmp_str2_sz)) > 0) - { - tmp = rb_str_new(tmp_str, tmp_str_sz); - tmp2 = rb_str_new(tmp_str2, tmp_str2_sz); - rb_hash_aset(ret, tmp, tmp2); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(string, string)"); - } - - return ret; - case HYPERDATATYPE_MAP_STRING_INT64: - ret = rb_hash_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_map_string_int_next(&iter, &tmp_str, &tmp_str_sz, &tmp_i)) > 0) - { - tmp = rb_str_new(tmp_str, tmp_str_sz); - tmp2 = LL2NUM(tmp_i); - rb_hash_aset(ret, tmp, tmp2); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(string, int)"); - } - - return ret; - case HYPERDATATYPE_MAP_STRING_FLOAT: - ret = rb_hash_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_map_string_float_next(&iter, &tmp_str, &tmp_str_sz, &tmp_d)) > 0) - { - tmp = rb_str_new(tmp_str, tmp_str_sz); - tmp2 = rb_float_new(tmp_d); - rb_hash_aset(ret, tmp, tmp2); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(string, float)"); - } - - return ret; - case HYPERDATATYPE_MAP_INT64_STRING: - ret = rb_hash_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_map_int_string_next(&iter, &tmp_i, &tmp_str, &tmp_str_sz)) > 0) - { - tmp = LL2NUM(tmp_i); - tmp2 = rb_str_new(tmp_str, tmp_str_sz); - rb_hash_aset(ret, tmp, tmp2); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(int, string)"); - } - - return ret; - case HYPERDATATYPE_MAP_INT64_INT64: - ret = rb_hash_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_map_int_int_next(&iter, &tmp_i, &tmp_i2)) > 0) - { - tmp = LL2NUM(tmp_i); - tmp2 = LL2NUM(tmp_i2); - rb_hash_aset(ret, tmp, tmp2); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(int, int)"); - } - - return ret; - case HYPERDATATYPE_MAP_INT64_FLOAT: - ret = rb_hash_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_map_int_float_next(&iter, &tmp_i, &tmp_d)) > 0) - { - tmp = LL2NUM(tmp_i); - tmp2 = rb_float_new(tmp_d); - rb_hash_aset(ret, tmp, tmp2); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(int, float)"); - } - - return ret; - case HYPERDATATYPE_MAP_FLOAT_STRING: - ret = rb_hash_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_map_float_string_next(&iter, &tmp_d, &tmp_str, &tmp_str_sz)) > 0) - { - tmp = rb_float_new(tmp_d); - tmp2 = rb_str_new(tmp_str, tmp_str_sz); - rb_hash_aset(ret, tmp, tmp2); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(float, string)"); - } - - return ret; - case HYPERDATATYPE_MAP_FLOAT_INT64: - ret = rb_hash_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_map_float_int_next(&iter, &tmp_d, &tmp_i)) > 0) - { - tmp = rb_float_new(tmp_d); - tmp2 = LL2NUM(tmp_i); - rb_hash_aset(ret, tmp, tmp2); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(float, int)"); - } - - return ret; - case HYPERDATATYPE_MAP_FLOAT_FLOAT: - ret = rb_hash_new(); - hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); - - while ((result = hyperdex_ds_iterate_map_float_float_next(&iter, &tmp_d, &tmp_d2)) > 0) - { - tmp = rb_float_new(tmp_d); - tmp2 = rb_float_new(tmp_d2); - rb_hash_aset(ret, tmp, tmp2); - } - - if (result < 0) - { - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(float, float)"); - } - - return ret; - case HYPERDATATYPE_GENERIC: - case HYPERDATATYPE_LIST_GENERIC: - case HYPERDATATYPE_SET_GENERIC: - case HYPERDATATYPE_MAP_GENERIC: - case HYPERDATATYPE_MAP_STRING_KEYONLY: - case HYPERDATATYPE_MAP_INT64_KEYONLY: - case HYPERDATATYPE_MAP_FLOAT_KEYONLY: - case HYPERDATATYPE_GARBAGE: - default: - hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed attributes"); - return Qnil; - } + struct hyperdex_ds_iterator iter; + const char *tmp_str = NULL; + size_t tmp_str_sz = 0; + const char *tmp_str2 = NULL; + size_t tmp_str2_sz = 0; + int64_t tmp_i = 0; + int64_t tmp_i2 = 0; + double tmp_d = 0; + double tmp_d2 = 0; + int result = 0; + VALUE ret = Qnil; + VALUE tmp = Qnil; + VALUE tmp2 = Qnil; + switch (attrs->datatype) + { + case HYPERDATATYPE_STRING: + return rb_str_new(attrs->value, attrs->value_sz); + case HYPERDATATYPE_INT64: + if (hyperdex_ds_unpack_int(attrs->value, attrs->value_sz, &tmp_i) < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed int"); + } + return LL2NUM(tmp_i); + case HYPERDATATYPE_FLOAT: + if (hyperdex_ds_unpack_float(attrs->value, attrs->value_sz, &tmp_d) < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed float"); + } + return rb_float_new(tmp_d); + case HYPERDATATYPE_DOCUMENT: + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_WRONGTYPE, "Ruby bindings do not support JSON objects"); + case HYPERDATATYPE_LIST_STRING: + ret = rb_ary_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_list_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) + { + tmp = rb_str_new(tmp_str, tmp_str_sz); + rb_ary_push(ret, tmp); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed list(string)"); + } + return ret; + case HYPERDATATYPE_LIST_INT64: + ret = rb_ary_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_list_int_next(&iter, &tmp_i)) > 0) + { + tmp = LL2NUM(tmp_i); + rb_ary_push(ret, tmp); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed list(int)"); + } + return ret; + case HYPERDATATYPE_LIST_FLOAT: + ret = rb_ary_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_list_float_next(&iter, &tmp_d)) > 0) + { + tmp = rb_float_new(tmp_d); + rb_ary_push(ret, tmp); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed list(float)"); + } + return ret; + case HYPERDATATYPE_SET_STRING: + ret = rb_ary_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_set_string_next(&iter, &tmp_str, &tmp_str_sz)) > 0) + { + tmp = rb_str_new(tmp_str, tmp_str_sz); + rb_ary_push(ret, tmp); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed set(string)"); + } + return rb_class_new_instance(1, &ret, Set); + case HYPERDATATYPE_SET_INT64: + ret = rb_ary_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_set_int_next(&iter, &tmp_i)) > 0) + { + tmp = LL2NUM(tmp_i); + rb_ary_push(ret, tmp); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed set(int)"); + } + return rb_class_new_instance(1, &ret, Set); + case HYPERDATATYPE_SET_FLOAT: + ret = rb_ary_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_set_float_next(&iter, &tmp_d)) > 0) + { + tmp = rb_float_new(tmp_d); + rb_ary_push(ret, tmp); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed set(float)"); + } + return rb_class_new_instance(1, &ret, Set); + case HYPERDATATYPE_MAP_STRING_STRING: + ret = rb_hash_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_map_string_string_next(&iter, &tmp_str, &tmp_str_sz, &tmp_str2, &tmp_str2_sz)) > 0) + { + tmp = rb_str_new(tmp_str, tmp_str_sz); + tmp2 = rb_str_new(tmp_str2, tmp_str2_sz); + rb_hash_aset(ret, tmp, tmp2); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(string, string)"); + } + return ret; + case HYPERDATATYPE_MAP_STRING_INT64: + ret = rb_hash_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_map_string_int_next(&iter, &tmp_str, &tmp_str_sz, &tmp_i)) > 0) + { + tmp = rb_str_new(tmp_str, tmp_str_sz); + tmp2 = LL2NUM(tmp_i); + rb_hash_aset(ret, tmp, tmp2); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(string, int)"); + } + return ret; + case HYPERDATATYPE_MAP_STRING_FLOAT: + ret = rb_hash_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_map_string_float_next(&iter, &tmp_str, &tmp_str_sz, &tmp_d)) > 0) + { + tmp = rb_str_new(tmp_str, tmp_str_sz); + tmp2 = rb_float_new(tmp_d); + rb_hash_aset(ret, tmp, tmp2); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(string, float)"); + } + return ret; + case HYPERDATATYPE_MAP_INT64_STRING: + ret = rb_hash_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_map_int_string_next(&iter, &tmp_i, &tmp_str, &tmp_str_sz)) > 0) + { + tmp = LL2NUM(tmp_i); + tmp2 = rb_str_new(tmp_str, tmp_str_sz); + rb_hash_aset(ret, tmp, tmp2); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(int, string)"); + } + return ret; + case HYPERDATATYPE_MAP_INT64_INT64: + ret = rb_hash_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_map_int_int_next(&iter, &tmp_i, &tmp_i2)) > 0) + { + tmp = LL2NUM(tmp_i); + tmp2 = LL2NUM(tmp_i2); + rb_hash_aset(ret, tmp, tmp2); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(int, int)"); + } + return ret; + case HYPERDATATYPE_MAP_INT64_FLOAT: + ret = rb_hash_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_map_int_float_next(&iter, &tmp_i, &tmp_d)) > 0) + { + tmp = LL2NUM(tmp_i); + tmp2 = rb_float_new(tmp_d); + rb_hash_aset(ret, tmp, tmp2); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(int, float)"); + } + return ret; + case HYPERDATATYPE_MAP_FLOAT_STRING: + ret = rb_hash_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_map_float_string_next(&iter, &tmp_d, &tmp_str, &tmp_str_sz)) > 0) + { + tmp = rb_float_new(tmp_d); + tmp2 = rb_str_new(tmp_str, tmp_str_sz); + rb_hash_aset(ret, tmp, tmp2); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(float, string)"); + } + return ret; + case HYPERDATATYPE_MAP_FLOAT_INT64: + ret = rb_hash_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_map_float_int_next(&iter, &tmp_d, &tmp_i)) > 0) + { + tmp = rb_float_new(tmp_d); + tmp2 = LL2NUM(tmp_i); + rb_hash_aset(ret, tmp, tmp2); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(float, int)"); + } + return ret; + case HYPERDATATYPE_MAP_FLOAT_FLOAT: + ret = rb_hash_new(); + hyperdex_ds_iterator_init(&iter, attrs->datatype, attrs->value, attrs->value_sz); + while ((result = hyperdex_ds_iterate_map_float_float_next(&iter, &tmp_d, &tmp_d2)) > 0) + { + tmp = rb_float_new(tmp_d); + tmp2 = rb_float_new(tmp_d2); + rb_hash_aset(ret, tmp, tmp2); + } + if (result < 0) + { + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed map(float, float)"); + } + return ret; + case HYPERDATATYPE_GENERIC: + case HYPERDATATYPE_LIST_GENERIC: + case HYPERDATATYPE_SET_GENERIC: + case HYPERDATATYPE_MAP_GENERIC: + case HYPERDATATYPE_MAP_STRING_KEYONLY: + case HYPERDATATYPE_MAP_INT64_KEYONLY: + case HYPERDATATYPE_MAP_FLOAT_KEYONLY: + case HYPERDATATYPE_GARBAGE: + default: + hyperdex_ruby_client_throw_exception(HYPERDEX_CLIENT_SERVERERROR, "server sent malformed attributes"); + return Qnil; + } } static VALUE -hyperdex_ruby_client_build_attributes(const struct hyperdex_client_attribute* attrs, +hyperdex_ruby_client_build_attributes(const struct hyperdex_client_attribute *attrs, size_t attrs_sz) { - VALUE ret = rb_hash_new(); - VALUE val = Qnil; - size_t i = 0; - - for (i = 0; i < attrs_sz; ++i) - { - val = hyperdex_ruby_client_build_attribute(attrs + i); - rb_hash_aset(ret, ID2SYM(rb_intern(attrs[i].attr)), val); - } - - return ret; + VALUE ret = rb_hash_new(); + VALUE val = Qnil; + size_t i = 0; + for (i = 0; i < attrs_sz; ++i) + { + val = hyperdex_ruby_client_build_attribute(attrs + i); + rb_hash_aset(ret, ID2SYM(rb_intern(attrs[i].attr)), val); + } + return ret; } /******************************* Deferred Class *******************************/ struct hyperdex_ruby_client_deferred { - VALUE client; - struct hyperdex_ds_arena* arena; - int64_t reqid; - enum hyperdex_client_returncode status; - const struct hyperdex_client_attribute* attrs; - size_t attrs_sz; - const char* description; - uint64_t count; - int finished; - VALUE (*encode_return)(struct hyperdex_ruby_client_deferred* d); + VALUE client; + struct hyperdex_ds_arena *arena; + int64_t reqid; + enum hyperdex_client_returncode status; + const struct hyperdex_client_attribute *attrs; + size_t attrs_sz; + const char *description; + uint64_t count; + int finished; + VALUE (*encode_return)(struct hyperdex_ruby_client_deferred *d); }; void -hyperdex_ruby_client_deferred_mark(struct hyperdex_ruby_client_deferred* dfrd) +hyperdex_ruby_client_deferred_mark(struct hyperdex_ruby_client_deferred *dfrd) { - if (dfrd) - { - rb_gc_mark(dfrd->client); - } + if (dfrd) + { + rb_gc_mark(dfrd->client); + } } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" void -hyperdex_ruby_client_deferred_free(struct hyperdex_ruby_client_deferred* dfrd) +hyperdex_ruby_client_deferred_free(struct hyperdex_ruby_client_deferred *dfrd) { - if (dfrd) - { - if (dfrd->arena) - { - hyperdex_ds_arena_destroy(dfrd->arena); - } - - if (dfrd->attrs) - { - hyperdex_client_destroy_attrs(dfrd->attrs, dfrd->attrs_sz); - } - - if (dfrd->description) - { - free((void*)dfrd->description); - } - - free(dfrd); - } + if (dfrd) + { + if (dfrd->arena) + { + hyperdex_ds_arena_destroy(dfrd->arena); + } + if (dfrd->attrs) + { + hyperdex_client_destroy_attrs(dfrd->attrs, dfrd->attrs_sz); + } + if (dfrd->description) + { + free((void *)dfrd->description); + } + free(dfrd); + } } #pragma GCC diagnostic pop static VALUE hyperdex_ruby_client_deferred_alloc(VALUE class) { - struct hyperdex_ruby_client_deferred* dfrd; - dfrd = malloc(sizeof(struct hyperdex_ruby_client_deferred)); - - if (!dfrd) - { - hyperdex_ruby_out_of_memory(); - return Qnil; - } - - memset(dfrd, 0, sizeof(struct hyperdex_ruby_client_deferred)); - dfrd->client = Qnil; - dfrd->arena = hyperdex_ds_arena_create(); - - if (!dfrd->arena) - { - hyperdex_ruby_out_of_memory(); - return Qnil; - } - - dfrd->reqid = -1; - dfrd->status = HYPERDEX_CLIENT_GARBAGE; - dfrd->attrs = NULL; - dfrd->attrs_sz = 0; - dfrd->description = NULL; - dfrd->count = 0; - dfrd->finished = 0; - dfrd->encode_return = NULL; - return Data_Wrap_Struct(class, hyperdex_ruby_client_deferred_mark, hyperdex_ruby_client_deferred_free, dfrd); + struct hyperdex_ruby_client_deferred *dfrd; + dfrd = malloc(sizeof(struct hyperdex_ruby_client_deferred)); + if (!dfrd) + { + hyperdex_ruby_out_of_memory(); + return Qnil; + } + memset(dfrd, 0, sizeof(struct hyperdex_ruby_client_deferred)); + dfrd->client = Qnil; + dfrd->arena = hyperdex_ds_arena_create(); + if (!dfrd->arena) + { + hyperdex_ruby_out_of_memory(); + return Qnil; + } + dfrd->reqid = -1; + dfrd->status = HYPERDEX_CLIENT_GARBAGE; + dfrd->attrs = NULL; + dfrd->attrs_sz = 0; + dfrd->description = NULL; + dfrd->count = 0; + dfrd->finished = 0; + dfrd->encode_return = NULL; + return Data_Wrap_Struct(class, hyperdex_ruby_client_deferred_mark, hyperdex_ruby_client_deferred_free, dfrd); } static VALUE hyperdex_ruby_client_deferred_init(VALUE self, VALUE client) { - struct hyperdex_ruby_client_deferred* dfrd = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_deferred, dfrd); - dfrd->client = client; - return self; + struct hyperdex_ruby_client_deferred *dfrd = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_deferred, dfrd); + dfrd->client = client; + return self; } static VALUE hyperdex_ruby_client_deferred_callback(VALUE self) { - VALUE ops; - struct hyperdex_ruby_client_deferred* dfrd = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_deferred, dfrd); - dfrd->finished = 1; - ops = rb_iv_get(dfrd->client, "ops"); - rb_hash_delete(ops, INT2NUM(dfrd->reqid)); - return Qnil; + VALUE ops; + struct hyperdex_ruby_client_deferred *dfrd = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_deferred, dfrd); + dfrd->finished = 1; + ops = rb_iv_get(dfrd->client, "ops"); + rb_hash_delete(ops, INT2NUM(dfrd->reqid)); + return Qnil; } static VALUE hyperdex_ruby_client_deferred_wait(VALUE self) { - struct hyperdex_ruby_client_deferred* dfrd = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_deferred, dfrd); - - while (!dfrd->finished && dfrd->reqid >= 0) - { - rb_funcall(dfrd->client, rb_intern("loop"), 0); - } - - dfrd->finished = 1; - assert(dfrd->encode_return); - return dfrd->encode_return(dfrd); + struct hyperdex_ruby_client_deferred *dfrd = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_deferred, dfrd); + while (!dfrd->finished && dfrd->reqid >= 0) + { + rb_funcall(dfrd->client, rb_intern("loop"), 0); + } + dfrd->finished = 1; + assert(dfrd->encode_return); + return dfrd->encode_return(dfrd); } static VALUE -hyperdex_ruby_client_deferred_encode_status(struct hyperdex_ruby_client_deferred* d) +hyperdex_ruby_client_deferred_encode_status(struct hyperdex_ruby_client_deferred *d) { - struct hyperdex_client* client = NULL; - - if (d->status == HYPERDEX_CLIENT_SUCCESS) - { - return Qtrue; - } - else if (d->status == HYPERDEX_CLIENT_NOTFOUND) - { - return Qnil; - } - else if (d->status == HYPERDEX_CLIENT_CMPFAIL) - { - return Qfalse; - } - else - { - Data_Get_Struct(d->client, struct hyperdex_client, client); - hyperdex_ruby_client_throw_exception(d->status, hyperdex_client_error_message(client)); - return Qnil; - } + struct hyperdex_client *client = NULL; + if (d->status == HYPERDEX_CLIENT_SUCCESS) + { + return Qtrue; + } + else if (d->status == HYPERDEX_CLIENT_NOTFOUND) + { + return Qnil; + } + else if (d->status == HYPERDEX_CLIENT_CMPFAIL) + { + return Qfalse; + } + else + { + Data_Get_Struct(d->client, struct hyperdex_client, client); + hyperdex_ruby_client_throw_exception(d->status, hyperdex_client_error_message(client)); + return Qnil; + } } static VALUE -hyperdex_ruby_client_deferred_encode_status_attributes(struct hyperdex_ruby_client_deferred* d) +hyperdex_ruby_client_deferred_encode_status_attributes(struct hyperdex_ruby_client_deferred *d) { - struct hyperdex_client* client = NULL; - - if (d->status == HYPERDEX_CLIENT_SUCCESS) - { - return hyperdex_ruby_client_build_attributes(d->attrs, d->attrs_sz); - } - else if (d->status == HYPERDEX_CLIENT_NOTFOUND) - { - return Qnil; - } - else if (d->status == HYPERDEX_CLIENT_CMPFAIL) - { - return Qfalse; - } - else - { - Data_Get_Struct(d->client, struct hyperdex_client, client); - hyperdex_ruby_client_throw_exception(d->status, hyperdex_client_error_message(client)); - return Qnil; - } + struct hyperdex_client *client = NULL; + if (d->status == HYPERDEX_CLIENT_SUCCESS) + { + return hyperdex_ruby_client_build_attributes(d->attrs, d->attrs_sz); + } + else if (d->status == HYPERDEX_CLIENT_NOTFOUND) + { + return Qnil; + } + else if (d->status == HYPERDEX_CLIENT_CMPFAIL) + { + return Qfalse; + } + else + { + Data_Get_Struct(d->client, struct hyperdex_client, client); + hyperdex_ruby_client_throw_exception(d->status, hyperdex_client_error_message(client)); + return Qnil; + } } static VALUE -hyperdex_ruby_client_deferred_encode_status_count(struct hyperdex_ruby_client_deferred* d) +hyperdex_ruby_client_deferred_encode_status_count(struct hyperdex_ruby_client_deferred *d) { - struct hyperdex_client* client = NULL; - - if (d->status == HYPERDEX_CLIENT_SUCCESS) - { - return INT2NUM(d->count); - } - else if (d->status == HYPERDEX_CLIENT_NOTFOUND) - { - return Qnil; - } - else if (d->status == HYPERDEX_CLIENT_CMPFAIL) - { - return Qfalse; - } - else - { - Data_Get_Struct(d->client, struct hyperdex_client, client); - hyperdex_ruby_client_throw_exception(d->status, hyperdex_client_error_message(client)); - return Qnil; - } + struct hyperdex_client *client = NULL; + if (d->status == HYPERDEX_CLIENT_SUCCESS) + { + return INT2NUM(d->count); + } + else if (d->status == HYPERDEX_CLIENT_NOTFOUND) + { + return Qnil; + } + else if (d->status == HYPERDEX_CLIENT_CMPFAIL) + { + return Qfalse; + } + else + { + Data_Get_Struct(d->client, struct hyperdex_client, client); + hyperdex_ruby_client_throw_exception(d->status, hyperdex_client_error_message(client)); + return Qnil; + } } static VALUE -hyperdex_ruby_client_deferred_encode_status_description(struct hyperdex_ruby_client_deferred* d) +hyperdex_ruby_client_deferred_encode_status_description(struct hyperdex_ruby_client_deferred *d) { - struct hyperdex_client* client = NULL; - - if (d->status == HYPERDEX_CLIENT_SUCCESS) - { - return rb_str_new2(d->description); - } - else if (d->status == HYPERDEX_CLIENT_NOTFOUND) - { - return Qnil; - } - else if (d->status == HYPERDEX_CLIENT_CMPFAIL) - { - return Qfalse; - } - else - { - Data_Get_Struct(d->client, struct hyperdex_client, client); - hyperdex_ruby_client_throw_exception(d->status, hyperdex_client_error_message(client)); - return Qnil; - } + struct hyperdex_client *client = NULL; + if (d->status == HYPERDEX_CLIENT_SUCCESS) + { + return rb_str_new2(d->description); + } + else if (d->status == HYPERDEX_CLIENT_NOTFOUND) + { + return Qnil; + } + else if (d->status == HYPERDEX_CLIENT_CMPFAIL) + { + return Qfalse; + } + else + { + Data_Get_Struct(d->client, struct hyperdex_client, client); + hyperdex_ruby_client_throw_exception(d->status, hyperdex_client_error_message(client)); + return Qnil; + } } /******************************* Iterator Class *******************************/ struct hyperdex_ruby_client_iterator { - VALUE client; - VALUE backlogged; - struct hyperdex_ds_arena* arena; - int64_t reqid; - enum hyperdex_client_returncode status; - const struct hyperdex_client_attribute* attrs; - size_t attrs_sz; - int finished; - VALUE (*encode_return)(struct hyperdex_ruby_client_iterator* d); + VALUE client; + VALUE backlogged; + struct hyperdex_ds_arena *arena; + int64_t reqid; + enum hyperdex_client_returncode status; + const struct hyperdex_client_attribute *attrs; + size_t attrs_sz; + int finished; + VALUE (*encode_return)(struct hyperdex_ruby_client_iterator *d); }; void -hyperdex_ruby_client_iterator_mark(struct hyperdex_ruby_client_iterator* iter) +hyperdex_ruby_client_iterator_mark(struct hyperdex_ruby_client_iterator *iter) { - if (iter) - { - rb_gc_mark(iter->client); - } + if (iter) + { + rb_gc_mark(iter->client); + } } void -hyperdex_ruby_client_iterator_free(struct hyperdex_ruby_client_iterator* iter) +hyperdex_ruby_client_iterator_free(struct hyperdex_ruby_client_iterator *iter) { - if (iter) - { - if (iter->arena) - { - hyperdex_ds_arena_destroy(iter->arena); - } - - if (iter->attrs) - { - hyperdex_client_destroy_attrs(iter->attrs, iter->attrs_sz); - } - - free(iter); - } + if (iter) + { + if (iter->arena) + { + hyperdex_ds_arena_destroy(iter->arena); + } + if (iter->attrs) + { + hyperdex_client_destroy_attrs(iter->attrs, iter->attrs_sz); + } + free(iter); + } } static VALUE hyperdex_ruby_client_iterator_alloc(VALUE class) { - struct hyperdex_ruby_client_iterator* iter; - iter = malloc(sizeof(struct hyperdex_ruby_client_iterator)); - - if (!iter) - { - hyperdex_ruby_out_of_memory(); - return Qnil; - } - - memset(iter, 0, sizeof(struct hyperdex_ruby_client_iterator)); - iter->client = Qnil; - iter->backlogged = rb_ary_new(); - iter->arena = hyperdex_ds_arena_create(); - - if (!iter->arena) - { - hyperdex_ruby_out_of_memory(); - return Qnil; - } - - iter->reqid = -1; - iter->status = HYPERDEX_CLIENT_GARBAGE; - iter->attrs = NULL; - iter->attrs_sz = 0; - iter->encode_return = NULL; - return Data_Wrap_Struct(class, hyperdex_ruby_client_iterator_mark, hyperdex_ruby_client_iterator_free, iter); + struct hyperdex_ruby_client_iterator *iter; + iter = malloc(sizeof(struct hyperdex_ruby_client_iterator)); + if (!iter) + { + hyperdex_ruby_out_of_memory(); + return Qnil; + } + memset(iter, 0, sizeof(struct hyperdex_ruby_client_iterator)); + iter->client = Qnil; + iter->backlogged = rb_ary_new(); + iter->arena = hyperdex_ds_arena_create(); + if (!iter->arena) + { + hyperdex_ruby_out_of_memory(); + return Qnil; + } + iter->reqid = -1; + iter->status = HYPERDEX_CLIENT_GARBAGE; + iter->attrs = NULL; + iter->attrs_sz = 0; + iter->encode_return = NULL; + return Data_Wrap_Struct(class, hyperdex_ruby_client_iterator_mark, hyperdex_ruby_client_iterator_free, iter); } static VALUE hyperdex_ruby_client_iterator_init(VALUE self, VALUE client) { - struct hyperdex_ruby_client_iterator* iter = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_iterator, iter); - iter->client = client; - return self; + struct hyperdex_ruby_client_iterator *iter = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_iterator, iter); + iter->client = client; + return self; } static VALUE hyperdex_ruby_client_iterator_callback(VALUE self) { - VALUE ops; - VALUE obj; - struct hyperdex_ruby_client_iterator* iter = NULL; - struct hyperdex_client* client; - Data_Get_Struct(self, struct hyperdex_ruby_client_iterator, iter); - Data_Get_Struct(iter->client, struct hyperdex_client, client); - - if (iter->status == HYPERDEX_CLIENT_SEARCHDONE) - { - iter->finished = 1; - ops = rb_iv_get(iter->client, "ops"); - rb_hash_delete(ops, INT2NUM(iter->reqid)); - } - else if (iter->status == HYPERDEX_CLIENT_SUCCESS) - { - obj = iter->encode_return(iter); - hyperdex_client_destroy_attrs(iter->attrs, iter->attrs_sz); - iter->attrs = NULL; - iter->attrs_sz = 0; - rb_ary_push(iter->backlogged, obj); - } - else - { - obj = hyperdex_ruby_client_create_exception(iter->status, - hyperdex_client_error_message(client)); - rb_ary_push(iter->backlogged, obj); - } - - return Qnil; + VALUE ops; + VALUE obj; + struct hyperdex_ruby_client_iterator *iter = NULL; + struct hyperdex_client *client; + Data_Get_Struct(self, struct hyperdex_ruby_client_iterator, iter); + Data_Get_Struct(iter->client, struct hyperdex_client, client); + if (iter->status == HYPERDEX_CLIENT_SEARCHDONE) + { + iter->finished = 1; + ops = rb_iv_get(iter->client, "ops"); + rb_hash_delete(ops, INT2NUM(iter->reqid)); + } + else if (iter->status == HYPERDEX_CLIENT_SUCCESS) + { + obj = iter->encode_return(iter); + hyperdex_client_destroy_attrs(iter->attrs, iter->attrs_sz); + iter->attrs = NULL; + iter->attrs_sz = 0; + rb_ary_push(iter->backlogged, obj); + } + else + { + obj = hyperdex_ruby_client_create_exception(iter->status, + hyperdex_client_error_message(client)); + rb_ary_push(iter->backlogged, obj); + } + return Qnil; } static VALUE hyperdex_ruby_client_iterator_has_next(VALUE self) { - struct hyperdex_ruby_client_iterator* iter = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_iterator, iter); - - while (!iter->finished && RARRAY_LEN(iter->backlogged) == 0) - { - rb_funcall(iter->client, rb_intern("loop"), 0); - } - - return RARRAY_LEN(iter->backlogged) > 0 ? Qtrue : Qfalse; + struct hyperdex_ruby_client_iterator *iter = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_iterator, iter); + while (!iter->finished && RARRAY_LEN(iter->backlogged) == 0) + { + rb_funcall(iter->client, rb_intern("loop"), 0); + } + return RARRAY_LEN(iter->backlogged) > 0 ? Qtrue : Qfalse; } static VALUE hyperdex_ruby_client_iterator_next(VALUE self) { - struct hyperdex_ruby_client_iterator* iter = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_iterator, iter); - return rb_ary_shift(iter->backlogged); + struct hyperdex_ruby_client_iterator *iter = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_iterator, iter); + return rb_ary_shift(iter->backlogged); } static VALUE -hyperdex_ruby_client_iterator_encode_status_attributes(struct hyperdex_ruby_client_iterator* it) +hyperdex_ruby_client_iterator_encode_status_attributes(struct hyperdex_ruby_client_iterator *it) { - struct hyperdex_client* client = NULL; - - if (it->status == HYPERDEX_CLIENT_SUCCESS) - { - return hyperdex_ruby_client_build_attributes(it->attrs, it->attrs_sz); - } - else if (it->status == HYPERDEX_CLIENT_NOTFOUND) - { - return Qnil; - } - else if (it->status == HYPERDEX_CLIENT_CMPFAIL) - { - return Qfalse; - } - else - { - Data_Get_Struct(it->client, struct hyperdex_client, client); - hyperdex_ruby_client_throw_exception(it->status, hyperdex_client_error_message(client)); - return Qnil; - } + struct hyperdex_client *client = NULL; + if (it->status == HYPERDEX_CLIENT_SUCCESS) + { + return hyperdex_ruby_client_build_attributes(it->attrs, it->attrs_sz); + } + else if (it->status == HYPERDEX_CLIENT_NOTFOUND) + { + return Qnil; + } + else if (it->status == HYPERDEX_CLIENT_CMPFAIL) + { + return Qfalse; + } + else + { + Data_Get_Struct(it->client, struct hyperdex_client, client); + hyperdex_ruby_client_throw_exception(it->status, hyperdex_client_error_message(client)); + return Qnil; + } } /******************************** Client Class ********************************/ @@ -1433,65 +1302,60 @@ hyperdex_ruby_client_iterator_encode_status_attributes(struct hyperdex_ruby_clie static VALUE hyperdex_ruby_client_alloc(VALUE class) { - struct hyperdex_client* client = NULL; - return Data_Wrap_Struct(class, 0, hyperdex_client_destroy, client); + struct hyperdex_client *client = NULL; + return Data_Wrap_Struct(class, 0, hyperdex_client_destroy, client); } static VALUE hyperdex_ruby_client_init(VALUE self, VALUE host, VALUE port) { - VALUE ops; - struct hyperdex_client* client = NULL; - client = hyperdex_client_create(StringValueCStr(host), NUM2UINT(port)); - - if (!client) - { - rb_raise(rb_eSystemCallError, "Could not create Client instance"); - return Qnil; - } - - DATA_PTR(self) = client; - ops = rb_hash_new(); - if (ops == Qnil) return Qnil; - rb_iv_set(self, "ops", ops); - rb_iv_set(self, "tmp", Qnil); - return self; + VALUE ops; + struct hyperdex_client *client = NULL; + client = hyperdex_client_create(StringValueCStr(host), NUM2UINT(port)); + if (!client) + { + rb_raise(rb_eSystemCallError, "Could not create Client instance"); + return Qnil; + } + DATA_PTR(self) = client; + ops = rb_hash_new(); + if (ops == Qnil) return Qnil; + rb_iv_set(self, "ops", ops); + rb_iv_set(self, "tmp", Qnil); + return self; } static VALUE hyperdex_ruby_client_loop(int argc, VALUE *argv, VALUE self) { - struct hyperdex_client* client; - enum hyperdex_client_returncode rc; - int64_t ret; - VALUE ops; - VALUE op; - VALUE timeout; - - rb_scan_args(argc, argv, "01", &timeout); - if (NIL_P(timeout)) { - timeout = INT2NUM(-1); - } - - Data_Get_Struct(self, struct hyperdex_client, client); - ret = hyperdex_client_loop(client, NUM2INT(timeout), &rc); - - if (ret < 0) - { - if (rc != HYPERDEX_CLIENT_TIMEOUT) - { - hyperdex_ruby_client_throw_exception(rc, hyperdex_client_error_message(client)); - } - - return Qnil; - } - else - { - ops = rb_iv_get(self, "ops"); - op = rb_hash_lookup(ops, LONG2NUM(ret)); - rb_funcall(op, rb_intern("callback"), 0); - return op; - } + struct hyperdex_client *client; + enum hyperdex_client_returncode rc; + int64_t ret; + VALUE ops; + VALUE op; + VALUE timeout; + rb_scan_args(argc, argv, "01", &timeout); + if (NIL_P(timeout)) + { + timeout = INT2NUM(-1); + } + Data_Get_Struct(self, struct hyperdex_client, client); + ret = hyperdex_client_loop(client, NUM2INT(timeout), &rc); + if (ret < 0) + { + if (rc != HYPERDEX_CLIENT_TIMEOUT) + { + hyperdex_ruby_client_throw_exception(rc, hyperdex_client_error_message(client)); + } + return Qnil; + } + else + { + ops = rb_iv_get(self, "ops"); + op = rb_hash_lookup(ops, LONG2NUM(ret)); + rb_funcall(op, rb_intern("callback"), 0); + return op; + } } #include "bindings/ruby/definitions.c" @@ -1499,179 +1363,173 @@ hyperdex_ruby_client_loop(int argc, VALUE *argv, VALUE self) /********************************* Predicates *********************************/ static void -hyperdex_ruby_client_predicate_mark(struct hyperdex_ruby_client_predicate* pred) +hyperdex_ruby_client_predicate_mark(struct hyperdex_ruby_client_predicate *pred) { - size_t i = 0; - - if (!pred) - { - return; - } - - for (i = 0; i < pred->num_checks; ++i) - { - rb_gc_mark(pred->checks[i].v); - } + size_t i = 0; + if (!pred) + { + return; + } + for (i = 0; i < pred->num_checks; ++i) + { + rb_gc_mark(pred->checks[i].v); + } } static VALUE hyperdex_ruby_client_predicate_alloc1(VALUE class) { - struct hyperdex_ruby_client_predicate* pred = NULL; - size_t sz = offsetof(struct hyperdex_ruby_client_predicate, checks) - + sizeof(struct hyperdex_ruby_client_predicate_inner); - pred = malloc(sz); - - if (!pred) - { - hyperdex_ruby_out_of_memory(); - return Qnil; - } - - memset(pred, 0, sz); - pred->num_checks = 1; - return Data_Wrap_Struct(class, hyperdex_ruby_client_predicate_mark, free, pred); + struct hyperdex_ruby_client_predicate *pred = NULL; + size_t sz = offsetof(struct hyperdex_ruby_client_predicate, checks) + + sizeof(struct hyperdex_ruby_client_predicate_inner); + pred = malloc(sz); + if (!pred) + { + hyperdex_ruby_out_of_memory(); + return Qnil; + } + memset(pred, 0, sz); + pred->num_checks = 1; + return Data_Wrap_Struct(class, hyperdex_ruby_client_predicate_mark, free, pred); } static VALUE hyperdex_ruby_client_predicate_alloc2(VALUE class) { - struct hyperdex_ruby_client_predicate* pred = NULL; - size_t sz = offsetof(struct hyperdex_ruby_client_predicate, checks) - + 2 * sizeof(struct hyperdex_ruby_client_predicate_inner); - pred = malloc(sz); - - if (!pred) - { - hyperdex_ruby_out_of_memory(); - return Qnil; - } - - memset(pred, 0, sz); - pred->num_checks = 2; - return Data_Wrap_Struct(class, hyperdex_ruby_client_predicate_mark, free, pred); + struct hyperdex_ruby_client_predicate *pred = NULL; + size_t sz = offsetof(struct hyperdex_ruby_client_predicate, checks) + + 2 * sizeof(struct hyperdex_ruby_client_predicate_inner); + pred = malloc(sz); + if (!pred) + { + hyperdex_ruby_out_of_memory(); + return Qnil; + } + memset(pred, 0, sz); + pred->num_checks = 2; + return Data_Wrap_Struct(class, hyperdex_ruby_client_predicate_mark, free, pred); } static VALUE hyperdex_ruby_client_predicate_init(VALUE self) { - struct hyperdex_ruby_client_predicate* pred = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); - pred->checks[0].v = Qnil; - pred->checks[0].predicate = HYPERPREDICATE_FAIL; - return self; + struct hyperdex_ruby_client_predicate *pred = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); + pred->checks[0].v = Qnil; + pred->checks[0].predicate = HYPERPREDICATE_FAIL; + return self; } static VALUE hyperdex_ruby_client_predicate_equals_init(VALUE self, VALUE v) { - struct hyperdex_ruby_client_predicate* pred = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); - pred->checks[0].v = v; - pred->checks[0].predicate = HYPERPREDICATE_EQUALS; - return self; + struct hyperdex_ruby_client_predicate *pred = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); + pred->checks[0].v = v; + pred->checks[0].predicate = HYPERPREDICATE_EQUALS; + return self; } static VALUE hyperdex_ruby_client_predicate_lessequal_init(VALUE self, VALUE v) { - struct hyperdex_ruby_client_predicate* pred = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); - pred->checks[0].v = v; - pred->checks[0].predicate = HYPERPREDICATE_LESS_EQUAL; - return self; + struct hyperdex_ruby_client_predicate *pred = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); + pred->checks[0].v = v; + pred->checks[0].predicate = HYPERPREDICATE_LESS_EQUAL; + return self; } static VALUE hyperdex_ruby_client_predicate_greaterequal_init(VALUE self, VALUE v) { - struct hyperdex_ruby_client_predicate* pred = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); - pred->checks[0].v = v; - pred->checks[0].predicate = HYPERPREDICATE_GREATER_EQUAL; - return self; + struct hyperdex_ruby_client_predicate *pred = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); + pred->checks[0].v = v; + pred->checks[0].predicate = HYPERPREDICATE_GREATER_EQUAL; + return self; } static VALUE hyperdex_ruby_client_predicate_lessthan_init(VALUE self, VALUE v) { - struct hyperdex_ruby_client_predicate* pred = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); - pred->checks[0].v = v; - pred->checks[0].predicate = HYPERPREDICATE_LESS_THAN; - return self; + struct hyperdex_ruby_client_predicate *pred = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); + pred->checks[0].v = v; + pred->checks[0].predicate = HYPERPREDICATE_LESS_THAN; + return self; } static VALUE hyperdex_ruby_client_predicate_greaterthan_init(VALUE self, VALUE v) { - struct hyperdex_ruby_client_predicate* pred = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); - pred->checks[0].v = v; - pred->checks[0].predicate = HYPERPREDICATE_GREATER_THAN; - return self; + struct hyperdex_ruby_client_predicate *pred = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); + pred->checks[0].v = v; + pred->checks[0].predicate = HYPERPREDICATE_GREATER_THAN; + return self; } static VALUE hyperdex_ruby_client_predicate_range_init(VALUE self, VALUE lower, VALUE upper) { - struct hyperdex_ruby_client_predicate* pred = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); - pred->checks[0].v = lower; - pred->checks[0].predicate = HYPERPREDICATE_GREATER_EQUAL; - pred->checks[1].v = upper; - pred->checks[1].predicate = HYPERPREDICATE_LESS_EQUAL; - return self; + struct hyperdex_ruby_client_predicate *pred = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); + pred->checks[0].v = lower; + pred->checks[0].predicate = HYPERPREDICATE_GREATER_EQUAL; + pred->checks[1].v = upper; + pred->checks[1].predicate = HYPERPREDICATE_LESS_EQUAL; + return self; } static VALUE hyperdex_ruby_client_predicate_regex_init(VALUE self, VALUE v) { - struct hyperdex_ruby_client_predicate* pred = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); - pred->checks[0].v = v; - pred->checks[0].predicate = HYPERPREDICATE_REGEX; - return self; + struct hyperdex_ruby_client_predicate *pred = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); + pred->checks[0].v = v; + pred->checks[0].predicate = HYPERPREDICATE_REGEX; + return self; } static VALUE hyperdex_ruby_client_predicate_lengthequals_init(VALUE self, VALUE v) { - struct hyperdex_ruby_client_predicate* pred = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); - pred->checks[0].v = v; - pred->checks[0].predicate = HYPERPREDICATE_LENGTH_EQUALS; - return self; + struct hyperdex_ruby_client_predicate *pred = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); + pred->checks[0].v = v; + pred->checks[0].predicate = HYPERPREDICATE_LENGTH_EQUALS; + return self; } static VALUE hyperdex_ruby_client_predicate_lengthlessequal_init(VALUE self, VALUE v) { - struct hyperdex_ruby_client_predicate* pred = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); - pred->checks[0].v = v; - pred->checks[0].predicate = HYPERPREDICATE_LENGTH_LESS_EQUAL; - return self; + struct hyperdex_ruby_client_predicate *pred = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); + pred->checks[0].v = v; + pred->checks[0].predicate = HYPERPREDICATE_LENGTH_LESS_EQUAL; + return self; } static VALUE hyperdex_ruby_client_predicate_lengthgreaterequal_init(VALUE self, VALUE v) { - struct hyperdex_ruby_client_predicate* pred = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); - pred->checks[0].v = v; - pred->checks[0].predicate = HYPERPREDICATE_LENGTH_GREATER_EQUAL; - return self; + struct hyperdex_ruby_client_predicate *pred = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); + pred->checks[0].v = v; + pred->checks[0].predicate = HYPERPREDICATE_LENGTH_GREATER_EQUAL; + return self; } static VALUE hyperdex_ruby_client_predicate_contains_init(VALUE self, VALUE v) { - struct hyperdex_ruby_client_predicate* pred = NULL; - Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); - pred->checks[0].v = v; - pred->checks[0].predicate = HYPERPREDICATE_CONTAINS; - return self; + struct hyperdex_ruby_client_predicate *pred = NULL; + Data_Get_Struct(self, struct hyperdex_ruby_client_predicate, pred); + pred->checks[0].v = v; + pred->checks[0].predicate = HYPERPREDICATE_CONTAINS; + return self; } /******************************* Inititalization ******************************/ @@ -1679,99 +1537,81 @@ hyperdex_ruby_client_predicate_contains_init(VALUE self, VALUE v) void Init_hyperdex_client() { - /* require the set type */ - rb_require("set"); - Set = rb_path2class("Set"); - - /* setup the module */ - mod_hyperdex_client = rb_define_module_under(mod_hyperdex, "Client"); - - /* create the Exception class */ - class_exception = rb_define_class_under(mod_hyperdex_client, "HyperDexClientException", rb_eStandardError); - rb_define_attr(class_exception, "status", 1, 0); - rb_define_attr(class_exception, "symbol", 1, 0); - - /* create the Deferred class */ - class_deferred = rb_define_class_under(mod_hyperdex_client, "Deferred", rb_cObject); - rb_define_alloc_func(class_deferred, hyperdex_ruby_client_deferred_alloc); - rb_define_method(class_deferred, "initialize", hyperdex_ruby_client_deferred_init, 1); - rb_define_method(class_deferred, "callback", hyperdex_ruby_client_deferred_callback, 0); - rb_define_method(class_deferred, "wait", hyperdex_ruby_client_deferred_wait, 0); - - /* create the Iterator class */ - class_iterator = rb_define_class_under(mod_hyperdex_client, "Iterator", rb_cObject); - rb_define_alloc_func(class_iterator, hyperdex_ruby_client_iterator_alloc); - rb_define_method(class_iterator, "initialize", hyperdex_ruby_client_iterator_init, 1); - rb_define_method(class_iterator, "callback", hyperdex_ruby_client_iterator_callback, 0); - rb_define_method(class_iterator, "has_next", hyperdex_ruby_client_iterator_has_next, 0); - rb_define_method(class_iterator, "next", hyperdex_ruby_client_iterator_next, 0); - - /* create the Client class */ - class_client = rb_define_class_under(mod_hyperdex_client, "Client", rb_cObject); - rb_define_alloc_func(class_client, hyperdex_ruby_client_alloc); - rb_define_method(class_client, "initialize", hyperdex_ruby_client_init, 2); - rb_define_method(class_client, "loop", hyperdex_ruby_client_loop, -1); - - /* include the generated rb_define_* calls */ + /* require the set type */ + rb_require("set"); + Set = rb_path2class("Set"); + /* setup the module */ + mod_hyperdex_client = rb_define_module_under(mod_hyperdex, "Client"); + /* create the Exception class */ + class_exception = rb_define_class_under(mod_hyperdex_client, "HyperDexClientException", rb_eStandardError); + rb_define_attr(class_exception, "status", 1, 0); + rb_define_attr(class_exception, "symbol", 1, 0); + /* create the Deferred class */ + class_deferred = rb_define_class_under(mod_hyperdex_client, "Deferred", rb_cObject); + rb_define_alloc_func(class_deferred, hyperdex_ruby_client_deferred_alloc); + rb_define_method(class_deferred, "initialize", hyperdex_ruby_client_deferred_init, 1); + rb_define_method(class_deferred, "callback", hyperdex_ruby_client_deferred_callback, 0); + rb_define_method(class_deferred, "wait", hyperdex_ruby_client_deferred_wait, 0); + /* create the Iterator class */ + class_iterator = rb_define_class_under(mod_hyperdex_client, "Iterator", rb_cObject); + rb_define_alloc_func(class_iterator, hyperdex_ruby_client_iterator_alloc); + rb_define_method(class_iterator, "initialize", hyperdex_ruby_client_iterator_init, 1); + rb_define_method(class_iterator, "callback", hyperdex_ruby_client_iterator_callback, 0); + rb_define_method(class_iterator, "has_next", hyperdex_ruby_client_iterator_has_next, 0); + rb_define_method(class_iterator, "next", hyperdex_ruby_client_iterator_next, 0); + /* create the Client class */ + class_client = rb_define_class_under(mod_hyperdex_client, "Client", rb_cObject); + rb_define_alloc_func(class_client, hyperdex_ruby_client_alloc); + rb_define_method(class_client, "initialize", hyperdex_ruby_client_init, 2); + rb_define_method(class_client, "loop", hyperdex_ruby_client_loop, -1); + /* include the generated rb_define_* calls */ #include "bindings/ruby/prototypes.c" - - /* create the Predicate class */ - class_predicate = rb_define_class_under(mod_hyperdex_client, "Predicate", rb_cObject); - rb_define_alloc_func(class_predicate, hyperdex_ruby_client_predicate_alloc1); - rb_define_method(class_predicate, "initialize", hyperdex_ruby_client_predicate_init, 1); - - /* create the Equals class */ - class_equals = rb_define_class_under(mod_hyperdex_client, "Equals", class_predicate); - rb_define_alloc_func(class_equals , hyperdex_ruby_client_predicate_alloc1); - rb_define_method(class_equals , "initialize", hyperdex_ruby_client_predicate_equals_init, 1); - - /* create the LessEqual class */ - class_lessequal = rb_define_class_under(mod_hyperdex_client, "LessEqual", class_predicate); - rb_define_alloc_func(class_lessequal , hyperdex_ruby_client_predicate_alloc1); - rb_define_method(class_lessequal , "initialize", hyperdex_ruby_client_predicate_lessequal_init, 1); - - /* create the GreaterEqual class */ - class_greaterequal = rb_define_class_under(mod_hyperdex_client, "GreaterEqual", class_predicate); - rb_define_alloc_func(class_greaterequal , hyperdex_ruby_client_predicate_alloc1); - rb_define_method(class_greaterequal , "initialize", hyperdex_ruby_client_predicate_greaterequal_init, 1); - - /* create the LessThan class */ - class_lessthan = rb_define_class_under(mod_hyperdex_client, "LessThan", class_predicate); - rb_define_alloc_func(class_lessthan , hyperdex_ruby_client_predicate_alloc1); - rb_define_method(class_lessthan , "initialize", hyperdex_ruby_client_predicate_lessthan_init, 1); - - /* create the GreaterThan class */ - class_greaterthan = rb_define_class_under(mod_hyperdex_client, "GreaterThan", class_predicate); - rb_define_alloc_func(class_greaterthan , hyperdex_ruby_client_predicate_alloc1); - rb_define_method(class_greaterthan , "initialize", hyperdex_ruby_client_predicate_greaterthan_init, 1); - - /* create the Range class */ - class_range = rb_define_class_under(mod_hyperdex_client, "Range", class_predicate); - rb_define_alloc_func(class_range , hyperdex_ruby_client_predicate_alloc2); - rb_define_method(class_range , "initialize", hyperdex_ruby_client_predicate_range_init, 2); - - /* create the Regex class */ - class_regex = rb_define_class_under(mod_hyperdex_client, "Regex", class_predicate); - rb_define_alloc_func(class_regex , hyperdex_ruby_client_predicate_alloc1); - rb_define_method(class_regex , "initialize", hyperdex_ruby_client_predicate_regex_init, 1); - - /* create the LengthEquals class */ - class_lengthequals = rb_define_class_under(mod_hyperdex_client, "LengthEquals", class_predicate); - rb_define_alloc_func(class_lengthequals , hyperdex_ruby_client_predicate_alloc1); - rb_define_method(class_lengthequals , "initialize", hyperdex_ruby_client_predicate_lengthequals_init, 1); - - /* create the LengthLessEqual class */ - class_lengthlessequal = rb_define_class_under(mod_hyperdex_client, "LengthLessEqual", class_predicate); - rb_define_alloc_func(class_lengthlessequal , hyperdex_ruby_client_predicate_alloc1); - rb_define_method(class_lengthlessequal , "initialize", hyperdex_ruby_client_predicate_lengthlessequal_init, 1); - - /* create the LengthGreaterEqual class */ - class_lengthgreaterequal = rb_define_class_under(mod_hyperdex_client, "LengthGreaterEqual", class_predicate); - rb_define_alloc_func(class_lengthgreaterequal , hyperdex_ruby_client_predicate_alloc1); - rb_define_method(class_lengthgreaterequal , "initialize", hyperdex_ruby_client_predicate_lengthgreaterequal_init, 1); - - /* create the Contains class */ - class_contains = rb_define_class_under(mod_hyperdex_client, "Contains", class_predicate); - rb_define_alloc_func(class_contains , hyperdex_ruby_client_predicate_alloc1); - rb_define_method(class_contains , "initialize", hyperdex_ruby_client_predicate_contains_init, 1); + /* create the Predicate class */ + class_predicate = rb_define_class_under(mod_hyperdex_client, "Predicate", rb_cObject); + rb_define_alloc_func(class_predicate, hyperdex_ruby_client_predicate_alloc1); + rb_define_method(class_predicate, "initialize", hyperdex_ruby_client_predicate_init, 1); + /* create the Equals class */ + class_equals = rb_define_class_under(mod_hyperdex_client, "Equals", class_predicate); + rb_define_alloc_func(class_equals , hyperdex_ruby_client_predicate_alloc1); + rb_define_method(class_equals , "initialize", hyperdex_ruby_client_predicate_equals_init, 1); + /* create the LessEqual class */ + class_lessequal = rb_define_class_under(mod_hyperdex_client, "LessEqual", class_predicate); + rb_define_alloc_func(class_lessequal , hyperdex_ruby_client_predicate_alloc1); + rb_define_method(class_lessequal , "initialize", hyperdex_ruby_client_predicate_lessequal_init, 1); + /* create the GreaterEqual class */ + class_greaterequal = rb_define_class_under(mod_hyperdex_client, "GreaterEqual", class_predicate); + rb_define_alloc_func(class_greaterequal , hyperdex_ruby_client_predicate_alloc1); + rb_define_method(class_greaterequal , "initialize", hyperdex_ruby_client_predicate_greaterequal_init, 1); + /* create the LessThan class */ + class_lessthan = rb_define_class_under(mod_hyperdex_client, "LessThan", class_predicate); + rb_define_alloc_func(class_lessthan , hyperdex_ruby_client_predicate_alloc1); + rb_define_method(class_lessthan , "initialize", hyperdex_ruby_client_predicate_lessthan_init, 1); + /* create the GreaterThan class */ + class_greaterthan = rb_define_class_under(mod_hyperdex_client, "GreaterThan", class_predicate); + rb_define_alloc_func(class_greaterthan , hyperdex_ruby_client_predicate_alloc1); + rb_define_method(class_greaterthan , "initialize", hyperdex_ruby_client_predicate_greaterthan_init, 1); + /* create the Range class */ + class_range = rb_define_class_under(mod_hyperdex_client, "Range", class_predicate); + rb_define_alloc_func(class_range , hyperdex_ruby_client_predicate_alloc2); + rb_define_method(class_range , "initialize", hyperdex_ruby_client_predicate_range_init, 2); + /* create the Regex class */ + class_regex = rb_define_class_under(mod_hyperdex_client, "Regex", class_predicate); + rb_define_alloc_func(class_regex , hyperdex_ruby_client_predicate_alloc1); + rb_define_method(class_regex , "initialize", hyperdex_ruby_client_predicate_regex_init, 1); + /* create the LengthEquals class */ + class_lengthequals = rb_define_class_under(mod_hyperdex_client, "LengthEquals", class_predicate); + rb_define_alloc_func(class_lengthequals , hyperdex_ruby_client_predicate_alloc1); + rb_define_method(class_lengthequals , "initialize", hyperdex_ruby_client_predicate_lengthequals_init, 1); + /* create the LengthLessEqual class */ + class_lengthlessequal = rb_define_class_under(mod_hyperdex_client, "LengthLessEqual", class_predicate); + rb_define_alloc_func(class_lengthlessequal , hyperdex_ruby_client_predicate_alloc1); + rb_define_method(class_lengthlessequal , "initialize", hyperdex_ruby_client_predicate_lengthlessequal_init, 1); + /* create the LengthGreaterEqual class */ + class_lengthgreaterequal = rb_define_class_under(mod_hyperdex_client, "LengthGreaterEqual", class_predicate); + rb_define_alloc_func(class_lengthgreaterequal , hyperdex_ruby_client_predicate_alloc1); + rb_define_method(class_lengthgreaterequal , "initialize", hyperdex_ruby_client_predicate_lengthgreaterequal_init, 1); + /* create the Contains class */ + class_contains = rb_define_class_under(mod_hyperdex_client, "Contains", class_predicate); + rb_define_alloc_func(class_contains , hyperdex_ruby_client_predicate_alloc1); + rb_define_method(class_contains , "initialize", hyperdex_ruby_client_predicate_contains_init, 1); } diff --git a/bindings/ruby/definitions.c b/bindings/ruby/definitions.c index a902b3b3d..ea52cffcb 100644 --- a/bindings/ruby/definitions.c +++ b/bindings/ruby/definitions.c @@ -28,1880 +28,1852 @@ /* This file is generated by bindings/ruby.py */ static VALUE -hyperdex_ruby_client_asynccall__spacename_key__status_attributes(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), VALUE self, VALUE spacename, VALUE key) -{ - VALUE op; - const char* in_space; - const char* in_key; - size_t in_key_sz; - struct hyperdex_client* client; - struct hyperdex_ruby_client_deferred* o; - op = rb_class_new_instance(1, &self, class_deferred); - rb_iv_set(self, "tmp", op); - Data_Get_Struct(self, struct hyperdex_client, client); - Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); - hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); - hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); - o->reqid = f(client, in_space, in_key, in_key_sz, &o->status, &o->attrs, &o->attrs_sz); - - if (o->reqid < 0) - { - hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); - } - - o->encode_return = hyperdex_ruby_client_deferred_encode_status_attributes; - rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); - rb_iv_set(self, "tmp", Qnil); - return op; -} - -static VALUE -hyperdex_ruby_client_asynccall__spacename_key_attributenames__status_attributes(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const char** attrnames, size_t attrnames_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), VALUE self, VALUE spacename, VALUE key, VALUE attributenames) -{ - VALUE op; - const char* in_space; - const char* in_key; - size_t in_key_sz; - const char** in_attrnames; - size_t in_attrnames_sz; - struct hyperdex_client* client; - struct hyperdex_ruby_client_deferred* o; - op = rb_class_new_instance(1, &self, class_deferred); - rb_iv_set(self, "tmp", op); - Data_Get_Struct(self, struct hyperdex_client, client); - Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); - hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); - hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); - hyperdex_ruby_client_convert_attributenames(o->arena, attributenames, &in_attrnames, &in_attrnames_sz); - o->reqid = f(client, in_space, in_key, in_key_sz, in_attrnames, in_attrnames_sz, &o->status, &o->attrs, &o->attrs_sz); - - if (o->reqid < 0) - { - hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); - } - - o->encode_return = hyperdex_ruby_client_deferred_encode_status_attributes; - rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); - rb_iv_set(self, "tmp", Qnil); - return op; -} - -static VALUE -hyperdex_ruby_client_asynccall__spacename_key_attributes__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status), VALUE self, VALUE spacename, VALUE key, VALUE attributes) -{ - VALUE op; - const char* in_space; - const char* in_key; - size_t in_key_sz; - const struct hyperdex_client_attribute* in_attrs; - size_t in_attrs_sz; - struct hyperdex_client* client; - struct hyperdex_ruby_client_deferred* o; - op = rb_class_new_instance(1, &self, class_deferred); - rb_iv_set(self, "tmp", op); - Data_Get_Struct(self, struct hyperdex_client, client); - Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); - hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); - hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); - hyperdex_ruby_client_convert_attributes(o->arena, attributes, &in_attrs, &in_attrs_sz); - o->reqid = f(client, in_space, in_key, in_key_sz, in_attrs, in_attrs_sz, &o->status); - - if (o->reqid < 0) - { - hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); - } - - o->encode_return = hyperdex_ruby_client_deferred_encode_status; - rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); - rb_iv_set(self, "tmp", Qnil); - return op; -} - -static VALUE -hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status), VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) -{ - VALUE op; - const char* in_space; - const char* in_key; - size_t in_key_sz; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - const struct hyperdex_client_attribute* in_attrs; - size_t in_attrs_sz; - struct hyperdex_client* client; - struct hyperdex_ruby_client_deferred* o; - op = rb_class_new_instance(1, &self, class_deferred); - rb_iv_set(self, "tmp", op); - Data_Get_Struct(self, struct hyperdex_client, client); - Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); - hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); - hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); - hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); - hyperdex_ruby_client_convert_attributes(o->arena, attributes, &in_attrs, &in_attrs_sz); - o->reqid = f(client, in_space, in_key, in_key_sz, in_checks, in_checks_sz, in_attrs, in_attrs_sz, &o->status); - - if (o->reqid < 0) - { - hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); - } - - o->encode_return = hyperdex_ruby_client_deferred_encode_status; - rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); - rb_iv_set(self, "tmp", Qnil); - return op; -} - -static VALUE -hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_attribute* attrs, size_t attrs_sz, enum hyperdex_client_returncode* status, uint64_t* count), VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) -{ - VALUE op; - const char* in_space; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - const struct hyperdex_client_attribute* in_attrs; - size_t in_attrs_sz; - struct hyperdex_client* client; - struct hyperdex_ruby_client_deferred* o; - op = rb_class_new_instance(1, &self, class_deferred); - rb_iv_set(self, "tmp", op); - Data_Get_Struct(self, struct hyperdex_client, client); - Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); - hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); - hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); - hyperdex_ruby_client_convert_attributes(o->arena, attributes, &in_attrs, &in_attrs_sz); - o->reqid = f(client, in_space, in_checks, in_checks_sz, in_attrs, in_attrs_sz, &o->status, &o->count); - - if (o->reqid < 0) - { - hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); - } - - o->encode_return = hyperdex_ruby_client_deferred_encode_status_count; - rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); - rb_iv_set(self, "tmp", Qnil); - return op; -} - -static VALUE -hyperdex_ruby_client_asynccall__spacename_key__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, enum hyperdex_client_returncode* status), VALUE self, VALUE spacename, VALUE key) -{ - VALUE op; - const char* in_space; - const char* in_key; - size_t in_key_sz; - struct hyperdex_client* client; - struct hyperdex_ruby_client_deferred* o; - op = rb_class_new_instance(1, &self, class_deferred); - rb_iv_set(self, "tmp", op); - Data_Get_Struct(self, struct hyperdex_client, client); - Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); - hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); - hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); - o->reqid = f(client, in_space, in_key, in_key_sz, &o->status); - - if (o->reqid < 0) - { - hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); - } - - o->encode_return = hyperdex_ruby_client_deferred_encode_status; - rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); - rb_iv_set(self, "tmp", Qnil); - return op; -} - -static VALUE -hyperdex_ruby_client_asynccall__spacename_key_predicates__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status), VALUE self, VALUE spacename, VALUE key, VALUE predicates) -{ - VALUE op; - const char* in_space; - const char* in_key; - size_t in_key_sz; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - struct hyperdex_client* client; - struct hyperdex_ruby_client_deferred* o; - op = rb_class_new_instance(1, &self, class_deferred); - rb_iv_set(self, "tmp", op); - Data_Get_Struct(self, struct hyperdex_client, client); - Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); - hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); - hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); - hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); - o->reqid = f(client, in_space, in_key, in_key_sz, in_checks, in_checks_sz, &o->status); - - if (o->reqid < 0) - { - hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); - } - - o->encode_return = hyperdex_ruby_client_deferred_encode_status; - rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); - rb_iv_set(self, "tmp", Qnil); - return op; -} - -static VALUE -hyperdex_ruby_client_asynccall__spacename_predicates__status_count(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, uint64_t* count), VALUE self, VALUE spacename, VALUE predicates) -{ - VALUE op; - const char* in_space; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - struct hyperdex_client* client; - struct hyperdex_ruby_client_deferred* o; - op = rb_class_new_instance(1, &self, class_deferred); - rb_iv_set(self, "tmp", op); - Data_Get_Struct(self, struct hyperdex_client, client); - Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); - hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); - hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); - o->reqid = f(client, in_space, in_checks, in_checks_sz, &o->status, &o->count); - - if (o->reqid < 0) - { - hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); - } - - o->encode_return = hyperdex_ruby_client_deferred_encode_status_count; - rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); - rb_iv_set(self, "tmp", Qnil); - return op; -} - -static VALUE -hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status), VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) -{ - VALUE op; - const char* in_space; - const char* in_key; - size_t in_key_sz; - const struct hyperdex_client_map_attribute* in_mapattrs; - size_t in_mapattrs_sz; - struct hyperdex_client* client; - struct hyperdex_ruby_client_deferred* o; - op = rb_class_new_instance(1, &self, class_deferred); - rb_iv_set(self, "tmp", op); - Data_Get_Struct(self, struct hyperdex_client, client); - Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); - hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); - hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); - hyperdex_ruby_client_convert_mapattributes(o->arena, mapattributes, &in_mapattrs, &in_mapattrs_sz); - o->reqid = f(client, in_space, in_key, in_key_sz, in_mapattrs, in_mapattrs_sz, &o->status); - - if (o->reqid < 0) - { - hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); - } - - o->encode_return = hyperdex_ruby_client_deferred_encode_status; - rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); - rb_iv_set(self, "tmp", Qnil); - return op; -} - -static VALUE -hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(int64_t (*f)(struct hyperdex_client* client, const char* space, const char* key, size_t key_sz, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status), VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) -{ - VALUE op; - const char* in_space; - const char* in_key; - size_t in_key_sz; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - const struct hyperdex_client_map_attribute* in_mapattrs; - size_t in_mapattrs_sz; - struct hyperdex_client* client; - struct hyperdex_ruby_client_deferred* o; - op = rb_class_new_instance(1, &self, class_deferred); - rb_iv_set(self, "tmp", op); - Data_Get_Struct(self, struct hyperdex_client, client); - Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); - hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); - hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); - hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); - hyperdex_ruby_client_convert_mapattributes(o->arena, mapattributes, &in_mapattrs, &in_mapattrs_sz); - o->reqid = f(client, in_space, in_key, in_key_sz, in_checks, in_checks_sz, in_mapattrs, in_mapattrs_sz, &o->status); - - if (o->reqid < 0) - { - hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); - } - - o->encode_return = hyperdex_ruby_client_deferred_encode_status; - rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); - rb_iv_set(self, "tmp", Qnil); - return op; -} - -static VALUE -hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode* status, uint64_t* count), VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) -{ - VALUE op; - const char* in_space; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - const struct hyperdex_client_map_attribute* in_mapattrs; - size_t in_mapattrs_sz; - struct hyperdex_client* client; - struct hyperdex_ruby_client_deferred* o; - op = rb_class_new_instance(1, &self, class_deferred); - rb_iv_set(self, "tmp", op); - Data_Get_Struct(self, struct hyperdex_client, client); - Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); - hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); - hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); - hyperdex_ruby_client_convert_mapattributes(o->arena, mapattributes, &in_mapattrs, &in_mapattrs_sz); - o->reqid = f(client, in_space, in_checks, in_checks_sz, in_mapattrs, in_mapattrs_sz, &o->status, &o->count); - - if (o->reqid < 0) - { - hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); - } - - o->encode_return = hyperdex_ruby_client_deferred_encode_status_count; - rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); - rb_iv_set(self, "tmp", Qnil); - return op; -} - -static VALUE -hyperdex_ruby_client_iterator__spacename_predicates__status_attributes(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), VALUE self, VALUE spacename, VALUE predicates) -{ - VALUE op; - const char* in_space; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - struct hyperdex_client* client; - struct hyperdex_ruby_client_iterator* o; - op = rb_class_new_instance(1, &self, class_iterator); - rb_iv_set(self, "tmp", op); - Data_Get_Struct(self, struct hyperdex_client, client); - Data_Get_Struct(op, struct hyperdex_ruby_client_iterator, o); - hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); - hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); - o->reqid = f(client, in_space, in_checks, in_checks_sz, &o->status, &o->attrs, &o->attrs_sz); - - if (o->reqid < 0) - { - hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); - } - - o->encode_return = hyperdex_ruby_client_iterator_encode_status_attributes; - rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); - rb_iv_set(self, "tmp", Qnil); - return op; -} - -static VALUE -hyperdex_ruby_client_asynccall__spacename_predicates__status_description(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, enum hyperdex_client_returncode* status, const char** description), VALUE self, VALUE spacename, VALUE predicates) -{ - VALUE op; - const char* in_space; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - struct hyperdex_client* client; - struct hyperdex_ruby_client_deferred* o; - op = rb_class_new_instance(1, &self, class_deferred); - rb_iv_set(self, "tmp", op); - Data_Get_Struct(self, struct hyperdex_client, client); - Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); - hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); - hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); - o->reqid = f(client, in_space, in_checks, in_checks_sz, &o->status, &o->description); - - if (o->reqid < 0) - { - hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); - } - - o->encode_return = hyperdex_ruby_client_deferred_encode_status_description; - rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); - rb_iv_set(self, "tmp", Qnil); - return op; -} - -static VALUE -hyperdex_ruby_client_iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(int64_t (*f)(struct hyperdex_client* client, const char* space, const struct hyperdex_client_attribute_check* checks, size_t checks_sz, const char* sort_by, uint64_t limit, int maxmin, enum hyperdex_client_returncode* status, const struct hyperdex_client_attribute** attrs, size_t* attrs_sz), VALUE self, VALUE spacename, VALUE predicates, VALUE sortby, VALUE limit, VALUE maxmin) -{ - VALUE op; - const char* in_space; - const struct hyperdex_client_attribute_check* in_checks; - size_t in_checks_sz; - const char* in_sort_by; - uint64_t in_limit; - int in_maxmin; - struct hyperdex_client* client; - struct hyperdex_ruby_client_iterator* o; - op = rb_class_new_instance(1, &self, class_iterator); - rb_iv_set(self, "tmp", op); - Data_Get_Struct(self, struct hyperdex_client, client); - Data_Get_Struct(op, struct hyperdex_ruby_client_iterator, o); - hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); - hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); - hyperdex_ruby_client_convert_sortby(o->arena, sortby, &in_sort_by); - hyperdex_ruby_client_convert_limit(o->arena, limit, &in_limit); - hyperdex_ruby_client_convert_maxmin(o->arena, maxmin, &in_maxmin); - o->reqid = f(client, in_space, in_checks, in_checks_sz, in_sort_by, in_limit, in_maxmin, &o->status, &o->attrs, &o->attrs_sz); - - if (o->reqid < 0) - { - hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); - } - - o->encode_return = hyperdex_ruby_client_iterator_encode_status_attributes; - rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); - rb_iv_set(self, "tmp", Qnil); - return op; +hyperdex_ruby_client_asynccall__spacename_key__status_attributes(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), VALUE self, VALUE spacename, VALUE key) +{ + VALUE op; + const char *in_space; + const char *in_key; + size_t in_key_sz; + struct hyperdex_client *client; + struct hyperdex_ruby_client_deferred *o; + op = rb_class_new_instance(1, &self, class_deferred); + rb_iv_set(self, "tmp", op); + Data_Get_Struct(self, struct hyperdex_client, client); + Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); + hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); + hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); + o->reqid = f(client, in_space, in_key, in_key_sz, &o->status, &o->attrs, &o->attrs_sz); + if (o->reqid < 0) + { + hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); + } + o->encode_return = hyperdex_ruby_client_deferred_encode_status_attributes; + rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); + rb_iv_set(self, "tmp", Qnil); + return op; +} + +static VALUE +hyperdex_ruby_client_asynccall__spacename_key_attributenames__status_attributes(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const char **attrnames, size_t attrnames_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), VALUE self, VALUE spacename, VALUE key, VALUE attributenames) +{ + VALUE op; + const char *in_space; + const char *in_key; + size_t in_key_sz; + const char **in_attrnames; + size_t in_attrnames_sz; + struct hyperdex_client *client; + struct hyperdex_ruby_client_deferred *o; + op = rb_class_new_instance(1, &self, class_deferred); + rb_iv_set(self, "tmp", op); + Data_Get_Struct(self, struct hyperdex_client, client); + Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); + hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); + hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); + hyperdex_ruby_client_convert_attributenames(o->arena, attributenames, &in_attrnames, &in_attrnames_sz); + o->reqid = f(client, in_space, in_key, in_key_sz, in_attrnames, in_attrnames_sz, &o->status, &o->attrs, &o->attrs_sz); + if (o->reqid < 0) + { + hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); + } + o->encode_return = hyperdex_ruby_client_deferred_encode_status_attributes; + rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); + rb_iv_set(self, "tmp", Qnil); + return op; +} + +static VALUE +hyperdex_ruby_client_asynccall__spacename_key_attributes__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status), VALUE self, VALUE spacename, VALUE key, VALUE attributes) +{ + VALUE op; + const char *in_space; + const char *in_key; + size_t in_key_sz; + const struct hyperdex_client_attribute *in_attrs; + size_t in_attrs_sz; + struct hyperdex_client *client; + struct hyperdex_ruby_client_deferred *o; + op = rb_class_new_instance(1, &self, class_deferred); + rb_iv_set(self, "tmp", op); + Data_Get_Struct(self, struct hyperdex_client, client); + Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); + hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); + hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); + hyperdex_ruby_client_convert_attributes(o->arena, attributes, &in_attrs, &in_attrs_sz); + o->reqid = f(client, in_space, in_key, in_key_sz, in_attrs, in_attrs_sz, &o->status); + if (o->reqid < 0) + { + hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); + } + o->encode_return = hyperdex_ruby_client_deferred_encode_status; + rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); + rb_iv_set(self, "tmp", Qnil); + return op; +} + +static VALUE +hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status), VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) +{ + VALUE op; + const char *in_space; + const char *in_key; + size_t in_key_sz; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + const struct hyperdex_client_attribute *in_attrs; + size_t in_attrs_sz; + struct hyperdex_client *client; + struct hyperdex_ruby_client_deferred *o; + op = rb_class_new_instance(1, &self, class_deferred); + rb_iv_set(self, "tmp", op); + Data_Get_Struct(self, struct hyperdex_client, client); + Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); + hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); + hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); + hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); + hyperdex_ruby_client_convert_attributes(o->arena, attributes, &in_attrs, &in_attrs_sz); + o->reqid = f(client, in_space, in_key, in_key_sz, in_checks, in_checks_sz, in_attrs, in_attrs_sz, &o->status); + if (o->reqid < 0) + { + hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); + } + o->encode_return = hyperdex_ruby_client_deferred_encode_status; + rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); + rb_iv_set(self, "tmp", Qnil); + return op; +} + +static VALUE +hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_attribute *attrs, size_t attrs_sz, enum hyperdex_client_returncode *status, uint64_t *count), VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) +{ + VALUE op; + const char *in_space; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + const struct hyperdex_client_attribute *in_attrs; + size_t in_attrs_sz; + struct hyperdex_client *client; + struct hyperdex_ruby_client_deferred *o; + op = rb_class_new_instance(1, &self, class_deferred); + rb_iv_set(self, "tmp", op); + Data_Get_Struct(self, struct hyperdex_client, client); + Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); + hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); + hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); + hyperdex_ruby_client_convert_attributes(o->arena, attributes, &in_attrs, &in_attrs_sz); + o->reqid = f(client, in_space, in_checks, in_checks_sz, in_attrs, in_attrs_sz, &o->status, &o->count); + if (o->reqid < 0) + { + hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); + } + o->encode_return = hyperdex_ruby_client_deferred_encode_status_count; + rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); + rb_iv_set(self, "tmp", Qnil); + return op; +} + +static VALUE +hyperdex_ruby_client_asynccall__spacename_key__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, enum hyperdex_client_returncode *status), VALUE self, VALUE spacename, VALUE key) +{ + VALUE op; + const char *in_space; + const char *in_key; + size_t in_key_sz; + struct hyperdex_client *client; + struct hyperdex_ruby_client_deferred *o; + op = rb_class_new_instance(1, &self, class_deferred); + rb_iv_set(self, "tmp", op); + Data_Get_Struct(self, struct hyperdex_client, client); + Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); + hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); + hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); + o->reqid = f(client, in_space, in_key, in_key_sz, &o->status); + if (o->reqid < 0) + { + hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); + } + o->encode_return = hyperdex_ruby_client_deferred_encode_status; + rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); + rb_iv_set(self, "tmp", Qnil); + return op; +} + +static VALUE +hyperdex_ruby_client_asynccall__spacename_key_predicates__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status), VALUE self, VALUE spacename, VALUE key, VALUE predicates) +{ + VALUE op; + const char *in_space; + const char *in_key; + size_t in_key_sz; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + struct hyperdex_client *client; + struct hyperdex_ruby_client_deferred *o; + op = rb_class_new_instance(1, &self, class_deferred); + rb_iv_set(self, "tmp", op); + Data_Get_Struct(self, struct hyperdex_client, client); + Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); + hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); + hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); + hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); + o->reqid = f(client, in_space, in_key, in_key_sz, in_checks, in_checks_sz, &o->status); + if (o->reqid < 0) + { + hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); + } + o->encode_return = hyperdex_ruby_client_deferred_encode_status; + rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); + rb_iv_set(self, "tmp", Qnil); + return op; +} + +static VALUE +hyperdex_ruby_client_asynccall__spacename_predicates__status_count(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, uint64_t *count), VALUE self, VALUE spacename, VALUE predicates) +{ + VALUE op; + const char *in_space; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + struct hyperdex_client *client; + struct hyperdex_ruby_client_deferred *o; + op = rb_class_new_instance(1, &self, class_deferred); + rb_iv_set(self, "tmp", op); + Data_Get_Struct(self, struct hyperdex_client, client); + Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); + hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); + hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); + o->reqid = f(client, in_space, in_checks, in_checks_sz, &o->status, &o->count); + if (o->reqid < 0) + { + hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); + } + o->encode_return = hyperdex_ruby_client_deferred_encode_status_count; + rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); + rb_iv_set(self, "tmp", Qnil); + return op; +} + +static VALUE +hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status), VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) +{ + VALUE op; + const char *in_space; + const char *in_key; + size_t in_key_sz; + const struct hyperdex_client_map_attribute *in_mapattrs; + size_t in_mapattrs_sz; + struct hyperdex_client *client; + struct hyperdex_ruby_client_deferred *o; + op = rb_class_new_instance(1, &self, class_deferred); + rb_iv_set(self, "tmp", op); + Data_Get_Struct(self, struct hyperdex_client, client); + Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); + hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); + hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); + hyperdex_ruby_client_convert_mapattributes(o->arena, mapattributes, &in_mapattrs, &in_mapattrs_sz); + o->reqid = f(client, in_space, in_key, in_key_sz, in_mapattrs, in_mapattrs_sz, &o->status); + if (o->reqid < 0) + { + hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); + } + o->encode_return = hyperdex_ruby_client_deferred_encode_status; + rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); + rb_iv_set(self, "tmp", Qnil); + return op; +} + +static VALUE +hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(int64_t (*f)(struct hyperdex_client *client, const char *space, const char *key, size_t key_sz, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status), VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) +{ + VALUE op; + const char *in_space; + const char *in_key; + size_t in_key_sz; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + const struct hyperdex_client_map_attribute *in_mapattrs; + size_t in_mapattrs_sz; + struct hyperdex_client *client; + struct hyperdex_ruby_client_deferred *o; + op = rb_class_new_instance(1, &self, class_deferred); + rb_iv_set(self, "tmp", op); + Data_Get_Struct(self, struct hyperdex_client, client); + Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); + hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); + hyperdex_ruby_client_convert_key(o->arena, key, &in_key, &in_key_sz); + hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); + hyperdex_ruby_client_convert_mapattributes(o->arena, mapattributes, &in_mapattrs, &in_mapattrs_sz); + o->reqid = f(client, in_space, in_key, in_key_sz, in_checks, in_checks_sz, in_mapattrs, in_mapattrs_sz, &o->status); + if (o->reqid < 0) + { + hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); + } + o->encode_return = hyperdex_ruby_client_deferred_encode_status; + rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); + rb_iv_set(self, "tmp", Qnil); + return op; +} + +static VALUE +hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, enum hyperdex_client_returncode *status, uint64_t *count), VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) +{ + VALUE op; + const char *in_space; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + const struct hyperdex_client_map_attribute *in_mapattrs; + size_t in_mapattrs_sz; + struct hyperdex_client *client; + struct hyperdex_ruby_client_deferred *o; + op = rb_class_new_instance(1, &self, class_deferred); + rb_iv_set(self, "tmp", op); + Data_Get_Struct(self, struct hyperdex_client, client); + Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); + hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); + hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); + hyperdex_ruby_client_convert_mapattributes(o->arena, mapattributes, &in_mapattrs, &in_mapattrs_sz); + o->reqid = f(client, in_space, in_checks, in_checks_sz, in_mapattrs, in_mapattrs_sz, &o->status, &o->count); + if (o->reqid < 0) + { + hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); + } + o->encode_return = hyperdex_ruby_client_deferred_encode_status_count; + rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); + rb_iv_set(self, "tmp", Qnil); + return op; +} + +static VALUE +hyperdex_ruby_client_iterator__spacename_predicates__status_attributes(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), VALUE self, VALUE spacename, VALUE predicates) +{ + VALUE op; + const char *in_space; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + struct hyperdex_client *client; + struct hyperdex_ruby_client_iterator *o; + op = rb_class_new_instance(1, &self, class_iterator); + rb_iv_set(self, "tmp", op); + Data_Get_Struct(self, struct hyperdex_client, client); + Data_Get_Struct(op, struct hyperdex_ruby_client_iterator, o); + hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); + hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); + o->reqid = f(client, in_space, in_checks, in_checks_sz, &o->status, &o->attrs, &o->attrs_sz); + if (o->reqid < 0) + { + hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); + } + o->encode_return = hyperdex_ruby_client_iterator_encode_status_attributes; + rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); + rb_iv_set(self, "tmp", Qnil); + return op; +} + +static VALUE +hyperdex_ruby_client_asynccall__spacename_predicates__status_description(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, enum hyperdex_client_returncode *status, const char **description), VALUE self, VALUE spacename, VALUE predicates) +{ + VALUE op; + const char *in_space; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + struct hyperdex_client *client; + struct hyperdex_ruby_client_deferred *o; + op = rb_class_new_instance(1, &self, class_deferred); + rb_iv_set(self, "tmp", op); + Data_Get_Struct(self, struct hyperdex_client, client); + Data_Get_Struct(op, struct hyperdex_ruby_client_deferred, o); + hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); + hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); + o->reqid = f(client, in_space, in_checks, in_checks_sz, &o->status, &o->description); + if (o->reqid < 0) + { + hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); + } + o->encode_return = hyperdex_ruby_client_deferred_encode_status_description; + rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); + rb_iv_set(self, "tmp", Qnil); + return op; +} + +static VALUE +hyperdex_ruby_client_iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(int64_t (*f)(struct hyperdex_client *client, const char *space, const struct hyperdex_client_attribute_check *checks, size_t checks_sz, const char *sort_by, uint64_t limit, int maxmin, enum hyperdex_client_returncode *status, const struct hyperdex_client_attribute **attrs, size_t *attrs_sz), VALUE self, VALUE spacename, VALUE predicates, VALUE sortby, VALUE limit, VALUE maxmin) +{ + VALUE op; + const char *in_space; + const struct hyperdex_client_attribute_check *in_checks; + size_t in_checks_sz; + const char *in_sort_by; + uint64_t in_limit; + int in_maxmin; + struct hyperdex_client *client; + struct hyperdex_ruby_client_iterator *o; + op = rb_class_new_instance(1, &self, class_iterator); + rb_iv_set(self, "tmp", op); + Data_Get_Struct(self, struct hyperdex_client, client); + Data_Get_Struct(op, struct hyperdex_ruby_client_iterator, o); + hyperdex_ruby_client_convert_spacename(o->arena, spacename, &in_space); + hyperdex_ruby_client_convert_predicates(o->arena, predicates, &in_checks, &in_checks_sz); + hyperdex_ruby_client_convert_sortby(o->arena, sortby, &in_sort_by); + hyperdex_ruby_client_convert_limit(o->arena, limit, &in_limit); + hyperdex_ruby_client_convert_maxmin(o->arena, maxmin, &in_maxmin); + o->reqid = f(client, in_space, in_checks, in_checks_sz, in_sort_by, in_limit, in_maxmin, &o->status, &o->attrs, &o->attrs_sz); + if (o->reqid < 0) + { + hyperdex_ruby_client_throw_exception(o->status, hyperdex_client_error_message(client)); + } + o->encode_return = hyperdex_ruby_client_iterator_encode_status_attributes; + rb_hash_aset(rb_iv_get(self, "ops"), LONG2NUM(o->reqid), op); + rb_iv_set(self, "tmp", Qnil); + return op; } static VALUE hyperdex_ruby_client_get(VALUE self, VALUE spacename, VALUE key) { - return hyperdex_ruby_client_asynccall__spacename_key__status_attributes(hyperdex_client_get, self, spacename, key); + return hyperdex_ruby_client_asynccall__spacename_key__status_attributes(hyperdex_client_get, self, spacename, key); } VALUE hyperdex_ruby_client_wait_get(VALUE self, VALUE spacename, VALUE key) { - VALUE deferred = hyperdex_ruby_client_get(self, spacename, key); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_get(self, spacename, key); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_get_partial(VALUE self, VALUE spacename, VALUE key, VALUE attributenames) { - return hyperdex_ruby_client_asynccall__spacename_key_attributenames__status_attributes(hyperdex_client_get_partial, self, spacename, key, attributenames); + return hyperdex_ruby_client_asynccall__spacename_key_attributenames__status_attributes(hyperdex_client_get_partial, self, spacename, key, attributenames); } VALUE hyperdex_ruby_client_wait_get_partial(VALUE self, VALUE spacename, VALUE key, VALUE attributenames) { - VALUE deferred = hyperdex_ruby_client_get_partial(self, spacename, key, attributenames); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_get_partial(self, spacename, key, attributenames); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_put(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_put, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_put, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_put(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_put(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_put(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_put(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_put, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_put, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_put(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_put(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_put(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_put_or_create(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_put_or_create, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_put_or_create, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_put_or_create(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_put_or_create(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_put_or_create(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_put(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_put, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_put, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_put(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_put(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_put(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_put_if_not_exist(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_put_if_not_exist, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_put_if_not_exist, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_put_if_not_exist(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_put_if_not_exist(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_put_if_not_exist(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_del(VALUE self, VALUE spacename, VALUE key) { - return hyperdex_ruby_client_asynccall__spacename_key__status(hyperdex_client_del, self, spacename, key); + return hyperdex_ruby_client_asynccall__spacename_key__status(hyperdex_client_del, self, spacename, key); } VALUE hyperdex_ruby_client_wait_del(VALUE self, VALUE spacename, VALUE key) { - VALUE deferred = hyperdex_ruby_client_del(self, spacename, key); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_del(self, spacename, key); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_del(VALUE self, VALUE spacename, VALUE key, VALUE predicates) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates__status(hyperdex_client_cond_del, self, spacename, key, predicates); + return hyperdex_ruby_client_asynccall__spacename_key_predicates__status(hyperdex_client_cond_del, self, spacename, key, predicates); } VALUE hyperdex_ruby_client_wait_cond_del(VALUE self, VALUE spacename, VALUE key, VALUE predicates) { - VALUE deferred = hyperdex_ruby_client_cond_del(self, spacename, key, predicates); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_del(self, spacename, key, predicates); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_del(VALUE self, VALUE spacename, VALUE predicates) { - return hyperdex_ruby_client_asynccall__spacename_predicates__status_count(hyperdex_client_group_del, self, spacename, predicates); + return hyperdex_ruby_client_asynccall__spacename_predicates__status_count(hyperdex_client_group_del, self, spacename, predicates); } VALUE hyperdex_ruby_client_wait_group_del(VALUE self, VALUE spacename, VALUE predicates) { - VALUE deferred = hyperdex_ruby_client_group_del(self, spacename, predicates); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_del(self, spacename, predicates); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_atomic_add(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_add, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_add, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_atomic_add(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_atomic_add(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_atomic_add(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_atomic_add(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_add, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_add, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_atomic_add(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_atomic_add(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_atomic_add(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_atomic_add(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_add, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_add, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_atomic_add(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_atomic_add(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_atomic_add(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_atomic_sub(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_sub, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_sub, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_atomic_sub(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_atomic_sub(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_atomic_sub(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_atomic_sub(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_sub, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_sub, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_atomic_sub(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_atomic_sub(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_atomic_sub(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_atomic_sub(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_sub, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_sub, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_atomic_sub(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_atomic_sub(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_atomic_sub(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_atomic_mul(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_mul, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_mul, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_atomic_mul(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_atomic_mul(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_atomic_mul(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_atomic_mul(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_mul, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_mul, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_atomic_mul(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_atomic_mul(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_atomic_mul(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_atomic_mul(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_mul, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_mul, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_atomic_mul(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_atomic_mul(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_atomic_mul(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_atomic_div(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_div, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_div, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_atomic_div(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_atomic_div(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_atomic_div(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_atomic_div(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_div, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_div, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_atomic_div(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_atomic_div(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_atomic_div(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_atomic_div(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_div, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_div, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_atomic_div(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_atomic_div(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_atomic_div(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_atomic_mod(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_mod, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_mod, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_atomic_mod(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_atomic_mod(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_atomic_mod(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_atomic_mod(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_mod, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_mod, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_atomic_mod(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_atomic_mod(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_atomic_mod(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_atomic_mod(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_mod, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_mod, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_atomic_mod(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_atomic_mod(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_atomic_mod(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_atomic_and(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_and, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_and, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_atomic_and(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_atomic_and(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_atomic_and(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_atomic_and(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_and, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_and, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_atomic_and(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_atomic_and(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_atomic_and(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_atomic_and(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_and, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_and, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_atomic_and(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_atomic_and(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_atomic_and(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_atomic_or(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_or, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_or, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_atomic_or(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_atomic_or(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_atomic_or(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_atomic_or(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_or, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_or, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_atomic_or(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_atomic_or(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_atomic_or(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_atomic_or(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_or, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_or, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_atomic_or(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_atomic_or(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_atomic_or(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_atomic_xor(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_xor, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_xor, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_atomic_xor(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_atomic_xor(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_atomic_xor(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_atomic_xor(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_xor, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_xor, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_atomic_xor(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_atomic_xor(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_atomic_xor(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_atomic_xor(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_xor, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_xor, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_atomic_xor(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_atomic_xor(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_atomic_xor(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_atomic_min(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_min, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_min, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_atomic_min(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_atomic_min(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_atomic_min(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_atomic_min(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_min, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_min, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_atomic_min(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_atomic_min(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_atomic_min(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_atomic_min(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_min, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_min, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_atomic_min(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_atomic_min(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_atomic_min(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_atomic_max(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_max, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_atomic_max, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_atomic_max(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_atomic_max(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_atomic_max(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_atomic_max(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_max, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_atomic_max, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_atomic_max(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_atomic_max(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_atomic_max(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_atomic_max(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_max, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_atomic_max, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_atomic_max(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_atomic_max(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_atomic_max(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_string_prepend(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_string_prepend, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_string_prepend, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_string_prepend(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_string_prepend(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_string_prepend(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_string_prepend(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_prepend, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_prepend, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_string_prepend(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_string_prepend(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_string_prepend(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_string_prepend(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_prepend, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_prepend, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_string_prepend(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_string_prepend(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_string_prepend(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_string_append(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_string_append, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_string_append, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_string_append(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_string_append(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_string_append(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_string_append(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_append, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_append, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_string_append(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_string_append(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_string_append(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_string_append(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_append, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_append, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_string_append(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_string_append(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_string_append(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_string_ltrim(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_string_ltrim, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_string_ltrim, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_string_ltrim(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_string_ltrim(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_string_ltrim(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_string_ltrim(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_ltrim, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_ltrim, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_string_ltrim(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_string_ltrim(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_string_ltrim(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_string_ltrim(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_ltrim, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_ltrim, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_string_ltrim(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_string_ltrim(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_string_ltrim(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_string_rtrim(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_string_rtrim, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_string_rtrim, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_string_rtrim(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_string_rtrim(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_string_rtrim(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_string_rtrim(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_rtrim, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_string_rtrim, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_string_rtrim(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_string_rtrim(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_string_rtrim(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_string_rtrim(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_rtrim, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_string_rtrim, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_string_rtrim(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_string_rtrim(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_string_rtrim(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_list_lpush(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_list_lpush, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_list_lpush, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_list_lpush(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_list_lpush(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_list_lpush(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_list_lpush(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_list_lpush, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_list_lpush, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_list_lpush(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_list_lpush(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_list_lpush(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_list_lpush(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_list_lpush, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_list_lpush, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_list_lpush(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_list_lpush(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_list_lpush(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_list_rpush(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_list_rpush, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_list_rpush, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_list_rpush(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_list_rpush(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_list_rpush(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_list_rpush(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_list_rpush, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_list_rpush, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_list_rpush(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_list_rpush(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_list_rpush(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_list_rpush(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_list_rpush, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_list_rpush, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_list_rpush(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_list_rpush(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_list_rpush(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_set_add(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_set_add, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_set_add, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_set_add(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_set_add(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_set_add(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_set_add(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_add, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_add, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_set_add(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_set_add(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_set_add(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_set_add(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_add, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_add, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_set_add(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_set_add(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_set_add(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_set_remove(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_set_remove, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_set_remove, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_set_remove(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_set_remove(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_set_remove(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_set_remove(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_remove, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_remove, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_set_remove(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_set_remove(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_set_remove(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_set_remove(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_remove, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_remove, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_set_remove(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_set_remove(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_set_remove(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_set_intersect(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_set_intersect, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_set_intersect, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_set_intersect(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_set_intersect(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_set_intersect(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_set_intersect(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_intersect, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_intersect, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_set_intersect(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_set_intersect(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_set_intersect(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_set_intersect(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_intersect, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_intersect, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_set_intersect(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_set_intersect(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_set_intersect(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_set_union(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_set_union, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_set_union, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_set_union(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_set_union(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_set_union(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_set_union(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_union, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_set_union, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_set_union(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_set_union(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_set_union(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_set_union(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_union, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_set_union, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_set_union(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_set_union(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_set_union(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_document_rename(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_document_rename, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_document_rename, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_document_rename(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_document_rename(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_document_rename(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_document_rename(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_document_rename, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_document_rename, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_document_rename(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_document_rename(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_document_rename(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_document_rename(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_document_rename, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_document_rename, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_document_rename(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_document_rename(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_document_rename(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_document_unset(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_document_unset, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_document_unset, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_document_unset(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_document_unset(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_document_unset(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_document_unset(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_document_unset, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_document_unset, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_document_unset(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_document_unset(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_document_unset(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_document_unset(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_document_unset, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_document_unset, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_document_unset(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_document_unset(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_document_unset(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_map_add(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_add, self, spacename, key, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_add, self, spacename, key, mapattributes); } VALUE hyperdex_ruby_client_wait_map_add(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_map_add(self, spacename, key, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_map_add(self, spacename, key, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_map_add(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_add, self, spacename, key, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_add, self, spacename, key, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_cond_map_add(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_cond_map_add(self, spacename, key, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_map_add(self, spacename, key, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_map_add(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_add, self, spacename, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_add, self, spacename, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_group_map_add(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_group_map_add(self, spacename, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_map_add(self, spacename, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_map_remove(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_map_remove, self, spacename, key, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_attributes__status(hyperdex_client_map_remove, self, spacename, key, attributes); } VALUE hyperdex_ruby_client_wait_map_remove(VALUE self, VALUE spacename, VALUE key, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_map_remove(self, spacename, key, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_map_remove(self, spacename, key, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_map_remove(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_map_remove, self, spacename, key, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_attributes__status(hyperdex_client_cond_map_remove, self, spacename, key, predicates, attributes); } VALUE hyperdex_ruby_client_wait_cond_map_remove(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_cond_map_remove(self, spacename, key, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_map_remove(self, spacename, key, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_map_remove(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_map_remove, self, spacename, predicates, attributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_attributes__status_count(hyperdex_client_group_map_remove, self, spacename, predicates, attributes); } VALUE hyperdex_ruby_client_wait_group_map_remove(VALUE self, VALUE spacename, VALUE predicates, VALUE attributes) { - VALUE deferred = hyperdex_ruby_client_group_map_remove(self, spacename, predicates, attributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_map_remove(self, spacename, predicates, attributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_map_atomic_add(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_add, self, spacename, key, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_add, self, spacename, key, mapattributes); } VALUE hyperdex_ruby_client_wait_map_atomic_add(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_map_atomic_add(self, spacename, key, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_map_atomic_add(self, spacename, key, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_map_atomic_add(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_add, self, spacename, key, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_add, self, spacename, key, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_cond_map_atomic_add(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_cond_map_atomic_add(self, spacename, key, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_map_atomic_add(self, spacename, key, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_map_atomic_add(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_add, self, spacename, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_add, self, spacename, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_group_map_atomic_add(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_group_map_atomic_add(self, spacename, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_map_atomic_add(self, spacename, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_map_atomic_sub(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_sub, self, spacename, key, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_sub, self, spacename, key, mapattributes); } VALUE hyperdex_ruby_client_wait_map_atomic_sub(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_map_atomic_sub(self, spacename, key, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_map_atomic_sub(self, spacename, key, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_map_atomic_sub(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_sub, self, spacename, key, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_sub, self, spacename, key, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_cond_map_atomic_sub(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_cond_map_atomic_sub(self, spacename, key, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_map_atomic_sub(self, spacename, key, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_map_atomic_sub(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_sub, self, spacename, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_sub, self, spacename, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_group_map_atomic_sub(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_group_map_atomic_sub(self, spacename, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_map_atomic_sub(self, spacename, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_map_atomic_mul(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_mul, self, spacename, key, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_mul, self, spacename, key, mapattributes); } VALUE hyperdex_ruby_client_wait_map_atomic_mul(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_map_atomic_mul(self, spacename, key, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_map_atomic_mul(self, spacename, key, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_map_atomic_mul(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_mul, self, spacename, key, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_mul, self, spacename, key, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_cond_map_atomic_mul(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_cond_map_atomic_mul(self, spacename, key, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_map_atomic_mul(self, spacename, key, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_map_atomic_mul(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_mul, self, spacename, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_mul, self, spacename, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_group_map_atomic_mul(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_group_map_atomic_mul(self, spacename, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_map_atomic_mul(self, spacename, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_map_atomic_div(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_div, self, spacename, key, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_div, self, spacename, key, mapattributes); } VALUE hyperdex_ruby_client_wait_map_atomic_div(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_map_atomic_div(self, spacename, key, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_map_atomic_div(self, spacename, key, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_map_atomic_div(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_div, self, spacename, key, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_div, self, spacename, key, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_cond_map_atomic_div(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_cond_map_atomic_div(self, spacename, key, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_map_atomic_div(self, spacename, key, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_map_atomic_div(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_div, self, spacename, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_div, self, spacename, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_group_map_atomic_div(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_group_map_atomic_div(self, spacename, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_map_atomic_div(self, spacename, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_map_atomic_mod(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_mod, self, spacename, key, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_mod, self, spacename, key, mapattributes); } VALUE hyperdex_ruby_client_wait_map_atomic_mod(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_map_atomic_mod(self, spacename, key, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_map_atomic_mod(self, spacename, key, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_map_atomic_mod(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_mod, self, spacename, key, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_mod, self, spacename, key, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_cond_map_atomic_mod(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_cond_map_atomic_mod(self, spacename, key, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_map_atomic_mod(self, spacename, key, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_map_atomic_mod(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_mod, self, spacename, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_mod, self, spacename, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_group_map_atomic_mod(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_group_map_atomic_mod(self, spacename, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_map_atomic_mod(self, spacename, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_map_atomic_and(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_and, self, spacename, key, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_and, self, spacename, key, mapattributes); } VALUE hyperdex_ruby_client_wait_map_atomic_and(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_map_atomic_and(self, spacename, key, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_map_atomic_and(self, spacename, key, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_map_atomic_and(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_and, self, spacename, key, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_and, self, spacename, key, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_cond_map_atomic_and(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_cond_map_atomic_and(self, spacename, key, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_map_atomic_and(self, spacename, key, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_map_atomic_and(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_and, self, spacename, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_and, self, spacename, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_group_map_atomic_and(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_group_map_atomic_and(self, spacename, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_map_atomic_and(self, spacename, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_map_atomic_or(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_or, self, spacename, key, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_or, self, spacename, key, mapattributes); } VALUE hyperdex_ruby_client_wait_map_atomic_or(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_map_atomic_or(self, spacename, key, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_map_atomic_or(self, spacename, key, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_map_atomic_or(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_or, self, spacename, key, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_or, self, spacename, key, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_cond_map_atomic_or(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_cond_map_atomic_or(self, spacename, key, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_map_atomic_or(self, spacename, key, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_map_atomic_or(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_or, self, spacename, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_or, self, spacename, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_group_map_atomic_or(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_group_map_atomic_or(self, spacename, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_map_atomic_or(self, spacename, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_map_atomic_xor(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_xor, self, spacename, key, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_xor, self, spacename, key, mapattributes); } VALUE hyperdex_ruby_client_wait_map_atomic_xor(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_map_atomic_xor(self, spacename, key, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_map_atomic_xor(self, spacename, key, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_map_atomic_xor(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_xor, self, spacename, key, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_xor, self, spacename, key, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_cond_map_atomic_xor(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_cond_map_atomic_xor(self, spacename, key, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_map_atomic_xor(self, spacename, key, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_map_atomic_xor(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_xor, self, spacename, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_xor, self, spacename, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_group_map_atomic_xor(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_group_map_atomic_xor(self, spacename, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_map_atomic_xor(self, spacename, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_map_string_prepend(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_string_prepend, self, spacename, key, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_string_prepend, self, spacename, key, mapattributes); } VALUE hyperdex_ruby_client_wait_map_string_prepend(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_map_string_prepend(self, spacename, key, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_map_string_prepend(self, spacename, key, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_map_string_prepend(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_string_prepend, self, spacename, key, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_string_prepend, self, spacename, key, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_cond_map_string_prepend(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_cond_map_string_prepend(self, spacename, key, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_map_string_prepend(self, spacename, key, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_map_string_prepend(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_string_prepend, self, spacename, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_string_prepend, self, spacename, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_group_map_string_prepend(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_group_map_string_prepend(self, spacename, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_map_string_prepend(self, spacename, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_map_string_append(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_string_append, self, spacename, key, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_string_append, self, spacename, key, mapattributes); } VALUE hyperdex_ruby_client_wait_map_string_append(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_map_string_append(self, spacename, key, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_map_string_append(self, spacename, key, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_map_string_append(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_string_append, self, spacename, key, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_string_append, self, spacename, key, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_cond_map_string_append(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_cond_map_string_append(self, spacename, key, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_map_string_append(self, spacename, key, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_map_string_append(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_string_append, self, spacename, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_string_append, self, spacename, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_group_map_string_append(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_group_map_string_append(self, spacename, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_map_string_append(self, spacename, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_map_atomic_min(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_min, self, spacename, key, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_min, self, spacename, key, mapattributes); } VALUE hyperdex_ruby_client_wait_map_atomic_min(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_map_atomic_min(self, spacename, key, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_map_atomic_min(self, spacename, key, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_map_atomic_min(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_min, self, spacename, key, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_min, self, spacename, key, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_cond_map_atomic_min(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_cond_map_atomic_min(self, spacename, key, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_map_atomic_min(self, spacename, key, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_map_atomic_min(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_min, self, spacename, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_min, self, spacename, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_group_map_atomic_min(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_group_map_atomic_min(self, spacename, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_map_atomic_min(self, spacename, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_map_atomic_max(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_max, self, spacename, key, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_mapattributes__status(hyperdex_client_map_atomic_max, self, spacename, key, mapattributes); } VALUE hyperdex_ruby_client_wait_map_atomic_max(VALUE self, VALUE spacename, VALUE key, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_map_atomic_max(self, spacename, key, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_map_atomic_max(self, spacename, key, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_cond_map_atomic_max(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_max, self, spacename, key, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_key_predicates_mapattributes__status(hyperdex_client_cond_map_atomic_max, self, spacename, key, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_cond_map_atomic_max(VALUE self, VALUE spacename, VALUE key, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_cond_map_atomic_max(self, spacename, key, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_cond_map_atomic_max(self, spacename, key, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_group_map_atomic_max(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_max, self, spacename, predicates, mapattributes); + return hyperdex_ruby_client_asynccall__spacename_predicates_mapattributes__status_count(hyperdex_client_group_map_atomic_max, self, spacename, predicates, mapattributes); } VALUE hyperdex_ruby_client_wait_group_map_atomic_max(VALUE self, VALUE spacename, VALUE predicates, VALUE mapattributes) { - VALUE deferred = hyperdex_ruby_client_group_map_atomic_max(self, spacename, predicates, mapattributes); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_group_map_atomic_max(self, spacename, predicates, mapattributes); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_search(VALUE self, VALUE spacename, VALUE predicates) { - return hyperdex_ruby_client_iterator__spacename_predicates__status_attributes(hyperdex_client_search, self, spacename, predicates); + return hyperdex_ruby_client_iterator__spacename_predicates__status_attributes(hyperdex_client_search, self, spacename, predicates); } static VALUE hyperdex_ruby_client_search_describe(VALUE self, VALUE spacename, VALUE predicates) { - return hyperdex_ruby_client_asynccall__spacename_predicates__status_description(hyperdex_client_search_describe, self, spacename, predicates); + return hyperdex_ruby_client_asynccall__spacename_predicates__status_description(hyperdex_client_search_describe, self, spacename, predicates); } VALUE hyperdex_ruby_client_wait_search_describe(VALUE self, VALUE spacename, VALUE predicates) { - VALUE deferred = hyperdex_ruby_client_search_describe(self, spacename, predicates); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_search_describe(self, spacename, predicates); + return rb_funcall(deferred, rb_intern("wait"), 0); } static VALUE hyperdex_ruby_client_sorted_search(VALUE self, VALUE spacename, VALUE predicates, VALUE sortby, VALUE limit, VALUE maxmin) { - return hyperdex_ruby_client_iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(hyperdex_client_sorted_search, self, spacename, predicates, sortby, limit, maxmin); + return hyperdex_ruby_client_iterator__spacename_predicates_sortby_limit_maxmin__status_attributes(hyperdex_client_sorted_search, self, spacename, predicates, sortby, limit, maxmin); } static VALUE hyperdex_ruby_client_count(VALUE self, VALUE spacename, VALUE predicates) { - return hyperdex_ruby_client_asynccall__spacename_predicates__status_count(hyperdex_client_count, self, spacename, predicates); + return hyperdex_ruby_client_asynccall__spacename_predicates__status_count(hyperdex_client_count, self, spacename, predicates); } VALUE hyperdex_ruby_client_wait_count(VALUE self, VALUE spacename, VALUE predicates) { - VALUE deferred = hyperdex_ruby_client_count(self, spacename, predicates); - return rb_funcall(deferred, rb_intern("wait"), 0); + VALUE deferred = hyperdex_ruby_client_count(self, spacename, predicates); + return rb_funcall(deferred, rb_intern("wait"), 0); } diff --git a/bindings/ruby/hyperdex.c b/bindings/ruby/hyperdex.c index 41fe0a90e..27ffe3054 100644 --- a/bindings/ruby/hyperdex.c +++ b/bindings/ruby/hyperdex.c @@ -43,12 +43,11 @@ Init_hyperdex_admin(); HYPERDEX_API void Init_hyperdex() { - mod_hyperdex = rb_define_module("HyperDex"); - + mod_hyperdex = rb_define_module("HyperDex"); #ifdef HYPERDEX_CLIENT - Init_hyperdex_client(); + Init_hyperdex_client(); #endif #ifdef HYPERDEX_ADMIN - Init_hyperdex_admin(); + Init_hyperdex_admin(); #endif }; diff --git a/cityhash/city.cc b/cityhash/city.cc index d453143c6..d41245266 100644 --- a/cityhash/city.cc +++ b/cityhash/city.cc @@ -42,16 +42,18 @@ typedef std::pair uint128; using namespace std; -static uint64 UNALIGNED_LOAD64(const char *p) { - uint64 result; - memcpy(&result, p, sizeof(result)); - return result; +static uint64 UNALIGNED_LOAD64(const char *p) +{ + uint64 result; + memcpy(&result, p, sizeof(result)); + return result; } -static uint32 UNALIGNED_LOAD32(const char *p) { - uint32 result; - memcpy(&result, p, sizeof(result)); - return result; +static uint32 UNALIGNED_LOAD32(const char *p) +{ + uint32 result; + memcpy(&result, p, sizeof(result)); + return result; } #ifdef _MSC_VER @@ -104,12 +106,14 @@ static uint32 UNALIGNED_LOAD32(const char *p) { #endif #endif -static uint64 Fetch64(const char *p) { - return uint64_in_expected_order(UNALIGNED_LOAD64(p)); +static uint64 Fetch64(const char *p) +{ + return uint64_in_expected_order(UNALIGNED_LOAD64(p)); } -static uint32 Fetch32(const char *p) { - return uint32_in_expected_order(UNALIGNED_LOAD32(p)); +static uint32 Fetch32(const char *p) +{ + return uint32_in_expected_order(UNALIGNED_LOAD32(p)); } // Some primes between 2^63 and 2^64 for various uses. @@ -124,387 +128,426 @@ static const uint32_t c2 = 0x1b873593; // A 32-bit to 32-bit integer hash copied from Murmur3. static uint32 fmix(uint32 h) { - h ^= h >> 16; - h *= 0x85ebca6b; - h ^= h >> 13; - h *= 0xc2b2ae35; - h ^= h >> 16; - return h; + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + return h; } -static uint32 Rotate32(uint32 val, int shift) { - // Avoid shifting by 32: doing so yields an undefined result. - return shift == 0 ? val : ((val >> shift) | (val << (32 - shift))); +static uint32 Rotate32(uint32 val, int shift) +{ + // Avoid shifting by 32: doing so yields an undefined result. + return shift == 0 ? val : ((val >> shift) | (val << (32 - shift))); } #undef PERMUTE3 #define PERMUTE3(a, b, c) do { std::swap(a, b); std::swap(a, c); } while (0) -static uint32 Mur(uint32 a, uint32 h) { - // Helper from Murmur3 for combining two 32-bit values. - a *= c1; - a = Rotate32(a, 17); - a *= c2; - h ^= a; - h = Rotate32(h, 19); - return h * 5 + 0xe6546b64; +static uint32 Mur(uint32 a, uint32 h) +{ + // Helper from Murmur3 for combining two 32-bit values. + a *= c1; + a = Rotate32(a, 17); + a *= c2; + h ^= a; + h = Rotate32(h, 19); + return h * 5 + 0xe6546b64; } -static uint32 Hash32Len13to24(const char *s, size_t len) { - uint32 a = Fetch32(s - 4 + (len >> 1)); - uint32 b = Fetch32(s + 4); - uint32 c = Fetch32(s + len - 8); - uint32 d = Fetch32(s + (len >> 1)); - uint32 e = Fetch32(s); - uint32 f = Fetch32(s + len - 4); - uint32 h = len; - - return fmix(Mur(f, Mur(e, Mur(d, Mur(c, Mur(b, Mur(a, h))))))); +static uint32 Hash32Len13to24(const char *s, size_t len) +{ + uint32 a = Fetch32(s - 4 + (len >> 1)); + uint32 b = Fetch32(s + 4); + uint32 c = Fetch32(s + len - 8); + uint32 d = Fetch32(s + (len >> 1)); + uint32 e = Fetch32(s); + uint32 f = Fetch32(s + len - 4); + uint32 h = len; + return fmix(Mur(f, Mur(e, Mur(d, Mur(c, Mur(b, Mur(a, h))))))); } -static uint32 Hash32Len0to4(const char *s, size_t len) { - uint32 b = 0; - uint32 c = 9; - for (size_t i = 0; i < len; i++) { - signed char v = s[i]; - b = b * c1 + v; - c ^= b; - } - return fmix(Mur(b, Mur(len, c))); +static uint32 Hash32Len0to4(const char *s, size_t len) +{ + uint32 b = 0; + uint32 c = 9; + for (size_t i = 0; i < len; i++) + { + signed char v = s[i]; + b = b * c1 + v; + c ^= b; + } + return fmix(Mur(b, Mur(len, c))); } -static uint32 Hash32Len5to12(const char *s, size_t len) { - uint32 a = len, b = len * 5, c = 9, d = b; - a += Fetch32(s); - b += Fetch32(s + len - 4); - c += Fetch32(s + ((len >> 1) & 4)); - return fmix(Mur(c, Mur(b, Mur(a, d)))); +static uint32 Hash32Len5to12(const char *s, size_t len) +{ + uint32 a = len, b = len * 5, c = 9, d = b; + a += Fetch32(s); + b += Fetch32(s + len - 4); + c += Fetch32(s + ((len >> 1) & 4)); + return fmix(Mur(c, Mur(b, Mur(a, d)))); } -uint32 CityHash32(const char *s, size_t len) { - if (len <= 24) { - return len <= 12 ? - (len <= 4 ? Hash32Len0to4(s, len) : Hash32Len5to12(s, len)) : - Hash32Len13to24(s, len); - } - - // len > 24 - uint32 h = len, g = c1 * len, f = g; - uint32 a0 = Rotate32(Fetch32(s + len - 4) * c1, 17) * c2; - uint32 a1 = Rotate32(Fetch32(s + len - 8) * c1, 17) * c2; - uint32 a2 = Rotate32(Fetch32(s + len - 16) * c1, 17) * c2; - uint32 a3 = Rotate32(Fetch32(s + len - 12) * c1, 17) * c2; - uint32 a4 = Rotate32(Fetch32(s + len - 20) * c1, 17) * c2; - h ^= a0; - h = Rotate32(h, 19); - h = h * 5 + 0xe6546b64; - h ^= a2; - h = Rotate32(h, 19); - h = h * 5 + 0xe6546b64; - g ^= a1; - g = Rotate32(g, 19); - g = g * 5 + 0xe6546b64; - g ^= a3; - g = Rotate32(g, 19); - g = g * 5 + 0xe6546b64; - f += a4; - f = Rotate32(f, 19); - f = f * 5 + 0xe6546b64; - size_t iters = (len - 1) / 20; - do { - uint32 b0 = Rotate32(Fetch32(s) * c1, 17) * c2; - uint32 b1 = Fetch32(s + 4); - uint32 b2 = Rotate32(Fetch32(s + 8) * c1, 17) * c2; - uint32 b3 = Rotate32(Fetch32(s + 12) * c1, 17) * c2; - uint32 b4 = Fetch32(s + 16); - h ^= b0; - h = Rotate32(h, 18); - h = h * 5 + 0xe6546b64; - f += b1; - f = Rotate32(f, 19); - f = f * c1; - g += b2; - g = Rotate32(g, 18); - g = g * 5 + 0xe6546b64; - h ^= b3 + b1; - h = Rotate32(h, 19); - h = h * 5 + 0xe6546b64; - g ^= b4; - g = bswap_32(g) * 5; - h += b4 * 5; - h = bswap_32(h); - f += b0; - PERMUTE3(f, h, g); - s += 20; - } while (--iters != 0); - g = Rotate32(g, 11) * c1; - g = Rotate32(g, 17) * c1; - f = Rotate32(f, 11) * c1; - f = Rotate32(f, 17) * c1; - h = Rotate32(h + g, 19); - h = h * 5 + 0xe6546b64; - h = Rotate32(h, 17) * c1; - h = Rotate32(h + f, 19); - h = h * 5 + 0xe6546b64; - h = Rotate32(h, 17) * c1; - return h; +uint32 CityHash32(const char *s, size_t len) +{ + if (len <= 24) + { + return len <= 12 ? + (len <= 4 ? Hash32Len0to4(s, len) : Hash32Len5to12(s, len)) : + Hash32Len13to24(s, len); + } + // len > 24 + uint32 h = len, g = c1 * len, f = g; + uint32 a0 = Rotate32(Fetch32(s + len - 4) * c1, 17) * c2; + uint32 a1 = Rotate32(Fetch32(s + len - 8) * c1, 17) * c2; + uint32 a2 = Rotate32(Fetch32(s + len - 16) * c1, 17) * c2; + uint32 a3 = Rotate32(Fetch32(s + len - 12) * c1, 17) * c2; + uint32 a4 = Rotate32(Fetch32(s + len - 20) * c1, 17) * c2; + h ^= a0; + h = Rotate32(h, 19); + h = h * 5 + 0xe6546b64; + h ^= a2; + h = Rotate32(h, 19); + h = h * 5 + 0xe6546b64; + g ^= a1; + g = Rotate32(g, 19); + g = g * 5 + 0xe6546b64; + g ^= a3; + g = Rotate32(g, 19); + g = g * 5 + 0xe6546b64; + f += a4; + f = Rotate32(f, 19); + f = f * 5 + 0xe6546b64; + size_t iters = (len - 1) / 20; + do + { + uint32 b0 = Rotate32(Fetch32(s) * c1, 17) * c2; + uint32 b1 = Fetch32(s + 4); + uint32 b2 = Rotate32(Fetch32(s + 8) * c1, 17) * c2; + uint32 b3 = Rotate32(Fetch32(s + 12) * c1, 17) * c2; + uint32 b4 = Fetch32(s + 16); + h ^= b0; + h = Rotate32(h, 18); + h = h * 5 + 0xe6546b64; + f += b1; + f = Rotate32(f, 19); + f = f * c1; + g += b2; + g = Rotate32(g, 18); + g = g * 5 + 0xe6546b64; + h ^= b3 + b1; + h = Rotate32(h, 19); + h = h * 5 + 0xe6546b64; + g ^= b4; + g = bswap_32(g) * 5; + h += b4 * 5; + h = bswap_32(h); + f += b0; + PERMUTE3(f, h, g); + s += 20; + } + while (--iters != 0); + g = Rotate32(g, 11) * c1; + g = Rotate32(g, 17) * c1; + f = Rotate32(f, 11) * c1; + f = Rotate32(f, 17) * c1; + h = Rotate32(h + g, 19); + h = h * 5 + 0xe6546b64; + h = Rotate32(h, 17) * c1; + h = Rotate32(h + f, 19); + h = h * 5 + 0xe6546b64; + h = Rotate32(h, 17) * c1; + return h; } // Bitwise right rotate. Normally this will compile to a single // instruction, especially if the shift is a manifest constant. -static uint64 Rotate(uint64 val, int shift) { - // Avoid shifting by 64: doing so yields an undefined result. - return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); +static uint64 Rotate(uint64 val, int shift) +{ + // Avoid shifting by 64: doing so yields an undefined result. + return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); } -static uint64 ShiftMix(uint64 val) { - return val ^ (val >> 47); +static uint64 ShiftMix(uint64 val) +{ + return val ^ (val >> 47); } -static uint64 HashLen16(uint64 u, uint64 v) { - return Hash128to64(uint128(u, v)); +static uint64 HashLen16(uint64 u, uint64 v) +{ + return Hash128to64(uint128(u, v)); } -static uint64 HashLen16(uint64 u, uint64 v, uint64 mul) { - // Murmur-inspired hashing. - uint64 a = (u ^ v) * mul; - a ^= (a >> 47); - uint64 b = (v ^ a) * mul; - b ^= (b >> 47); - b *= mul; - return b; +static uint64 HashLen16(uint64 u, uint64 v, uint64 mul) +{ + // Murmur-inspired hashing. + uint64 a = (u ^ v) * mul; + a ^= (a >> 47); + uint64 b = (v ^ a) * mul; + b ^= (b >> 47); + b *= mul; + return b; } -static uint64 HashLen0to16(const char *s, size_t len) { - if (len >= 8) { - uint64 mul = k2 + len * 2; - uint64 a = Fetch64(s) + k2; - uint64 b = Fetch64(s + len - 8); - uint64 c = Rotate(b, 37) * mul + a; - uint64 d = (Rotate(a, 25) + b) * mul; - return HashLen16(c, d, mul); - } - if (len >= 4) { - uint64 mul = k2 + len * 2; - uint64 a = Fetch32(s); - return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul); - } - if (len > 0) { - uint8 a = s[0]; - uint8 b = s[len >> 1]; - uint8 c = s[len - 1]; - uint32 y = static_cast(a) + (static_cast(b) << 8); - uint32 z = len + (static_cast(c) << 2); - return ShiftMix(y * k2 ^ z * k0) * k2; - } - return k2; +static uint64 HashLen0to16(const char *s, size_t len) +{ + if (len >= 8) + { + uint64 mul = k2 + len * 2; + uint64 a = Fetch64(s) + k2; + uint64 b = Fetch64(s + len - 8); + uint64 c = Rotate(b, 37) * mul + a; + uint64 d = (Rotate(a, 25) + b) * mul; + return HashLen16(c, d, mul); + } + if (len >= 4) + { + uint64 mul = k2 + len * 2; + uint64 a = Fetch32(s); + return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul); + } + if (len > 0) + { + uint8 a = s[0]; + uint8 b = s[len >> 1]; + uint8 c = s[len - 1]; + uint32 y = static_cast(a) + (static_cast(b) << 8); + uint32 z = len + (static_cast(c) << 2); + return ShiftMix(y * k2 ^ z * k0) * k2; + } + return k2; } // This probably works well for 16-byte strings as well, but it may be overkill // in that case. -static uint64 HashLen17to32(const char *s, size_t len) { - uint64 mul = k2 + len * 2; - uint64 a = Fetch64(s) * k1; - uint64 b = Fetch64(s + 8); - uint64 c = Fetch64(s + len - 8) * mul; - uint64 d = Fetch64(s + len - 16) * k2; - return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d, - a + Rotate(b + k2, 18) + c, mul); +static uint64 HashLen17to32(const char *s, size_t len) +{ + uint64 mul = k2 + len * 2; + uint64 a = Fetch64(s) * k1; + uint64 b = Fetch64(s + 8); + uint64 c = Fetch64(s + len - 8) * mul; + uint64 d = Fetch64(s + len - 16) * k2; + return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d, + a + Rotate(b + k2, 18) + c, mul); } // Return a 16-byte hash for 48 bytes. Quick and dirty. // Callers do best to use "random-looking" values for a and b. static pair WeakHashLen32WithSeeds( - uint64 w, uint64 x, uint64 y, uint64 z, uint64 a, uint64 b) { - a += w; - b = Rotate(b + a + z, 21); - uint64 c = a; - a += x; - a += y; - b += Rotate(a, 44); - return make_pair(a + z, b + c); + uint64 w, uint64 x, uint64 y, uint64 z, uint64 a, uint64 b) +{ + a += w; + b = Rotate(b + a + z, 21); + uint64 c = a; + a += x; + a += y; + b += Rotate(a, 44); + return make_pair(a + z, b + c); } // Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. static pair WeakHashLen32WithSeeds( - const char* s, uint64 a, uint64 b) { - return WeakHashLen32WithSeeds(Fetch64(s), - Fetch64(s + 8), - Fetch64(s + 16), - Fetch64(s + 24), - a, - b); + const char *s, uint64 a, uint64 b) +{ + return WeakHashLen32WithSeeds(Fetch64(s), + Fetch64(s + 8), + Fetch64(s + 16), + Fetch64(s + 24), + a, + b); } // Return an 8-byte hash for 33 to 64 bytes. -static uint64 HashLen33to64(const char *s, size_t len) { - uint64 mul = k2 + len * 2; - uint64 a = Fetch64(s) * k2; - uint64 b = Fetch64(s + 8); - uint64 c = Fetch64(s + len - 24); - uint64 d = Fetch64(s + len - 32); - uint64 e = Fetch64(s + 16) * k2; - uint64 f = Fetch64(s + 24) * 9; - uint64 g = Fetch64(s + len - 8); - uint64 h = Fetch64(s + len - 16) * mul; - uint64 u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9; - uint64 v = ((a + g) ^ d) + f + 1; - uint64 w = bswap_64((u + v) * mul) + h; - uint64 x = Rotate(e + f, 42) + c; - uint64 y = (bswap_64((v + w) * mul) + g) * mul; - uint64 z = e + f + c; - a = bswap_64((x + z) * mul + y) + b; - b = ShiftMix((z + a) * mul + d + h) * mul; - return b + x; +static uint64 HashLen33to64(const char *s, size_t len) +{ + uint64 mul = k2 + len * 2; + uint64 a = Fetch64(s) * k2; + uint64 b = Fetch64(s + 8); + uint64 c = Fetch64(s + len - 24); + uint64 d = Fetch64(s + len - 32); + uint64 e = Fetch64(s + 16) * k2; + uint64 f = Fetch64(s + 24) * 9; + uint64 g = Fetch64(s + len - 8); + uint64 h = Fetch64(s + len - 16) * mul; + uint64 u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9; + uint64 v = ((a + g) ^ d) + f + 1; + uint64 w = bswap_64((u + v) * mul) + h; + uint64 x = Rotate(e + f, 42) + c; + uint64 y = (bswap_64((v + w) * mul) + g) * mul; + uint64 z = e + f + c; + a = bswap_64((x + z) * mul + y) + b; + b = ShiftMix((z + a) * mul + d + h) * mul; + return b + x; } -uint64 CityHash64(const char *s, size_t len) { - if (len <= 32) { - if (len <= 16) { - return HashLen0to16(s, len); - } else { - return HashLen17to32(s, len); - } - } else if (len <= 64) { - return HashLen33to64(s, len); - } - - // For strings over 64 bytes we hash the end first, and then as we - // loop we keep 56 bytes of state: v, w, x, y, and z. - uint64 x = Fetch64(s + len - 40); - uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56); - uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24)); - pair v = WeakHashLen32WithSeeds(s + len - 64, len, z); - pair w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x); - x = x * k1 + Fetch64(s); - - // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. - len = (len - 1) & ~static_cast(63); - do { - x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; - y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; - x ^= w.second; - y += v.first + Fetch64(s + 40); - z = Rotate(z + w.first, 33) * k1; - v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); - w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); - std::swap(z, x); - s += 64; - len -= 64; - } while (len != 0); - return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z, - HashLen16(v.second, w.second) + x); +uint64 CityHash64(const char *s, size_t len) +{ + if (len <= 32) + { + if (len <= 16) + { + return HashLen0to16(s, len); + } + else + { + return HashLen17to32(s, len); + } + } + else if (len <= 64) + { + return HashLen33to64(s, len); + } + // For strings over 64 bytes we hash the end first, and then as we + // loop we keep 56 bytes of state: v, w, x, y, and z. + uint64 x = Fetch64(s + len - 40); + uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56); + uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24)); + pair v = WeakHashLen32WithSeeds(s + len - 64, len, z); + pair w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x); + x = x * k1 + Fetch64(s); + // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. + len = (len - 1) & ~static_cast(63); + do + { + x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; + y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; + x ^= w.second; + y += v.first + Fetch64(s + 40); + z = Rotate(z + w.first, 33) * k1; + v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); + w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); + std::swap(z, x); + s += 64; + len -= 64; + } + while (len != 0); + return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z, + HashLen16(v.second, w.second) + x); } -uint64 CityHash64WithSeed(const char *s, size_t len, uint64 seed) { - return CityHash64WithSeeds(s, len, k2, seed); +uint64 CityHash64WithSeed(const char *s, size_t len, uint64 seed) +{ + return CityHash64WithSeeds(s, len, k2, seed); } uint64 CityHash64WithSeeds(const char *s, size_t len, - uint64 seed0, uint64 seed1) { - return HashLen16(CityHash64(s, len) - seed0, seed1); + uint64 seed0, uint64 seed1) +{ + return HashLen16(CityHash64(s, len) - seed0, seed1); } // A subroutine for CityHash128(). Returns a decent 128-bit hash for strings // of any length representable in signed long. Based on City and Murmur. -static uint128 CityMurmur(const char *s, size_t len, uint128 seed) { - uint64 a = Uint128Low64(seed); - uint64 b = Uint128High64(seed); - uint64 c = 0; - uint64 d = 0; - signed long l = len - 16; - if (l <= 0) { // len <= 16 - a = ShiftMix(a * k1) * k1; - c = b * k1 + HashLen0to16(s, len); - d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c)); - } else { // len > 16 - c = HashLen16(Fetch64(s + len - 8) + k1, a); - d = HashLen16(b + len, c + Fetch64(s + len - 16)); - a += d; - do { - a ^= ShiftMix(Fetch64(s) * k1) * k1; - a *= k1; - b ^= a; - c ^= ShiftMix(Fetch64(s + 8) * k1) * k1; - c *= k1; - d ^= c; - s += 16; - l -= 16; - } while (l > 0); - } - a = HashLen16(a, c); - b = HashLen16(d, b); - return uint128(a ^ b, HashLen16(b, a)); +static uint128 CityMurmur(const char *s, size_t len, uint128 seed) +{ + uint64 a = Uint128Low64(seed); + uint64 b = Uint128High64(seed); + uint64 c = 0; + uint64 d = 0; + signed long l = len - 16; + if (l <= 0) // len <= 16 + { + a = ShiftMix(a * k1) * k1; + c = b * k1 + HashLen0to16(s, len); + d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c)); + } + else // len > 16 + { + c = HashLen16(Fetch64(s + len - 8) + k1, a); + d = HashLen16(b + len, c + Fetch64(s + len - 16)); + a += d; + do + { + a ^= ShiftMix(Fetch64(s) * k1) * k1; + a *= k1; + b ^= a; + c ^= ShiftMix(Fetch64(s + 8) * k1) * k1; + c *= k1; + d ^= c; + s += 16; + l -= 16; + } + while (l > 0); + } + a = HashLen16(a, c); + b = HashLen16(d, b); + return uint128(a ^ b, HashLen16(b, a)); } -uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) { - if (len < 128) { - return CityMurmur(s, len, seed); - } - - // We expect len >= 128 to be the common case. Keep 56 bytes of state: - // v, w, x, y, and z. - pair v, w; - uint64 x = Uint128Low64(seed); - uint64 y = Uint128High64(seed); - uint64 z = len * k1; - v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s); - v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8); - w.first = Rotate(y + z, 35) * k1 + x; - w.second = Rotate(x + Fetch64(s + 88), 53) * k1; - - // This is the same inner loop as CityHash64(), manually unrolled. - do { - x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; - y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; - x ^= w.second; - y += v.first + Fetch64(s + 40); - z = Rotate(z + w.first, 33) * k1; - v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); - w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); - std::swap(z, x); - s += 64; - x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; - y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; - x ^= w.second; - y += v.first + Fetch64(s + 40); - z = Rotate(z + w.first, 33) * k1; - v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); - w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); - std::swap(z, x); - s += 64; - len -= 128; - } while (LIKELY(len >= 128)); - x += Rotate(v.first + z, 49) * k0; - y = y * k0 + Rotate(w.second, 37); - z = z * k0 + Rotate(w.first, 27); - w.first *= 9; - v.first *= k0; - // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s. - for (size_t tail_done = 0; tail_done < len; ) { - tail_done += 32; - y = Rotate(x + y, 42) * k0 + v.second; - w.first += Fetch64(s + len - tail_done + 16); - x = x * k0 + w.first; - z += w.second + Fetch64(s + len - tail_done); - w.second += v.first; - v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second); - v.first *= k0; - } - // At this point our 56 bytes of state should contain more than - // enough information for a strong 128-bit hash. We use two - // different 56-byte-to-8-byte hashes to get a 16-byte final result. - x = HashLen16(x, v.first); - y = HashLen16(y + z, w.first); - return uint128(HashLen16(x + v.second, w.second) + y, - HashLen16(x + w.second, y + v.second)); +uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) +{ + if (len < 128) + { + return CityMurmur(s, len, seed); + } + // We expect len >= 128 to be the common case. Keep 56 bytes of state: + // v, w, x, y, and z. + pair v, w; + uint64 x = Uint128Low64(seed); + uint64 y = Uint128High64(seed); + uint64 z = len * k1; + v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s); + v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8); + w.first = Rotate(y + z, 35) * k1 + x; + w.second = Rotate(x + Fetch64(s + 88), 53) * k1; + // This is the same inner loop as CityHash64(), manually unrolled. + do + { + x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; + y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; + x ^= w.second; + y += v.first + Fetch64(s + 40); + z = Rotate(z + w.first, 33) * k1; + v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); + w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); + std::swap(z, x); + s += 64; + x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; + y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; + x ^= w.second; + y += v.first + Fetch64(s + 40); + z = Rotate(z + w.first, 33) * k1; + v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); + w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); + std::swap(z, x); + s += 64; + len -= 128; + } + while (LIKELY(len >= 128)); + x += Rotate(v.first + z, 49) * k0; + y = y * k0 + Rotate(w.second, 37); + z = z * k0 + Rotate(w.first, 27); + w.first *= 9; + v.first *= k0; + // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s. + for (size_t tail_done = 0; tail_done < len; ) + { + tail_done += 32; + y = Rotate(x + y, 42) * k0 + v.second; + w.first += Fetch64(s + len - tail_done + 16); + x = x * k0 + w.first; + z += w.second + Fetch64(s + len - tail_done); + w.second += v.first; + v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second); + v.first *= k0; + } + // At this point our 56 bytes of state should contain more than + // enough information for a strong 128-bit hash. We use two + // different 56-byte-to-8-byte hashes to get a 16-byte final result. + x = HashLen16(x, v.first); + y = HashLen16(y + z, w.first); + return uint128(HashLen16(x + v.second, w.second) + y, + HashLen16(x + w.second, y + v.second)); } -uint128 CityHash128(const char *s, size_t len) { - return len >= 16 ? - CityHash128WithSeed(s + 16, len - 16, - uint128(Fetch64(s), Fetch64(s + 8) + k0)) : - CityHash128WithSeed(s, len, uint128(k0, k1)); +uint128 CityHash128(const char *s, size_t len) +{ + return len >= 16 ? + CityHash128WithSeed(s + 16, len - 16, + uint128(Fetch64(s), Fetch64(s + 8) + k0)) : + CityHash128WithSeed(s, len, uint128(k0, k1)); } #ifdef __SSE4_2__ @@ -513,129 +556,150 @@ uint128 CityHash128(const char *s, size_t len) { // Requires len >= 240. static void CityHashCrc256Long(const char *s, size_t len, - uint32 seed, uint64 *result) { - uint64 a = Fetch64(s + 56) + k0; - uint64 b = Fetch64(s + 96) + k0; - uint64 c = result[0] = HashLen16(b, len); - uint64 d = result[1] = Fetch64(s + 120) * k0 + len; - uint64 e = Fetch64(s + 184) + seed; - uint64 f = 0; - uint64 g = 0; - uint64 h = c + d; - uint64 x = seed; - uint64 y = 0; - uint64 z = 0; - - // 240 bytes of input per iter. - size_t iters = len / 240; - len -= iters * 240; - do { + uint32 seed, uint64 *result) +{ + uint64 a = Fetch64(s + 56) + k0; + uint64 b = Fetch64(s + 96) + k0; + uint64 c = result[0] = HashLen16(b, len); + uint64 d = result[1] = Fetch64(s + 120) * k0 + len; + uint64 e = Fetch64(s + 184) + seed; + uint64 f = 0; + uint64 g = 0; + uint64 h = c + d; + uint64 x = seed; + uint64 y = 0; + uint64 z = 0; + // 240 bytes of input per iter. + size_t iters = len / 240; + len -= iters * 240; + do + { #undef CHUNK #define CHUNK(r) \ - PERMUTE3(x, z, y); \ - b += Fetch64(s); \ - c += Fetch64(s + 8); \ - d += Fetch64(s + 16); \ - e += Fetch64(s + 24); \ - f += Fetch64(s + 32); \ - a += b; \ - h += f; \ - b += c; \ - f += d; \ - g += e; \ - e += z; \ - g += x; \ - z = _mm_crc32_u64(z, b + g); \ - y = _mm_crc32_u64(y, e + h); \ - x = _mm_crc32_u64(x, f + a); \ - e = Rotate(e, r); \ - c += e; \ - s += 40 - - CHUNK(0); PERMUTE3(a, h, c); - CHUNK(33); PERMUTE3(a, h, f); - CHUNK(0); PERMUTE3(b, h, f); - CHUNK(42); PERMUTE3(b, h, d); - CHUNK(0); PERMUTE3(b, h, e); - CHUNK(33); PERMUTE3(a, h, e); - } while (--iters > 0); - - while (len >= 40) { - CHUNK(29); - e ^= Rotate(a, 20); - h += Rotate(b, 30); - g ^= Rotate(c, 40); - f += Rotate(d, 34); - PERMUTE3(c, h, g); - len -= 40; - } - if (len > 0) { - s = s + len - 40; - CHUNK(33); - e ^= Rotate(a, 43); - h += Rotate(b, 42); - g ^= Rotate(c, 41); - f += Rotate(d, 40); - } - result[0] ^= h; - result[1] ^= g; - g += h; - a = HashLen16(a, g + z); - x += y << 32; - b += x; - c = HashLen16(c, z) + h; - d = HashLen16(d, e + result[0]); - g += e; - h += HashLen16(x, f); - e = HashLen16(a, d) + g; - z = HashLen16(b, c) + a; - y = HashLen16(g, h) + c; - result[0] = e + z + y + x; - a = ShiftMix((a + y) * k0) * k0 + b; - result[1] += a + result[0]; - a = ShiftMix(a * k0) * k0 + c; - result[2] = a + result[1]; - a = ShiftMix((a + e) * k0) * k0; - result[3] = a + result[2]; + PERMUTE3(x, z, y); \ + b += Fetch64(s); \ + c += Fetch64(s + 8); \ + d += Fetch64(s + 16); \ + e += Fetch64(s + 24); \ + f += Fetch64(s + 32); \ + a += b; \ + h += f; \ + b += c; \ + f += d; \ + g += e; \ + e += z; \ + g += x; \ + z = _mm_crc32_u64(z, b + g); \ + y = _mm_crc32_u64(y, e + h); \ + x = _mm_crc32_u64(x, f + a); \ + e = Rotate(e, r); \ + c += e; \ + s += 40 + CHUNK(0); + PERMUTE3(a, h, c); + CHUNK(33); + PERMUTE3(a, h, f); + CHUNK(0); + PERMUTE3(b, h, f); + CHUNK(42); + PERMUTE3(b, h, d); + CHUNK(0); + PERMUTE3(b, h, e); + CHUNK(33); + PERMUTE3(a, h, e); + } + while (--iters > 0); + while (len >= 40) + { + CHUNK(29); + e ^= Rotate(a, 20); + h += Rotate(b, 30); + g ^= Rotate(c, 40); + f += Rotate(d, 34); + PERMUTE3(c, h, g); + len -= 40; + } + if (len > 0) + { + s = s + len - 40; + CHUNK(33); + e ^= Rotate(a, 43); + h += Rotate(b, 42); + g ^= Rotate(c, 41); + f += Rotate(d, 40); + } + result[0] ^= h; + result[1] ^= g; + g += h; + a = HashLen16(a, g + z); + x += y << 32; + b += x; + c = HashLen16(c, z) + h; + d = HashLen16(d, e + result[0]); + g += e; + h += HashLen16(x, f); + e = HashLen16(a, d) + g; + z = HashLen16(b, c) + a; + y = HashLen16(g, h) + c; + result[0] = e + z + y + x; + a = ShiftMix((a + y) * k0) * k0 + b; + result[1] += a + result[0]; + a = ShiftMix(a * k0) * k0 + c; + result[2] = a + result[1]; + a = ShiftMix((a + e) * k0) * k0; + result[3] = a + result[2]; } // Requires len < 240. -static void CityHashCrc256Short(const char *s, size_t len, uint64 *result) { - char buf[240]; - memcpy(buf, s, len); - memset(buf + len, 0, 240 - len); - CityHashCrc256Long(buf, 240, ~static_cast(len), result); +static void CityHashCrc256Short(const char *s, size_t len, uint64 *result) +{ + char buf[240]; + memcpy(buf, s, len); + memset(buf + len, 0, 240 - len); + CityHashCrc256Long(buf, 240, ~static_cast(len), result); } -void CityHashCrc256(const char *s, size_t len, uint64 *result) { - if (LIKELY(len >= 240)) { - CityHashCrc256Long(s, len, 0, result); - } else { - CityHashCrc256Short(s, len, result); - } +void CityHashCrc256(const char *s, size_t len, uint64 *result) +{ + if (LIKELY(len >= 240)) + { + CityHashCrc256Long(s, len, 0, result); + } + else + { + CityHashCrc256Short(s, len, result); + } } -uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) { - if (len <= 900) { - return CityHash128WithSeed(s, len, seed); - } else { - uint64 result[4]; - CityHashCrc256(s, len, result); - uint64 u = Uint128High64(seed) + result[0]; - uint64 v = Uint128Low64(seed) + result[1]; - return uint128(HashLen16(u, v + result[2]), - HashLen16(Rotate(v, 32), u * k0 + result[3])); - } +uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) +{ + if (len <= 900) + { + return CityHash128WithSeed(s, len, seed); + } + else + { + uint64 result[4]; + CityHashCrc256(s, len, result); + uint64 u = Uint128High64(seed) + result[0]; + uint64 v = Uint128Low64(seed) + result[1]; + return uint128(HashLen16(u, v + result[2]), + HashLen16(Rotate(v, 32), u * k0 + result[3])); + } } -uint128 CityHashCrc128(const char *s, size_t len) { - if (len <= 900) { - return CityHash128(s, len); - } else { - uint64 result[4]; - CityHashCrc256(s, len, result); - return uint128(result[2], result[3]); - } +uint128 CityHashCrc128(const char *s, size_t len) +{ + if (len <= 900) + { + return CityHash128(s, len); + } + else + { + uint64 result[4]; + CityHashCrc256(s, len, result); + return uint128(result[2], result[3]); + } } #endif diff --git a/cityhash/city.h b/cityhash/city.h index cb2ac7925..e1b8c28df 100644 --- a/cityhash/city.h +++ b/cityhash/city.h @@ -70,8 +70,8 @@ typedef std::pair uint128_t; -inline uint64_t Uint128Low64(const uint128_t& x) { return x.first; } -inline uint64_t Uint128High64(const uint128_t& x) { return x.second; } +inline uint64_t Uint128Low64(const uint128_t &x) { return x.first; } +inline uint64_t Uint128High64(const uint128_t &x) { return x.second; } // Hash function for a byte array. uint64_t CityHash64(const char *buf, size_t len); @@ -97,15 +97,16 @@ uint32_t CityHash32(const char *buf, size_t len); // Hash 128 input bits down to 64 bits of output. // This is intended to be a reasonably good hash function. -inline uint64_t Hash128to64(const uint128_t& x) { - // Murmur-inspired hashing. - const uint64_t kMul = 0x9ddfea08eb382d69ULL; - uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; - a ^= (a >> 47); - uint64_t b = (Uint128High64(x) ^ a) * kMul; - b ^= (b >> 47); - b *= kMul; - return b; +inline uint64_t Hash128to64(const uint128_t &x) +{ + // Murmur-inspired hashing. + const uint64_t kMul = 0x9ddfea08eb382d69ULL; + uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; + a ^= (a >> 47); + uint64_t b = (Uint128High64(x) ^ a) * kMul; + b ^= (b >> 47); + b *= kMul; + return b; } #endif // CITY_HASH_H_ diff --git a/cityhash/test/city.cc b/cityhash/test/city.cc index 6e580d926..812e21d98 100644 --- a/cityhash/test/city.cc +++ b/cityhash/test/city.cc @@ -44,1294 +44,1905 @@ static char data[kDataSize]; static int errors = 0; // global error count // Initialize data to pseudorandom values. -void setup() { - uint64 a = 9; - uint64 b = 777; - for (int i = 0; i < kDataSize; i++) { - a += b; - b += a; - a = (a ^ (a >> 41)) * k0; - b = (b ^ (b >> 41)) * k0 + i; - uint8 u = b >> 37; - memcpy(data + i, &u, 1); // uint8 -> char - } +void setup() +{ + uint64 a = 9; + uint64 b = 777; + for (int i = 0; i < kDataSize; i++) + { + a += b; + b += a; + a = (a ^ (a >> 41)) * k0; + b = (b ^ (b >> 41)) * k0 + i; + uint8 u = b >> 37; + memcpy(data + i, &u, 1); // uint8 -> char + } } #if 1 #define C(x) 0x ## x ## ULL -static const uint64 testdata[kTestSize][16] = { -{C(9ae16a3b2f90404f), C(75106db890237a4a), C(3feac5f636039766), C(3df09dfc64c09a2b), C(3cb540c392e51e29), C(6b56343feac0663), C(5b7bc50fd8e8ad92), -C(3df09dfc64c09a2b), C(3cb540c392e51e29), C(6b56343feac0663), C(5b7bc50fd8e8ad92), -C(95162f24e6a5f930), C(6808bdf4f1eb06e0), C(b3b1f3a67b624d82), C(c9a62f12bd4cd80b), -C(dc56d17a)}, -{C(541150e87f415e96), C(1aef0d24b3148a1a), C(bacc300e1e82345a), C(c3cdc41e1df33513), C(2c138ff2596d42f6), C(f58e9082aed3055f), C(162e192b2957163d), -C(c3cdc41e1df33513), C(2c138ff2596d42f6), C(f58e9082aed3055f), C(162e192b2957163d), -C(fb99e85e0d16f90c), C(608462c15bdf27e8), C(e7d2c5c943572b62), C(1baaa9327642798c), -C(99929334)}, -{C(f3786a4b25827c1), C(34ee1a2bf767bd1c), C(2f15ca2ebfb631f2), C(3149ba1dac77270d), C(70e2e076e30703c), C(59bcc9659bc5296), C(9ecbc8132ae2f1d7), -C(3149ba1dac77270d), C(70e2e076e30703c), C(59bcc9659bc5296), C(9ecbc8132ae2f1d7), -C(a01d30789bad7cf2), C(ae03fe371981a0e0), C(127e3883b8788934), C(d0ac3d4c0a6fca32), -C(4252edb7)}, -{C(ef923a7a1af78eab), C(79163b1e1e9a9b18), C(df3b2aca6e1e4a30), C(2193fb7620cbf23b), C(8b6a8ff06cda8302), C(1a44469afd3e091f), C(8b0449376612506), -C(2193fb7620cbf23b), C(8b6a8ff06cda8302), C(1a44469afd3e091f), C(8b0449376612506), -C(e9d9d41c32ad91d1), C(b44ab09f58e3c608), C(19e9175f9fcf784), C(839b3c9581b4a480), -C(ebc34f3c)}, -{C(11df592596f41d88), C(843ec0bce9042f9c), C(cce2ea1e08b1eb30), C(4d09e42f09cc3495), C(666236631b9f253b), C(d28b3763cd02b6a3), C(43b249e57c4d0c1b), -C(4d09e42f09cc3495), C(666236631b9f253b), C(d28b3763cd02b6a3), C(43b249e57c4d0c1b), -C(3887101c8adea101), C(8a9355d4efc91df0), C(3e610944cc9fecfd), C(5bf9eb60b08ac0ce), -C(26f2b463)}, -{C(831f448bdc5600b3), C(62a24be3120a6919), C(1b44098a41e010da), C(dc07df53b949c6b), C(d2b11b2081aeb002), C(d212b02c1b13f772), C(c0bed297b4be1912), -C(dc07df53b949c6b), C(d2b11b2081aeb002), C(d212b02c1b13f772), C(c0bed297b4be1912), -C(682d3d2ad304e4af), C(40e9112a655437a1), C(268b09f7ee09843f), C(6b9698d43859ca47), -C(b042c047)}, -{C(3eca803e70304894), C(d80de767e4a920a), C(a51cfbb292efd53d), C(d183dcda5f73edfa), C(3a93cbf40f30128c), C(1a92544d0b41dbda), C(aec2c4bee81975e1), -C(d183dcda5f73edfa), C(3a93cbf40f30128c), C(1a92544d0b41dbda), C(aec2c4bee81975e1), -C(5f91814d1126ba4b), C(f8ac57eee87fcf1f), C(c55c644a5d0023cd), C(adb761e827825ff2), -C(e73bb0a8)}, -{C(1b5a063fb4c7f9f1), C(318dbc24af66dee9), C(10ef7b32d5c719af), C(b140a02ef5c97712), C(b7d00ef065b51b33), C(635121d532897d98), C(532daf21b312a6d6), -C(b140a02ef5c97712), C(b7d00ef065b51b33), C(635121d532897d98), C(532daf21b312a6d6), -C(c0b09b75d943910), C(8c84dfb5ef2a8e96), C(e5c06034b0353433), C(3170faf1c33a45dd), -C(91dfdd75)}, -{C(a0f10149a0e538d6), C(69d008c20f87419f), C(41b36376185b3e9e), C(26b6689960ccf81d), C(55f23b27bb9efd94), C(3a17f6166dd765db), C(c891a8a62931e782), -C(26b6689960ccf81d), C(55f23b27bb9efd94), C(3a17f6166dd765db), C(c891a8a62931e782), -C(23852dc37ddd2607), C(8b7f1b1ec897829e), C(d1d69452a54eed8a), C(56431f2bd766ec24), -C(c87f95de)}, -{C(fb8d9c70660b910b), C(a45b0cc3476bff1b), C(b28d1996144f0207), C(98ec31113e5e35d2), C(5e4aeb853f1b9aa7), C(bcf5c8fe4465b7c8), C(b1ea3a8243996f15), -C(98ec31113e5e35d2), C(5e4aeb853f1b9aa7), C(bcf5c8fe4465b7c8), C(b1ea3a8243996f15), -C(cabbccedb6407571), C(d1e40a84c445ec3a), C(33302aa908cf4039), C(9f15f79211b5cdf8), -C(3f5538ef)}, -{C(236827beae282a46), C(e43970221139c946), C(4f3ac6faa837a3aa), C(71fec0f972248915), C(2170ec2061f24574), C(9eb346b6caa36e82), C(2908f0fdbca48e73), -C(71fec0f972248915), C(2170ec2061f24574), C(9eb346b6caa36e82), C(2908f0fdbca48e73), -C(8101c99f07c64abb), C(b9f4b02b1b6a96a7), C(583a2b10cd222f88), C(199dae4cf9db24c), -C(70eb1a1f)}, -{C(c385e435136ecf7c), C(d9d17368ff6c4a08), C(1b31eed4e5251a67), C(df01a322c43a6200), C(298b65a1714b5a7e), C(933b83f0aedf23c), C(157bcb44d63f765a), -C(df01a322c43a6200), C(298b65a1714b5a7e), C(933b83f0aedf23c), C(157bcb44d63f765a), -C(d6e9fc7a272d8b51), C(3ee5073ef1a9b777), C(63149e31fac02c59), C(2f7979ff636ba1d8), -C(cfd63b83)}, -{C(e3f6828b6017086d), C(21b4d1900554b3b0), C(bef38be1809e24f1), C(d93251758985ee6c), C(32a9e9f82ba2a932), C(3822aacaa95f3329), C(db349b2f90a490d8), -C(d93251758985ee6c), C(32a9e9f82ba2a932), C(3822aacaa95f3329), C(db349b2f90a490d8), -C(8d49194a894a19ca), C(79a78b06e42738e6), C(7e0f1eda3d390c66), C(1c291d7e641100a5), -C(894a52ef)}, -{C(851fff285561dca0), C(4d1277d73cdf416f), C(28ccffa61010ebe2), C(77a4ccacd131d9ee), C(e1d08eeb2f0e29aa), C(70b9e3051383fa45), C(582d0120425caba), -C(77a4ccacd131d9ee), C(e1d08eeb2f0e29aa), C(70b9e3051383fa45), C(582d0120425caba), -C(a740eef1846e4564), C(572dddb74ac3ae00), C(fdb5ca9579163bbd), C(a649b9b799c615d2), -C(9cde6a54)}, -{C(61152a63595a96d9), C(d1a3a91ef3a7ba45), C(443b6bb4a493ad0c), C(a154296d11362d06), C(d0f0bf1f1cb02fc1), C(ccb87e09309f90d1), C(b24a8e4881911101), -C(a154296d11362d06), C(d0f0bf1f1cb02fc1), C(ccb87e09309f90d1), C(b24a8e4881911101), -C(1a481b4528559f58), C(bf837a3150896995), C(4989ef6b941a3757), C(2e725ab72d0b2948), -C(6c4898d5)}, -{C(44473e03be306c88), C(30097761f872472a), C(9fd1b669bfad82d7), C(3bab18b164396783), C(47e385ff9d4c06f), C(18062081bf558df), C(63416eb68f104a36), -C(3bab18b164396783), C(47e385ff9d4c06f), C(18062081bf558df), C(63416eb68f104a36), -C(4abda1560c47ac80), C(1ea0e63dc6587aee), C(33ec79d92ebc1de), C(94f9dccef771e048), -C(13e1978e)}, -{C(3ead5f21d344056), C(fb6420393cfb05c3), C(407932394cbbd303), C(ac059617f5906673), C(94d50d3dcd3069a7), C(2b26c3b92dea0f0), C(99b7374cc78fc3fb), -C(ac059617f5906673), C(94d50d3dcd3069a7), C(2b26c3b92dea0f0), C(99b7374cc78fc3fb), -C(1a8e3c73cdd40ee8), C(cbb5fca06747f45b), C(ceec44238b291841), C(28bf35cce9c90a25), -C(51b4ba8)}, -{C(6abbfde37ee03b5b), C(83febf188d2cc113), C(cda7b62d94d5b8ee), C(a4375590b8ae7c82), C(168fd42f9ecae4ff), C(23bbde43de2cb214), C(a8c333112a243c8c), -C(a4375590b8ae7c82), C(168fd42f9ecae4ff), C(23bbde43de2cb214), C(a8c333112a243c8c), -C(10ac012e8c518b49), C(64a44605d8b29458), C(a67e701d2a679075), C(3a3a20f43ec92303), -C(b6b06e40)}, -{C(943e7ed63b3c080), C(1ef207e9444ef7f8), C(ef4a9f9f8c6f9b4a), C(6b54fc38d6a84108), C(32f4212a47a4665), C(6b5a9a8f64ee1da6), C(9f74e86c6da69421), -C(6b54fc38d6a84108), C(32f4212a47a4665), C(6b5a9a8f64ee1da6), C(9f74e86c6da69421), -C(946dd0cb30c1a08e), C(fdf376956907eaaa), C(a59074c6eec03028), C(b1a3abcf283f34ac), -C(240a2f2)}, -{C(d72ce05171ef8a1a), C(c6bd6bd869203894), C(c760e6396455d23a), C(f86af0b40dcce7b), C(8d3c15d613394d3c), C(491e400491cd4ece), C(7c19d3530ea3547f), -C(f86af0b40dcce7b), C(8d3c15d613394d3c), C(491e400491cd4ece), C(7c19d3530ea3547f), -C(1362963a1dc32af9), C(fb9bc11762e1385c), C(9e164ef1f5376083), C(6c15819b5e828a7e), -C(5dcefc30)}, -{C(4182832b52d63735), C(337097e123eea414), C(b5a72ca0456df910), C(7ebc034235bc122f), C(d9a7783d4edd8049), C(5f8b04a15ae42361), C(fc193363336453dd), -C(7ebc034235bc122f), C(d9a7783d4edd8049), C(5f8b04a15ae42361), C(fc193363336453dd), -C(9b6c50224ef8c4f8), C(ba225c7942d16c3f), C(6f6d55226a73c412), C(abca061fe072152a), -C(7a48b105)}, -{C(d6cdae892584a2cb), C(58de0fa4eca17dcd), C(43df30b8f5f1cb00), C(9e4ea5a4941e097d), C(547e048d5a9daaba), C(eb6ecbb0b831d185), C(e0168df5fad0c670), -C(9e4ea5a4941e097d), C(547e048d5a9daaba), C(eb6ecbb0b831d185), C(e0168df5fad0c670), -C(afa9705f98c2c96a), C(749436f48137a96b), C(759c041fc21df486), C(b23bf400107aa2ec), -C(fd55007b)}, -{C(5c8e90bc267c5ee4), C(e9ae044075d992d9), C(f234cbfd1f0a1e59), C(ce2744521944f14c), C(104f8032f99dc152), C(4e7f425bfac67ca7), C(9461b911a1c6d589), -C(ce2744521944f14c), C(104f8032f99dc152), C(4e7f425bfac67ca7), C(9461b911a1c6d589), -C(5e5ecc726db8b60d), C(cce68b0586083b51), C(8a7f8e54a9cba0fc), C(42f010181d16f049), -C(6b95894c)}, -{C(bbd7f30ac310a6f3), C(b23b570d2666685f), C(fb13fb08c9814fe7), C(4ee107042e512374), C(1e2c8c0d16097e13), C(210c7500995aa0e6), C(6c13190557106457), -C(4ee107042e512374), C(1e2c8c0d16097e13), C(210c7500995aa0e6), C(6c13190557106457), -C(a99b31c96777f381), C(8312ae8301d386c0), C(ed5042b2a4fa96a3), C(d71d1bb23907fe97), -C(3360e827)}, -{C(36a097aa49519d97), C(8204380a73c4065), C(77c2004bdd9e276a), C(6ee1f817ce0b7aee), C(e9dcb3507f0596ca), C(6bc63c666b5100e2), C(e0b056f1821752af), -C(6ee1f817ce0b7aee), C(e9dcb3507f0596ca), C(6bc63c666b5100e2), C(e0b056f1821752af), -C(8ea1114e60292678), C(904b80b46becc77), C(46cd9bb6e9dff52f), C(4c91e3b698355540), -C(45177e0b)}, -{C(dc78cb032c49217), C(112464083f83e03a), C(96ae53e28170c0f5), C(d367ff54952a958), C(cdad930657371147), C(aa24dc2a9573d5fe), C(eb136daa89da5110), -C(d367ff54952a958), C(cdad930657371147), C(aa24dc2a9573d5fe), C(eb136daa89da5110), -C(de623005f6d46057), C(b50c0c92b95e9b7f), C(a8aa54050b81c978), C(573fb5c7895af9b5), -C(7c6fffe4)}, -{C(441593e0da922dfe), C(936ef46061469b32), C(204a1921197ddd87), C(50d8a70e7a8d8f56), C(256d150ae75dab76), C(e81f4c4a1989036a), C(d0f8db365f9d7e00), -C(50d8a70e7a8d8f56), C(256d150ae75dab76), C(e81f4c4a1989036a), C(d0f8db365f9d7e00), -C(753d686677b14522), C(9f76e0cb6f2d0a66), C(ab14f95988ec0d39), C(97621d9da9c9812f), -C(bbc78da4)}, -{C(2ba3883d71cc2133), C(72f2bbb32bed1a3c), C(27e1bd96d4843251), C(a90f761e8db1543a), C(c339e23c09703cd8), C(f0c6624c4b098fd3), C(1bae2053e41fa4d9), -C(a90f761e8db1543a), C(c339e23c09703cd8), C(f0c6624c4b098fd3), C(1bae2053e41fa4d9), -C(3589e273c22ba059), C(63798246e5911a0b), C(18e710ec268fc5dc), C(714a122de1d074f3), -C(c5c25d39)}, -{C(f2b6d2adf8423600), C(7514e2f016a48722), C(43045743a50396ba), C(23dacb811652ad4f), C(c982da480e0d4c7d), C(3a9c8ed5a399d0a9), C(951b8d084691d4e4), -C(23dacb811652ad4f), C(c982da480e0d4c7d), C(3a9c8ed5a399d0a9), C(951b8d084691d4e4), -C(d9f87b4988cff2f7), C(217a191d986aa3bc), C(6ad23c56b480350), C(dd78673938ceb2e7), -C(b6e5d06e)}, -{C(38fffe7f3680d63c), C(d513325255a7a6d1), C(31ed47790f6ca62f), C(c801faaa0a2e331f), C(491dbc58279c7f88), C(9c0178848321c97a), C(9d934f814f4d6a3c), -C(c801faaa0a2e331f), C(491dbc58279c7f88), C(9c0178848321c97a), C(9d934f814f4d6a3c), -C(606a3e4fc8763192), C(bc15cb36a677ee84), C(52d5904157e1fe71), C(1588dd8b1145b79b), -C(6178504e)}, -{C(b7477bf0b9ce37c6), C(63b1c580a7fd02a4), C(f6433b9f10a5dac), C(68dd76db9d64eca7), C(36297682b64b67), C(42b192d71f414b7a), C(79692cef44fa0206), -C(68dd76db9d64eca7), C(36297682b64b67), C(42b192d71f414b7a), C(79692cef44fa0206), -C(f0979252f4776d07), C(4b87cd4f1c9bbf52), C(51b84bbc6312c710), C(150720fbf85428a7), -C(bd4c3637)}, -{C(55bdb0e71e3edebd), C(c7ab562bcf0568bc), C(43166332f9ee684f), C(b2e25964cd409117), C(a010599d6287c412), C(fa5d6461e768dda2), C(cb3ce74e8ec4f906), -C(b2e25964cd409117), C(a010599d6287c412), C(fa5d6461e768dda2), C(cb3ce74e8ec4f906), -C(6120abfd541a2610), C(aa88b148cc95794d), C(2686ca35df6590e3), C(c6b02d18616ce94d), -C(6e7ac474)}, -{C(782fa1b08b475e7), C(fb7138951c61b23b), C(9829105e234fb11e), C(9a8c431f500ef06e), C(d848581a580b6c12), C(fecfe11e13a2bdb4), C(6c4fa0273d7db08c), -C(9a8c431f500ef06e), C(d848581a580b6c12), C(fecfe11e13a2bdb4), C(6c4fa0273d7db08c), -C(482f43bf5ae59fcb), C(f651fbca105d79e6), C(f09f78695d865817), C(7a99d0092085cf47), -C(1fb4b518)}, -{C(c5dc19b876d37a80), C(15ffcff666cfd710), C(e8c30c72003103e2), C(7870765b470b2c5d), C(78a9103ff960d82), C(7bb50ffc9fac74b3), C(477e70ab2b347db2), -C(7870765b470b2c5d), C(78a9103ff960d82), C(7bb50ffc9fac74b3), C(477e70ab2b347db2), -C(a625238bdf7c07cf), C(1128d515174809f5), C(b0f1647e82f45873), C(17792d1c4f222c39), -C(31d13d6d)}, -{C(5e1141711d2d6706), C(b537f6dee8de6933), C(3af0a1fbbe027c54), C(ea349dbc16c2e441), C(38a7455b6a877547), C(5f97b9750e365411), C(e8cde7f93af49a3), -C(ea349dbc16c2e441), C(38a7455b6a877547), C(5f97b9750e365411), C(e8cde7f93af49a3), -C(ba101925ec1f7e26), C(d5e84cab8192c71e), C(e256427726fdd633), C(a4f38e2c6116890d), -C(26fa72e3)}, -{C(782edf6da001234f), C(f48cbd5c66c48f3), C(808754d1e64e2a32), C(5d9dde77353b1a6d), C(11f58c54581fa8b1), C(da90fa7c28c37478), C(5e9a2eafc670a88a), -C(5d9dde77353b1a6d), C(11f58c54581fa8b1), C(da90fa7c28c37478), C(5e9a2eafc670a88a), -C(e35e1bc172e011ef), C(bf9255a4450ae7fe), C(55f85194e26bc55f), C(4f327873e14d0e54), -C(6a7433bf)}, -{C(d26285842ff04d44), C(8f38d71341eacca9), C(5ca436f4db7a883c), C(bf41e5376b9f0eec), C(2252d21eb7e1c0e9), C(f4b70a971855e732), C(40c7695aa3662afd), -C(bf41e5376b9f0eec), C(2252d21eb7e1c0e9), C(f4b70a971855e732), C(40c7695aa3662afd), -C(770fe19e16ab73bb), C(d603ebda6393d749), C(e58c62439aa50dbd), C(96d51e5a02d2d7cf), -C(4e6df758)}, -{C(c6ab830865a6bae6), C(6aa8e8dd4b98815c), C(efe3846713c371e5), C(a1924cbf0b5f9222), C(7f4872369c2b4258), C(cd6da30530f3ea89), C(b7f8b9a704e6cea1), -C(a1924cbf0b5f9222), C(7f4872369c2b4258), C(cd6da30530f3ea89), C(b7f8b9a704e6cea1), -C(fa06ff40433fd535), C(fb1c36fe8f0737f1), C(bb7050561171f80), C(b1bc23235935d897), -C(d57f63ea)}, -{C(44b3a1929232892), C(61dca0e914fc217), C(a607cc142096b964), C(f7dbc8433c89b274), C(2f5f70581c9b7d32), C(39bf5e5fec82dcca), C(8ade56388901a619), -C(f7dbc8433c89b274), C(2f5f70581c9b7d32), C(39bf5e5fec82dcca), C(8ade56388901a619), -C(c1c6a725caab3ea9), C(c1c7906c2f80b898), C(9c3871a04cc884e6), C(df01813cbbdf217f), -C(52ef73b3)}, -{C(4b603d7932a8de4f), C(fae64c464b8a8f45), C(8fafab75661d602a), C(8ffe870ef4adc087), C(65bea2be41f55b54), C(82f3503f636aef1), C(5f78a282378b6bb0), -C(8ffe870ef4adc087), C(65bea2be41f55b54), C(82f3503f636aef1), C(5f78a282378b6bb0), -C(7bf2422c0beceddb), C(9d238d4780114bd), C(7ad198311906597f), C(ec8f892c0422aca3), -C(3cb36c3)}, -{C(4ec0b54cf1566aff), C(30d2c7269b206bf4), C(77c22e82295e1061), C(3df9b04434771542), C(feddce785ccb661f), C(a644aff716928297), C(dd46aee73824b4ed), -C(3df9b04434771542), C(feddce785ccb661f), C(a644aff716928297), C(dd46aee73824b4ed), -C(bf8d71879da29b02), C(fc82dccbfc8022a0), C(31bfcd0d9f48d1d3), C(c64ee24d0e7b5f8b), -C(72c39bea)}, -{C(ed8b7a4b34954ff7), C(56432de31f4ee757), C(85bd3abaa572b155), C(7d2c38a926dc1b88), C(5245b9eb4cd6791d), C(fb53ab03b9ad0855), C(3664026c8fc669d7), -C(7d2c38a926dc1b88), C(5245b9eb4cd6791d), C(fb53ab03b9ad0855), C(3664026c8fc669d7), -C(45024d5080bc196), C(b236ebec2cc2740), C(27231ad0e3443be4), C(145780b63f809250), -C(a65aa25c)}, -{C(5d28b43694176c26), C(714cc8bc12d060ae), C(3437726273a83fe6), C(864b1b28ec16ea86), C(6a78a5a4039ec2b9), C(8e959533e35a766), C(347b7c22b75ae65f), -C(864b1b28ec16ea86), C(6a78a5a4039ec2b9), C(8e959533e35a766), C(347b7c22b75ae65f), -C(5005892bb61e647c), C(fe646519b4a1894d), C(cd801026f74a8a53), C(8713463e9a1ab9ce), -C(74740539)}, -{C(6a1ef3639e1d202e), C(919bc1bd145ad928), C(30f3f7e48c28a773), C(2e8c49d7c7aaa527), C(5e2328fc8701db7c), C(89ef1afca81f7de8), C(b1857db11985d296), -C(2e8c49d7c7aaa527), C(5e2328fc8701db7c), C(89ef1afca81f7de8), C(b1857db11985d296), -C(17763d695f616115), C(b8f7bf1fcdc8322c), C(cf0c61938ab07a27), C(1122d3e6edb4e866), -C(c3ae3c26)}, -{C(159f4d9e0307b111), C(3e17914a5675a0c), C(af849bd425047b51), C(3b69edadf357432b), C(3a2e311c121e6bf2), C(380fad1e288d57e5), C(bf7c7e8ef0e3b83a), -C(3b69edadf357432b), C(3a2e311c121e6bf2), C(380fad1e288d57e5), C(bf7c7e8ef0e3b83a), -C(92966d5f4356ae9b), C(2a03fc66c4d6c036), C(2516d8bddb0d5259), C(b3ffe9737ff5090), -C(f29db8a2)}, -{C(cc0a840725a7e25b), C(57c69454396e193a), C(976eaf7eee0b4540), C(cd7a46850b95e901), C(c57f7d060dda246f), C(6b9406ead64079bf), C(11b28e20a573b7bd), -C(cd7a46850b95e901), C(c57f7d060dda246f), C(6b9406ead64079bf), C(11b28e20a573b7bd), -C(2d6db356e9369ace), C(dc0afe10fba193), C(5cdb10885dbbfce), C(5c700e205782e35a), -C(1ef4cbf4)}, -{C(a2b27ee22f63c3f1), C(9ebde0ce1b3976b2), C(2fe6a92a257af308), C(8c1df927a930af59), C(a462f4423c9e384e), C(236542255b2ad8d9), C(595d201a2c19d5bc), -C(8c1df927a930af59), C(a462f4423c9e384e), C(236542255b2ad8d9), C(595d201a2c19d5bc), -C(22c87d4604a67f3), C(585a06eb4bc44c4f), C(b4175a7ac7eabcd8), C(a457d3eeba14ab8c), -C(a9be6c41)}, -{C(d8f2f234899bcab3), C(b10b037297c3a168), C(debea2c510ceda7f), C(9498fefb890287ce), C(ae68c2be5b1a69a6), C(6189dfba34ed656c), C(91658f95836e5206), -C(9498fefb890287ce), C(ae68c2be5b1a69a6), C(6189dfba34ed656c), C(91658f95836e5206), -C(c0bb4fff32aecd4d), C(94125f505a50eef9), C(6ac406e7cfbce5bb), C(344a4b1dcdb7f5d8), -C(fa31801)}, -{C(584f28543864844f), C(d7cee9fc2d46f20d), C(a38dca5657387205), C(7a0b6dbab9a14e69), C(c6d0a9d6b0e31ac4), C(a674d85812c7cf6), C(63538c0351049940), -C(7a0b6dbab9a14e69), C(c6d0a9d6b0e31ac4), C(a674d85812c7cf6), C(63538c0351049940), -C(9710e5f0bc93d1d), C(c2bea5bd7c54ddd4), C(48739af2bed0d32d), C(ba2c4e09e21fba85), -C(8331c5d8)}, -{C(a94be46dd9aa41af), C(a57e5b7723d3f9bd), C(34bf845a52fd2f), C(843b58463c8df0ae), C(74b258324e916045), C(bdd7353230eb2b38), C(fad31fced7abade5), -C(843b58463c8df0ae), C(74b258324e916045), C(bdd7353230eb2b38), C(fad31fced7abade5), -C(2436aeafb0046f85), C(65bc9af9e5e33161), C(92733b1b3ae90628), C(f48143eaf78a7a89), -C(e9876db8)}, -{C(9a87bea227491d20), C(a468657e2b9c43e7), C(af9ba60db8d89ef7), C(cc76f429ea7a12bb), C(5f30eaf2bb14870a), C(434e824cb3e0cd11), C(431a4d382e39d16e), -C(cc76f429ea7a12bb), C(5f30eaf2bb14870a), C(434e824cb3e0cd11), C(431a4d382e39d16e), -C(9e51f913c4773a8), C(32ab1925823d0add), C(99c61b54c1d8f69d), C(38cfb80f02b43b1f), -C(27b0604e)}, -{C(27688c24958d1a5c), C(e3b4a1c9429cf253), C(48a95811f70d64bc), C(328063229db22884), C(67e9c95f8ba96028), C(7c6bf01c60436075), C(fa55161e7d9030b2), -C(328063229db22884), C(67e9c95f8ba96028), C(7c6bf01c60436075), C(fa55161e7d9030b2), -C(dadbc2f0dab91681), C(da39d7a4934ca11), C(162e845d24c1b45c), C(eb5b9dcd8c6ed31b), -C(dcec07f2)}, -{C(5d1d37790a1873ad), C(ed9cd4bcc5fa1090), C(ce51cde05d8cd96a), C(f72c26e624407e66), C(a0eb541bdbc6d409), C(c3f40a2f40b3b213), C(6a784de68794492d), -C(f72c26e624407e66), C(a0eb541bdbc6d409), C(c3f40a2f40b3b213), C(6a784de68794492d), -C(10a38a23dbef7937), C(6a5560f853252278), C(c3387bbf3c7b82ba), C(fbee7c12eb072805), -C(cff0a82a)}, -{C(1f03fd18b711eea9), C(566d89b1946d381a), C(6e96e83fc92563ab), C(405f66cf8cae1a32), C(d7261740d8f18ce6), C(fea3af64a413d0b2), C(d64d1810e83520fe), -C(405f66cf8cae1a32), C(d7261740d8f18ce6), C(fea3af64a413d0b2), C(d64d1810e83520fe), -C(e1334a00a580c6e8), C(454049e1b52c15f), C(8895d823d9778247), C(efa7f2e88b826618), -C(fec83621)}, -{C(f0316f286cf527b6), C(f84c29538de1aa5a), C(7612ed3c923d4a71), C(d4eccebe9393ee8a), C(2eb7867c2318cc59), C(1ce621fd700fe396), C(686450d7a346878a), -C(d4eccebe9393ee8a), C(2eb7867c2318cc59), C(1ce621fd700fe396), C(686450d7a346878a), -C(75a5f37579f8b4cb), C(500cc16eb6541dc7), C(b7b02317b539d9a6), C(3519ddff5bc20a29), -C(743d8dc)}, -{C(297008bcb3e3401d), C(61a8e407f82b0c69), C(a4a35bff0524fa0e), C(7a61d8f552a53442), C(821d1d8d8cfacf35), C(7cc06361b86d0559), C(119b617a8c2be199), -C(7a61d8f552a53442), C(821d1d8d8cfacf35), C(7cc06361b86d0559), C(119b617a8c2be199), -C(2996487da6721759), C(61a901376070b91d), C(d88dee12ae9c9b3c), C(5665491be1fa53a7), -C(64d41d26)}, -{C(43c6252411ee3be), C(b4ca1b8077777168), C(2746dc3f7da1737f), C(2247a4b2058d1c50), C(1b3fa184b1d7bcc0), C(deb85613995c06ed), C(cbe1d957485a3ccd), -C(2247a4b2058d1c50), C(1b3fa184b1d7bcc0), C(deb85613995c06ed), C(cbe1d957485a3ccd), -C(dfe241f8f33c96b6), C(6597eb05019c2109), C(da344b2a63a219cf), C(79b8e3887612378a), -C(acd90c81)}, -{C(ce38a9a54fad6599), C(6d6f4a90b9e8755e), C(c3ecc79ff105de3f), C(e8b9ee96efa2d0e), C(90122905c4ab5358), C(84f80c832d71979c), C(229310f3ffbbf4c6), -C(e8b9ee96efa2d0e), C(90122905c4ab5358), C(84f80c832d71979c), C(229310f3ffbbf4c6), -C(cc9eb42100cd63a7), C(7a283f2f3da7b9f), C(359b061d314e7a72), C(d0d959720028862), -C(7c746a4b)}, -{C(270a9305fef70cf), C(600193999d884f3a), C(f4d49eae09ed8a1), C(2e091b85660f1298), C(bfe37fae1cdd64c9), C(8dddfbab930f6494), C(2ccf4b08f5d417a), -C(2e091b85660f1298), C(bfe37fae1cdd64c9), C(8dddfbab930f6494), C(2ccf4b08f5d417a), -C(365c2ee85582fe6), C(dee027bcd36db62a), C(b150994d3c7e5838), C(fdfd1a0e692e436d), -C(b1047e99)}, -{C(e71be7c28e84d119), C(eb6ace59932736e6), C(70c4397807ba12c5), C(7a9d77781ac53509), C(4489c3ccfda3b39c), C(fa722d4f243b4964), C(25f15800bffdd122), -C(7a9d77781ac53509), C(4489c3ccfda3b39c), C(fa722d4f243b4964), C(25f15800bffdd122), -C(ed85e4157fbd3297), C(aab1967227d59efd), C(2199631212eb3839), C(3e4c19359aae1cc2), -C(d1fd1068)}, -{C(b5b58c24b53aaa19), C(d2a6ab0773dd897f), C(ef762fe01ecb5b97), C(9deefbcfa4cab1f1), C(b58f5943cd2492ba), C(a96dcc4d1f4782a7), C(102b62a82309dde5), -C(9deefbcfa4cab1f1), C(b58f5943cd2492ba), C(a96dcc4d1f4782a7), C(102b62a82309dde5), -C(35fe52684763b338), C(afe2616651eaad1f), C(43e38715bdfa05e7), C(83c9ba83b5ec4a40), -C(56486077)}, -{C(44dd59bd301995cf), C(3ccabd76493ada1a), C(540db4c87d55ef23), C(cfc6d7adda35797), C(14c7d1f32332cf03), C(2d553ffbff3be99d), C(c91c4ee0cb563182), -C(cfc6d7adda35797), C(14c7d1f32332cf03), C(2d553ffbff3be99d), C(c91c4ee0cb563182), -C(9aa5e507f49136f0), C(760c5dd1a82c4888), C(beea7e974a1cfb5c), C(640b247774fe4bf7), -C(6069be80)}, -{C(b4d4789eb6f2630b), C(bf6973263ce8ef0e), C(d1c75c50844b9d3), C(bce905900c1ec6ea), C(c30f304f4045487d), C(a5c550166b3a142b), C(2f482b4e35327287), -C(bce905900c1ec6ea), C(c30f304f4045487d), C(a5c550166b3a142b), C(2f482b4e35327287), -C(15b21ddddf355438), C(496471fa3006bab), C(2a8fd458d06c1a32), C(db91e8ae812f0b8d), -C(2078359b)}, -{C(12807833c463737c), C(58e927ea3b3776b4), C(72dd20ef1c2f8ad0), C(910b610de7a967bf), C(801bc862120f6bf5), C(9653efeed5897681), C(f5367ff83e9ebbb3), -C(910b610de7a967bf), C(801bc862120f6bf5), C(9653efeed5897681), C(f5367ff83e9ebbb3), -C(cf56d489afd1b0bf), C(c7c793715cae3de8), C(631f91d64abae47c), C(5f1f42fb14a444a2), -C(9ea21004)}, -{C(e88419922b87176f), C(bcf32f41a7ddbf6f), C(d6ebefd8085c1a0f), C(d1d44fe99451ef72), C(ec951ba8e51e3545), C(c0ca86b360746e96), C(aa679cc066a8040b), -C(d1d44fe99451ef72), C(ec951ba8e51e3545), C(c0ca86b360746e96), C(aa679cc066a8040b), -C(51065861ece6ffc1), C(76777368a2997e11), C(87f278f46731100c), C(bbaa4140bdba4527), -C(9c9cfe88)}, -{C(105191e0ec8f7f60), C(5918dbfcca971e79), C(6b285c8a944767b9), C(d3e86ac4f5eccfa4), C(e5399df2b106ca1), C(814aadfacd217f1d), C(2754e3def1c405a9), -C(d3e86ac4f5eccfa4), C(e5399df2b106ca1), C(814aadfacd217f1d), C(2754e3def1c405a9), -C(99290323b9f06e74), C(a9782e043f271461), C(13c8b3b8c275a860), C(6038d620e581e9e7), -C(b70a6ddd)}, -{C(a5b88bf7399a9f07), C(fca3ddfd96461cc4), C(ebe738fdc0282fc6), C(69afbc800606d0fb), C(6104b97a9db12df7), C(fcc09198bb90bf9f), C(c5e077e41a65ba91), -C(69afbc800606d0fb), C(6104b97a9db12df7), C(fcc09198bb90bf9f), C(c5e077e41a65ba91), -C(db261835ee8aa08e), C(db0ee662e5796dc9), C(fc1880ecec499e5f), C(648866fbe1502034), -C(dea37298)}, -{C(d08c3f5747d84f50), C(4e708b27d1b6f8ac), C(70f70fd734888606), C(909ae019d761d019), C(368bf4aab1b86ef9), C(308bd616d5460239), C(4fd33269f76783ea), -C(909ae019d761d019), C(368bf4aab1b86ef9), C(308bd616d5460239), C(4fd33269f76783ea), -C(7d53b37c19713eab), C(6bba6eabda58a897), C(91abb50efc116047), C(4e902f347e0e0e35), -C(8f480819)}, -{C(2f72d12a40044b4b), C(889689352fec53de), C(f03e6ad87eb2f36), C(ef79f28d874b9e2d), C(b512089e8e63b76c), C(24dc06833bf193a9), C(3c23308ba8e99d7e), -C(ef79f28d874b9e2d), C(b512089e8e63b76c), C(24dc06833bf193a9), C(3c23308ba8e99d7e), -C(5ceff7b85cacefb7), C(ef390338898cd73), C(b12967d7d2254f54), C(de874cbd8aef7b75), -C(30b3b16)}, -{C(aa1f61fdc5c2e11e), C(c2c56cd11277ab27), C(a1e73069fdf1f94f), C(8184bab36bb79df0), C(c81929ce8655b940), C(301b11bf8a4d8ce8), C(73126fd45ab75de9), -C(8184bab36bb79df0), C(c81929ce8655b940), C(301b11bf8a4d8ce8), C(73126fd45ab75de9), -C(4bd6f76e4888229a), C(9aae355b54a756d5), C(ca3de9726f6e99d5), C(83f80cac5bc36852), -C(f31bc4e8)}, -{C(9489b36fe2246244), C(3355367033be74b8), C(5f57c2277cbce516), C(bc61414f9802ecaf), C(8edd1e7a50562924), C(48f4ab74a35e95f2), C(cc1afcfd99a180e7), -C(bc61414f9802ecaf), C(8edd1e7a50562924), C(48f4ab74a35e95f2), C(cc1afcfd99a180e7), -C(517dd5e3acf66110), C(7dd3ad9e8978b30d), C(1f6d5dfc70de812b), C(947daaba6441aaf3), -C(419f953b)}, -{C(358d7c0476a044cd), C(e0b7b47bcbd8854f), C(ffb42ec696705519), C(d45e44c263e95c38), C(df61db53923ae3b1), C(f2bc948cc4fc027c), C(8a8000c6066772a3), -C(d45e44c263e95c38), C(df61db53923ae3b1), C(f2bc948cc4fc027c), C(8a8000c6066772a3), -C(9fd93c942d31fa17), C(d7651ecebe09cbd3), C(68682cefb6a6f165), C(541eb99a2dcee40e), -C(20e9e76d)}, -{C(b0c48df14275265a), C(9da4448975905efa), C(d716618e414ceb6d), C(30e888af70df1e56), C(4bee54bd47274f69), C(178b4059e1a0afe5), C(6e2c96b7f58e5178), -C(30e888af70df1e56), C(4bee54bd47274f69), C(178b4059e1a0afe5), C(6e2c96b7f58e5178), -C(bb429d3b9275e9bc), C(c198013f09cafdc6), C(ec0a6ee4fb5de348), C(744e1e8ed2eb1eb0), -C(646f0ff8)}, -{C(daa70bb300956588), C(410ea6883a240c6d), C(f5c8239fb5673eb3), C(8b1d7bb4903c105f), C(cfb1c322b73891d4), C(5f3b792b22f07297), C(fd64061f8be86811), -C(8b1d7bb4903c105f), C(cfb1c322b73891d4), C(5f3b792b22f07297), C(fd64061f8be86811), -C(1d2db712921cfc2b), C(cd1b2b2f2cee18ae), C(6b6f8790dc7feb09), C(46c179efa3f0f518), -C(eeb7eca8)}, -{C(4ec97a20b6c4c7c2), C(5913b1cd454f29fd), C(a9629f9daf06d685), C(852c9499156a8f3), C(3a180a6abfb79016), C(9fc3c4764037c3c9), C(2890c42fc0d972cf), -C(852c9499156a8f3), C(3a180a6abfb79016), C(9fc3c4764037c3c9), C(2890c42fc0d972cf), -C(1f92231d4e537651), C(fab8bb07aa54b7b9), C(e05d2d771c485ed4), C(d50b34bf808ca731), -C(8112bb9)}, -{C(5c3323628435a2e8), C(1bea45ce9e72a6e3), C(904f0a7027ddb52e), C(939f31de14dcdc7b), C(a68fdf4379df068), C(f169e1f0b835279d), C(7498e432f9619b27), -C(939f31de14dcdc7b), C(a68fdf4379df068), C(f169e1f0b835279d), C(7498e432f9619b27), -C(1aa2a1f11088e785), C(d6ad72f45729de78), C(9a63814157c80267), C(55538e35c648e435), -C(85a6d477)}, -{C(c1ef26bea260abdb), C(6ee423f2137f9280), C(df2118b946ed0b43), C(11b87fb1b900cc39), C(e33e59b90dd815b1), C(aa6cb5c4bafae741), C(739699951ca8c713), -C(11b87fb1b900cc39), C(e33e59b90dd815b1), C(aa6cb5c4bafae741), C(739699951ca8c713), -C(2b4389a967310077), C(1d5382568a31c2c9), C(55d1e787fbe68991), C(277c254bc31301e7), -C(56f76c84)}, -{C(6be7381b115d653a), C(ed046190758ea511), C(de6a45ffc3ed1159), C(a64760e4041447d0), C(e3eac49f3e0c5109), C(dd86c4d4cb6258e2), C(efa9857afd046c7f), -C(a64760e4041447d0), C(e3eac49f3e0c5109), C(dd86c4d4cb6258e2), C(efa9857afd046c7f), -C(fab793dae8246f16), C(c9e3b121b31d094c), C(a2a0f55858465226), C(dba6f0ff39436344), -C(9af45d55)}, -{C(ae3eece1711b2105), C(14fd3f4027f81a4a), C(abb7e45177d151db), C(501f3e9b18861e44), C(465201170074e7d8), C(96d5c91970f2cb12), C(40fd28c43506c95d), -C(501f3e9b18861e44), C(465201170074e7d8), C(96d5c91970f2cb12), C(40fd28c43506c95d), -C(e86c4b07802aaff3), C(f317d14112372a70), C(641b13e587711650), C(4915421ab1090eaa), -C(d1c33760)}, -{C(376c28588b8fb389), C(6b045e84d8491ed2), C(4e857effb7d4e7dc), C(154dd79fd2f984b4), C(f11171775622c1c3), C(1fbe30982e78e6f0), C(a460a15dcf327e44), -C(154dd79fd2f984b4), C(f11171775622c1c3), C(1fbe30982e78e6f0), C(a460a15dcf327e44), -C(f359e0900cc3d582), C(7e11070447976d00), C(324e6daf276ea4b5), C(7aa6e2df0cc94fa2), -C(c56bbf69)}, -{C(58d943503bb6748f), C(419c6c8e88ac70f6), C(586760cbf3d3d368), C(b7e164979d5ccfc1), C(12cb4230d26bf286), C(f1bf910d44bd84cb), C(b32c24c6a40272), -C(b7e164979d5ccfc1), C(12cb4230d26bf286), C(f1bf910d44bd84cb), C(b32c24c6a40272), -C(11ed12e34c48c039), C(b0c2538e51d0a6ac), C(4269bb773e1d553a), C(e35a9dbabd34867), -C(abecfb9b)}, -{C(dfff5989f5cfd9a1), C(bcee2e7ea3a96f83), C(681c7874adb29017), C(3ff6c8ac7c36b63a), C(48bc8831d849e326), C(30b078e76b0214e2), C(42954e6ad721b920), -C(3ff6c8ac7c36b63a), C(48bc8831d849e326), C(30b078e76b0214e2), C(42954e6ad721b920), -C(f9aeb33d164b4472), C(7b353b110831dbdc), C(16f64c82f44ae17b), C(b71244cc164b3b2b), -C(8de13255)}, -{C(7fb19eb1a496e8f5), C(d49e5dfdb5c0833f), C(c0d5d7b2f7c48dc7), C(1a57313a32f22dde), C(30af46e49850bf8b), C(aa0fe8d12f808f83), C(443e31d70873bb6b), -C(1a57313a32f22dde), C(30af46e49850bf8b), C(aa0fe8d12f808f83), C(443e31d70873bb6b), -C(bbeb67c49c9fdc13), C(18f1e2a88f59f9d5), C(fb1b05038e5def11), C(d0450b5ce4c39c52), -C(a98ee299)}, -{C(5dba5b0dadccdbaa), C(4ba8da8ded87fcdc), C(f693fdd25badf2f0), C(e9029e6364286587), C(ae69f49ecb46726c), C(18e002679217c405), C(bd6d66e85332ae9f), -C(e9029e6364286587), C(ae69f49ecb46726c), C(18e002679217c405), C(bd6d66e85332ae9f), -C(6bf330b1c353dd2a), C(74e9f2e71e3a4152), C(3f85560b50f6c413), C(d33a52a47eaed2b4), -C(3015f556)}, -{C(688bef4b135a6829), C(8d31d82abcd54e8e), C(f95f8a30d55036d7), C(3d8c90e27aa2e147), C(2ec937ce0aa236b4), C(89b563996d3a0b78), C(39b02413b23c3f08), -C(3d8c90e27aa2e147), C(2ec937ce0aa236b4), C(89b563996d3a0b78), C(39b02413b23c3f08), -C(8d475a2e64faf2d2), C(48567f7dca46ecaf), C(254cda08d5f87a6d), C(ec6ae9f729c47039), -C(5a430e29)}, -{C(d8323be05433a412), C(8d48fa2b2b76141d), C(3d346f23978336a5), C(4d50c7537562033f), C(57dc7625b61dfe89), C(9723a9f4c08ad93a), C(5309596f48ab456b), -C(4d50c7537562033f), C(57dc7625b61dfe89), C(9723a9f4c08ad93a), C(5309596f48ab456b), -C(7e453088019d220f), C(8776067ba6ab9714), C(67e1d06bd195de39), C(74a1a32f8994b918), -C(2797add0)}, -{C(3b5404278a55a7fc), C(23ca0b327c2d0a81), C(a6d65329571c892c), C(45504801e0e6066b), C(86e6c6d6152a3d04), C(4f3db1c53eca2952), C(d24d69b3e9ef10f3), -C(45504801e0e6066b), C(86e6c6d6152a3d04), C(4f3db1c53eca2952), C(d24d69b3e9ef10f3), -C(93a0de2219e66a70), C(8932c7115ccb1f8a), C(5ef503fdf2841a8c), C(38064dd9efa80a41), -C(27d55016)}, -{C(2a96a3f96c5e9bbc), C(8caf8566e212dda8), C(904de559ca16e45e), C(f13bc2d9c2fe222e), C(be4ccec9a6cdccfd), C(37b2cbdd973a3ac9), C(7b3223cd9c9497be), -C(f13bc2d9c2fe222e), C(be4ccec9a6cdccfd), C(37b2cbdd973a3ac9), C(7b3223cd9c9497be), -C(d5904440f376f889), C(62b13187699c473c), C(4751b89251f26726), C(9500d84fa3a61ba8), -C(84945a82)}, -{C(22bebfdcc26d18ff), C(4b4d8dcb10807ba1), C(40265eee30c6b896), C(3752b423073b119a), C(377dc5eb7c662bdb), C(2b9f07f93a6c25b9), C(96f24ede2bdc0718), -C(3752b423073b119a), C(377dc5eb7c662bdb), C(2b9f07f93a6c25b9), C(96f24ede2bdc0718), -C(f7699b12c31417bd), C(17b366f401c58b2), C(bf60188d5f437b37), C(484436e56df17f04), -C(3ef7e224)}, -{C(627a2249ec6bbcc2), C(c0578b462a46735a), C(4974b8ee1c2d4f1f), C(ebdbb918eb6d837f), C(8fb5f218dd84147c), C(c77dd1f881df2c54), C(62eac298ec226dc3), -C(ebdbb918eb6d837f), C(8fb5f218dd84147c), C(c77dd1f881df2c54), C(62eac298ec226dc3), -C(43eded83c4b60bd0), C(9a0a403b5487503b), C(25f305d9147f0bda), C(3ad417f511bc1e64), -C(35ed8dc8)}, -{C(3abaf1667ba2f3e0), C(ee78476b5eeadc1), C(7e56ac0a6ca4f3f4), C(f1b9b413df9d79ed), C(a7621b6fd02db503), C(d92f7ba9928a4ffe), C(53f56babdcae96a6), -C(f1b9b413df9d79ed), C(a7621b6fd02db503), C(d92f7ba9928a4ffe), C(53f56babdcae96a6), -C(5302b89fc48713ab), C(d03e3b04dbe7a2f2), C(fa74ef8af6d376a7), C(103c8cdea1050ef2), -C(6a75e43d)}, -{C(3931ac68c5f1b2c9), C(efe3892363ab0fb0), C(40b707268337cd36), C(a53a6b64b1ac85c9), C(d50e7f86ee1b832b), C(7bab08fdd26ba0a4), C(7587743c18fe2475), -C(a53a6b64b1ac85c9), C(d50e7f86ee1b832b), C(7bab08fdd26ba0a4), C(7587743c18fe2475), -C(e3b5d5d490cf5761), C(dfc053f7d065edd5), C(42ffd8d5fb70129f), C(599ca38677cccdc3), -C(235d9805)}, -{C(b98fb0606f416754), C(46a6e5547ba99c1e), C(c909d82112a8ed2), C(dbfaae9642b3205a), C(f676a1339402bcb9), C(f4f12a5b1ac11f29), C(7db8bad81249dee4), -C(dbfaae9642b3205a), C(f676a1339402bcb9), C(f4f12a5b1ac11f29), C(7db8bad81249dee4), -C(b26e46f2da95922e), C(2aaedd5e12e3c611), C(a0e2d9082966074), C(c64da8a167add63d), -C(f7d69572)}, -{C(7f7729a33e58fcc4), C(2e4bc1e7a023ead4), C(e707008ea7ca6222), C(47418a71800334a0), C(d10395d8fc64d8a4), C(8257a30062cb66f), C(6786f9b2dc1ff18a), -C(47418a71800334a0), C(d10395d8fc64d8a4), C(8257a30062cb66f), C(6786f9b2dc1ff18a), -C(5633f437bb2f180f), C(e5a3a405737d22d6), C(ca0ff1ef6f7f0b74), C(d0ae600684b16df8), -C(bacd0199)}, -{C(42a0aa9ce82848b3), C(57232730e6bee175), C(f89bb3f370782031), C(caa33cf9b4f6619c), C(b2c8648ad49c209f), C(9e89ece0712db1c0), C(101d8274a711a54b), -C(caa33cf9b4f6619c), C(b2c8648ad49c209f), C(9e89ece0712db1c0), C(101d8274a711a54b), -C(538e79f1e70135cd), C(e1f5a76f983c844e), C(653c082fd66088fc), C(1b9c9b464b654958), -C(e428f50e)}, -{C(6b2c6d38408a4889), C(de3ef6f68fb25885), C(20754f456c203361), C(941f5023c0c943f9), C(dfdeb9564fd66f24), C(2140cec706b9d406), C(7b22429b131e9c72), -C(941f5023c0c943f9), C(dfdeb9564fd66f24), C(2140cec706b9d406), C(7b22429b131e9c72), -C(94215c22eb940f45), C(d28b9ed474f7249a), C(6f25e88f2fbf9f56), C(b6718f9e605b38ac), -C(81eaaad3)}, -{C(930380a3741e862a), C(348d28638dc71658), C(89dedcfd1654ea0d), C(7e7f61684080106), C(837ace9794582976), C(5ac8ca76a357eb1b), C(32b58308625661fb), -C(7e7f61684080106), C(837ace9794582976), C(5ac8ca76a357eb1b), C(32b58308625661fb), -C(c09705c4572025d9), C(f9187f6af0291303), C(1c0edd8ee4b02538), C(e6cb105daa0578a), -C(addbd3e3)}, -{C(94808b5d2aa25f9a), C(cec72968128195e0), C(d9f4da2bdc1e130f), C(272d8dd74f3006cc), C(ec6c2ad1ec03f554), C(4ad276b249a5d5dd), C(549a22a17c0cde12), -C(272d8dd74f3006cc), C(ec6c2ad1ec03f554), C(4ad276b249a5d5dd), C(549a22a17c0cde12), -C(602119cb824d7cde), C(f4d3cef240ef35fa), C(e889895e01911bc7), C(785a7e5ac20e852b), -C(e66dbca0)}, -{C(b31abb08ae6e3d38), C(9eb9a95cbd9e8223), C(8019e79b7ee94ea9), C(7b2271a7a3248e22), C(3b4f700e5a0ba523), C(8ebc520c227206fe), C(da3f861490f5d291), -C(7b2271a7a3248e22), C(3b4f700e5a0ba523), C(8ebc520c227206fe), C(da3f861490f5d291), -C(d08a689f9f3aa60e), C(547c1b97a068661f), C(4b15a67fa29172f0), C(eaf40c085191d80f), -C(afe11fd5)}, -{C(dccb5534a893ea1a), C(ce71c398708c6131), C(fe2396315457c164), C(3f1229f4d0fd96fb), C(33130aa5fa9d43f2), C(e42693d5b34e63ab), C(2f4ef2be67f62104), -C(3f1229f4d0fd96fb), C(33130aa5fa9d43f2), C(e42693d5b34e63ab), C(2f4ef2be67f62104), -C(372e5153516e37b9), C(af9ec142ab12cc86), C(777920c09345e359), C(e7c4a383bef8adc6), -C(a71a406f)}, -{C(6369163565814de6), C(8feb86fb38d08c2f), C(4976933485cc9a20), C(7d3e82d5ba29a90d), C(d5983cc93a9d126a), C(37e9dfd950e7b692), C(80673be6a7888b87), -C(7d3e82d5ba29a90d), C(d5983cc93a9d126a), C(37e9dfd950e7b692), C(80673be6a7888b87), -C(57f732dc600808bc), C(59477199802cc78b), C(f824810eb8f2c2de), C(c4a3437f05b3b61c), -C(9d90eaf5)}, -{C(edee4ff253d9f9b3), C(96ef76fb279ef0ad), C(a4d204d179db2460), C(1f3dcdfa513512d6), C(4dc7ec07283117e4), C(4438bae88ae28bf9), C(aa7eae72c9244a0d), -C(1f3dcdfa513512d6), C(4dc7ec07283117e4), C(4438bae88ae28bf9), C(aa7eae72c9244a0d), -C(b9aedc8d3ecc72df), C(b75a8eb090a77d62), C(6b15677f9cd91507), C(51d8282cb3a9ddbf), -C(6665db10)}, -{C(941993df6e633214), C(929bc1beca5b72c6), C(141fc52b8d55572d), C(b3b782ad308f21ed), C(4f2676485041dee0), C(bfe279aed5cb4bc8), C(2a62508a467a22ff), -C(b3b782ad308f21ed), C(4f2676485041dee0), C(bfe279aed5cb4bc8), C(2a62508a467a22ff), -C(e74d29eab742385d), C(56b05cd90ecfc293), C(c603728ea73f8844), C(8638fcd21bc692c4), -C(9c977cbf)}, -{C(859838293f64cd4c), C(484403b39d44ad79), C(bf674e64d64b9339), C(44d68afda9568f08), C(478568ed51ca1d65), C(679c204ad3d9e766), C(b28e788878488dc1), -C(44d68afda9568f08), C(478568ed51ca1d65), C(679c204ad3d9e766), C(b28e788878488dc1), -C(d001a84d3a84fae6), C(d376958fe4cb913e), C(17435277e36c86f0), C(23657b263c347aa6), -C(ee83ddd4)}, -{C(c19b5648e0d9f555), C(328e47b2b7562993), C(e756b92ba4bd6a51), C(c3314e362764ddb8), C(6481c084ee9ec6b5), C(ede23fb9a251771), C(bd617f2643324590), -C(c3314e362764ddb8), C(6481c084ee9ec6b5), C(ede23fb9a251771), C(bd617f2643324590), -C(d2d30c9b95e030f5), C(8a517312ffc5795e), C(8b1f325033bd535e), C(3ee6e867e03f2892), -C(26519cc)}, -{C(f963b63b9006c248), C(9e9bf727ffaa00bc), C(c73bacc75b917e3a), C(2c6aa706129cc54c), C(17a706f59a49f086), C(c7c1eec455217145), C(6adfdc6e07602d42), -C(2c6aa706129cc54c), C(17a706f59a49f086), C(c7c1eec455217145), C(6adfdc6e07602d42), -C(fb75fca30d848dd2), C(5228c9ed14653ed4), C(953958910153b1a2), C(a430103a24f42a5d), -C(a485a53f)}, -{C(6a8aa0852a8c1f3b), C(c8f1e5e206a21016), C(2aa554aed1ebb524), C(fc3e3c322cd5d89b), C(b7e3911dc2bd4ebb), C(fcd6da5e5fae833a), C(51ed3c41f87f9118), -C(fc3e3c322cd5d89b), C(b7e3911dc2bd4ebb), C(fcd6da5e5fae833a), C(51ed3c41f87f9118), -C(f31750cbc19c420a), C(186dab1abada1d86), C(ca7f88cb894b3cd7), C(2859eeb1c373790c), -C(f62bc412)}, -{C(740428b4d45e5fb8), C(4c95a4ce922cb0a5), C(e99c3ba78feae796), C(914f1ea2fdcebf5c), C(9566453c07cd0601), C(9841bf66d0462cd), C(79140c1c18536aeb), -C(914f1ea2fdcebf5c), C(9566453c07cd0601), C(9841bf66d0462cd), C(79140c1c18536aeb), -C(a963b930b05820c2), C(6a7d9fa0c8c45153), C(64214c40d07cf39b), C(7057daf1d806c014), -C(8975a436)}, -{C(658b883b3a872b86), C(2f0e303f0f64827a), C(975337e23dc45e1), C(99468a917986162b), C(7b31434aac6e0af0), C(f6915c1562c7d82f), C(e4071d82a6dd71db), -C(99468a917986162b), C(7b31434aac6e0af0), C(f6915c1562c7d82f), C(e4071d82a6dd71db), -C(5f5331f077b5d996), C(7b314ba21b747a4f), C(5a73cb9521da17f5), C(12ed435fae286d86), -C(94ff7f41)}, -{C(6df0a977da5d27d4), C(891dd0e7cb19508), C(fd65434a0b71e680), C(8799e4740e573c50), C(9e739b52d0f341e8), C(cdfd34ba7d7b03eb), C(5061812ce6c88499), -C(8799e4740e573c50), C(9e739b52d0f341e8), C(cdfd34ba7d7b03eb), C(5061812ce6c88499), -C(612b8d8f2411dc5c), C(878bd883d29c7787), C(47a846727182bb), C(ec4949508c8b3b9a), -C(760aa031)}, -{C(a900275464ae07ef), C(11f2cfda34beb4a3), C(9abf91e5a1c38e4), C(8063d80ab26f3d6d), C(4177b4b9b4f0393f), C(6de42ba8672b9640), C(d0bccdb72c51c18), -C(8063d80ab26f3d6d), C(4177b4b9b4f0393f), C(6de42ba8672b9640), C(d0bccdb72c51c18), -C(af3f611b7f22cf12), C(3863c41492645755), C(928c7a616a8f14f9), C(a82c78eb2eadc58b), -C(3bda76df)}, -{C(810bc8aa0c40bcb0), C(448a019568d01441), C(f60ec52f60d3aeae), C(52c44837aa6dfc77), C(15d8d8fccdd6dc5b), C(345b793ccfa93055), C(932160fe802ca975), -C(52c44837aa6dfc77), C(15d8d8fccdd6dc5b), C(345b793ccfa93055), C(932160fe802ca975), -C(a624b0dd93fc18cd), C(d955b254c2037f1e), C(e540533d370a664c), C(2ba4ec12514e9d7), -C(498e2e65)}, -{C(22036327deb59ed7), C(adc05ceb97026a02), C(48bff0654262672b), C(c791b313aba3f258), C(443c7757a4727bee), C(e30e4b2372171bdf), C(f3db986c4156f3cb), -C(c791b313aba3f258), C(443c7757a4727bee), C(e30e4b2372171bdf), C(f3db986c4156f3cb), -C(a939aefab97c6e15), C(dbeb8acf1d5b0e6c), C(1e0eab667a795bba), C(80dd539902df4d50), -C(d38deb48)}, -{C(7d14dfa9772b00c8), C(595735efc7eeaed7), C(29872854f94c3507), C(bc241579d8348401), C(16dc832804d728f0), C(e9cc71ae64e3f09e), C(bef634bc978bac31), -C(bc241579d8348401), C(16dc832804d728f0), C(e9cc71ae64e3f09e), C(bef634bc978bac31), -C(7f64b1fa2a9129e), C(71d831bd530ac7f3), C(c7ad0a8a6d5be6f1), C(82a7d3a815c7aaab), -C(82b3fb6b)}, -{C(2d777cddb912675d), C(278d7b10722a13f9), C(f5c02bfb7cc078af), C(4283001239888836), C(f44ca39a6f79db89), C(ed186122d71bcc9f), C(8620017ab5f3ba3b), -C(4283001239888836), C(f44ca39a6f79db89), C(ed186122d71bcc9f), C(8620017ab5f3ba3b), -C(e787472187f176c), C(267e64c4728cf181), C(f1ba4b3007c15e30), C(8e3a75d5b02ecfc0), -C(e500e25f)}, -{C(f2ec98824e8aa613), C(5eb7e3fb53fe3bed), C(12c22860466e1dd4), C(374dd4288e0b72e5), C(ff8916db706c0df4), C(cb1a9e85de5e4b8d), C(d4d12afb67a27659), -C(374dd4288e0b72e5), C(ff8916db706c0df4), C(cb1a9e85de5e4b8d), C(d4d12afb67a27659), -C(feb69095d1ba175a), C(e2003aab23a47fad), C(8163a3ecab894b49), C(46d356674ce041f6), -C(bd2bb07c)}, -{C(5e763988e21f487f), C(24189de8065d8dc5), C(d1519d2403b62aa0), C(9136456740119815), C(4d8ff7733b27eb83), C(ea3040bc0c717ef8), C(7617ab400dfadbc), -C(9136456740119815), C(4d8ff7733b27eb83), C(ea3040bc0c717ef8), C(7617ab400dfadbc), -C(fb336770c10b17a1), C(6123b68b5b31f151), C(1e147d5f295eccf2), C(9ecbb1333556f977), -C(3a2b431d)}, -{C(48949dc327bb96ad), C(e1fd21636c5c50b4), C(3f6eb7f13a8712b4), C(14cf7f02dab0eee8), C(6d01750605e89445), C(4f1cf4006e613b78), C(57c40c4db32bec3b), -C(14cf7f02dab0eee8), C(6d01750605e89445), C(4f1cf4006e613b78), C(57c40c4db32bec3b), -C(1fde5a347f4a326e), C(cb5a54308adb0e3f), C(14994b2ba447a23c), C(7067d0abb4257b68), -C(7322a83d)}, -{C(b7c4209fb24a85c5), C(b35feb319c79ce10), C(f0d3de191833b922), C(570d62758ddf6397), C(5e0204fb68a7b800), C(4383a9236f8b5a2b), C(7bc1a64641d803a4), -C(570d62758ddf6397), C(5e0204fb68a7b800), C(4383a9236f8b5a2b), C(7bc1a64641d803a4), -C(5434d61285099f7a), C(d49449aacdd5dd67), C(97855ba0e9a7d75d), C(da67328062f3a62f), -C(a645ca1c)}, -{C(9c9e5be0943d4b05), C(b73dc69e45201cbb), C(aab17180bfe5083d), C(c738a77a9a55f0e2), C(705221addedd81df), C(fd9bd8d397abcfa3), C(8ccf0004aa86b795), -C(c738a77a9a55f0e2), C(705221addedd81df), C(fd9bd8d397abcfa3), C(8ccf0004aa86b795), -C(2bb5db2280068206), C(8c22d29f307a01d), C(274a22de02f473c8), C(b8791870f4268182), -C(8909a45a)}, -{C(3898bca4dfd6638d), C(f911ff35efef0167), C(24bdf69e5091fc88), C(9b82567ab6560796), C(891b69462b41c224), C(8eccc7e4f3af3b51), C(381e54c3c8f1c7d0), -C(9b82567ab6560796), C(891b69462b41c224), C(8eccc7e4f3af3b51), C(381e54c3c8f1c7d0), -C(c80fbc489a558a55), C(1ba88e062a663af7), C(af7b1ef1c0116303), C(bd20e1a5a6b1a0cd), -C(bd30074c)}, -{C(5b5d2557400e68e7), C(98d610033574cee), C(dfd08772ce385deb), C(3c13e894365dc6c2), C(26fc7bbcda3f0ef), C(dbb71106cdbfea36), C(785239a742c6d26d), -C(3c13e894365dc6c2), C(26fc7bbcda3f0ef), C(dbb71106cdbfea36), C(785239a742c6d26d), -C(f810c415ae05b2f4), C(bb9b9e7398526088), C(70128f1bf830a32b), C(bcc73f82b6410899), -C(c17cf001)}, -{C(a927ed8b2bf09bb6), C(606e52f10ae94eca), C(71c2203feb35a9ee), C(6e65ec14a8fb565), C(34bff6f2ee5a7f79), C(2e329a5be2c011b), C(73161c93331b14f9), -C(6e65ec14a8fb565), C(34bff6f2ee5a7f79), C(2e329a5be2c011b), C(73161c93331b14f9), -C(15d13f2408aecf88), C(9f5b61b8a4b55b31), C(8fe25a43b296dba6), C(bdad03b7300f284e), -C(26ffd25a)}, -{C(8d25746414aedf28), C(34b1629d28b33d3a), C(4d5394aea5f82d7b), C(379f76458a3c8957), C(79dd080f9843af77), C(c46f0a7847f60c1d), C(af1579c5797703cc), -C(379f76458a3c8957), C(79dd080f9843af77), C(c46f0a7847f60c1d), C(af1579c5797703cc), -C(8b7d31f338755c14), C(2eff97679512aaa8), C(df07d68e075179ed), C(c8fa6c7a729e7f1f), -C(f1d8ce3c)}, -{C(b5bbdb73458712f2), C(1ff887b3c2a35137), C(7f7231f702d0ace9), C(1e6f0910c3d25bd8), C(ad9e250862102467), C(1c842a07abab30cd), C(cd8124176bac01ac), -C(1e6f0910c3d25bd8), C(ad9e250862102467), C(1c842a07abab30cd), C(cd8124176bac01ac), -C(ea6ebe7a79b67edc), C(73f598ac9db26713), C(4f4e72d7460b8fc), C(365dc4b9fdf13f21), -C(3ee8fb17)}, -{C(3d32a26e3ab9d254), C(fc4070574dc30d3a), C(f02629579c2b27c9), C(b1cf09b0184a4834), C(5c03db48eb6cc159), C(f18c7fcf34d1df47), C(dfb043419ecf1fa9), -C(b1cf09b0184a4834), C(5c03db48eb6cc159), C(f18c7fcf34d1df47), C(dfb043419ecf1fa9), -C(dcd78d13f9ca658f), C(4355d408ffe8e49f), C(81eefee908b593b4), C(590c213c20e981a3), -C(a77acc2a)}, -{C(9371d3c35fa5e9a5), C(42967cf4d01f30), C(652d1eeae704145c), C(ceaf1a0d15234f15), C(1450a54e45ba9b9), C(65e9c1fd885aa932), C(354d4bc034ba8cbe), -C(ceaf1a0d15234f15), C(1450a54e45ba9b9), C(65e9c1fd885aa932), C(354d4bc034ba8cbe), -C(8fd4ff484c08fb4b), C(bf46749866f69ba0), C(cf1c21ede82c9477), C(4217548c43da109), -C(f4556dee)}, -{C(cbaa3cb8f64f54e0), C(76c3b48ee5c08417), C(9f7d24e87e61ce9), C(85b8e53f22e19507), C(bb57137739ca486b), C(c77f131cca38f761), C(c56ac3cf275be121), -C(85b8e53f22e19507), C(bb57137739ca486b), C(c77f131cca38f761), C(c56ac3cf275be121), -C(9ec1a6c9109d2685), C(3dad0922e76afdb0), C(fd58cbf952958103), C(7b04c908e78639a1), -C(de287a64)}, -{C(b2e23e8116c2ba9f), C(7e4d9c0060101151), C(3310da5e5028f367), C(adc52dddb76f6e5e), C(4aad4e925a962b68), C(204b79b7f7168e64), C(df29ed6671c36952), -C(adc52dddb76f6e5e), C(4aad4e925a962b68), C(204b79b7f7168e64), C(df29ed6671c36952), -C(e02927cac396d210), C(5d500e71742b638a), C(5c9998af7f27b124), C(3fba9a2573dc2f7), -C(878e55b9)}, -{C(8aa77f52d7868eb9), C(4d55bd587584e6e2), C(d2db37041f495f5), C(ce030d15b5fe2f4), C(86b4a7a0780c2431), C(ee070a9ae5b51db7), C(edc293d9595be5d8), -C(ce030d15b5fe2f4), C(86b4a7a0780c2431), C(ee070a9ae5b51db7), C(edc293d9595be5d8), -C(3dfc5ec108260a2b), C(8afe28c7123bf4e2), C(da82ef38023a7a5f), C(3e1f77b0174b77c3), -C(7648486)}, -{C(858fea922c7fe0c3), C(cfe8326bf733bc6f), C(4e5e2018cf8f7dfc), C(64fd1bc011e5bab7), C(5c9e858728015568), C(97ac42c2b00b29b1), C(7f89caf08c109aee), -C(64fd1bc011e5bab7), C(5c9e858728015568), C(97ac42c2b00b29b1), C(7f89caf08c109aee), -C(9a8af34fd0e9dacf), C(bbc54161aa1507e0), C(7cda723ccbbfe5ee), C(2c289d839fb93f58), -C(57ac0fb1)}, -{C(46ef25fdec8392b1), C(e48d7b6d42a5cd35), C(56a6fe1c175299ca), C(fdfa836b41dcef62), C(2f8db8030e847e1b), C(5ba0a49ac4f9b0f8), C(dae897ed3e3fce44), -C(fdfa836b41dcef62), C(2f8db8030e847e1b), C(5ba0a49ac4f9b0f8), C(dae897ed3e3fce44), -C(9c432e31aef626e7), C(9a36e1c6cd6e3dd), C(5095a167c34d19d), C(a70005cfa6babbea), -C(d01967ca)}, -{C(8d078f726b2df464), C(b50ee71cdcabb299), C(f4af300106f9c7ba), C(7d222caae025158a), C(cc028d5fd40241b9), C(dd42515b639e6f97), C(e08e86531a58f87f), -C(7d222caae025158a), C(cc028d5fd40241b9), C(dd42515b639e6f97), C(e08e86531a58f87f), -C(d93612c835b37d7b), C(91dd61729b2fa7f4), C(ba765a1bdda09db7), C(55258b451b2b1297), -C(96ecdf74)}, -{C(35ea86e6960ca950), C(34fe1fe234fc5c76), C(a00207a3dc2a72b7), C(80395e48739e1a67), C(74a67d8f7f43c3d7), C(dd2bdd1d62246c6e), C(a1f44298ba80acf6), -C(80395e48739e1a67), C(74a67d8f7f43c3d7), C(dd2bdd1d62246c6e), C(a1f44298ba80acf6), -C(ad86d86c187bf38), C(26feea1f2eee240d), C(ed7f1fd066b23897), C(a768cf1e0fbb502), -C(779f5506)}, -{C(8aee9edbc15dd011), C(51f5839dc8462695), C(b2213e17c37dca2d), C(133b299a939745c5), C(796e2aac053f52b3), C(e8d9fe1521a4a222), C(819a8863e5d1c290), -C(133b299a939745c5), C(796e2aac053f52b3), C(e8d9fe1521a4a222), C(819a8863e5d1c290), -C(c0737f0fe34d36ad), C(e6d6d4a267a5cc31), C(98300a7911674c23), C(bef189661c257098), -C(3c94c2de)}, -{C(c3e142ba98432dda), C(911d060cab126188), C(b753fbfa8365b844), C(fd1a9ba5e71b08a2), C(7ac0dc2ed7778533), C(b543161ff177188a), C(492fc08a6186f3f4), -C(fd1a9ba5e71b08a2), C(7ac0dc2ed7778533), C(b543161ff177188a), C(492fc08a6186f3f4), -C(fc4745f516afd3b6), C(88c30370a53080e), C(65a1bb34abc465e2), C(abbd14662911c8b3), -C(39f98faf)}, -{C(123ba6b99c8cd8db), C(448e582672ee07c4), C(cebe379292db9e65), C(938f5bbab544d3d6), C(d2a95f9f2d376d73), C(68b2f16149e81aa3), C(ad7e32f82d86c79d), -C(938f5bbab544d3d6), C(d2a95f9f2d376d73), C(68b2f16149e81aa3), C(ad7e32f82d86c79d), -C(4574015ae8626ce2), C(455aa6137386a582), C(658ad2542e8ec20), C(e31d7be2ca35d00), -C(7af31199)}, -{C(ba87acef79d14f53), C(b3e0fcae63a11558), C(d5ac313a593a9f45), C(eea5f5a9f74af591), C(578710bcc36fbea2), C(7a8393432188931d), C(705cfc5ec7cc172), -C(eea5f5a9f74af591), C(578710bcc36fbea2), C(7a8393432188931d), C(705cfc5ec7cc172), -C(da85ebe5fc427976), C(bfa5c7a454df54c8), C(4632b72a81bf66d2), C(5dd72877db539ee2), -C(e341a9d6)}, -{C(bcd3957d5717dc3), C(2da746741b03a007), C(873816f4b1ece472), C(2b826f1a2c08c289), C(da50f56863b55e74), C(b18712f6b3eed83b), C(bdc7cc05ab4c685f), -C(2b826f1a2c08c289), C(da50f56863b55e74), C(b18712f6b3eed83b), C(bdc7cc05ab4c685f), -C(9e45fb833d1b0af), C(d7213081db29d82e), C(d2a6b6c6a09ed55e), C(98a7686cba323ca9), -C(ca24aeeb)}, -{C(61442ff55609168e), C(6447c5fc76e8c9cf), C(6a846de83ae15728), C(effc2663cffc777f), C(93214f8f463afbed), C(a156ef06066f4e4e), C(a407b6ed8769d51e), -C(effc2663cffc777f), C(93214f8f463afbed), C(a156ef06066f4e4e), C(a407b6ed8769d51e), -C(bb2f9ed29745c02a), C(981eecd435b36ad9), C(461a5a05fb9cdff4), C(bd6cb2a87b9f910c), -C(b2252b57)}, -{C(dbe4b1b2d174757f), C(506512da18712656), C(6857f3e0b8dd95f), C(5a4fc2728a9bb671), C(ebb971522ec38759), C(1a5a093e6cf1f72b), C(729b057fe784f504), -C(5a4fc2728a9bb671), C(ebb971522ec38759), C(1a5a093e6cf1f72b), C(729b057fe784f504), -C(71fcbf42a767f9cf), C(114cfe772da6cdd), C(60cdf9cb629d9d7a), C(e270d10ad088b24e), -C(72c81da1)}, -{C(531e8e77b363161c), C(eece0b43e2dae030), C(8294b82c78f34ed1), C(e777b1fd580582f2), C(7b880f58da112699), C(562c6b189a6333f4), C(139d64f88a611d4), -C(e777b1fd580582f2), C(7b880f58da112699), C(562c6b189a6333f4), C(139d64f88a611d4), -C(53d8ef17eda64fa4), C(bf3eded14dc60a04), C(2b5c559cf5ec07c5), C(8895f7339d03a48a), -C(6b9fce95)}, -{C(f71e9c926d711e2b), C(d77af2853a4ceaa1), C(9aa0d6d76a36fae7), C(dd16cd0fbc08393), C(29a414a5d8c58962), C(72793d8d1022b5b2), C(2e8e69cf7cbffdf0), -C(dd16cd0fbc08393), C(29a414a5d8c58962), C(72793d8d1022b5b2), C(2e8e69cf7cbffdf0), -C(3721c0473aa99c9a), C(1cff4ed9c31cd91c), C(4990735033cc482b), C(7fdf8c701c72f577), -C(19399857)}, -{C(cb20ac28f52df368), C(e6705ee7880996de), C(9b665cc3ec6972f2), C(4260e8c254e9924b), C(f197a6eb4591572d), C(8e867ff0fb7ab27c), C(f95502fb503efaf3), -C(4260e8c254e9924b), C(f197a6eb4591572d), C(8e867ff0fb7ab27c), C(f95502fb503efaf3), -C(30c41876b08e3e22), C(958e2419e3cd22f4), C(f0f3aa1fe119a107), C(481662310a379100), -C(3c57a994)}, -{C(e4a794b4acb94b55), C(89795358057b661b), C(9c4cdcec176d7a70), C(4890a83ee435bc8b), C(d8c1c00fceb00914), C(9e7111ba234f900f), C(eb8dbab364d8b604), -C(4890a83ee435bc8b), C(d8c1c00fceb00914), C(9e7111ba234f900f), C(eb8dbab364d8b604), -C(b3261452963eebb), C(6cf94b02792c4f95), C(d88fa815ef1e8fc), C(2d687af66604c73), -C(c053e729)}, -{C(cb942e91443e7208), C(e335de8125567c2a), C(d4d74d268b86df1f), C(8ba0fdd2ffc8b239), C(f413b366c1ffe02f), C(c05b2717c59a8a28), C(981188eab4fcc8fb), -C(8ba0fdd2ffc8b239), C(f413b366c1ffe02f), C(c05b2717c59a8a28), C(981188eab4fcc8fb), -C(e563f49a1d9072ba), C(3c6a3aa4a26367dc), C(ba0db13448653f34), C(31065d756074d7d6), -C(51cbbba7)}, -{C(ecca7563c203f7ba), C(177ae2423ef34bb2), C(f60b7243400c5731), C(cf1edbfe7330e94e), C(881945906bcb3cc6), C(4acf0293244855da), C(65ae042c1c2a28c2), -C(cf1edbfe7330e94e), C(881945906bcb3cc6), C(4acf0293244855da), C(65ae042c1c2a28c2), -C(b25fa0a1cab33559), C(d98e8daa28124131), C(fce17f50b9c351b3), C(3f995ccf7386864b), -C(1acde79a)}, -{C(1652cb940177c8b5), C(8c4fe7d85d2a6d6d), C(f6216ad097e54e72), C(f6521b912b368ae6), C(a9fe4eff81d03e73), C(d6f623629f80d1a3), C(2b9604f32cb7dc34), -C(f6521b912b368ae6), C(a9fe4eff81d03e73), C(d6f623629f80d1a3), C(2b9604f32cb7dc34), -C(2a43d84dcf59c7e2), C(d0a197c70c5dae0b), C(6e84d4bbc71d76a0), C(c7e94620378c6cb2), -C(2d160d13)}, -{C(31fed0fc04c13ce8), C(3d5d03dbf7ff240a), C(727c5c9b51581203), C(6b5ffc1f54fecb29), C(a8e8e7ad5b9a21d9), C(c4d5a32cd6aac22d), C(d7e274ad22d4a79a), -C(6b5ffc1f54fecb29), C(a8e8e7ad5b9a21d9), C(c4d5a32cd6aac22d), C(d7e274ad22d4a79a), -C(368841ea5731a112), C(feaf7bc2e73ca48f), C(636fb272e9ea1f6), C(5d9cb7580c3f6207), -C(787f5801)}, -{C(e7b668947590b9b3), C(baa41ad32938d3fa), C(abcbc8d4ca4b39e4), C(381ee1b7ea534f4e), C(da3759828e3de429), C(3e015d76729f9955), C(cbbec51a6485fbde), -C(381ee1b7ea534f4e), C(da3759828e3de429), C(3e015d76729f9955), C(cbbec51a6485fbde), -C(9b86605281f20727), C(fc6fcf508676982a), C(3b135f7a813a1040), C(d3a4706bea1db9c9), -C(c9629828)}, -{C(1de2119923e8ef3c), C(6ab27c096cf2fe14), C(8c3658edca958891), C(4cc8ed3ada5f0f2), C(4a496b77c1f1c04e), C(9085b0a862084201), C(a1894bde9e3dee21), -C(4cc8ed3ada5f0f2), C(4a496b77c1f1c04e), C(9085b0a862084201), C(a1894bde9e3dee21), -C(367fb472dc5b277d), C(7d39ccca16fc6745), C(763f988d70db9106), C(a8b66f7fecb70f02), -C(be139231)}, -{C(1269df1e69e14fa7), C(992f9d58ac5041b7), C(e97fcf695a7cbbb4), C(e5d0549802d15008), C(424c134ecd0db834), C(6fc44fd91be15c6c), C(a1a5ef95d50e537d), -C(e5d0549802d15008), C(424c134ecd0db834), C(6fc44fd91be15c6c), C(a1a5ef95d50e537d), -C(d1e3daf5d05f5308), C(4c7f81600eaa1327), C(109d1b8d1f9d0d2b), C(871e8699e0aeb862), -C(7df699ef)}, -{C(820826d7aba567ff), C(1f73d28e036a52f3), C(41c4c5a73f3b0893), C(aa0d74d4a98db89b), C(36fd486d07c56e1d), C(d0ad23cbb6660d8a), C(1264a84665b35e19), -C(aa0d74d4a98db89b), C(36fd486d07c56e1d), C(d0ad23cbb6660d8a), C(1264a84665b35e19), -C(789682bf7d781b33), C(6bfa6abd2fb5722d), C(6779cb3623d33900), C(435ca5214e1ee5f0), -C(8ce6b96d)}, -{C(ffe0547e4923cef9), C(3534ed49b9da5b02), C(548a273700fba03d), C(28ac84ca70958f7e), C(d8ae575a68faa731), C(2aaaee9b9dcffd4c), C(6c7faab5c285c6da), -C(28ac84ca70958f7e), C(d8ae575a68faa731), C(2aaaee9b9dcffd4c), C(6c7faab5c285c6da), -C(45d94235f99ba78f), C(ab5ea16f39497f5b), C(fb4d6c86fccbdca3), C(8104e6310a5fd2c7), -C(6f9ed99c)}, -{C(72da8d1b11d8bc8b), C(ba94b56b91b681c6), C(4e8cc51bd9b0fc8c), C(43505ed133be672a), C(e8f2f9d973c2774e), C(677b9b9c7cad6d97), C(4e1f5d56ef17b906), -C(43505ed133be672a), C(e8f2f9d973c2774e), C(677b9b9c7cad6d97), C(4e1f5d56ef17b906), -C(eea3a6038f983767), C(87109f077f86db01), C(ecc1ca41f74d61cc), C(34a87e86e83bed17), -C(e0244796)}, -{C(d62ab4e3f88fc797), C(ea86c7aeb6283ae4), C(b5b93e09a7fe465), C(4344a1a0134afe2), C(ff5c17f02b62341d), C(3214c6a587ce4644), C(a905e7ed0629d05c), -C(4344a1a0134afe2), C(ff5c17f02b62341d), C(3214c6a587ce4644), C(a905e7ed0629d05c), -C(b5c72690cd716e82), C(7c6097649e6ebe7b), C(7ceee8c6e56a4dcd), C(80ca849dc53eb9e4), -C(4ccf7e75)}, -{C(d0f06c28c7b36823), C(1008cb0874de4bb8), C(d6c7ff816c7a737b), C(489b697fe30aa65f), C(4da0fb621fdc7817), C(dc43583b82c58107), C(4b0261debdec3cd6), -C(489b697fe30aa65f), C(4da0fb621fdc7817), C(dc43583b82c58107), C(4b0261debdec3cd6), -C(a9748d7b6c0e016c), C(7e8828f7ba4b034b), C(da0fa54348a2512a), C(ebf9745c0962f9ad), -C(915cef86)}, -{C(99b7042460d72ec6), C(2a53e5e2b8e795c2), C(53a78132d9e1b3e3), C(c043e67e6fc64118), C(ff0abfe926d844d3), C(f2a9fe5db2e910fe), C(ce352cdc84a964dd), -C(c043e67e6fc64118), C(ff0abfe926d844d3), C(f2a9fe5db2e910fe), C(ce352cdc84a964dd), -C(b89bc028aa5e6063), C(a354e7fdac04459c), C(68d6547e6e980189), C(c968dddfd573773e), -C(5cb59482)}, -{C(4f4dfcfc0ec2bae5), C(841233148268a1b8), C(9248a76ab8be0d3), C(334c5a25b5903a8c), C(4c94fef443122128), C(743e7d8454655c40), C(1ab1e6d1452ae2cd), -C(334c5a25b5903a8c), C(4c94fef443122128), C(743e7d8454655c40), C(1ab1e6d1452ae2cd), -C(fec766de4a8e476c), C(cc0929da9567e71b), C(5f9ef5b5f150c35a), C(87659cabd649768f), -C(6ca3f532)}, -{C(fe86bf9d4422b9ae), C(ebce89c90641ef9c), C(1c84e2292c0b5659), C(8bde625a10a8c50d), C(eb8271ded1f79a0b), C(14dc6844f0de7a3c), C(f85b2f9541e7e6da), -C(8bde625a10a8c50d), C(eb8271ded1f79a0b), C(14dc6844f0de7a3c), C(f85b2f9541e7e6da), -C(2fe22cfd1683b961), C(ea1d75c5b7aa01ca), C(9eef60a44876bb95), C(950c818e505c6f7f), -C(e24f3859)}, -{C(a90d81060932dbb0), C(8acfaa88c5fbe92b), C(7c6f3447e90f7f3f), C(dd52fc14c8dd3143), C(1bc7508516e40628), C(3059730266ade626), C(ffa526822f391c2), -C(dd52fc14c8dd3143), C(1bc7508516e40628), C(3059730266ade626), C(ffa526822f391c2), -C(e25232d7afc8a406), C(d2b8a5a3f3b5f670), C(6630f33edb7dfe32), C(c71250ba68c4ea86), -C(adf5a9c7)}, -{C(17938a1b0e7f5952), C(22cadd2f56f8a4be), C(84b0d1183d5ed7c1), C(c1336b92fef91bf6), C(80332a3945f33fa9), C(a0f68b86f726ff92), C(a3db5282cf5f4c0b), -C(c1336b92fef91bf6), C(80332a3945f33fa9), C(a0f68b86f726ff92), C(a3db5282cf5f4c0b), -C(82640b6fc4916607), C(2dc2a3aa1a894175), C(8b4c852bdee7cc9), C(10b9d0a08b55ff83), -C(32264b75)}, -{C(de9e0cb0e16f6e6d), C(238e6283aa4f6594), C(4fb9c914c2f0a13b), C(497cb912b670f3b), C(d963a3f02ff4a5b6), C(4fccefae11b50391), C(42ba47db3f7672f), -C(497cb912b670f3b), C(d963a3f02ff4a5b6), C(4fccefae11b50391), C(42ba47db3f7672f), -C(1d6b655a1889feef), C(5f319abf8fafa19f), C(715c2e49deb14620), C(8d9153082ecdcea4), -C(a64b3376)}, -{C(6d4b876d9b146d1a), C(aab2d64ce8f26739), C(d315f93600e83fe5), C(2fe9fabdbe7fdd4), C(755db249a2d81a69), C(f27929f360446d71), C(79a1bf957c0c1b92), -C(2fe9fabdbe7fdd4), C(755db249a2d81a69), C(f27929f360446d71), C(79a1bf957c0c1b92), -C(3c8a28d4c936c9cd), C(df0d3d13b2c6a902), C(c76702dd97cd2edd), C(1aa220f7be16517), -C(d33890e)}, -{C(e698fa3f54e6ea22), C(bd28e20e7455358c), C(9ace161f6ea76e66), C(d53fb7e3c93a9e4), C(737ae71b051bf108), C(7ac71feb84c2df42), C(3d8075cd293a15b4), -C(d53fb7e3c93a9e4), C(737ae71b051bf108), C(7ac71feb84c2df42), C(3d8075cd293a15b4), -C(bf8cee5e095d8a7c), C(e7086b3c7608143a), C(e55b0c2fa938d70c), C(fffb5f58e643649c), -C(926d4b63)}, -{C(7bc0deed4fb349f7), C(1771aff25dc722fa), C(19ff0644d9681917), C(cf7d7f25bd70cd2c), C(9464ed9baeb41b4f), C(b9064f5c3cb11b71), C(237e39229b012b20), -C(cf7d7f25bd70cd2c), C(9464ed9baeb41b4f), C(b9064f5c3cb11b71), C(237e39229b012b20), -C(dd54d3f5d982dffe), C(7fc7562dbfc81dbf), C(5b0dd1924f70945), C(f1760537d8261135), -C(d51ba539)}, -{C(db4b15e88533f622), C(256d6d2419b41ce9), C(9d7c5378396765d5), C(9040e5b936b8661b), C(276e08fa53ac27fd), C(8c944d39c2bdd2cc), C(e2514c9802a5743c), -C(9040e5b936b8661b), C(276e08fa53ac27fd), C(8c944d39c2bdd2cc), C(e2514c9802a5743c), -C(e82107b11ac90386), C(7d6a22bc35055e6), C(fd6ea9d1c438d8ae), C(be6015149e981553), -C(7f37636d)}, -{C(922834735e86ecb2), C(363382685b88328e), C(e9c92960d7144630), C(8431b1bfd0a2379c), C(90383913aea283f9), C(a6163831eb4924d2), C(5f3921b4f9084aee), -C(8431b1bfd0a2379c), C(90383913aea283f9), C(a6163831eb4924d2), C(5f3921b4f9084aee), -C(7a70061a1473e579), C(5b19d80dcd2c6331), C(6196b97931faad27), C(869bf6828e237c3f), -C(b98026c0)}, -{C(30f1d72c812f1eb8), C(b567cd4a69cd8989), C(820b6c992a51f0bc), C(c54677a80367125e), C(3204fbdba462e606), C(8563278afc9eae69), C(262147dd4bf7e566), -C(c54677a80367125e), C(3204fbdba462e606), C(8563278afc9eae69), C(262147dd4bf7e566), -C(2178b63e7ee2d230), C(e9c61ad81f5bff26), C(9af7a81b3c501eca), C(44104a3859f0238f), -C(b877767e)}, -{C(168884267f3817e9), C(5b376e050f637645), C(1c18314abd34497a), C(9598f6ab0683fcc2), C(1c805abf7b80e1ee), C(dec9ac42ee0d0f32), C(8cd72e3912d24663), -C(9598f6ab0683fcc2), C(1c805abf7b80e1ee), C(dec9ac42ee0d0f32), C(8cd72e3912d24663), -C(1f025d405f1c1d87), C(bf7b6221e1668f8f), C(52316f64e692dbb0), C(7bf43df61ec51b39), -C(aefae77)}, -{C(82e78596ee3e56a7), C(25697d9c87f30d98), C(7600a8342834924d), C(6ba372f4b7ab268b), C(8c3237cf1fe243df), C(3833fc51012903df), C(8e31310108c5683f), -C(6ba372f4b7ab268b), C(8c3237cf1fe243df), C(3833fc51012903df), C(8e31310108c5683f), -C(126593715c2de429), C(48ca8f35a3f54b90), C(b9322b632f4f8b0), C(926bb169b7337693), -C(f686911)}, -{C(aa2d6cf22e3cc252), C(9b4dec4f5e179f16), C(76fb0fba1d99a99a), C(9a62af3dbba140da), C(27857ea044e9dfc1), C(33abce9da2272647), C(b22a7993aaf32556), -C(9a62af3dbba140da), C(27857ea044e9dfc1), C(33abce9da2272647), C(b22a7993aaf32556), -C(bf8f88f8019bedf0), C(ed2d7f01fb273905), C(6b45f15901b481cd), C(f88ebb413ba6a8d5), -C(3deadf12)}, -{C(7bf5ffd7f69385c7), C(fc077b1d8bc82879), C(9c04e36f9ed83a24), C(82065c62e6582188), C(8ef787fd356f5e43), C(2922e53e36e17dfa), C(9805f223d385010b), -C(82065c62e6582188), C(8ef787fd356f5e43), C(2922e53e36e17dfa), C(9805f223d385010b), -C(692154f3491b787d), C(e7e64700e414fbf), C(757d4d4ab65069a0), C(cd029446a8e348e2), -C(ccf02a4e)}, -{C(e89c8ff9f9c6e34b), C(f54c0f669a49f6c4), C(fc3e46f5d846adef), C(22f2aa3df2221cc), C(f66fea90f5d62174), C(b75defaeaa1dd2a7), C(9b994cd9a7214fd5), -C(22f2aa3df2221cc), C(f66fea90f5d62174), C(b75defaeaa1dd2a7), C(9b994cd9a7214fd5), -C(fac675a31804b773), C(98bcb3b820c50fc6), C(e14af64d28cf0885), C(27466fbd2b360eb5), -C(176c1722)}, -{C(a18fbcdccd11e1f4), C(8248216751dfd65e), C(40c089f208d89d7c), C(229b79ab69ae97d), C(a87aabc2ec26e582), C(be2b053721eb26d2), C(10febd7f0c3d6fcb), -C(229b79ab69ae97d), C(a87aabc2ec26e582), C(be2b053721eb26d2), C(10febd7f0c3d6fcb), -C(9cc5b9b2f6e3bf7b), C(655d8495fe624a86), C(6381a9f3d1f2bd7e), C(79ebabbfc25c83e2), -C(26f82ad)}, -{C(2d54f40cc4088b17), C(59d15633b0cd1399), C(a8cc04bb1bffd15b), C(d332cdb073d8dc46), C(272c56466868cb46), C(7e7fcbe35ca6c3f3), C(ee8f51e5a70399d4), -C(d332cdb073d8dc46), C(272c56466868cb46), C(7e7fcbe35ca6c3f3), C(ee8f51e5a70399d4), -C(16737a9c7581fe7b), C(ed04bf52f4b75dcb), C(9707ffb36bd30c1a), C(1390f236fdc0de3e), -C(b5244f42)}, -{C(69276946cb4e87c7), C(62bdbe6183be6fa9), C(3ba9773dac442a1a), C(702e2afc7f5a1825), C(8c49b11ea8151fdc), C(caf3fef61f5a86fa), C(ef0b2ee8649d7272), -C(702e2afc7f5a1825), C(8c49b11ea8151fdc), C(caf3fef61f5a86fa), C(ef0b2ee8649d7272), -C(9e34a4e08d9441e1), C(7bdc0cd64d5af533), C(a926b14d99e3d868), C(fca923a17788cce4), -C(49a689e5)}, -{C(668174a3f443df1d), C(407299392da1ce86), C(c2a3f7d7f2c5be28), C(a590b202a7a5807b), C(968d2593f7ccb54e), C(9dd8d669e3e95dec), C(ee0cc5dd58b6e93a), -C(a590b202a7a5807b), C(968d2593f7ccb54e), C(9dd8d669e3e95dec), C(ee0cc5dd58b6e93a), -C(ac65d5a9466fb483), C(221be538b2c9d806), C(5cbe9441784f9fd9), C(d4c7d5d6e3c122b8), -C(59fcdd3)}, -{C(5e29be847bd5046), C(b561c7f19c8f80c3), C(5e5abd5021ccaeaf), C(7432d63888e0c306), C(74bbceeed479cb71), C(6471586599575fdf), C(6a859ad23365cba2), -C(7432d63888e0c306), C(74bbceeed479cb71), C(6471586599575fdf), C(6a859ad23365cba2), -C(f9ceec84acd18dcc), C(74a242ff1907437c), C(f70890194e1ee913), C(777dfcb4bb01f0ba), -C(4f4b04e9)}, -{C(cd0d79f2164da014), C(4c386bb5c5d6ca0c), C(8e771b03647c3b63), C(69db23875cb0b715), C(ada8dd91504ae37f), C(46bf18dbf045ed6a), C(e1b5f67b0645ab63), -C(69db23875cb0b715), C(ada8dd91504ae37f), C(46bf18dbf045ed6a), C(e1b5f67b0645ab63), -C(877be8f5dcddff4), C(6d471b5f9ca2e2d1), C(802c86d6f495b9bb), C(a1f9b9b22b3be704), -C(8b00f891)}, -{C(e0e6fc0b1628af1d), C(29be5fb4c27a2949), C(1c3f781a604d3630), C(c4af7faf883033aa), C(9bd296c4e9453cac), C(ca45426c1f7e33f9), C(a6bbdcf7074d40c5), -C(c4af7faf883033aa), C(9bd296c4e9453cac), C(ca45426c1f7e33f9), C(a6bbdcf7074d40c5), -C(e13a005d7142733b), C(c02b7925c5eeefaf), C(d39119a60441e2d5), C(3c24c710df8f4d43), -C(16e114f3)}, -{C(2058927664adfd93), C(6e8f968c7963baa5), C(af3dced6fff7c394), C(42e34cf3d53c7876), C(9cddbb26424dc5e), C(64f6340a6d8eddad), C(2196e488eb2a3a4b), -C(42e34cf3d53c7876), C(9cddbb26424dc5e), C(64f6340a6d8eddad), C(2196e488eb2a3a4b), -C(c9e9da25911a16fd), C(e21b4683f3e196a8), C(cb80bf1a4c6fdbb4), C(53792e9b3c3e67f8), -C(d6b6dadc)}, -{C(dc107285fd8e1af7), C(a8641a0609321f3f), C(db06e89ffdc54466), C(bcc7a81ed5432429), C(b6d7bdc6ad2e81f1), C(93605ec471aa37db), C(a2a73f8a85a8e397), -C(bcc7a81ed5432429), C(b6d7bdc6ad2e81f1), C(93605ec471aa37db), C(a2a73f8a85a8e397), -C(10a012b8ca7ac24b), C(aac5fd63351595cf), C(5bb4c648a226dea0), C(9d11ecb2b5c05c5f), -C(897e20ac)}, -{C(fbba1afe2e3280f1), C(755a5f392f07fce), C(9e44a9a15402809a), C(6226a32e25099848), C(ea895661ecf53004), C(4d7e0158db2228b9), C(e5a7d82922f69842), -C(6226a32e25099848), C(ea895661ecf53004), C(4d7e0158db2228b9), C(e5a7d82922f69842), -C(2cea7713b69840ca), C(18de7b9ae938375b), C(f127cca08f3cc665), C(b1c22d727665ad2), -C(f996e05d)}, -{C(bfa10785ddc1011b), C(b6e1c4d2f670f7de), C(517d95604e4fcc1f), C(ca6552a0dfb82c73), C(b024cdf09e34ba07), C(66cd8c5a95d7393b), C(e3939acf790d4a74), -C(ca6552a0dfb82c73), C(b024cdf09e34ba07), C(66cd8c5a95d7393b), C(e3939acf790d4a74), -C(97827541a1ef051e), C(ac2fce47ebe6500c), C(b3f06d3bddf3bd6a), C(1d74afb25e1ce5fe), -C(c4306af6)}, -{C(534cc35f0ee1eb4e), C(b703820f1f3b3dce), C(884aa164cf22363), C(f14ef7f47d8a57a3), C(80d1f86f2e061d7c), C(401d6c2f151b5a62), C(e988460224108944), -C(f14ef7f47d8a57a3), C(80d1f86f2e061d7c), C(401d6c2f151b5a62), C(e988460224108944), -C(7804d4135f68cd19), C(5487b4b39e69fe8e), C(8cc5999015358a27), C(8f3729b61c2d5601), -C(6dcad433)}, -{C(7ca6e3933995dac), C(fd118c77daa8188), C(3aceb7b5e7da6545), C(c8389799445480db), C(5389f5df8aacd50d), C(d136581f22fab5f), C(c2f31f85991da417), -C(c8389799445480db), C(5389f5df8aacd50d), C(d136581f22fab5f), C(c2f31f85991da417), -C(aefbf9ff84035a43), C(8accbaf44adadd7c), C(e57f3657344b67f5), C(21490e5e8abdec51), -C(3c07374d)}, -{C(f0d6044f6efd7598), C(e044d6ba4369856e), C(91968e4f8c8a1a4c), C(70bd1968996bffc2), C(4c613de5d8ab32ac), C(fe1f4f97206f79d8), C(ac0434f2c4e213a9), -C(70bd1968996bffc2), C(4c613de5d8ab32ac), C(fe1f4f97206f79d8), C(ac0434f2c4e213a9), -C(7490e9d82cfe22ca), C(5fbbf7f987454238), C(c39e0dc8368ce949), C(22201d3894676c71), -C(f0f4602c)}, -{C(3d69e52049879d61), C(76610636ea9f74fe), C(e9bf5602f89310c0), C(8eeb177a86053c11), C(e390122c345f34a2), C(1e30e47afbaaf8d6), C(7b892f68e5f91732), -C(8eeb177a86053c11), C(e390122c345f34a2), C(1e30e47afbaaf8d6), C(7b892f68e5f91732), -C(b87922525fa44158), C(f440a1ee1a1a766b), C(ee8efad279d08c5c), C(421f910c5b60216e), -C(3e1ea071)}, -{C(79da242a16acae31), C(183c5f438e29d40), C(6d351710ae92f3de), C(27233b28b5b11e9b), C(c7dfe8988a942700), C(570ed11c4abad984), C(4b4c04632f48311a), -C(27233b28b5b11e9b), C(c7dfe8988a942700), C(570ed11c4abad984), C(4b4c04632f48311a), -C(12f33235442cbf9), C(a35315ca0b5b8cdb), C(d8abde62ead5506b), C(fc0fcf8478ad5266), -C(67580f0c)}, -{C(461c82656a74fb57), C(d84b491b275aa0f7), C(8f262cb29a6eb8b2), C(49fa3070bc7b06d0), C(f12ed446bd0c0539), C(6d43ac5d1dd4b240), C(7609524fe90bec93), -C(49fa3070bc7b06d0), C(f12ed446bd0c0539), C(6d43ac5d1dd4b240), C(7609524fe90bec93), -C(391c2b2e076ec241), C(f5e62deda7839f7b), C(3c7b3186a10d870f), C(77ef4f2cba4f1005), -C(4e109454)}, -{C(53c1a66d0b13003), C(731f060e6fe797fc), C(daa56811791371e3), C(57466046cf6896ed), C(8ac37e0e8b25b0c6), C(3e6074b52ad3cf18), C(aa491ce7b45db297), -C(57466046cf6896ed), C(8ac37e0e8b25b0c6), C(3e6074b52ad3cf18), C(aa491ce7b45db297), -C(f7a9227c5e5e22c3), C(3d92e0841e29ce28), C(2d30da5b2859e59d), C(ff37fa1c9cbfafc2), -C(88a474a7)}, -{C(d3a2efec0f047e9), C(1cabce58853e58ea), C(7a17b2eae3256be4), C(c2dcc9758c910171), C(cb5cddaeff4ddb40), C(5d7cc5869baefef1), C(9644c5853af9cfeb), -C(c2dcc9758c910171), C(cb5cddaeff4ddb40), C(5d7cc5869baefef1), C(9644c5853af9cfeb), -C(255c968184694ee1), C(4e4d726eda360927), C(7d27dd5b6d100377), C(9a300e2020ddea2c), -C(5b5bedd)}, -{C(43c64d7484f7f9b2), C(5da002b64aafaeb7), C(b576c1e45800a716), C(3ee84d3d5b4ca00b), C(5cbc6d701894c3f9), C(d9e946f5ae1ca95), C(24ca06e67f0b1833), -C(3ee84d3d5b4ca00b), C(5cbc6d701894c3f9), C(d9e946f5ae1ca95), C(24ca06e67f0b1833), -C(3413d46b4152650e), C(cbdfdbc2ab516f9c), C(2aad8acb739e0c6c), C(2bfc950d9f9fa977), -C(1aaddfa7)}, -{C(a7dec6ad81cf7fa1), C(180c1ab708683063), C(95e0fd7008d67cff), C(6b11c5073687208), C(7e0a57de0d453f3), C(e48c267d4f646867), C(2168e9136375f9cb), -C(6b11c5073687208), C(7e0a57de0d453f3), C(e48c267d4f646867), C(2168e9136375f9cb), -C(64da194aeeea7fdf), C(a3b9f01fa5885678), C(c316f8ee2eb2bd17), C(a7e4d80f83e4427f), -C(5be07fd8)}, -{C(5408a1df99d4aff), C(b9565e588740f6bd), C(abf241813b08006e), C(7da9e81d89fda7ad), C(274157cabe71440d), C(2c22d9a480b331f7), C(e835c8ac746472d5), -C(7da9e81d89fda7ad), C(274157cabe71440d), C(2c22d9a480b331f7), C(e835c8ac746472d5), -C(2038ce817a201ae4), C(46f3289dfe1c5e40), C(435578a42d4b7c56), C(f96d9f409fcf561), -C(cbca8606)}, -{C(a8b27a6bcaeeed4b), C(aec1eeded6a87e39), C(9daf246d6fed8326), C(d45a938b79f54e8f), C(366b219d6d133e48), C(5b14be3c25c49405), C(fdd791d48811a572), -C(d45a938b79f54e8f), C(366b219d6d133e48), C(5b14be3c25c49405), C(fdd791d48811a572), -C(3de67b8d9e95d335), C(903c01307cfbeed5), C(af7d65f32274f1d1), C(4dba141b5fc03c42), -C(bde64d01)}, -{C(9a952a8246fdc269), C(d0dcfcac74ef278c), C(250f7139836f0f1f), C(c83d3c5f4e5f0320), C(694e7adeb2bf32e5), C(7ad09538a3da27f5), C(2b5c18f934aa5303), -C(c83d3c5f4e5f0320), C(694e7adeb2bf32e5), C(7ad09538a3da27f5), C(2b5c18f934aa5303), -C(c4dad7703d34326e), C(825569e2bcdc6a25), C(b83d267709ca900d), C(44ed05151f5d74e6), -C(ee90cf33)}, -{C(c930841d1d88684f), C(5eb66eb18b7f9672), C(e455d413008a2546), C(bc271bc0df14d647), C(b071100a9ff2edbb), C(2b1a4c1cc31a119a), C(b5d7caa1bd946cef), -C(bc271bc0df14d647), C(b071100a9ff2edbb), C(2b1a4c1cc31a119a), C(b5d7caa1bd946cef), -C(e02623ae10f4aadd), C(d79f600389cd06fd), C(1e8da7965303e62b), C(86f50e10eeab0925), -C(4305c3ce)}, -{C(94dc6971e3cf071a), C(994c7003b73b2b34), C(ea16e85978694e5), C(336c1b59a1fc19f6), C(c173acaecc471305), C(db1267d24f3f3f36), C(e9a5ee98627a6e78), -C(336c1b59a1fc19f6), C(c173acaecc471305), C(db1267d24f3f3f36), C(e9a5ee98627a6e78), -C(718f334204305ae5), C(e3b53c148f98d22c), C(a184012df848926), C(6e96386127d51183), -C(4b3a1d76)}, -{C(7fc98006e25cac9), C(77fee0484cda86a7), C(376ec3d447060456), C(84064a6dcf916340), C(fbf55a26790e0ebb), C(2e7f84151c31a5c2), C(9f7f6d76b950f9bf), -C(84064a6dcf916340), C(fbf55a26790e0ebb), C(2e7f84151c31a5c2), C(9f7f6d76b950f9bf), -C(125e094fbee2b146), C(5706aa72b2eef7c2), C(1c4a2daa905ee66e), C(83d48029b5451694), -C(a8bb6d80)}, -{C(bd781c4454103f6), C(612197322f49c931), C(b9cf17fd7e5462d5), C(e38e526cd3324364), C(85f2b63a5b5e840a), C(485d7cef5aaadd87), C(d2b837a462f6db6d), -C(e38e526cd3324364), C(85f2b63a5b5e840a), C(485d7cef5aaadd87), C(d2b837a462f6db6d), -C(3e41cef031520d9a), C(82df73902d7f67e), C(3ba6fd54c15257cb), C(22f91f079be42d40), -C(1f9fa607)}, -{C(da60e6b14479f9df), C(3bdccf69ece16792), C(18ebf45c4fecfdc9), C(16818ee9d38c6664), C(5519fa9a1e35a329), C(cbd0001e4b08ed8), C(41a965e37a0c731b), -C(16818ee9d38c6664), C(5519fa9a1e35a329), C(cbd0001e4b08ed8), C(41a965e37a0c731b), -C(66e7b5dcca1ca28f), C(963b2d993614347d), C(9b6fc6f41d411106), C(aaaecaccf7848c0c), -C(8d0e4ed2)}, -{C(4ca56a348b6c4d3), C(60618537c3872514), C(2fbb9f0e65871b09), C(30278016830ddd43), C(f046646d9012e074), C(c62a5804f6e7c9da), C(98d51f5830e2bc1e), -C(30278016830ddd43), C(f046646d9012e074), C(c62a5804f6e7c9da), C(98d51f5830e2bc1e), -C(7b2cbe5d37e3f29e), C(7b8c3ed50bda4aa0), C(3ea60cc24639e038), C(f7706de9fb0b5801), -C(1bf31347)}, -{C(ebd22d4b70946401), C(6863602bf7139017), C(c0b1ac4e11b00666), C(7d2782b82bd494b6), C(97159ba1c26b304b), C(42b3b0fd431b2ac2), C(faa81f82691c830c), -C(7d2782b82bd494b6), C(97159ba1c26b304b), C(42b3b0fd431b2ac2), C(faa81f82691c830c), -C(7cc6449234c7e185), C(aeaa6fa643ca86a5), C(1412db1c0f2e0133), C(4df2fe3e4072934f), -C(1ae3fc5b)}, -{C(3cc4693d6cbcb0c), C(501689ea1c70ffa), C(10a4353e9c89e364), C(58c8aba7475e2d95), C(3e2f291698c9427a), C(e8710d19c9de9e41), C(65dda22eb04cf953), -C(58c8aba7475e2d95), C(3e2f291698c9427a), C(e8710d19c9de9e41), C(65dda22eb04cf953), -C(d7729c48c250cffa), C(ef76162b2ddfba4b), C(52371e17f4d51f6d), C(ddd002112ff0c833), -C(459c3930)}, -{C(38908e43f7ba5ef0), C(1ab035d4e7781e76), C(41d133e8c0a68ff7), C(d1090893afaab8bc), C(96c4fe6922772807), C(4522426c2b4205eb), C(efad99a1262e7e0d), -C(d1090893afaab8bc), C(96c4fe6922772807), C(4522426c2b4205eb), C(efad99a1262e7e0d), -C(c7696029abdb465e), C(4e18eaf03d517651), C(d006bced54c86ac8), C(4330326d1021860c), -C(e00c4184)}, -{C(34983ccc6aa40205), C(21802cad34e72bc4), C(1943e8fb3c17bb8), C(fc947167f69c0da5), C(ae79cfdb91b6f6c1), C(7b251d04c26cbda3), C(128a33a79060d25e), -C(fc947167f69c0da5), C(ae79cfdb91b6f6c1), C(7b251d04c26cbda3), C(128a33a79060d25e), -C(1eca842dbfe018dd), C(50a4cd2ee0ba9c63), C(c2f5c97d8399682f), C(3f929fc7cbe8ecbb), -C(ffc7a781)}, -{C(86215c45dcac9905), C(ea546afe851cae4b), C(d85b6457e489e374), C(b7609c8e70386d66), C(36e6ccc278d1636d), C(2f873307c08e6a1c), C(10f252a758505289), -C(b7609c8e70386d66), C(36e6ccc278d1636d), C(2f873307c08e6a1c), C(10f252a758505289), -C(c8977646e81ab4b6), C(8017b745cd80213b), C(960687db359bea0), C(ef4a470660799488), -C(6a125480)}, -{C(420fc255c38db175), C(d503cd0f3c1208d1), C(d4684e74c825a0bc), C(4c10537443152f3d), C(720451d3c895e25d), C(aff60c4d11f513fd), C(881e8d6d2d5fb953), -C(4c10537443152f3d), C(720451d3c895e25d), C(aff60c4d11f513fd), C(881e8d6d2d5fb953), -C(9dec034a043f1f55), C(e27a0c22e7bfb39d), C(2220b959128324), C(53240272152dbd8b), -C(88a1512b)}, -{C(1d7a31f5bc8fe2f9), C(4763991092dcf836), C(ed695f55b97416f4), C(f265edb0c1c411d7), C(30e1e9ec5262b7e6), C(c2c3ba061ce7957a), C(d975f93b89a16409), -C(f265edb0c1c411d7), C(30e1e9ec5262b7e6), C(c2c3ba061ce7957a), C(d975f93b89a16409), -C(e9d703123f43450a), C(41383fedfed67c82), C(6e9f43ecbbbd6004), C(c7ccd23a24e77b8), -C(549bbbe5)}, -{C(94129a84c376a26e), C(c245e859dc231933), C(1b8f74fecf917453), C(e9369d2e9007e74b), C(b1375915d1136052), C(926c2021fe1d2351), C(1d943addaaa2e7e6), -C(e9369d2e9007e74b), C(b1375915d1136052), C(926c2021fe1d2351), C(1d943addaaa2e7e6), -C(f5f515869c246738), C(7e309cd0e1c0f2a0), C(153c3c36cf523e3b), C(4931c66872ea6758), -C(c133d38c)}, -{C(1d3a9809dab05c8d), C(adddeb4f71c93e8), C(ef342eb36631edb), C(301d7a61c4b3dbca), C(861336c3f0552d61), C(12c6db947471300f), C(a679ef0ed761deb9), -C(301d7a61c4b3dbca), C(861336c3f0552d61), C(12c6db947471300f), C(a679ef0ed761deb9), -C(5f713b720efcd147), C(37ac330a333aa6b), C(3309dc9ec1616eef), C(52301d7a908026b5), -C(fcace348)}, -{C(90fa3ccbd60848da), C(dfa6e0595b569e11), C(e585d067a1f5135d), C(6cef866ec295abea), C(c486c0d9214beb2d), C(d6e490944d5fe100), C(59df3175d72c9f38), -C(6cef866ec295abea), C(c486c0d9214beb2d), C(d6e490944d5fe100), C(59df3175d72c9f38), -C(3f23aeb4c04d1443), C(9bf0515cd8d24770), C(958554f60ccaade2), C(5182863c90132fe8), -C(ed7b6f9a)}, -{C(2dbb4fc71b554514), C(9650e04b86be0f82), C(60f2304fba9274d3), C(fcfb9443e997cab), C(f13310d96dec2772), C(709cad2045251af2), C(afd0d30cc6376dad), -C(fcfb9443e997cab), C(f13310d96dec2772), C(709cad2045251af2), C(afd0d30cc6376dad), -C(59d4bed30d550d0d), C(58006d4e22d8aad1), C(eee12d2362d1f13b), C(35cf1d7faaf1d228), -C(6d907dda)}, -{C(b98bf4274d18374a), C(1b669fd4c7f9a19a), C(b1f5972b88ba2b7a), C(73119c99e6d508be), C(5d4036a187735385), C(8fa66e192fd83831), C(2abf64b6b592ed57), -C(73119c99e6d508be), C(5d4036a187735385), C(8fa66e192fd83831), C(2abf64b6b592ed57), -C(d4501f95dd84b08c), C(bf1552439c8bea02), C(4f56fe753ba7e0ba), C(4ca8d35cc058cfcd), -C(7a4d48d5)}, -{C(d6781d0b5e18eb68), C(b992913cae09b533), C(58f6021caaee3a40), C(aafcb77497b5a20b), C(411819e5e79b77a3), C(bd779579c51c77ce), C(58d11f5dcf5d075d), -C(aafcb77497b5a20b), C(411819e5e79b77a3), C(bd779579c51c77ce), C(58d11f5dcf5d075d), -C(9eae76cde1cb4233), C(32fe25a9bf657970), C(1c0c807948edb06a), C(b8f29a3dfaee254d), -C(e686f3db)}, -{C(226651cf18f4884c), C(595052a874f0f51c), C(c9b75162b23bab42), C(3f44f873be4812ec), C(427662c1dbfaa7b2), C(a207ff9638fb6558), C(a738d919e45f550f), -C(3f44f873be4812ec), C(427662c1dbfaa7b2), C(a207ff9638fb6558), C(a738d919e45f550f), -C(cb186ea05717e7d6), C(1ca7d68a5871fdc1), C(5d4c119ea8ef3750), C(72b6a10fa2ff9406), -C(cce7c55)}, -{C(a734fb047d3162d6), C(e523170d240ba3a5), C(125a6972809730e8), C(d396a297799c24a1), C(8fee992e3069bad5), C(2e3a01b0697ccf57), C(ee9c7390bd901cfa), -C(d396a297799c24a1), C(8fee992e3069bad5), C(2e3a01b0697ccf57), C(ee9c7390bd901cfa), -C(56f2d9da0af28af2), C(3fdd37b2fe8437cb), C(3d13eeeb60d6aec0), C(2432ae62e800a5ce), -C(f58b96b)}, -{C(c6df6364a24f75a3), C(c294e2c84c4f5df8), C(a88df65c6a89313b), C(895fe8443183da74), C(c7f2f6f895a67334), C(a0d6b6a506691d31), C(24f51712b459a9f0), -C(895fe8443183da74), C(c7f2f6f895a67334), C(a0d6b6a506691d31), C(24f51712b459a9f0), -C(173a699481b9e088), C(1dee9b77bcbf45d3), C(32b98a646a8667d0), C(3adcd4ee28f42a0e), -C(1bbf6f60)}, -{C(d8d1364c1fbcd10), C(2d7cc7f54832deaa), C(4e22c876a7c57625), C(a3d5d1137d30c4bd), C(1e7d706a49bdfb9e), C(c63282b20ad86db2), C(aec97fa07916bfd6), -C(a3d5d1137d30c4bd), C(1e7d706a49bdfb9e), C(c63282b20ad86db2), C(aec97fa07916bfd6), -C(7c9ba3e52d44f73e), C(af62fd245811185d), C(8a9d2dacd8737652), C(bd2cce277d5fbec0), -C(ce5e0cc2)}, -{C(aae06f9146db885f), C(3598736441e280d9), C(fba339b117083e55), C(b22bf08d9f8aecf7), C(c182730de337b922), C(2b9adc87a0450a46), C(192c29a9cfc00aad), -C(b22bf08d9f8aecf7), C(c182730de337b922), C(2b9adc87a0450a46), C(192c29a9cfc00aad), -C(9fd733f1d84a59d9), C(d86bd5c9839ace15), C(af20b57303172876), C(9f63cb7161b5364c), -C(584cfd6f)}, -{C(8955ef07631e3bcc), C(7d70965ea3926f83), C(39aed4134f8b2db6), C(882efc2561715a9c), C(ef8132a18a540221), C(b20a3c87a8c257c1), C(f541b8628fad6c23), -C(882efc2561715a9c), C(ef8132a18a540221), C(b20a3c87a8c257c1), C(f541b8628fad6c23), -C(9552aed57a6e0467), C(4d9fdd56867611a7), C(c330279bf23b9eab), C(44dbbaea2fcb8eba), -C(8f9bbc33)}, -{C(ad611c609cfbe412), C(d3c00b18bf253877), C(90b2172e1f3d0bfd), C(371a98b2cb084883), C(33a2886ee9f00663), C(be9568818ed6e6bd), C(f244a0fa2673469a), -C(371a98b2cb084883), C(33a2886ee9f00663), C(be9568818ed6e6bd), C(f244a0fa2673469a), -C(b447050bd3e559e9), C(d3b695dae7a13383), C(ded0bb65be471188), C(ca3c7a2b78922cae), -C(d7640d95)}, -{C(d5339adc295d5d69), C(b633cc1dcb8b586a), C(ee84184cf5b1aeaf), C(89f3aab99afbd636), C(f420e004f8148b9a), C(6818073faa797c7c), C(dd3b4e21cbbf42ca), -C(89f3aab99afbd636), C(f420e004f8148b9a), C(6818073faa797c7c), C(dd3b4e21cbbf42ca), -C(6a2b7db261164844), C(cbead63d1895852a), C(93d37e1eae05e2f9), C(5d06db2703fbc3ae), -C(3d12a2b)}, -{C(40d0aeff521375a8), C(77ba1ad7ecebd506), C(547c6f1a7d9df427), C(21c2be098327f49b), C(7e035065ac7bbef5), C(6d7348e63023fb35), C(9d427dc1b67c3830), -C(21c2be098327f49b), C(7e035065ac7bbef5), C(6d7348e63023fb35), C(9d427dc1b67c3830), -C(4e3d018a43858341), C(cf924bb44d6b43c5), C(4618b6a26e3446ae), C(54d3013fac3ed469), -C(aaeafed0)}, -{C(8b2d54ae1a3df769), C(11e7adaee3216679), C(3483781efc563e03), C(9d097dd3152ab107), C(51e21d24126e8563), C(cba56cac884a1354), C(39abb1b595f0a977), -C(9d097dd3152ab107), C(51e21d24126e8563), C(cba56cac884a1354), C(39abb1b595f0a977), -C(81e6dd1c1109848f), C(1644b209826d7b15), C(6ac67e4e4b4812f0), C(b3a9f5622c935bf7), -C(95b9b814)}, -{C(99c175819b4eae28), C(932e8ff9f7a40043), C(ec78dcab07ca9f7c), C(c1a78b82ba815b74), C(458cbdfc82eb322a), C(17f4a192376ed8d7), C(6f9e92968bc8ccef), -C(c1a78b82ba815b74), C(458cbdfc82eb322a), C(17f4a192376ed8d7), C(6f9e92968bc8ccef), -C(93e098c333b39905), C(d59b1cace44b7fdc), C(f7a64ed78c64c7c5), C(7c6eca5dd87ec1ce), -C(45fbe66e)}, -{C(2a418335779b82fc), C(af0295987849a76b), C(c12bc5ff0213f46e), C(5aeead8d6cb25bb9), C(739315f7743ec3ff), C(9ab48d27111d2dcc), C(5b87bd35a975929b), -C(5aeead8d6cb25bb9), C(739315f7743ec3ff), C(9ab48d27111d2dcc), C(5b87bd35a975929b), -C(c3dd8d6d95a46bb3), C(7bf9093215a4f483), C(cb557d6ed84285bd), C(daf58422f261fdb5), -C(b4baa7a8)}, -{C(3b1fc6a3d279e67d), C(70ea1e49c226396), C(25505adcf104697c), C(ba1ffba29f0367aa), C(a20bec1dd15a8b6c), C(e9bf61d2dab0f774), C(f4f35bf5870a049c), -C(ba1ffba29f0367aa), C(a20bec1dd15a8b6c), C(e9bf61d2dab0f774), C(f4f35bf5870a049c), -C(26787efa5b92385), C(3d9533590ce30b59), C(a4da3e40530a01d4), C(6395deaefb70067c), -C(83e962fe)}, -{C(d97eacdf10f1c3c9), C(b54f4654043a36e0), C(b128f6eb09d1234), C(d8ad7ec84a9c9aa2), C(e256cffed11f69e6), C(2cf65e4958ad5bda), C(cfbf9b03245989a7), -C(d8ad7ec84a9c9aa2), C(e256cffed11f69e6), C(2cf65e4958ad5bda), C(cfbf9b03245989a7), -C(9fa51e6686cf4444), C(9425c117a34609d5), C(b25f7e2c6f30e96), C(ea5477c3f2b5afd1), -C(aac3531c)}, -{C(293a5c1c4e203cd4), C(6b3329f1c130cefe), C(f2e32f8ec76aac91), C(361e0a62c8187bff), C(6089971bb84d7133), C(93df7741588dd50b), C(c2a9b6abcd1d80b1), -C(361e0a62c8187bff), C(6089971bb84d7133), C(93df7741588dd50b), C(c2a9b6abcd1d80b1), -C(4d2f86869d79bc59), C(85cd24d8aa570ff), C(b0dcf6ef0e94bbb5), C(2037c69aa7a78421), -C(2b1db7cc)}, -{C(4290e018ffaedde7), C(a14948545418eb5e), C(72d851b202284636), C(4ec02f3d2f2b23f2), C(ab3580708aa7c339), C(cdce066fbab3f65), C(d8ed3ecf3c7647b9), -C(4ec02f3d2f2b23f2), C(ab3580708aa7c339), C(cdce066fbab3f65), C(d8ed3ecf3c7647b9), -C(6d2204b3e31f344a), C(61a4d87f80ee61d7), C(446c43dbed4b728f), C(73130ac94f58747e), -C(cf00cd31)}, -{C(f919a59cbde8bf2f), C(a56d04203b2dc5a5), C(38b06753ac871e48), C(c2c9fc637dbdfcfa), C(292ab8306d149d75), C(7f436b874b9ffc07), C(a5b56b0129218b80), -C(c2c9fc637dbdfcfa), C(292ab8306d149d75), C(7f436b874b9ffc07), C(a5b56b0129218b80), -C(9188f7bdc47ec050), C(cfe9345d03a15ade), C(40b520fb2750c49e), C(c2e83d343968af2e), -C(7d3c43b8)}, -{C(1d70a3f5521d7fa4), C(fb97b3fdc5891965), C(299d49bbbe3535af), C(e1a8286a7d67946e), C(52bd956f047b298), C(cbd74332dd4204ac), C(12b5be7752721976), -C(e1a8286a7d67946e), C(52bd956f047b298), C(cbd74332dd4204ac), C(12b5be7752721976), -C(278426e27f6204b6), C(932ca7a7cd610181), C(41647321f0a5914d), C(48f4aa61a0ae80db), -C(cbd5fac6)}, -{C(6af98d7b656d0d7c), C(d2e99ae96d6b5c0c), C(f63bd1603ef80627), C(bde51033ac0413f8), C(bc0272f691aec629), C(6204332651bebc44), C(1cbf00de026ea9bd), -C(bde51033ac0413f8), C(bc0272f691aec629), C(6204332651bebc44), C(1cbf00de026ea9bd), -C(b9c7ed6a75f3ff1e), C(7e310b76a5808e4f), C(acbbd1aad5531885), C(fc245f2473adeb9c), -C(76d0fec4)}, -{C(395b7a8adb96ab75), C(582df7165b20f4a), C(e52bd30e9ff657f9), C(6c71064996cbec8b), C(352c535edeefcb89), C(ac7f0aba15cd5ecd), C(3aba1ca8353e5c60), -C(6c71064996cbec8b), C(352c535edeefcb89), C(ac7f0aba15cd5ecd), C(3aba1ca8353e5c60), -C(5c30a288a80ce646), C(c2940488b6617674), C(925f8cc66b370575), C(aa65d1283b9bb0ef), -C(405e3402)}, -{C(3822dd82c7df012f), C(b9029b40bd9f122b), C(fd25b988468266c4), C(43e47bd5bab1e0ef), C(4a71f363421f282f), C(880b2f32a2b4e289), C(1299d4eda9d3eadf), -C(43e47bd5bab1e0ef), C(4a71f363421f282f), C(880b2f32a2b4e289), C(1299d4eda9d3eadf), -C(d713a40226f5564), C(4d8d34fedc769406), C(a85001b29cd9cac3), C(cae92352a41fd2b0), -C(c732c481)}, -{C(79f7efe4a80b951a), C(dd3a3fddfc6c9c41), C(ab4c812f9e27aa40), C(832954ec9d0de333), C(94c390aa9bcb6b8a), C(f3b32afdc1f04f82), C(d229c3b72e4b9a74), -C(832954ec9d0de333), C(94c390aa9bcb6b8a), C(f3b32afdc1f04f82), C(d229c3b72e4b9a74), -C(1d11860d7ed624a6), C(cadee20b3441b984), C(75307079bf306f7b), C(87902aa3b9753ba4), -C(a8d123c9)}, -{C(ae6e59f5f055921a), C(e9d9b7bf68e82), C(5ce4e4a5b269cc59), C(4960111789727567), C(149b8a37c7125ab6), C(78c7a13ab9749382), C(1c61131260ca151a), -C(4960111789727567), C(149b8a37c7125ab6), C(78c7a13ab9749382), C(1c61131260ca151a), -C(1e93276b35c309a0), C(2618f56230acde58), C(af61130a18e4febf), C(7145deb18e89befe), -C(1e80ad7d)}, -{C(8959dbbf07387d36), C(b4658afce48ea35d), C(8f3f82437d8cb8d6), C(6566d74954986ba5), C(99d5235cc82519a7), C(257a23805c2d825), C(ad75ccb968e93403), -C(6566d74954986ba5), C(99d5235cc82519a7), C(257a23805c2d825), C(ad75ccb968e93403), -C(b45bd4cf78e11f7f), C(80c5536bdc487983), C(a4fd76ecbf018c8a), C(3b9dac78a7a70d43), -C(52aeb863)}, -{C(4739613234278a49), C(99ea5bcd340bf663), C(258640912e712b12), C(c8a2827404991402), C(7ee5e78550f02675), C(2ec53952db5ac662), C(1526405a9df6794b), -C(c8a2827404991402), C(7ee5e78550f02675), C(2ec53952db5ac662), C(1526405a9df6794b), -C(eddc6271170c5e1f), C(f5a85f986001d9d6), C(95427c677bf58d58), C(53ed666dfa85cb29), -C(ef7c0c18)}, -{C(420e6c926bc54841), C(96dbbf6f4e7c75cd), C(d8d40fa70c3c67bb), C(3edbc10e4bfee91b), C(f0d681304c28ef68), C(77ea602029aaaf9c), C(90f070bd24c8483c), -C(3edbc10e4bfee91b), C(f0d681304c28ef68), C(77ea602029aaaf9c), C(90f070bd24c8483c), -C(28bc8e41e08ceb86), C(1eb56e48a65691ef), C(9fea5301c9202f0e), C(3fcb65091aa9f135), -C(b6ad4b68)}, -{C(c8601bab561bc1b7), C(72b26272a0ff869a), C(56fdfc986d6bc3c4), C(83707730cad725d4), C(c9ca88c3a779674a), C(e1c696fbbd9aa933), C(723f3baab1c17a45), -C(83707730cad725d4), C(c9ca88c3a779674a), C(e1c696fbbd9aa933), C(723f3baab1c17a45), -C(f82abc7a1d851682), C(30683836818e857d), C(78bfa3e89a5ab23f), C(6928234482b31817), -C(c1e46b17)}, -{C(b2d294931a0e20eb), C(284ffd9a0815bc38), C(1f8a103aac9bbe6), C(1ef8e98e1ea57269), C(5971116272f45a8b), C(187ad68ce95d8eac), C(e94e93ee4e8ecaa6), -C(1ef8e98e1ea57269), C(5971116272f45a8b), C(187ad68ce95d8eac), C(e94e93ee4e8ecaa6), -C(a0ff2a58611838b5), C(b01e03849bfbae6f), C(d081e202e28ea3ab), C(51836bcee762bf13), -C(57b8df25)}, -{C(7966f53c37b6c6d7), C(8e6abcfb3aa2b88f), C(7f2e5e0724e5f345), C(3eeb60c3f5f8143d), C(a25aec05c422a24f), C(b026b03ad3cca4db), C(e6e030028cc02a02), -C(3eeb60c3f5f8143d), C(a25aec05c422a24f), C(b026b03ad3cca4db), C(e6e030028cc02a02), -C(16fe679338b34bfc), C(c1be385b5c8a9de4), C(65af5df6567530eb), C(ed3b303df4dc6335), -C(e9fa36d6)}, -{C(be9bb0abd03b7368), C(13bca93a3031be55), C(e864f4f52b55b472), C(36a8d13a2cbb0939), C(254ac73907413230), C(73520d1522315a70), C(8c9fdb5cf1e1a507), -C(36a8d13a2cbb0939), C(254ac73907413230), C(73520d1522315a70), C(8c9fdb5cf1e1a507), -C(b3640570b926886), C(fba2344ee87f7bab), C(de57341ab448df05), C(385612ee094fa977), -C(8f8daefc)}, -{C(a08d128c5f1649be), C(a8166c3dbbe19aad), C(cb9f914f829ec62c), C(5b2b7ca856fad1c3), C(8093022d682e375d), C(ea5d163ba7ea231f), C(d6181d012c0de641), -C(5b2b7ca856fad1c3), C(8093022d682e375d), C(ea5d163ba7ea231f), C(d6181d012c0de641), -C(e7d40d0ab8b08159), C(2e82320f51b3a67e), C(27c2e356ea0b63a3), C(58842d01a2b1d077), -C(6e1bb7e)}, -{C(7c386f0ffe0465ac), C(530419c9d843dbf3), C(7450e3a4f72b8d8c), C(48b218e3b721810d), C(d3757ac8609bc7fc), C(111ba02a88aefc8), C(e86343137d3bfc2a), -C(48b218e3b721810d), C(d3757ac8609bc7fc), C(111ba02a88aefc8), C(e86343137d3bfc2a), -C(44ad26b51661b507), C(db1268670274f51e), C(62a5e75beae875f3), C(e266e7a44c5f28c6), -C(fd0076f0)}, -{C(bb362094e7ef4f8), C(ff3c2a48966f9725), C(55152803acd4a7fe), C(15747d8c505ffd00), C(438a15f391312cd6), C(e46ca62c26d821f5), C(be78d74c9f79cb44), -C(15747d8c505ffd00), C(438a15f391312cd6), C(e46ca62c26d821f5), C(be78d74c9f79cb44), -C(a8aa19f3aa59f09a), C(effb3cddab2c9267), C(d78e41ad97cb16a5), C(ace6821513527d32), -C(899b17b6)}, -{C(cd80dea24321eea4), C(52b4fdc8130c2b15), C(f3ea100b154bfb82), C(d9ccef1d4be46988), C(5ede0c4e383a5e66), C(da69683716a54d1e), C(bfc3fdf02d242d24), -C(d9ccef1d4be46988), C(5ede0c4e383a5e66), C(da69683716a54d1e), C(bfc3fdf02d242d24), -C(20ed30274651b3f5), C(4c659824169e86c6), C(637226dae5b52a0e), C(7e050dbd1c71dc7f), -C(e3e84e31)}, -{C(d599a04125372c3a), C(313136c56a56f363), C(1e993c3677625832), C(2870a99c76a587a4), C(99f74cc0b182dda4), C(8a5e895b2f0ca7b6), C(3d78882d5e0bb1dc), -C(2870a99c76a587a4), C(99f74cc0b182dda4), C(8a5e895b2f0ca7b6), C(3d78882d5e0bb1dc), -C(f466123732a3e25e), C(aca5e59716a40e50), C(261d2e7383d0e686), C(ce9362d6a42c15a7), -C(eef79b6b)}, -{C(dbbf541e9dfda0a), C(1479fceb6db4f844), C(31ab576b59062534), C(a3335c417687cf3a), C(92ff114ac45cda75), C(c3b8a627384f13b5), C(c4f25de33de8b3f7), -C(a3335c417687cf3a), C(92ff114ac45cda75), C(c3b8a627384f13b5), C(c4f25de33de8b3f7), -C(eacbf520578c5964), C(4cb19c5ab24f3215), C(e7d8a6f67f0c6e7), C(325c2413eb770ada), -C(868e3315)}, -{C(c2ee3288be4fe2bf), C(c65d2f5ddf32b92), C(af6ecdf121ba5485), C(c7cd48f7abf1fe59), C(ce600656ace6f53a), C(8a94a4381b108b34), C(f9d1276c64bf59fb), -C(c7cd48f7abf1fe59), C(ce600656ace6f53a), C(8a94a4381b108b34), C(f9d1276c64bf59fb), -C(219ce70ff5a112a5), C(e6026c576e2d28d7), C(b8e467f25015e3a6), C(950cb904f37af710), -C(4639a426)}, -{C(d86603ced1ed4730), C(f9de718aaada7709), C(db8b9755194c6535), C(d803e1eead47604c), C(ad00f7611970a71b), C(bc50036b16ce71f5), C(afba96210a2ca7d6), -C(d803e1eead47604c), C(ad00f7611970a71b), C(bc50036b16ce71f5), C(afba96210a2ca7d6), -C(28f7a7be1d6765f0), C(97bd888b93938c68), C(6ad41d1b407ded49), C(b9bfec098dc543e4), -C(f3213646)}, -{C(915263c671b28809), C(a815378e7ad762fd), C(abec6dc9b669f559), C(d17c928c5342477f), C(745130b795254ad5), C(8c5db926fe88f8ba), C(742a95c953e6d974), -C(d17c928c5342477f), C(745130b795254ad5), C(8c5db926fe88f8ba), C(742a95c953e6d974), -C(279db8057b5d3e96), C(98168411565b4ec4), C(50a72c54fa1125fa), C(27766a635db73638), -C(17f148e9)}, -{C(2b67cdd38c307a5e), C(cb1d45bb5c9fe1c), C(800baf2a02ec18ad), C(6531c1fe32bcb417), C(8c970d8df8cdbeb4), C(917ba5fc67e72b40), C(4b65e4e263e0a426), -C(6531c1fe32bcb417), C(8c970d8df8cdbeb4), C(917ba5fc67e72b40), C(4b65e4e263e0a426), -C(e0de33ce88a8b3a9), C(f8ef98a437e16b08), C(a5162c0c7c5f7b62), C(dbdac43361b2b881), -C(bfd94880)}, -{C(2d107419073b9cd0), C(a96db0740cef8f54), C(ec41ee91b3ecdc1b), C(ffe319654c8e7ebc), C(6a67b8f13ead5a72), C(6dd10a34f80d532f), C(6e9cfaece9fbca4), -C(ffe319654c8e7ebc), C(6a67b8f13ead5a72), C(6dd10a34f80d532f), C(6e9cfaece9fbca4), -C(b4468eb6a30aa7e9), C(e87995bee483222a), C(d036c2c90c609391), C(853306e82fa32247), -C(bb1fa7f3)}, -{C(f3e9487ec0e26dfc), C(1ab1f63224e837fa), C(119983bb5a8125d8), C(8950cfcf4bdf622c), C(8847dca82efeef2f), C(646b75b026708169), C(21cab4b1687bd8b), -C(8950cfcf4bdf622c), C(8847dca82efeef2f), C(646b75b026708169), C(21cab4b1687bd8b), -C(243b489a9eae6231), C(5f3e634c4b779876), C(ff8abd1548eaf646), C(c7962f5f0151914b), -C(88816b1)}, -{C(1160987c8fe86f7d), C(879e6db1481eb91b), C(d7dcb802bfe6885d), C(14453b5cc3d82396), C(4ef700c33ed278bc), C(1639c72ffc00d12e), C(fb140ee6155f700d), -C(14453b5cc3d82396), C(4ef700c33ed278bc), C(1639c72ffc00d12e), C(fb140ee6155f700d), -C(2e6b5c96a6620862), C(a1f136998cbe19c), C(74e058a3b6c5a712), C(93dcf6bd33928b17), -C(5c2faeb3)}, -{C(eab8112c560b967b), C(97f550b58e89dbae), C(846ed506d304051f), C(276aa37744b5a028), C(8c10800ee90ea573), C(e6e57d2b33a1e0b7), C(91f83563cd3b9dda), -C(276aa37744b5a028), C(8c10800ee90ea573), C(e6e57d2b33a1e0b7), C(91f83563cd3b9dda), -C(afbb4739570738a1), C(440ba98da5d8f69), C(fde4e9b0eda20350), C(e67dfa5a2138fa1), -C(51b5fc6f)}, -{C(1addcf0386d35351), C(b5f436561f8f1484), C(85d38e22181c9bb1), C(ff5c03f003c1fefe), C(e1098670afe7ff6), C(ea445030cf86de19), C(f155c68b5c2967f8), -C(ff5c03f003c1fefe), C(e1098670afe7ff6), C(ea445030cf86de19), C(f155c68b5c2967f8), -C(95d31b145dbb2e9e), C(914fe1ca3deb3265), C(6066020b1358ccc1), C(c74bb7e2dee15036), -C(33d94752)}, -{C(d445ba84bf803e09), C(1216c2497038f804), C(2293216ea2237207), C(e2164451c651adfb), C(b2534e65477f9823), C(4d70691a69671e34), C(15be4963dbde8143), -C(e2164451c651adfb), C(b2534e65477f9823), C(4d70691a69671e34), C(15be4963dbde8143), -C(762e75c406c5e9a3), C(7b7579f7e0356841), C(480533eb066dfce5), C(90ae14ea6bfeb4ae), -C(b0c92948)}, -{C(37235a096a8be435), C(d9b73130493589c2), C(3b1024f59378d3be), C(ad159f542d81f04e), C(49626a97a946096), C(d8d3998bf09fd304), C(d127a411eae69459), -C(ad159f542d81f04e), C(49626a97a946096), C(d8d3998bf09fd304), C(d127a411eae69459), -C(8f3253c4eb785a7b), C(4049062f37e62397), C(b9fa04d3b670e5c1), C(1211a7967ac9350f), -C(c7171590)}, -{C(763ad6ea2fe1c99d), C(cf7af5368ac1e26b), C(4d5e451b3bb8d3d4), C(3712eb913d04e2f2), C(2f9500d319c84d89), C(4ac6eb21a8cf06f9), C(7d1917afcde42744), -C(3712eb913d04e2f2), C(2f9500d319c84d89), C(4ac6eb21a8cf06f9), C(7d1917afcde42744), -C(6b58604b5dd10903), C(c4288dfbc1e319fc), C(230f75ca96817c6e), C(8894cba3b763756c), -C(240a67fb)}, -{C(ea627fc84cd1b857), C(85e372494520071f), C(69ec61800845780b), C(a3c1c5ca1b0367), C(eb6933997272bb3d), C(76a72cb62692a655), C(140bb5531edf756e), -C(a3c1c5ca1b0367), C(eb6933997272bb3d), C(76a72cb62692a655), C(140bb5531edf756e), -C(8d0d8067d1c925f4), C(7b3fa56d8d77a10c), C(2bd00287b0946d88), C(f08c8e4bd65b8970), -C(e1843cd5)}, -{C(1f2ffd79f2cdc0c8), C(726a1bc31b337aaa), C(678b7f275ef96434), C(5aa82bfaa99d3978), C(c18f96cade5ce18d), C(38404491f9e34c03), C(891fb8926ba0418c), -C(5aa82bfaa99d3978), C(c18f96cade5ce18d), C(38404491f9e34c03), C(891fb8926ba0418c), -C(e5f69a6398114c15), C(7b8ded3623bc6b1d), C(2f3e5c5da5ff70e8), C(1ab142addea6a9ec), -C(fda1452b)}, -{C(39a9e146ec4b3210), C(f63f75802a78b1ac), C(e2e22539c94741c3), C(8b305d532e61226e), C(caeae80da2ea2e), C(88a6289a76ac684e), C(8ce5b5f9df1cbd85), -C(8b305d532e61226e), C(caeae80da2ea2e), C(88a6289a76ac684e), C(8ce5b5f9df1cbd85), -C(8ae1fc4798e00d57), C(e7164b8fb364fc46), C(6a978c9bd3a66943), C(ef10d5ae4dd08dc), -C(a2cad330)}, -{C(74cba303e2dd9d6d), C(692699b83289fad1), C(dfb9aa7874678480), C(751390a8a5c41bdc), C(6ee5fbf87605d34), C(6ca73f610f3a8f7c), C(e898b3c996570ad), -C(751390a8a5c41bdc), C(6ee5fbf87605d34), C(6ca73f610f3a8f7c), C(e898b3c996570ad), -C(98168a5858fc7110), C(6f987fa27aa0daa2), C(f25e3e180d4b36a3), C(d0b03495aeb1be8a), -C(53467e16)}, -{C(4cbc2b73a43071e0), C(56c5db4c4ca4e0b7), C(1b275a162f46bd3d), C(b87a326e413604bf), C(d8f9a5fa214b03ab), C(8a8bb8265771cf88), C(a655319054f6e70f), -C(b87a326e413604bf), C(d8f9a5fa214b03ab), C(8a8bb8265771cf88), C(a655319054f6e70f), -C(b499cb8e65a9af44), C(bee7fafcc8307491), C(5d2e55fa9b27cda2), C(63b120f5fb2d6ee5), -C(da14a8d0)}, -{C(875638b9715d2221), C(d9ba0615c0c58740), C(616d4be2dfe825aa), C(5df25f13ea7bc284), C(165edfaafd2598fb), C(af7215c5c718c696), C(e9f2f9ca655e769), -C(5df25f13ea7bc284), C(165edfaafd2598fb), C(af7215c5c718c696), C(e9f2f9ca655e769), -C(e459cfcb565d3d2d), C(41d032631be2418a), C(c505db05fd946f60), C(54990394a714f5de), -C(67333551)}, -{C(fb686b2782994a8d), C(edee60693756bb48), C(e6bc3cae0ded2ef5), C(58eb4d03b2c3ddf5), C(6d2542995f9189f1), C(c0beec58a5f5fea2), C(ed67436f42e2a78b), -C(58eb4d03b2c3ddf5), C(6d2542995f9189f1), C(c0beec58a5f5fea2), C(ed67436f42e2a78b), -C(dfec763cdb2b5193), C(724a8d5345bd2d6), C(94d4fd1b81457c23), C(28e87c50cdede453), -C(a0ebd66e)}, -{C(ab21d81a911e6723), C(4c31b07354852f59), C(835da384c9384744), C(7f759dddc6e8549a), C(616dd0ca022c8735), C(94717ad4bc15ceb3), C(f66c7be808ab36e), -C(7f759dddc6e8549a), C(616dd0ca022c8735), C(94717ad4bc15ceb3), C(f66c7be808ab36e), -C(af8286b550b2f4b7), C(745bd217d20a9f40), C(c73bfb9c5430f015), C(55e65922666e3fc2), -C(4b769593)}, -{C(33d013cc0cd46ecf), C(3de726423aea122c), C(116af51117fe21a9), C(f271ba474edc562d), C(e6596e67f9dd3ebd), C(c0a288edf808f383), C(b3def70681c6babc), -C(f271ba474edc562d), C(e6596e67f9dd3ebd), C(c0a288edf808f383), C(b3def70681c6babc), -C(7da7864e9989b095), C(bf2f8718693cd8a1), C(264a9144166da776), C(61ad90676870beb6), -C(6aa75624)}, -{C(8ca92c7cd39fae5d), C(317e620e1bf20f1), C(4f0b33bf2194b97f), C(45744afcf131dbee), C(97222392c2559350), C(498a19b280c6d6ed), C(83ac2c36acdb8d49), -C(45744afcf131dbee), C(97222392c2559350), C(498a19b280c6d6ed), C(83ac2c36acdb8d49), -C(7a69645c294daa62), C(abe9d2be8275b3d2), C(39542019de371085), C(7f4efac8488cd6ad), -C(602a3f96)}, -{C(fdde3b03f018f43e), C(38f932946c78660), C(c84084ce946851ee), C(b6dd09ba7851c7af), C(570de4e1bb13b133), C(c4e784eb97211642), C(8285a7fcdcc7c58d), -C(b6dd09ba7851c7af), C(570de4e1bb13b133), C(c4e784eb97211642), C(8285a7fcdcc7c58d), -C(d421f47990da899b), C(8aed409c997eaa13), C(7a045929c2e29ccf), C(b373682a6202c86b), -C(cd183c4d)}, -{C(9c8502050e9c9458), C(d6d2a1a69964beb9), C(1675766f480229b5), C(216e1d6c86cb524c), C(d01cf6fd4f4065c0), C(fffa4ec5b482ea0f), C(a0e20ee6a5404ac1), -C(216e1d6c86cb524c), C(d01cf6fd4f4065c0), C(fffa4ec5b482ea0f), C(a0e20ee6a5404ac1), -C(c1b037e4eebaf85e), C(634e3d7c3ebf89eb), C(bcda972358c67d1), C(fd1352181e5b8578), -C(960a4d07)}, -{C(348176ca2fa2fdd2), C(3a89c514cc360c2d), C(9f90b8afb318d6d0), C(bceee07c11a9ac30), C(2e2d47dff8e77eb7), C(11a394cd7b6d614a), C(1d7c41d54e15cb4a), -C(bceee07c11a9ac30), C(2e2d47dff8e77eb7), C(11a394cd7b6d614a), C(1d7c41d54e15cb4a), -C(15baa5ae7312b0fc), C(f398f596cc984635), C(8ab8fdf87a6788e8), C(b2b5c1234ab47e2), -C(9ae998c4)}, -{C(4a3d3dfbbaea130b), C(4e221c920f61ed01), C(553fd6cd1304531f), C(bd2b31b5608143fe), C(ab717a10f2554853), C(293857f04d194d22), C(d51be8fa86f254f0), -C(bd2b31b5608143fe), C(ab717a10f2554853), C(293857f04d194d22), C(d51be8fa86f254f0), -C(1eee39e07686907e), C(639039fe0e8d3052), C(d6ec1470cef97ff), C(370c82b860034f0f), -C(74e2179d)}, -{C(b371f768cdf4edb9), C(bdef2ace6d2de0f0), C(e05b4100f7f1baec), C(b9e0d415b4ebd534), C(c97c2a27efaa33d7), C(591cdb35f84ef9da), C(a57d02d0e8e3756c), -C(b9e0d415b4ebd534), C(c97c2a27efaa33d7), C(591cdb35f84ef9da), C(a57d02d0e8e3756c), -C(23f55f12d7c5c87b), C(4c7ca0fe23221101), C(dbc3020480334564), C(d985992f32c236b1), -C(ee9bae25)}, -{C(7a1d2e96934f61f), C(eb1760ae6af7d961), C(887eb0da063005df), C(2228d6725e31b8ab), C(9b98f7e4d0142e70), C(b6a8c2115b8e0fe7), C(b591e2f5ab9b94b1), -C(2228d6725e31b8ab), C(9b98f7e4d0142e70), C(b6a8c2115b8e0fe7), C(b591e2f5ab9b94b1), -C(6c1feaa8065318e0), C(4e7e2ca21c2e81fb), C(e9fe5d8ce7993c45), C(ee411fa2f12cf8df), -C(b66edf10)}, -{C(8be53d466d4728f2), C(86a5ac8e0d416640), C(984aa464cdb5c8bb), C(87049e68f5d38e59), C(7d8ce44ec6bd7751), C(cc28d08ab414839c), C(6c8f0bd34fe843e3), -C(87049e68f5d38e59), C(7d8ce44ec6bd7751), C(cc28d08ab414839c), C(6c8f0bd34fe843e3), -C(b8496dcdc01f3e47), C(2f03125c282ac26), C(82a8797ba3f5ef07), C(7c977a4d10bf52b8), -C(d6209737)}, -{C(829677eb03abf042), C(43cad004b6bc2c0), C(f2f224756803971a), C(98d0dbf796480187), C(fbcb5f3e1bef5742), C(5af2a0463bf6e921), C(ad9555bf0120b3a3), -C(98d0dbf796480187), C(fbcb5f3e1bef5742), C(5af2a0463bf6e921), C(ad9555bf0120b3a3), -C(283e39b3dc99f447), C(bedaa1a4a0250c28), C(9d50546624ff9a57), C(4abaf523d1c090f6), -C(b994a88)}, -{C(754435bae3496fc), C(5707fc006f094dcf), C(8951c86ab19d8e40), C(57c5208e8f021a77), C(f7653fbb69cd9276), C(a484410af21d75cb), C(f19b6844b3d627e8), -C(57c5208e8f021a77), C(f7653fbb69cd9276), C(a484410af21d75cb), C(f19b6844b3d627e8), -C(f37400fc3ffd9514), C(36ae0d821734edfd), C(5f37820af1f1f306), C(be637d40e6a5ad0), -C(a05d43c0)}, -{C(fda9877ea8e3805f), C(31e868b6ffd521b7), C(b08c90681fb6a0fd), C(68110a7f83f5d3ff), C(6d77e045901b85a8), C(84ef681113036d8b), C(3b9f8e3928f56160), -C(68110a7f83f5d3ff), C(6d77e045901b85a8), C(84ef681113036d8b), C(3b9f8e3928f56160), -C(fc8b7f56c130835), C(a11f3e800638e841), C(d9572267f5cf28c1), C(7897c8149803f2aa), -C(c79f73a8)}, -{C(2e36f523ca8f5eb5), C(8b22932f89b27513), C(331cd6ecbfadc1bb), C(d1bfe4df12b04cbf), C(f58c17243fd63842), C(3a453cdba80a60af), C(5737b2ca7470ea95), -C(d1bfe4df12b04cbf), C(f58c17243fd63842), C(3a453cdba80a60af), C(5737b2ca7470ea95), -C(54d44a3f4477030c), C(8168e02d4869aa7f), C(77f383a17778559d), C(95e1737d77a268fc), -C(a490aff5)}, -{C(21a378ef76828208), C(a5c13037fa841da2), C(506d22a53fbe9812), C(61c9c95d91017da5), C(16f7c83ba68f5279), C(9c0619b0808d05f7), C(83c117ce4e6b70a3), -C(61c9c95d91017da5), C(16f7c83ba68f5279), C(9c0619b0808d05f7), C(83c117ce4e6b70a3), -C(cfb4c8af7fd01413), C(fdef04e602e72296), C(ed6124d337889b1), C(4919c86707b830da), -C(dfad65b4)}, -{C(ccdd5600054b16ca), C(f78846e84204cb7b), C(1f9faec82c24eac9), C(58634004c7b2d19a), C(24bb5f51ed3b9073), C(46409de018033d00), C(4a9805eed5ac802e), -C(58634004c7b2d19a), C(24bb5f51ed3b9073), C(46409de018033d00), C(4a9805eed5ac802e), -C(e18de8db306baf82), C(46bbf75f1fa025ff), C(5faf2fb09be09487), C(3fbc62bd4e558fb3), -C(1d07dfb)}, -{C(7854468f4e0cabd0), C(3a3f6b4f098d0692), C(ae2423ec7799d30d), C(29c3529eb165eeba), C(443de3703b657c35), C(66acbce31ae1bc8d), C(1acc99effe1d547e), -C(29c3529eb165eeba), C(443de3703b657c35), C(66acbce31ae1bc8d), C(1acc99effe1d547e), -C(cf07f8a57906573d), C(31bafb0bbb9a86e7), C(40c69492702a9346), C(7df61fdaa0b858af), -C(416df9a0)}, -{C(7f88db5346d8f997), C(88eac9aacc653798), C(68a4d0295f8eefa1), C(ae59ca86f4c3323d), C(25906c09906d5c4c), C(8dd2aa0c0a6584ae), C(232a7d96b38f40e9), -C(ae59ca86f4c3323d), C(25906c09906d5c4c), C(8dd2aa0c0a6584ae), C(232a7d96b38f40e9), -C(8986ee00a2ed0042), C(c49ae7e428c8a7d1), C(b7dd8280713ac9c2), C(e018720aed1ebc28), -C(1f8fb9cc)}, -{C(bb3fb5fb01d60fcf), C(1b7cc0847a215eb6), C(1246c994437990a1), C(d4edc954c07cd8f3), C(224f47e7c00a30ab), C(d5ad7ad7f41ef0c6), C(59e089281d869fd7), -C(d4edc954c07cd8f3), C(224f47e7c00a30ab), C(d5ad7ad7f41ef0c6), C(59e089281d869fd7), -C(f29340d07a14b6f1), C(c87c5ef76d9c4ef3), C(463118794193a9a), C(2922dcb0540f0dbc), -C(7abf48e3)}, -{C(2e783e1761acd84d), C(39158042bac975a0), C(1cd21c5a8071188d), C(b1b7ec44f9302176), C(5cb476450dc0c297), C(dc5ef652521ef6a2), C(3cc79a9e334e1f84), -C(b1b7ec44f9302176), C(5cb476450dc0c297), C(dc5ef652521ef6a2), C(3cc79a9e334e1f84), -C(769e2a283dbcc651), C(9f24b105c8511d3f), C(c31c15575de2f27e), C(ecfecf32c3ae2d66), -C(dea4e3dd)}, -{C(392058251cf22acc), C(944ec4475ead4620), C(b330a10b5cb94166), C(54bc9bee7cbe1767), C(485820bdbe442431), C(54d6120ea2972e90), C(f437a0341f29b72a), -C(54bc9bee7cbe1767), C(485820bdbe442431), C(54d6120ea2972e90), C(f437a0341f29b72a), -C(8f30885c784d5704), C(aa95376b16c7906a), C(e826928cfaf93dc3), C(20e8f54d1c16d7d8), -C(c6064f22)}, -{C(adf5c1e5d6419947), C(2a9747bc659d28aa), C(95c5b8cb1f5d62c), C(80973ea532b0f310), C(a471829aa9c17dd9), C(c2ff3479394804ab), C(6bf44f8606753636), -C(80973ea532b0f310), C(a471829aa9c17dd9), C(c2ff3479394804ab), C(6bf44f8606753636), -C(5184d2973e6dd827), C(121b96369a332d9a), C(5c25d3475ab69e50), C(26d2961d62884168), -C(743bed9c)}, -{C(6bc1db2c2bee5aba), C(e63b0ed635307398), C(7b2eca111f30dbbc), C(230d2b3e47f09830), C(ec8624a821c1caf4), C(ea6ec411cdbf1cb1), C(5f38ae82af364e27), -C(230d2b3e47f09830), C(ec8624a821c1caf4), C(ea6ec411cdbf1cb1), C(5f38ae82af364e27), -C(a519ef515ea7187c), C(6bad5efa7ebae05f), C(748abacb11a74a63), C(a28eef963d1396eb), -C(fce254d5)}, -{C(b00f898229efa508), C(83b7590ad7f6985c), C(2780e70a0592e41d), C(7122413bdbc94035), C(e7f90fae33bf7763), C(4b6bd0fb30b12387), C(557359c0c44f48ca), -C(7122413bdbc94035), C(e7f90fae33bf7763), C(4b6bd0fb30b12387), C(557359c0c44f48ca), -C(d5656c3d6bc5f0d), C(983ff8e5e784da99), C(628479671b445bf), C(e179a1e27ce68f5d), -C(e47ec9d1)}, -{C(b56eb769ce0d9a8c), C(ce196117bfbcaf04), C(b26c3c3797d66165), C(5ed12338f630ab76), C(fab19fcb319116d), C(167f5f42b521724b), C(c4aa56c409568d74), -C(5ed12338f630ab76), C(fab19fcb319116d), C(167f5f42b521724b), C(c4aa56c409568d74), -C(75fff4b42f8e9778), C(94218f94710c1ea3), C(b7b05efb738b06a6), C(83fff2deabf9cd3), -C(334a145c)}, -{C(70c0637675b94150), C(259e1669305b0a15), C(46e1dd9fd387a58d), C(fca4e5bc9292788e), C(cd509dc1facce41c), C(bbba575a59d82fe), C(4e2e71c15b45d4d3), -C(fca4e5bc9292788e), C(cd509dc1facce41c), C(bbba575a59d82fe), C(4e2e71c15b45d4d3), -C(5dc54582ead999c), C(72612d1571963c6f), C(30318a9d2d3d1829), C(785dd00f4cc9c9a0), -C(adec1e3c)}, -{C(74c0b8a6821faafe), C(abac39d7491370e7), C(faf0b2a48a4e6aed), C(967e970df9673d2a), C(d465247cffa415c0), C(33a1df0ca1107722), C(49fc2a10adce4a32), -C(967e970df9673d2a), C(d465247cffa415c0), C(33a1df0ca1107722), C(49fc2a10adce4a32), -C(c5707e079a284308), C(573028266635dda6), C(f786f5eee6127fa0), C(b30d79cebfb51266), -C(f6a9fbf8)}, -{C(5fb5e48ac7b7fa4f), C(a96170f08f5acbc7), C(bbf5c63d4f52a1e5), C(6cc09e60700563e9), C(d18f23221e964791), C(ffc23eeef7af26eb), C(693a954a3622a315), -C(815308a32a9b0daf), C(efb2ab27bf6fd0bd), C(9f1ffc0986111118), C(f9a3aa1778ea3985), -C(698fe54b2b93933b), C(dacc2b28404d0f10), C(815308a32a9b0daf), C(efb2ab27bf6fd0bd), -C(5398210c)}, +static const uint64 testdata[kTestSize][16] = +{ + { + C(9ae16a3b2f90404f), C(75106db890237a4a), C(3feac5f636039766), C(3df09dfc64c09a2b), C(3cb540c392e51e29), C(6b56343feac0663), C(5b7bc50fd8e8ad92), + C(3df09dfc64c09a2b), C(3cb540c392e51e29), C(6b56343feac0663), C(5b7bc50fd8e8ad92), + C(95162f24e6a5f930), C(6808bdf4f1eb06e0), C(b3b1f3a67b624d82), C(c9a62f12bd4cd80b), + C(dc56d17a) + }, + { + C(541150e87f415e96), C(1aef0d24b3148a1a), C(bacc300e1e82345a), C(c3cdc41e1df33513), C(2c138ff2596d42f6), C(f58e9082aed3055f), C(162e192b2957163d), + C(c3cdc41e1df33513), C(2c138ff2596d42f6), C(f58e9082aed3055f), C(162e192b2957163d), + C(fb99e85e0d16f90c), C(608462c15bdf27e8), C(e7d2c5c943572b62), C(1baaa9327642798c), + C(99929334) + }, + { + C(f3786a4b25827c1), C(34ee1a2bf767bd1c), C(2f15ca2ebfb631f2), C(3149ba1dac77270d), C(70e2e076e30703c), C(59bcc9659bc5296), C(9ecbc8132ae2f1d7), + C(3149ba1dac77270d), C(70e2e076e30703c), C(59bcc9659bc5296), C(9ecbc8132ae2f1d7), + C(a01d30789bad7cf2), C(ae03fe371981a0e0), C(127e3883b8788934), C(d0ac3d4c0a6fca32), + C(4252edb7) + }, + { + C(ef923a7a1af78eab), C(79163b1e1e9a9b18), C(df3b2aca6e1e4a30), C(2193fb7620cbf23b), C(8b6a8ff06cda8302), C(1a44469afd3e091f), C(8b0449376612506), + C(2193fb7620cbf23b), C(8b6a8ff06cda8302), C(1a44469afd3e091f), C(8b0449376612506), + C(e9d9d41c32ad91d1), C(b44ab09f58e3c608), C(19e9175f9fcf784), C(839b3c9581b4a480), + C(ebc34f3c) + }, + { + C(11df592596f41d88), C(843ec0bce9042f9c), C(cce2ea1e08b1eb30), C(4d09e42f09cc3495), C(666236631b9f253b), C(d28b3763cd02b6a3), C(43b249e57c4d0c1b), + C(4d09e42f09cc3495), C(666236631b9f253b), C(d28b3763cd02b6a3), C(43b249e57c4d0c1b), + C(3887101c8adea101), C(8a9355d4efc91df0), C(3e610944cc9fecfd), C(5bf9eb60b08ac0ce), + C(26f2b463) + }, + { + C(831f448bdc5600b3), C(62a24be3120a6919), C(1b44098a41e010da), C(dc07df53b949c6b), C(d2b11b2081aeb002), C(d212b02c1b13f772), C(c0bed297b4be1912), + C(dc07df53b949c6b), C(d2b11b2081aeb002), C(d212b02c1b13f772), C(c0bed297b4be1912), + C(682d3d2ad304e4af), C(40e9112a655437a1), C(268b09f7ee09843f), C(6b9698d43859ca47), + C(b042c047) + }, + { + C(3eca803e70304894), C(d80de767e4a920a), C(a51cfbb292efd53d), C(d183dcda5f73edfa), C(3a93cbf40f30128c), C(1a92544d0b41dbda), C(aec2c4bee81975e1), + C(d183dcda5f73edfa), C(3a93cbf40f30128c), C(1a92544d0b41dbda), C(aec2c4bee81975e1), + C(5f91814d1126ba4b), C(f8ac57eee87fcf1f), C(c55c644a5d0023cd), C(adb761e827825ff2), + C(e73bb0a8) + }, + { + C(1b5a063fb4c7f9f1), C(318dbc24af66dee9), C(10ef7b32d5c719af), C(b140a02ef5c97712), C(b7d00ef065b51b33), C(635121d532897d98), C(532daf21b312a6d6), + C(b140a02ef5c97712), C(b7d00ef065b51b33), C(635121d532897d98), C(532daf21b312a6d6), + C(c0b09b75d943910), C(8c84dfb5ef2a8e96), C(e5c06034b0353433), C(3170faf1c33a45dd), + C(91dfdd75) + }, + { + C(a0f10149a0e538d6), C(69d008c20f87419f), C(41b36376185b3e9e), C(26b6689960ccf81d), C(55f23b27bb9efd94), C(3a17f6166dd765db), C(c891a8a62931e782), + C(26b6689960ccf81d), C(55f23b27bb9efd94), C(3a17f6166dd765db), C(c891a8a62931e782), + C(23852dc37ddd2607), C(8b7f1b1ec897829e), C(d1d69452a54eed8a), C(56431f2bd766ec24), + C(c87f95de) + }, + { + C(fb8d9c70660b910b), C(a45b0cc3476bff1b), C(b28d1996144f0207), C(98ec31113e5e35d2), C(5e4aeb853f1b9aa7), C(bcf5c8fe4465b7c8), C(b1ea3a8243996f15), + C(98ec31113e5e35d2), C(5e4aeb853f1b9aa7), C(bcf5c8fe4465b7c8), C(b1ea3a8243996f15), + C(cabbccedb6407571), C(d1e40a84c445ec3a), C(33302aa908cf4039), C(9f15f79211b5cdf8), + C(3f5538ef) + }, + { + C(236827beae282a46), C(e43970221139c946), C(4f3ac6faa837a3aa), C(71fec0f972248915), C(2170ec2061f24574), C(9eb346b6caa36e82), C(2908f0fdbca48e73), + C(71fec0f972248915), C(2170ec2061f24574), C(9eb346b6caa36e82), C(2908f0fdbca48e73), + C(8101c99f07c64abb), C(b9f4b02b1b6a96a7), C(583a2b10cd222f88), C(199dae4cf9db24c), + C(70eb1a1f) + }, + { + C(c385e435136ecf7c), C(d9d17368ff6c4a08), C(1b31eed4e5251a67), C(df01a322c43a6200), C(298b65a1714b5a7e), C(933b83f0aedf23c), C(157bcb44d63f765a), + C(df01a322c43a6200), C(298b65a1714b5a7e), C(933b83f0aedf23c), C(157bcb44d63f765a), + C(d6e9fc7a272d8b51), C(3ee5073ef1a9b777), C(63149e31fac02c59), C(2f7979ff636ba1d8), + C(cfd63b83) + }, + { + C(e3f6828b6017086d), C(21b4d1900554b3b0), C(bef38be1809e24f1), C(d93251758985ee6c), C(32a9e9f82ba2a932), C(3822aacaa95f3329), C(db349b2f90a490d8), + C(d93251758985ee6c), C(32a9e9f82ba2a932), C(3822aacaa95f3329), C(db349b2f90a490d8), + C(8d49194a894a19ca), C(79a78b06e42738e6), C(7e0f1eda3d390c66), C(1c291d7e641100a5), + C(894a52ef) + }, + { + C(851fff285561dca0), C(4d1277d73cdf416f), C(28ccffa61010ebe2), C(77a4ccacd131d9ee), C(e1d08eeb2f0e29aa), C(70b9e3051383fa45), C(582d0120425caba), + C(77a4ccacd131d9ee), C(e1d08eeb2f0e29aa), C(70b9e3051383fa45), C(582d0120425caba), + C(a740eef1846e4564), C(572dddb74ac3ae00), C(fdb5ca9579163bbd), C(a649b9b799c615d2), + C(9cde6a54) + }, + { + C(61152a63595a96d9), C(d1a3a91ef3a7ba45), C(443b6bb4a493ad0c), C(a154296d11362d06), C(d0f0bf1f1cb02fc1), C(ccb87e09309f90d1), C(b24a8e4881911101), + C(a154296d11362d06), C(d0f0bf1f1cb02fc1), C(ccb87e09309f90d1), C(b24a8e4881911101), + C(1a481b4528559f58), C(bf837a3150896995), C(4989ef6b941a3757), C(2e725ab72d0b2948), + C(6c4898d5) + }, + { + C(44473e03be306c88), C(30097761f872472a), C(9fd1b669bfad82d7), C(3bab18b164396783), C(47e385ff9d4c06f), C(18062081bf558df), C(63416eb68f104a36), + C(3bab18b164396783), C(47e385ff9d4c06f), C(18062081bf558df), C(63416eb68f104a36), + C(4abda1560c47ac80), C(1ea0e63dc6587aee), C(33ec79d92ebc1de), C(94f9dccef771e048), + C(13e1978e) + }, + { + C(3ead5f21d344056), C(fb6420393cfb05c3), C(407932394cbbd303), C(ac059617f5906673), C(94d50d3dcd3069a7), C(2b26c3b92dea0f0), C(99b7374cc78fc3fb), + C(ac059617f5906673), C(94d50d3dcd3069a7), C(2b26c3b92dea0f0), C(99b7374cc78fc3fb), + C(1a8e3c73cdd40ee8), C(cbb5fca06747f45b), C(ceec44238b291841), C(28bf35cce9c90a25), + C(51b4ba8) + }, + { + C(6abbfde37ee03b5b), C(83febf188d2cc113), C(cda7b62d94d5b8ee), C(a4375590b8ae7c82), C(168fd42f9ecae4ff), C(23bbde43de2cb214), C(a8c333112a243c8c), + C(a4375590b8ae7c82), C(168fd42f9ecae4ff), C(23bbde43de2cb214), C(a8c333112a243c8c), + C(10ac012e8c518b49), C(64a44605d8b29458), C(a67e701d2a679075), C(3a3a20f43ec92303), + C(b6b06e40) + }, + { + C(943e7ed63b3c080), C(1ef207e9444ef7f8), C(ef4a9f9f8c6f9b4a), C(6b54fc38d6a84108), C(32f4212a47a4665), C(6b5a9a8f64ee1da6), C(9f74e86c6da69421), + C(6b54fc38d6a84108), C(32f4212a47a4665), C(6b5a9a8f64ee1da6), C(9f74e86c6da69421), + C(946dd0cb30c1a08e), C(fdf376956907eaaa), C(a59074c6eec03028), C(b1a3abcf283f34ac), + C(240a2f2) + }, + { + C(d72ce05171ef8a1a), C(c6bd6bd869203894), C(c760e6396455d23a), C(f86af0b40dcce7b), C(8d3c15d613394d3c), C(491e400491cd4ece), C(7c19d3530ea3547f), + C(f86af0b40dcce7b), C(8d3c15d613394d3c), C(491e400491cd4ece), C(7c19d3530ea3547f), + C(1362963a1dc32af9), C(fb9bc11762e1385c), C(9e164ef1f5376083), C(6c15819b5e828a7e), + C(5dcefc30) + }, + { + C(4182832b52d63735), C(337097e123eea414), C(b5a72ca0456df910), C(7ebc034235bc122f), C(d9a7783d4edd8049), C(5f8b04a15ae42361), C(fc193363336453dd), + C(7ebc034235bc122f), C(d9a7783d4edd8049), C(5f8b04a15ae42361), C(fc193363336453dd), + C(9b6c50224ef8c4f8), C(ba225c7942d16c3f), C(6f6d55226a73c412), C(abca061fe072152a), + C(7a48b105) + }, + { + C(d6cdae892584a2cb), C(58de0fa4eca17dcd), C(43df30b8f5f1cb00), C(9e4ea5a4941e097d), C(547e048d5a9daaba), C(eb6ecbb0b831d185), C(e0168df5fad0c670), + C(9e4ea5a4941e097d), C(547e048d5a9daaba), C(eb6ecbb0b831d185), C(e0168df5fad0c670), + C(afa9705f98c2c96a), C(749436f48137a96b), C(759c041fc21df486), C(b23bf400107aa2ec), + C(fd55007b) + }, + { + C(5c8e90bc267c5ee4), C(e9ae044075d992d9), C(f234cbfd1f0a1e59), C(ce2744521944f14c), C(104f8032f99dc152), C(4e7f425bfac67ca7), C(9461b911a1c6d589), + C(ce2744521944f14c), C(104f8032f99dc152), C(4e7f425bfac67ca7), C(9461b911a1c6d589), + C(5e5ecc726db8b60d), C(cce68b0586083b51), C(8a7f8e54a9cba0fc), C(42f010181d16f049), + C(6b95894c) + }, + { + C(bbd7f30ac310a6f3), C(b23b570d2666685f), C(fb13fb08c9814fe7), C(4ee107042e512374), C(1e2c8c0d16097e13), C(210c7500995aa0e6), C(6c13190557106457), + C(4ee107042e512374), C(1e2c8c0d16097e13), C(210c7500995aa0e6), C(6c13190557106457), + C(a99b31c96777f381), C(8312ae8301d386c0), C(ed5042b2a4fa96a3), C(d71d1bb23907fe97), + C(3360e827) + }, + { + C(36a097aa49519d97), C(8204380a73c4065), C(77c2004bdd9e276a), C(6ee1f817ce0b7aee), C(e9dcb3507f0596ca), C(6bc63c666b5100e2), C(e0b056f1821752af), + C(6ee1f817ce0b7aee), C(e9dcb3507f0596ca), C(6bc63c666b5100e2), C(e0b056f1821752af), + C(8ea1114e60292678), C(904b80b46becc77), C(46cd9bb6e9dff52f), C(4c91e3b698355540), + C(45177e0b) + }, + { + C(dc78cb032c49217), C(112464083f83e03a), C(96ae53e28170c0f5), C(d367ff54952a958), C(cdad930657371147), C(aa24dc2a9573d5fe), C(eb136daa89da5110), + C(d367ff54952a958), C(cdad930657371147), C(aa24dc2a9573d5fe), C(eb136daa89da5110), + C(de623005f6d46057), C(b50c0c92b95e9b7f), C(a8aa54050b81c978), C(573fb5c7895af9b5), + C(7c6fffe4) + }, + { + C(441593e0da922dfe), C(936ef46061469b32), C(204a1921197ddd87), C(50d8a70e7a8d8f56), C(256d150ae75dab76), C(e81f4c4a1989036a), C(d0f8db365f9d7e00), + C(50d8a70e7a8d8f56), C(256d150ae75dab76), C(e81f4c4a1989036a), C(d0f8db365f9d7e00), + C(753d686677b14522), C(9f76e0cb6f2d0a66), C(ab14f95988ec0d39), C(97621d9da9c9812f), + C(bbc78da4) + }, + { + C(2ba3883d71cc2133), C(72f2bbb32bed1a3c), C(27e1bd96d4843251), C(a90f761e8db1543a), C(c339e23c09703cd8), C(f0c6624c4b098fd3), C(1bae2053e41fa4d9), + C(a90f761e8db1543a), C(c339e23c09703cd8), C(f0c6624c4b098fd3), C(1bae2053e41fa4d9), + C(3589e273c22ba059), C(63798246e5911a0b), C(18e710ec268fc5dc), C(714a122de1d074f3), + C(c5c25d39) + }, + { + C(f2b6d2adf8423600), C(7514e2f016a48722), C(43045743a50396ba), C(23dacb811652ad4f), C(c982da480e0d4c7d), C(3a9c8ed5a399d0a9), C(951b8d084691d4e4), + C(23dacb811652ad4f), C(c982da480e0d4c7d), C(3a9c8ed5a399d0a9), C(951b8d084691d4e4), + C(d9f87b4988cff2f7), C(217a191d986aa3bc), C(6ad23c56b480350), C(dd78673938ceb2e7), + C(b6e5d06e) + }, + { + C(38fffe7f3680d63c), C(d513325255a7a6d1), C(31ed47790f6ca62f), C(c801faaa0a2e331f), C(491dbc58279c7f88), C(9c0178848321c97a), C(9d934f814f4d6a3c), + C(c801faaa0a2e331f), C(491dbc58279c7f88), C(9c0178848321c97a), C(9d934f814f4d6a3c), + C(606a3e4fc8763192), C(bc15cb36a677ee84), C(52d5904157e1fe71), C(1588dd8b1145b79b), + C(6178504e) + }, + { + C(b7477bf0b9ce37c6), C(63b1c580a7fd02a4), C(f6433b9f10a5dac), C(68dd76db9d64eca7), C(36297682b64b67), C(42b192d71f414b7a), C(79692cef44fa0206), + C(68dd76db9d64eca7), C(36297682b64b67), C(42b192d71f414b7a), C(79692cef44fa0206), + C(f0979252f4776d07), C(4b87cd4f1c9bbf52), C(51b84bbc6312c710), C(150720fbf85428a7), + C(bd4c3637) + }, + { + C(55bdb0e71e3edebd), C(c7ab562bcf0568bc), C(43166332f9ee684f), C(b2e25964cd409117), C(a010599d6287c412), C(fa5d6461e768dda2), C(cb3ce74e8ec4f906), + C(b2e25964cd409117), C(a010599d6287c412), C(fa5d6461e768dda2), C(cb3ce74e8ec4f906), + C(6120abfd541a2610), C(aa88b148cc95794d), C(2686ca35df6590e3), C(c6b02d18616ce94d), + C(6e7ac474) + }, + { + C(782fa1b08b475e7), C(fb7138951c61b23b), C(9829105e234fb11e), C(9a8c431f500ef06e), C(d848581a580b6c12), C(fecfe11e13a2bdb4), C(6c4fa0273d7db08c), + C(9a8c431f500ef06e), C(d848581a580b6c12), C(fecfe11e13a2bdb4), C(6c4fa0273d7db08c), + C(482f43bf5ae59fcb), C(f651fbca105d79e6), C(f09f78695d865817), C(7a99d0092085cf47), + C(1fb4b518) + }, + { + C(c5dc19b876d37a80), C(15ffcff666cfd710), C(e8c30c72003103e2), C(7870765b470b2c5d), C(78a9103ff960d82), C(7bb50ffc9fac74b3), C(477e70ab2b347db2), + C(7870765b470b2c5d), C(78a9103ff960d82), C(7bb50ffc9fac74b3), C(477e70ab2b347db2), + C(a625238bdf7c07cf), C(1128d515174809f5), C(b0f1647e82f45873), C(17792d1c4f222c39), + C(31d13d6d) + }, + { + C(5e1141711d2d6706), C(b537f6dee8de6933), C(3af0a1fbbe027c54), C(ea349dbc16c2e441), C(38a7455b6a877547), C(5f97b9750e365411), C(e8cde7f93af49a3), + C(ea349dbc16c2e441), C(38a7455b6a877547), C(5f97b9750e365411), C(e8cde7f93af49a3), + C(ba101925ec1f7e26), C(d5e84cab8192c71e), C(e256427726fdd633), C(a4f38e2c6116890d), + C(26fa72e3) + }, + { + C(782edf6da001234f), C(f48cbd5c66c48f3), C(808754d1e64e2a32), C(5d9dde77353b1a6d), C(11f58c54581fa8b1), C(da90fa7c28c37478), C(5e9a2eafc670a88a), + C(5d9dde77353b1a6d), C(11f58c54581fa8b1), C(da90fa7c28c37478), C(5e9a2eafc670a88a), + C(e35e1bc172e011ef), C(bf9255a4450ae7fe), C(55f85194e26bc55f), C(4f327873e14d0e54), + C(6a7433bf) + }, + { + C(d26285842ff04d44), C(8f38d71341eacca9), C(5ca436f4db7a883c), C(bf41e5376b9f0eec), C(2252d21eb7e1c0e9), C(f4b70a971855e732), C(40c7695aa3662afd), + C(bf41e5376b9f0eec), C(2252d21eb7e1c0e9), C(f4b70a971855e732), C(40c7695aa3662afd), + C(770fe19e16ab73bb), C(d603ebda6393d749), C(e58c62439aa50dbd), C(96d51e5a02d2d7cf), + C(4e6df758) + }, + { + C(c6ab830865a6bae6), C(6aa8e8dd4b98815c), C(efe3846713c371e5), C(a1924cbf0b5f9222), C(7f4872369c2b4258), C(cd6da30530f3ea89), C(b7f8b9a704e6cea1), + C(a1924cbf0b5f9222), C(7f4872369c2b4258), C(cd6da30530f3ea89), C(b7f8b9a704e6cea1), + C(fa06ff40433fd535), C(fb1c36fe8f0737f1), C(bb7050561171f80), C(b1bc23235935d897), + C(d57f63ea) + }, + { + C(44b3a1929232892), C(61dca0e914fc217), C(a607cc142096b964), C(f7dbc8433c89b274), C(2f5f70581c9b7d32), C(39bf5e5fec82dcca), C(8ade56388901a619), + C(f7dbc8433c89b274), C(2f5f70581c9b7d32), C(39bf5e5fec82dcca), C(8ade56388901a619), + C(c1c6a725caab3ea9), C(c1c7906c2f80b898), C(9c3871a04cc884e6), C(df01813cbbdf217f), + C(52ef73b3) + }, + { + C(4b603d7932a8de4f), C(fae64c464b8a8f45), C(8fafab75661d602a), C(8ffe870ef4adc087), C(65bea2be41f55b54), C(82f3503f636aef1), C(5f78a282378b6bb0), + C(8ffe870ef4adc087), C(65bea2be41f55b54), C(82f3503f636aef1), C(5f78a282378b6bb0), + C(7bf2422c0beceddb), C(9d238d4780114bd), C(7ad198311906597f), C(ec8f892c0422aca3), + C(3cb36c3) + }, + { + C(4ec0b54cf1566aff), C(30d2c7269b206bf4), C(77c22e82295e1061), C(3df9b04434771542), C(feddce785ccb661f), C(a644aff716928297), C(dd46aee73824b4ed), + C(3df9b04434771542), C(feddce785ccb661f), C(a644aff716928297), C(dd46aee73824b4ed), + C(bf8d71879da29b02), C(fc82dccbfc8022a0), C(31bfcd0d9f48d1d3), C(c64ee24d0e7b5f8b), + C(72c39bea) + }, + { + C(ed8b7a4b34954ff7), C(56432de31f4ee757), C(85bd3abaa572b155), C(7d2c38a926dc1b88), C(5245b9eb4cd6791d), C(fb53ab03b9ad0855), C(3664026c8fc669d7), + C(7d2c38a926dc1b88), C(5245b9eb4cd6791d), C(fb53ab03b9ad0855), C(3664026c8fc669d7), + C(45024d5080bc196), C(b236ebec2cc2740), C(27231ad0e3443be4), C(145780b63f809250), + C(a65aa25c) + }, + { + C(5d28b43694176c26), C(714cc8bc12d060ae), C(3437726273a83fe6), C(864b1b28ec16ea86), C(6a78a5a4039ec2b9), C(8e959533e35a766), C(347b7c22b75ae65f), + C(864b1b28ec16ea86), C(6a78a5a4039ec2b9), C(8e959533e35a766), C(347b7c22b75ae65f), + C(5005892bb61e647c), C(fe646519b4a1894d), C(cd801026f74a8a53), C(8713463e9a1ab9ce), + C(74740539) + }, + { + C(6a1ef3639e1d202e), C(919bc1bd145ad928), C(30f3f7e48c28a773), C(2e8c49d7c7aaa527), C(5e2328fc8701db7c), C(89ef1afca81f7de8), C(b1857db11985d296), + C(2e8c49d7c7aaa527), C(5e2328fc8701db7c), C(89ef1afca81f7de8), C(b1857db11985d296), + C(17763d695f616115), C(b8f7bf1fcdc8322c), C(cf0c61938ab07a27), C(1122d3e6edb4e866), + C(c3ae3c26) + }, + { + C(159f4d9e0307b111), C(3e17914a5675a0c), C(af849bd425047b51), C(3b69edadf357432b), C(3a2e311c121e6bf2), C(380fad1e288d57e5), C(bf7c7e8ef0e3b83a), + C(3b69edadf357432b), C(3a2e311c121e6bf2), C(380fad1e288d57e5), C(bf7c7e8ef0e3b83a), + C(92966d5f4356ae9b), C(2a03fc66c4d6c036), C(2516d8bddb0d5259), C(b3ffe9737ff5090), + C(f29db8a2) + }, + { + C(cc0a840725a7e25b), C(57c69454396e193a), C(976eaf7eee0b4540), C(cd7a46850b95e901), C(c57f7d060dda246f), C(6b9406ead64079bf), C(11b28e20a573b7bd), + C(cd7a46850b95e901), C(c57f7d060dda246f), C(6b9406ead64079bf), C(11b28e20a573b7bd), + C(2d6db356e9369ace), C(dc0afe10fba193), C(5cdb10885dbbfce), C(5c700e205782e35a), + C(1ef4cbf4) + }, + { + C(a2b27ee22f63c3f1), C(9ebde0ce1b3976b2), C(2fe6a92a257af308), C(8c1df927a930af59), C(a462f4423c9e384e), C(236542255b2ad8d9), C(595d201a2c19d5bc), + C(8c1df927a930af59), C(a462f4423c9e384e), C(236542255b2ad8d9), C(595d201a2c19d5bc), + C(22c87d4604a67f3), C(585a06eb4bc44c4f), C(b4175a7ac7eabcd8), C(a457d3eeba14ab8c), + C(a9be6c41) + }, + { + C(d8f2f234899bcab3), C(b10b037297c3a168), C(debea2c510ceda7f), C(9498fefb890287ce), C(ae68c2be5b1a69a6), C(6189dfba34ed656c), C(91658f95836e5206), + C(9498fefb890287ce), C(ae68c2be5b1a69a6), C(6189dfba34ed656c), C(91658f95836e5206), + C(c0bb4fff32aecd4d), C(94125f505a50eef9), C(6ac406e7cfbce5bb), C(344a4b1dcdb7f5d8), + C(fa31801) + }, + { + C(584f28543864844f), C(d7cee9fc2d46f20d), C(a38dca5657387205), C(7a0b6dbab9a14e69), C(c6d0a9d6b0e31ac4), C(a674d85812c7cf6), C(63538c0351049940), + C(7a0b6dbab9a14e69), C(c6d0a9d6b0e31ac4), C(a674d85812c7cf6), C(63538c0351049940), + C(9710e5f0bc93d1d), C(c2bea5bd7c54ddd4), C(48739af2bed0d32d), C(ba2c4e09e21fba85), + C(8331c5d8) + }, + { + C(a94be46dd9aa41af), C(a57e5b7723d3f9bd), C(34bf845a52fd2f), C(843b58463c8df0ae), C(74b258324e916045), C(bdd7353230eb2b38), C(fad31fced7abade5), + C(843b58463c8df0ae), C(74b258324e916045), C(bdd7353230eb2b38), C(fad31fced7abade5), + C(2436aeafb0046f85), C(65bc9af9e5e33161), C(92733b1b3ae90628), C(f48143eaf78a7a89), + C(e9876db8) + }, + { + C(9a87bea227491d20), C(a468657e2b9c43e7), C(af9ba60db8d89ef7), C(cc76f429ea7a12bb), C(5f30eaf2bb14870a), C(434e824cb3e0cd11), C(431a4d382e39d16e), + C(cc76f429ea7a12bb), C(5f30eaf2bb14870a), C(434e824cb3e0cd11), C(431a4d382e39d16e), + C(9e51f913c4773a8), C(32ab1925823d0add), C(99c61b54c1d8f69d), C(38cfb80f02b43b1f), + C(27b0604e) + }, + { + C(27688c24958d1a5c), C(e3b4a1c9429cf253), C(48a95811f70d64bc), C(328063229db22884), C(67e9c95f8ba96028), C(7c6bf01c60436075), C(fa55161e7d9030b2), + C(328063229db22884), C(67e9c95f8ba96028), C(7c6bf01c60436075), C(fa55161e7d9030b2), + C(dadbc2f0dab91681), C(da39d7a4934ca11), C(162e845d24c1b45c), C(eb5b9dcd8c6ed31b), + C(dcec07f2) + }, + { + C(5d1d37790a1873ad), C(ed9cd4bcc5fa1090), C(ce51cde05d8cd96a), C(f72c26e624407e66), C(a0eb541bdbc6d409), C(c3f40a2f40b3b213), C(6a784de68794492d), + C(f72c26e624407e66), C(a0eb541bdbc6d409), C(c3f40a2f40b3b213), C(6a784de68794492d), + C(10a38a23dbef7937), C(6a5560f853252278), C(c3387bbf3c7b82ba), C(fbee7c12eb072805), + C(cff0a82a) + }, + { + C(1f03fd18b711eea9), C(566d89b1946d381a), C(6e96e83fc92563ab), C(405f66cf8cae1a32), C(d7261740d8f18ce6), C(fea3af64a413d0b2), C(d64d1810e83520fe), + C(405f66cf8cae1a32), C(d7261740d8f18ce6), C(fea3af64a413d0b2), C(d64d1810e83520fe), + C(e1334a00a580c6e8), C(454049e1b52c15f), C(8895d823d9778247), C(efa7f2e88b826618), + C(fec83621) + }, + { + C(f0316f286cf527b6), C(f84c29538de1aa5a), C(7612ed3c923d4a71), C(d4eccebe9393ee8a), C(2eb7867c2318cc59), C(1ce621fd700fe396), C(686450d7a346878a), + C(d4eccebe9393ee8a), C(2eb7867c2318cc59), C(1ce621fd700fe396), C(686450d7a346878a), + C(75a5f37579f8b4cb), C(500cc16eb6541dc7), C(b7b02317b539d9a6), C(3519ddff5bc20a29), + C(743d8dc) + }, + { + C(297008bcb3e3401d), C(61a8e407f82b0c69), C(a4a35bff0524fa0e), C(7a61d8f552a53442), C(821d1d8d8cfacf35), C(7cc06361b86d0559), C(119b617a8c2be199), + C(7a61d8f552a53442), C(821d1d8d8cfacf35), C(7cc06361b86d0559), C(119b617a8c2be199), + C(2996487da6721759), C(61a901376070b91d), C(d88dee12ae9c9b3c), C(5665491be1fa53a7), + C(64d41d26) + }, + { + C(43c6252411ee3be), C(b4ca1b8077777168), C(2746dc3f7da1737f), C(2247a4b2058d1c50), C(1b3fa184b1d7bcc0), C(deb85613995c06ed), C(cbe1d957485a3ccd), + C(2247a4b2058d1c50), C(1b3fa184b1d7bcc0), C(deb85613995c06ed), C(cbe1d957485a3ccd), + C(dfe241f8f33c96b6), C(6597eb05019c2109), C(da344b2a63a219cf), C(79b8e3887612378a), + C(acd90c81) + }, + { + C(ce38a9a54fad6599), C(6d6f4a90b9e8755e), C(c3ecc79ff105de3f), C(e8b9ee96efa2d0e), C(90122905c4ab5358), C(84f80c832d71979c), C(229310f3ffbbf4c6), + C(e8b9ee96efa2d0e), C(90122905c4ab5358), C(84f80c832d71979c), C(229310f3ffbbf4c6), + C(cc9eb42100cd63a7), C(7a283f2f3da7b9f), C(359b061d314e7a72), C(d0d959720028862), + C(7c746a4b) + }, + { + C(270a9305fef70cf), C(600193999d884f3a), C(f4d49eae09ed8a1), C(2e091b85660f1298), C(bfe37fae1cdd64c9), C(8dddfbab930f6494), C(2ccf4b08f5d417a), + C(2e091b85660f1298), C(bfe37fae1cdd64c9), C(8dddfbab930f6494), C(2ccf4b08f5d417a), + C(365c2ee85582fe6), C(dee027bcd36db62a), C(b150994d3c7e5838), C(fdfd1a0e692e436d), + C(b1047e99) + }, + { + C(e71be7c28e84d119), C(eb6ace59932736e6), C(70c4397807ba12c5), C(7a9d77781ac53509), C(4489c3ccfda3b39c), C(fa722d4f243b4964), C(25f15800bffdd122), + C(7a9d77781ac53509), C(4489c3ccfda3b39c), C(fa722d4f243b4964), C(25f15800bffdd122), + C(ed85e4157fbd3297), C(aab1967227d59efd), C(2199631212eb3839), C(3e4c19359aae1cc2), + C(d1fd1068) + }, + { + C(b5b58c24b53aaa19), C(d2a6ab0773dd897f), C(ef762fe01ecb5b97), C(9deefbcfa4cab1f1), C(b58f5943cd2492ba), C(a96dcc4d1f4782a7), C(102b62a82309dde5), + C(9deefbcfa4cab1f1), C(b58f5943cd2492ba), C(a96dcc4d1f4782a7), C(102b62a82309dde5), + C(35fe52684763b338), C(afe2616651eaad1f), C(43e38715bdfa05e7), C(83c9ba83b5ec4a40), + C(56486077) + }, + { + C(44dd59bd301995cf), C(3ccabd76493ada1a), C(540db4c87d55ef23), C(cfc6d7adda35797), C(14c7d1f32332cf03), C(2d553ffbff3be99d), C(c91c4ee0cb563182), + C(cfc6d7adda35797), C(14c7d1f32332cf03), C(2d553ffbff3be99d), C(c91c4ee0cb563182), + C(9aa5e507f49136f0), C(760c5dd1a82c4888), C(beea7e974a1cfb5c), C(640b247774fe4bf7), + C(6069be80) + }, + { + C(b4d4789eb6f2630b), C(bf6973263ce8ef0e), C(d1c75c50844b9d3), C(bce905900c1ec6ea), C(c30f304f4045487d), C(a5c550166b3a142b), C(2f482b4e35327287), + C(bce905900c1ec6ea), C(c30f304f4045487d), C(a5c550166b3a142b), C(2f482b4e35327287), + C(15b21ddddf355438), C(496471fa3006bab), C(2a8fd458d06c1a32), C(db91e8ae812f0b8d), + C(2078359b) + }, + { + C(12807833c463737c), C(58e927ea3b3776b4), C(72dd20ef1c2f8ad0), C(910b610de7a967bf), C(801bc862120f6bf5), C(9653efeed5897681), C(f5367ff83e9ebbb3), + C(910b610de7a967bf), C(801bc862120f6bf5), C(9653efeed5897681), C(f5367ff83e9ebbb3), + C(cf56d489afd1b0bf), C(c7c793715cae3de8), C(631f91d64abae47c), C(5f1f42fb14a444a2), + C(9ea21004) + }, + { + C(e88419922b87176f), C(bcf32f41a7ddbf6f), C(d6ebefd8085c1a0f), C(d1d44fe99451ef72), C(ec951ba8e51e3545), C(c0ca86b360746e96), C(aa679cc066a8040b), + C(d1d44fe99451ef72), C(ec951ba8e51e3545), C(c0ca86b360746e96), C(aa679cc066a8040b), + C(51065861ece6ffc1), C(76777368a2997e11), C(87f278f46731100c), C(bbaa4140bdba4527), + C(9c9cfe88) + }, + { + C(105191e0ec8f7f60), C(5918dbfcca971e79), C(6b285c8a944767b9), C(d3e86ac4f5eccfa4), C(e5399df2b106ca1), C(814aadfacd217f1d), C(2754e3def1c405a9), + C(d3e86ac4f5eccfa4), C(e5399df2b106ca1), C(814aadfacd217f1d), C(2754e3def1c405a9), + C(99290323b9f06e74), C(a9782e043f271461), C(13c8b3b8c275a860), C(6038d620e581e9e7), + C(b70a6ddd) + }, + { + C(a5b88bf7399a9f07), C(fca3ddfd96461cc4), C(ebe738fdc0282fc6), C(69afbc800606d0fb), C(6104b97a9db12df7), C(fcc09198bb90bf9f), C(c5e077e41a65ba91), + C(69afbc800606d0fb), C(6104b97a9db12df7), C(fcc09198bb90bf9f), C(c5e077e41a65ba91), + C(db261835ee8aa08e), C(db0ee662e5796dc9), C(fc1880ecec499e5f), C(648866fbe1502034), + C(dea37298) + }, + { + C(d08c3f5747d84f50), C(4e708b27d1b6f8ac), C(70f70fd734888606), C(909ae019d761d019), C(368bf4aab1b86ef9), C(308bd616d5460239), C(4fd33269f76783ea), + C(909ae019d761d019), C(368bf4aab1b86ef9), C(308bd616d5460239), C(4fd33269f76783ea), + C(7d53b37c19713eab), C(6bba6eabda58a897), C(91abb50efc116047), C(4e902f347e0e0e35), + C(8f480819) + }, + { + C(2f72d12a40044b4b), C(889689352fec53de), C(f03e6ad87eb2f36), C(ef79f28d874b9e2d), C(b512089e8e63b76c), C(24dc06833bf193a9), C(3c23308ba8e99d7e), + C(ef79f28d874b9e2d), C(b512089e8e63b76c), C(24dc06833bf193a9), C(3c23308ba8e99d7e), + C(5ceff7b85cacefb7), C(ef390338898cd73), C(b12967d7d2254f54), C(de874cbd8aef7b75), + C(30b3b16) + }, + { + C(aa1f61fdc5c2e11e), C(c2c56cd11277ab27), C(a1e73069fdf1f94f), C(8184bab36bb79df0), C(c81929ce8655b940), C(301b11bf8a4d8ce8), C(73126fd45ab75de9), + C(8184bab36bb79df0), C(c81929ce8655b940), C(301b11bf8a4d8ce8), C(73126fd45ab75de9), + C(4bd6f76e4888229a), C(9aae355b54a756d5), C(ca3de9726f6e99d5), C(83f80cac5bc36852), + C(f31bc4e8) + }, + { + C(9489b36fe2246244), C(3355367033be74b8), C(5f57c2277cbce516), C(bc61414f9802ecaf), C(8edd1e7a50562924), C(48f4ab74a35e95f2), C(cc1afcfd99a180e7), + C(bc61414f9802ecaf), C(8edd1e7a50562924), C(48f4ab74a35e95f2), C(cc1afcfd99a180e7), + C(517dd5e3acf66110), C(7dd3ad9e8978b30d), C(1f6d5dfc70de812b), C(947daaba6441aaf3), + C(419f953b) + }, + { + C(358d7c0476a044cd), C(e0b7b47bcbd8854f), C(ffb42ec696705519), C(d45e44c263e95c38), C(df61db53923ae3b1), C(f2bc948cc4fc027c), C(8a8000c6066772a3), + C(d45e44c263e95c38), C(df61db53923ae3b1), C(f2bc948cc4fc027c), C(8a8000c6066772a3), + C(9fd93c942d31fa17), C(d7651ecebe09cbd3), C(68682cefb6a6f165), C(541eb99a2dcee40e), + C(20e9e76d) + }, + { + C(b0c48df14275265a), C(9da4448975905efa), C(d716618e414ceb6d), C(30e888af70df1e56), C(4bee54bd47274f69), C(178b4059e1a0afe5), C(6e2c96b7f58e5178), + C(30e888af70df1e56), C(4bee54bd47274f69), C(178b4059e1a0afe5), C(6e2c96b7f58e5178), + C(bb429d3b9275e9bc), C(c198013f09cafdc6), C(ec0a6ee4fb5de348), C(744e1e8ed2eb1eb0), + C(646f0ff8) + }, + { + C(daa70bb300956588), C(410ea6883a240c6d), C(f5c8239fb5673eb3), C(8b1d7bb4903c105f), C(cfb1c322b73891d4), C(5f3b792b22f07297), C(fd64061f8be86811), + C(8b1d7bb4903c105f), C(cfb1c322b73891d4), C(5f3b792b22f07297), C(fd64061f8be86811), + C(1d2db712921cfc2b), C(cd1b2b2f2cee18ae), C(6b6f8790dc7feb09), C(46c179efa3f0f518), + C(eeb7eca8) + }, + { + C(4ec97a20b6c4c7c2), C(5913b1cd454f29fd), C(a9629f9daf06d685), C(852c9499156a8f3), C(3a180a6abfb79016), C(9fc3c4764037c3c9), C(2890c42fc0d972cf), + C(852c9499156a8f3), C(3a180a6abfb79016), C(9fc3c4764037c3c9), C(2890c42fc0d972cf), + C(1f92231d4e537651), C(fab8bb07aa54b7b9), C(e05d2d771c485ed4), C(d50b34bf808ca731), + C(8112bb9) + }, + { + C(5c3323628435a2e8), C(1bea45ce9e72a6e3), C(904f0a7027ddb52e), C(939f31de14dcdc7b), C(a68fdf4379df068), C(f169e1f0b835279d), C(7498e432f9619b27), + C(939f31de14dcdc7b), C(a68fdf4379df068), C(f169e1f0b835279d), C(7498e432f9619b27), + C(1aa2a1f11088e785), C(d6ad72f45729de78), C(9a63814157c80267), C(55538e35c648e435), + C(85a6d477) + }, + { + C(c1ef26bea260abdb), C(6ee423f2137f9280), C(df2118b946ed0b43), C(11b87fb1b900cc39), C(e33e59b90dd815b1), C(aa6cb5c4bafae741), C(739699951ca8c713), + C(11b87fb1b900cc39), C(e33e59b90dd815b1), C(aa6cb5c4bafae741), C(739699951ca8c713), + C(2b4389a967310077), C(1d5382568a31c2c9), C(55d1e787fbe68991), C(277c254bc31301e7), + C(56f76c84) + }, + { + C(6be7381b115d653a), C(ed046190758ea511), C(de6a45ffc3ed1159), C(a64760e4041447d0), C(e3eac49f3e0c5109), C(dd86c4d4cb6258e2), C(efa9857afd046c7f), + C(a64760e4041447d0), C(e3eac49f3e0c5109), C(dd86c4d4cb6258e2), C(efa9857afd046c7f), + C(fab793dae8246f16), C(c9e3b121b31d094c), C(a2a0f55858465226), C(dba6f0ff39436344), + C(9af45d55) + }, + { + C(ae3eece1711b2105), C(14fd3f4027f81a4a), C(abb7e45177d151db), C(501f3e9b18861e44), C(465201170074e7d8), C(96d5c91970f2cb12), C(40fd28c43506c95d), + C(501f3e9b18861e44), C(465201170074e7d8), C(96d5c91970f2cb12), C(40fd28c43506c95d), + C(e86c4b07802aaff3), C(f317d14112372a70), C(641b13e587711650), C(4915421ab1090eaa), + C(d1c33760) + }, + { + C(376c28588b8fb389), C(6b045e84d8491ed2), C(4e857effb7d4e7dc), C(154dd79fd2f984b4), C(f11171775622c1c3), C(1fbe30982e78e6f0), C(a460a15dcf327e44), + C(154dd79fd2f984b4), C(f11171775622c1c3), C(1fbe30982e78e6f0), C(a460a15dcf327e44), + C(f359e0900cc3d582), C(7e11070447976d00), C(324e6daf276ea4b5), C(7aa6e2df0cc94fa2), + C(c56bbf69) + }, + { + C(58d943503bb6748f), C(419c6c8e88ac70f6), C(586760cbf3d3d368), C(b7e164979d5ccfc1), C(12cb4230d26bf286), C(f1bf910d44bd84cb), C(b32c24c6a40272), + C(b7e164979d5ccfc1), C(12cb4230d26bf286), C(f1bf910d44bd84cb), C(b32c24c6a40272), + C(11ed12e34c48c039), C(b0c2538e51d0a6ac), C(4269bb773e1d553a), C(e35a9dbabd34867), + C(abecfb9b) + }, + { + C(dfff5989f5cfd9a1), C(bcee2e7ea3a96f83), C(681c7874adb29017), C(3ff6c8ac7c36b63a), C(48bc8831d849e326), C(30b078e76b0214e2), C(42954e6ad721b920), + C(3ff6c8ac7c36b63a), C(48bc8831d849e326), C(30b078e76b0214e2), C(42954e6ad721b920), + C(f9aeb33d164b4472), C(7b353b110831dbdc), C(16f64c82f44ae17b), C(b71244cc164b3b2b), + C(8de13255) + }, + { + C(7fb19eb1a496e8f5), C(d49e5dfdb5c0833f), C(c0d5d7b2f7c48dc7), C(1a57313a32f22dde), C(30af46e49850bf8b), C(aa0fe8d12f808f83), C(443e31d70873bb6b), + C(1a57313a32f22dde), C(30af46e49850bf8b), C(aa0fe8d12f808f83), C(443e31d70873bb6b), + C(bbeb67c49c9fdc13), C(18f1e2a88f59f9d5), C(fb1b05038e5def11), C(d0450b5ce4c39c52), + C(a98ee299) + }, + { + C(5dba5b0dadccdbaa), C(4ba8da8ded87fcdc), C(f693fdd25badf2f0), C(e9029e6364286587), C(ae69f49ecb46726c), C(18e002679217c405), C(bd6d66e85332ae9f), + C(e9029e6364286587), C(ae69f49ecb46726c), C(18e002679217c405), C(bd6d66e85332ae9f), + C(6bf330b1c353dd2a), C(74e9f2e71e3a4152), C(3f85560b50f6c413), C(d33a52a47eaed2b4), + C(3015f556) + }, + { + C(688bef4b135a6829), C(8d31d82abcd54e8e), C(f95f8a30d55036d7), C(3d8c90e27aa2e147), C(2ec937ce0aa236b4), C(89b563996d3a0b78), C(39b02413b23c3f08), + C(3d8c90e27aa2e147), C(2ec937ce0aa236b4), C(89b563996d3a0b78), C(39b02413b23c3f08), + C(8d475a2e64faf2d2), C(48567f7dca46ecaf), C(254cda08d5f87a6d), C(ec6ae9f729c47039), + C(5a430e29) + }, + { + C(d8323be05433a412), C(8d48fa2b2b76141d), C(3d346f23978336a5), C(4d50c7537562033f), C(57dc7625b61dfe89), C(9723a9f4c08ad93a), C(5309596f48ab456b), + C(4d50c7537562033f), C(57dc7625b61dfe89), C(9723a9f4c08ad93a), C(5309596f48ab456b), + C(7e453088019d220f), C(8776067ba6ab9714), C(67e1d06bd195de39), C(74a1a32f8994b918), + C(2797add0) + }, + { + C(3b5404278a55a7fc), C(23ca0b327c2d0a81), C(a6d65329571c892c), C(45504801e0e6066b), C(86e6c6d6152a3d04), C(4f3db1c53eca2952), C(d24d69b3e9ef10f3), + C(45504801e0e6066b), C(86e6c6d6152a3d04), C(4f3db1c53eca2952), C(d24d69b3e9ef10f3), + C(93a0de2219e66a70), C(8932c7115ccb1f8a), C(5ef503fdf2841a8c), C(38064dd9efa80a41), + C(27d55016) + }, + { + C(2a96a3f96c5e9bbc), C(8caf8566e212dda8), C(904de559ca16e45e), C(f13bc2d9c2fe222e), C(be4ccec9a6cdccfd), C(37b2cbdd973a3ac9), C(7b3223cd9c9497be), + C(f13bc2d9c2fe222e), C(be4ccec9a6cdccfd), C(37b2cbdd973a3ac9), C(7b3223cd9c9497be), + C(d5904440f376f889), C(62b13187699c473c), C(4751b89251f26726), C(9500d84fa3a61ba8), + C(84945a82) + }, + { + C(22bebfdcc26d18ff), C(4b4d8dcb10807ba1), C(40265eee30c6b896), C(3752b423073b119a), C(377dc5eb7c662bdb), C(2b9f07f93a6c25b9), C(96f24ede2bdc0718), + C(3752b423073b119a), C(377dc5eb7c662bdb), C(2b9f07f93a6c25b9), C(96f24ede2bdc0718), + C(f7699b12c31417bd), C(17b366f401c58b2), C(bf60188d5f437b37), C(484436e56df17f04), + C(3ef7e224) + }, + { + C(627a2249ec6bbcc2), C(c0578b462a46735a), C(4974b8ee1c2d4f1f), C(ebdbb918eb6d837f), C(8fb5f218dd84147c), C(c77dd1f881df2c54), C(62eac298ec226dc3), + C(ebdbb918eb6d837f), C(8fb5f218dd84147c), C(c77dd1f881df2c54), C(62eac298ec226dc3), + C(43eded83c4b60bd0), C(9a0a403b5487503b), C(25f305d9147f0bda), C(3ad417f511bc1e64), + C(35ed8dc8) + }, + { + C(3abaf1667ba2f3e0), C(ee78476b5eeadc1), C(7e56ac0a6ca4f3f4), C(f1b9b413df9d79ed), C(a7621b6fd02db503), C(d92f7ba9928a4ffe), C(53f56babdcae96a6), + C(f1b9b413df9d79ed), C(a7621b6fd02db503), C(d92f7ba9928a4ffe), C(53f56babdcae96a6), + C(5302b89fc48713ab), C(d03e3b04dbe7a2f2), C(fa74ef8af6d376a7), C(103c8cdea1050ef2), + C(6a75e43d) + }, + { + C(3931ac68c5f1b2c9), C(efe3892363ab0fb0), C(40b707268337cd36), C(a53a6b64b1ac85c9), C(d50e7f86ee1b832b), C(7bab08fdd26ba0a4), C(7587743c18fe2475), + C(a53a6b64b1ac85c9), C(d50e7f86ee1b832b), C(7bab08fdd26ba0a4), C(7587743c18fe2475), + C(e3b5d5d490cf5761), C(dfc053f7d065edd5), C(42ffd8d5fb70129f), C(599ca38677cccdc3), + C(235d9805) + }, + { + C(b98fb0606f416754), C(46a6e5547ba99c1e), C(c909d82112a8ed2), C(dbfaae9642b3205a), C(f676a1339402bcb9), C(f4f12a5b1ac11f29), C(7db8bad81249dee4), + C(dbfaae9642b3205a), C(f676a1339402bcb9), C(f4f12a5b1ac11f29), C(7db8bad81249dee4), + C(b26e46f2da95922e), C(2aaedd5e12e3c611), C(a0e2d9082966074), C(c64da8a167add63d), + C(f7d69572) + }, + { + C(7f7729a33e58fcc4), C(2e4bc1e7a023ead4), C(e707008ea7ca6222), C(47418a71800334a0), C(d10395d8fc64d8a4), C(8257a30062cb66f), C(6786f9b2dc1ff18a), + C(47418a71800334a0), C(d10395d8fc64d8a4), C(8257a30062cb66f), C(6786f9b2dc1ff18a), + C(5633f437bb2f180f), C(e5a3a405737d22d6), C(ca0ff1ef6f7f0b74), C(d0ae600684b16df8), + C(bacd0199) + }, + { + C(42a0aa9ce82848b3), C(57232730e6bee175), C(f89bb3f370782031), C(caa33cf9b4f6619c), C(b2c8648ad49c209f), C(9e89ece0712db1c0), C(101d8274a711a54b), + C(caa33cf9b4f6619c), C(b2c8648ad49c209f), C(9e89ece0712db1c0), C(101d8274a711a54b), + C(538e79f1e70135cd), C(e1f5a76f983c844e), C(653c082fd66088fc), C(1b9c9b464b654958), + C(e428f50e) + }, + { + C(6b2c6d38408a4889), C(de3ef6f68fb25885), C(20754f456c203361), C(941f5023c0c943f9), C(dfdeb9564fd66f24), C(2140cec706b9d406), C(7b22429b131e9c72), + C(941f5023c0c943f9), C(dfdeb9564fd66f24), C(2140cec706b9d406), C(7b22429b131e9c72), + C(94215c22eb940f45), C(d28b9ed474f7249a), C(6f25e88f2fbf9f56), C(b6718f9e605b38ac), + C(81eaaad3) + }, + { + C(930380a3741e862a), C(348d28638dc71658), C(89dedcfd1654ea0d), C(7e7f61684080106), C(837ace9794582976), C(5ac8ca76a357eb1b), C(32b58308625661fb), + C(7e7f61684080106), C(837ace9794582976), C(5ac8ca76a357eb1b), C(32b58308625661fb), + C(c09705c4572025d9), C(f9187f6af0291303), C(1c0edd8ee4b02538), C(e6cb105daa0578a), + C(addbd3e3) + }, + { + C(94808b5d2aa25f9a), C(cec72968128195e0), C(d9f4da2bdc1e130f), C(272d8dd74f3006cc), C(ec6c2ad1ec03f554), C(4ad276b249a5d5dd), C(549a22a17c0cde12), + C(272d8dd74f3006cc), C(ec6c2ad1ec03f554), C(4ad276b249a5d5dd), C(549a22a17c0cde12), + C(602119cb824d7cde), C(f4d3cef240ef35fa), C(e889895e01911bc7), C(785a7e5ac20e852b), + C(e66dbca0) + }, + { + C(b31abb08ae6e3d38), C(9eb9a95cbd9e8223), C(8019e79b7ee94ea9), C(7b2271a7a3248e22), C(3b4f700e5a0ba523), C(8ebc520c227206fe), C(da3f861490f5d291), + C(7b2271a7a3248e22), C(3b4f700e5a0ba523), C(8ebc520c227206fe), C(da3f861490f5d291), + C(d08a689f9f3aa60e), C(547c1b97a068661f), C(4b15a67fa29172f0), C(eaf40c085191d80f), + C(afe11fd5) + }, + { + C(dccb5534a893ea1a), C(ce71c398708c6131), C(fe2396315457c164), C(3f1229f4d0fd96fb), C(33130aa5fa9d43f2), C(e42693d5b34e63ab), C(2f4ef2be67f62104), + C(3f1229f4d0fd96fb), C(33130aa5fa9d43f2), C(e42693d5b34e63ab), C(2f4ef2be67f62104), + C(372e5153516e37b9), C(af9ec142ab12cc86), C(777920c09345e359), C(e7c4a383bef8adc6), + C(a71a406f) + }, + { + C(6369163565814de6), C(8feb86fb38d08c2f), C(4976933485cc9a20), C(7d3e82d5ba29a90d), C(d5983cc93a9d126a), C(37e9dfd950e7b692), C(80673be6a7888b87), + C(7d3e82d5ba29a90d), C(d5983cc93a9d126a), C(37e9dfd950e7b692), C(80673be6a7888b87), + C(57f732dc600808bc), C(59477199802cc78b), C(f824810eb8f2c2de), C(c4a3437f05b3b61c), + C(9d90eaf5) + }, + { + C(edee4ff253d9f9b3), C(96ef76fb279ef0ad), C(a4d204d179db2460), C(1f3dcdfa513512d6), C(4dc7ec07283117e4), C(4438bae88ae28bf9), C(aa7eae72c9244a0d), + C(1f3dcdfa513512d6), C(4dc7ec07283117e4), C(4438bae88ae28bf9), C(aa7eae72c9244a0d), + C(b9aedc8d3ecc72df), C(b75a8eb090a77d62), C(6b15677f9cd91507), C(51d8282cb3a9ddbf), + C(6665db10) + }, + { + C(941993df6e633214), C(929bc1beca5b72c6), C(141fc52b8d55572d), C(b3b782ad308f21ed), C(4f2676485041dee0), C(bfe279aed5cb4bc8), C(2a62508a467a22ff), + C(b3b782ad308f21ed), C(4f2676485041dee0), C(bfe279aed5cb4bc8), C(2a62508a467a22ff), + C(e74d29eab742385d), C(56b05cd90ecfc293), C(c603728ea73f8844), C(8638fcd21bc692c4), + C(9c977cbf) + }, + { + C(859838293f64cd4c), C(484403b39d44ad79), C(bf674e64d64b9339), C(44d68afda9568f08), C(478568ed51ca1d65), C(679c204ad3d9e766), C(b28e788878488dc1), + C(44d68afda9568f08), C(478568ed51ca1d65), C(679c204ad3d9e766), C(b28e788878488dc1), + C(d001a84d3a84fae6), C(d376958fe4cb913e), C(17435277e36c86f0), C(23657b263c347aa6), + C(ee83ddd4) + }, + { + C(c19b5648e0d9f555), C(328e47b2b7562993), C(e756b92ba4bd6a51), C(c3314e362764ddb8), C(6481c084ee9ec6b5), C(ede23fb9a251771), C(bd617f2643324590), + C(c3314e362764ddb8), C(6481c084ee9ec6b5), C(ede23fb9a251771), C(bd617f2643324590), + C(d2d30c9b95e030f5), C(8a517312ffc5795e), C(8b1f325033bd535e), C(3ee6e867e03f2892), + C(26519cc) + }, + { + C(f963b63b9006c248), C(9e9bf727ffaa00bc), C(c73bacc75b917e3a), C(2c6aa706129cc54c), C(17a706f59a49f086), C(c7c1eec455217145), C(6adfdc6e07602d42), + C(2c6aa706129cc54c), C(17a706f59a49f086), C(c7c1eec455217145), C(6adfdc6e07602d42), + C(fb75fca30d848dd2), C(5228c9ed14653ed4), C(953958910153b1a2), C(a430103a24f42a5d), + C(a485a53f) + }, + { + C(6a8aa0852a8c1f3b), C(c8f1e5e206a21016), C(2aa554aed1ebb524), C(fc3e3c322cd5d89b), C(b7e3911dc2bd4ebb), C(fcd6da5e5fae833a), C(51ed3c41f87f9118), + C(fc3e3c322cd5d89b), C(b7e3911dc2bd4ebb), C(fcd6da5e5fae833a), C(51ed3c41f87f9118), + C(f31750cbc19c420a), C(186dab1abada1d86), C(ca7f88cb894b3cd7), C(2859eeb1c373790c), + C(f62bc412) + }, + { + C(740428b4d45e5fb8), C(4c95a4ce922cb0a5), C(e99c3ba78feae796), C(914f1ea2fdcebf5c), C(9566453c07cd0601), C(9841bf66d0462cd), C(79140c1c18536aeb), + C(914f1ea2fdcebf5c), C(9566453c07cd0601), C(9841bf66d0462cd), C(79140c1c18536aeb), + C(a963b930b05820c2), C(6a7d9fa0c8c45153), C(64214c40d07cf39b), C(7057daf1d806c014), + C(8975a436) + }, + { + C(658b883b3a872b86), C(2f0e303f0f64827a), C(975337e23dc45e1), C(99468a917986162b), C(7b31434aac6e0af0), C(f6915c1562c7d82f), C(e4071d82a6dd71db), + C(99468a917986162b), C(7b31434aac6e0af0), C(f6915c1562c7d82f), C(e4071d82a6dd71db), + C(5f5331f077b5d996), C(7b314ba21b747a4f), C(5a73cb9521da17f5), C(12ed435fae286d86), + C(94ff7f41) + }, + { + C(6df0a977da5d27d4), C(891dd0e7cb19508), C(fd65434a0b71e680), C(8799e4740e573c50), C(9e739b52d0f341e8), C(cdfd34ba7d7b03eb), C(5061812ce6c88499), + C(8799e4740e573c50), C(9e739b52d0f341e8), C(cdfd34ba7d7b03eb), C(5061812ce6c88499), + C(612b8d8f2411dc5c), C(878bd883d29c7787), C(47a846727182bb), C(ec4949508c8b3b9a), + C(760aa031) + }, + { + C(a900275464ae07ef), C(11f2cfda34beb4a3), C(9abf91e5a1c38e4), C(8063d80ab26f3d6d), C(4177b4b9b4f0393f), C(6de42ba8672b9640), C(d0bccdb72c51c18), + C(8063d80ab26f3d6d), C(4177b4b9b4f0393f), C(6de42ba8672b9640), C(d0bccdb72c51c18), + C(af3f611b7f22cf12), C(3863c41492645755), C(928c7a616a8f14f9), C(a82c78eb2eadc58b), + C(3bda76df) + }, + { + C(810bc8aa0c40bcb0), C(448a019568d01441), C(f60ec52f60d3aeae), C(52c44837aa6dfc77), C(15d8d8fccdd6dc5b), C(345b793ccfa93055), C(932160fe802ca975), + C(52c44837aa6dfc77), C(15d8d8fccdd6dc5b), C(345b793ccfa93055), C(932160fe802ca975), + C(a624b0dd93fc18cd), C(d955b254c2037f1e), C(e540533d370a664c), C(2ba4ec12514e9d7), + C(498e2e65) + }, + { + C(22036327deb59ed7), C(adc05ceb97026a02), C(48bff0654262672b), C(c791b313aba3f258), C(443c7757a4727bee), C(e30e4b2372171bdf), C(f3db986c4156f3cb), + C(c791b313aba3f258), C(443c7757a4727bee), C(e30e4b2372171bdf), C(f3db986c4156f3cb), + C(a939aefab97c6e15), C(dbeb8acf1d5b0e6c), C(1e0eab667a795bba), C(80dd539902df4d50), + C(d38deb48) + }, + { + C(7d14dfa9772b00c8), C(595735efc7eeaed7), C(29872854f94c3507), C(bc241579d8348401), C(16dc832804d728f0), C(e9cc71ae64e3f09e), C(bef634bc978bac31), + C(bc241579d8348401), C(16dc832804d728f0), C(e9cc71ae64e3f09e), C(bef634bc978bac31), + C(7f64b1fa2a9129e), C(71d831bd530ac7f3), C(c7ad0a8a6d5be6f1), C(82a7d3a815c7aaab), + C(82b3fb6b) + }, + { + C(2d777cddb912675d), C(278d7b10722a13f9), C(f5c02bfb7cc078af), C(4283001239888836), C(f44ca39a6f79db89), C(ed186122d71bcc9f), C(8620017ab5f3ba3b), + C(4283001239888836), C(f44ca39a6f79db89), C(ed186122d71bcc9f), C(8620017ab5f3ba3b), + C(e787472187f176c), C(267e64c4728cf181), C(f1ba4b3007c15e30), C(8e3a75d5b02ecfc0), + C(e500e25f) + }, + { + C(f2ec98824e8aa613), C(5eb7e3fb53fe3bed), C(12c22860466e1dd4), C(374dd4288e0b72e5), C(ff8916db706c0df4), C(cb1a9e85de5e4b8d), C(d4d12afb67a27659), + C(374dd4288e0b72e5), C(ff8916db706c0df4), C(cb1a9e85de5e4b8d), C(d4d12afb67a27659), + C(feb69095d1ba175a), C(e2003aab23a47fad), C(8163a3ecab894b49), C(46d356674ce041f6), + C(bd2bb07c) + }, + { + C(5e763988e21f487f), C(24189de8065d8dc5), C(d1519d2403b62aa0), C(9136456740119815), C(4d8ff7733b27eb83), C(ea3040bc0c717ef8), C(7617ab400dfadbc), + C(9136456740119815), C(4d8ff7733b27eb83), C(ea3040bc0c717ef8), C(7617ab400dfadbc), + C(fb336770c10b17a1), C(6123b68b5b31f151), C(1e147d5f295eccf2), C(9ecbb1333556f977), + C(3a2b431d) + }, + { + C(48949dc327bb96ad), C(e1fd21636c5c50b4), C(3f6eb7f13a8712b4), C(14cf7f02dab0eee8), C(6d01750605e89445), C(4f1cf4006e613b78), C(57c40c4db32bec3b), + C(14cf7f02dab0eee8), C(6d01750605e89445), C(4f1cf4006e613b78), C(57c40c4db32bec3b), + C(1fde5a347f4a326e), C(cb5a54308adb0e3f), C(14994b2ba447a23c), C(7067d0abb4257b68), + C(7322a83d) + }, + { + C(b7c4209fb24a85c5), C(b35feb319c79ce10), C(f0d3de191833b922), C(570d62758ddf6397), C(5e0204fb68a7b800), C(4383a9236f8b5a2b), C(7bc1a64641d803a4), + C(570d62758ddf6397), C(5e0204fb68a7b800), C(4383a9236f8b5a2b), C(7bc1a64641d803a4), + C(5434d61285099f7a), C(d49449aacdd5dd67), C(97855ba0e9a7d75d), C(da67328062f3a62f), + C(a645ca1c) + }, + { + C(9c9e5be0943d4b05), C(b73dc69e45201cbb), C(aab17180bfe5083d), C(c738a77a9a55f0e2), C(705221addedd81df), C(fd9bd8d397abcfa3), C(8ccf0004aa86b795), + C(c738a77a9a55f0e2), C(705221addedd81df), C(fd9bd8d397abcfa3), C(8ccf0004aa86b795), + C(2bb5db2280068206), C(8c22d29f307a01d), C(274a22de02f473c8), C(b8791870f4268182), + C(8909a45a) + }, + { + C(3898bca4dfd6638d), C(f911ff35efef0167), C(24bdf69e5091fc88), C(9b82567ab6560796), C(891b69462b41c224), C(8eccc7e4f3af3b51), C(381e54c3c8f1c7d0), + C(9b82567ab6560796), C(891b69462b41c224), C(8eccc7e4f3af3b51), C(381e54c3c8f1c7d0), + C(c80fbc489a558a55), C(1ba88e062a663af7), C(af7b1ef1c0116303), C(bd20e1a5a6b1a0cd), + C(bd30074c) + }, + { + C(5b5d2557400e68e7), C(98d610033574cee), C(dfd08772ce385deb), C(3c13e894365dc6c2), C(26fc7bbcda3f0ef), C(dbb71106cdbfea36), C(785239a742c6d26d), + C(3c13e894365dc6c2), C(26fc7bbcda3f0ef), C(dbb71106cdbfea36), C(785239a742c6d26d), + C(f810c415ae05b2f4), C(bb9b9e7398526088), C(70128f1bf830a32b), C(bcc73f82b6410899), + C(c17cf001) + }, + { + C(a927ed8b2bf09bb6), C(606e52f10ae94eca), C(71c2203feb35a9ee), C(6e65ec14a8fb565), C(34bff6f2ee5a7f79), C(2e329a5be2c011b), C(73161c93331b14f9), + C(6e65ec14a8fb565), C(34bff6f2ee5a7f79), C(2e329a5be2c011b), C(73161c93331b14f9), + C(15d13f2408aecf88), C(9f5b61b8a4b55b31), C(8fe25a43b296dba6), C(bdad03b7300f284e), + C(26ffd25a) + }, + { + C(8d25746414aedf28), C(34b1629d28b33d3a), C(4d5394aea5f82d7b), C(379f76458a3c8957), C(79dd080f9843af77), C(c46f0a7847f60c1d), C(af1579c5797703cc), + C(379f76458a3c8957), C(79dd080f9843af77), C(c46f0a7847f60c1d), C(af1579c5797703cc), + C(8b7d31f338755c14), C(2eff97679512aaa8), C(df07d68e075179ed), C(c8fa6c7a729e7f1f), + C(f1d8ce3c) + }, + { + C(b5bbdb73458712f2), C(1ff887b3c2a35137), C(7f7231f702d0ace9), C(1e6f0910c3d25bd8), C(ad9e250862102467), C(1c842a07abab30cd), C(cd8124176bac01ac), + C(1e6f0910c3d25bd8), C(ad9e250862102467), C(1c842a07abab30cd), C(cd8124176bac01ac), + C(ea6ebe7a79b67edc), C(73f598ac9db26713), C(4f4e72d7460b8fc), C(365dc4b9fdf13f21), + C(3ee8fb17) + }, + { + C(3d32a26e3ab9d254), C(fc4070574dc30d3a), C(f02629579c2b27c9), C(b1cf09b0184a4834), C(5c03db48eb6cc159), C(f18c7fcf34d1df47), C(dfb043419ecf1fa9), + C(b1cf09b0184a4834), C(5c03db48eb6cc159), C(f18c7fcf34d1df47), C(dfb043419ecf1fa9), + C(dcd78d13f9ca658f), C(4355d408ffe8e49f), C(81eefee908b593b4), C(590c213c20e981a3), + C(a77acc2a) + }, + { + C(9371d3c35fa5e9a5), C(42967cf4d01f30), C(652d1eeae704145c), C(ceaf1a0d15234f15), C(1450a54e45ba9b9), C(65e9c1fd885aa932), C(354d4bc034ba8cbe), + C(ceaf1a0d15234f15), C(1450a54e45ba9b9), C(65e9c1fd885aa932), C(354d4bc034ba8cbe), + C(8fd4ff484c08fb4b), C(bf46749866f69ba0), C(cf1c21ede82c9477), C(4217548c43da109), + C(f4556dee) + }, + { + C(cbaa3cb8f64f54e0), C(76c3b48ee5c08417), C(9f7d24e87e61ce9), C(85b8e53f22e19507), C(bb57137739ca486b), C(c77f131cca38f761), C(c56ac3cf275be121), + C(85b8e53f22e19507), C(bb57137739ca486b), C(c77f131cca38f761), C(c56ac3cf275be121), + C(9ec1a6c9109d2685), C(3dad0922e76afdb0), C(fd58cbf952958103), C(7b04c908e78639a1), + C(de287a64) + }, + { + C(b2e23e8116c2ba9f), C(7e4d9c0060101151), C(3310da5e5028f367), C(adc52dddb76f6e5e), C(4aad4e925a962b68), C(204b79b7f7168e64), C(df29ed6671c36952), + C(adc52dddb76f6e5e), C(4aad4e925a962b68), C(204b79b7f7168e64), C(df29ed6671c36952), + C(e02927cac396d210), C(5d500e71742b638a), C(5c9998af7f27b124), C(3fba9a2573dc2f7), + C(878e55b9) + }, + { + C(8aa77f52d7868eb9), C(4d55bd587584e6e2), C(d2db37041f495f5), C(ce030d15b5fe2f4), C(86b4a7a0780c2431), C(ee070a9ae5b51db7), C(edc293d9595be5d8), + C(ce030d15b5fe2f4), C(86b4a7a0780c2431), C(ee070a9ae5b51db7), C(edc293d9595be5d8), + C(3dfc5ec108260a2b), C(8afe28c7123bf4e2), C(da82ef38023a7a5f), C(3e1f77b0174b77c3), + C(7648486) + }, + { + C(858fea922c7fe0c3), C(cfe8326bf733bc6f), C(4e5e2018cf8f7dfc), C(64fd1bc011e5bab7), C(5c9e858728015568), C(97ac42c2b00b29b1), C(7f89caf08c109aee), + C(64fd1bc011e5bab7), C(5c9e858728015568), C(97ac42c2b00b29b1), C(7f89caf08c109aee), + C(9a8af34fd0e9dacf), C(bbc54161aa1507e0), C(7cda723ccbbfe5ee), C(2c289d839fb93f58), + C(57ac0fb1) + }, + { + C(46ef25fdec8392b1), C(e48d7b6d42a5cd35), C(56a6fe1c175299ca), C(fdfa836b41dcef62), C(2f8db8030e847e1b), C(5ba0a49ac4f9b0f8), C(dae897ed3e3fce44), + C(fdfa836b41dcef62), C(2f8db8030e847e1b), C(5ba0a49ac4f9b0f8), C(dae897ed3e3fce44), + C(9c432e31aef626e7), C(9a36e1c6cd6e3dd), C(5095a167c34d19d), C(a70005cfa6babbea), + C(d01967ca) + }, + { + C(8d078f726b2df464), C(b50ee71cdcabb299), C(f4af300106f9c7ba), C(7d222caae025158a), C(cc028d5fd40241b9), C(dd42515b639e6f97), C(e08e86531a58f87f), + C(7d222caae025158a), C(cc028d5fd40241b9), C(dd42515b639e6f97), C(e08e86531a58f87f), + C(d93612c835b37d7b), C(91dd61729b2fa7f4), C(ba765a1bdda09db7), C(55258b451b2b1297), + C(96ecdf74) + }, + { + C(35ea86e6960ca950), C(34fe1fe234fc5c76), C(a00207a3dc2a72b7), C(80395e48739e1a67), C(74a67d8f7f43c3d7), C(dd2bdd1d62246c6e), C(a1f44298ba80acf6), + C(80395e48739e1a67), C(74a67d8f7f43c3d7), C(dd2bdd1d62246c6e), C(a1f44298ba80acf6), + C(ad86d86c187bf38), C(26feea1f2eee240d), C(ed7f1fd066b23897), C(a768cf1e0fbb502), + C(779f5506) + }, + { + C(8aee9edbc15dd011), C(51f5839dc8462695), C(b2213e17c37dca2d), C(133b299a939745c5), C(796e2aac053f52b3), C(e8d9fe1521a4a222), C(819a8863e5d1c290), + C(133b299a939745c5), C(796e2aac053f52b3), C(e8d9fe1521a4a222), C(819a8863e5d1c290), + C(c0737f0fe34d36ad), C(e6d6d4a267a5cc31), C(98300a7911674c23), C(bef189661c257098), + C(3c94c2de) + }, + { + C(c3e142ba98432dda), C(911d060cab126188), C(b753fbfa8365b844), C(fd1a9ba5e71b08a2), C(7ac0dc2ed7778533), C(b543161ff177188a), C(492fc08a6186f3f4), + C(fd1a9ba5e71b08a2), C(7ac0dc2ed7778533), C(b543161ff177188a), C(492fc08a6186f3f4), + C(fc4745f516afd3b6), C(88c30370a53080e), C(65a1bb34abc465e2), C(abbd14662911c8b3), + C(39f98faf) + }, + { + C(123ba6b99c8cd8db), C(448e582672ee07c4), C(cebe379292db9e65), C(938f5bbab544d3d6), C(d2a95f9f2d376d73), C(68b2f16149e81aa3), C(ad7e32f82d86c79d), + C(938f5bbab544d3d6), C(d2a95f9f2d376d73), C(68b2f16149e81aa3), C(ad7e32f82d86c79d), + C(4574015ae8626ce2), C(455aa6137386a582), C(658ad2542e8ec20), C(e31d7be2ca35d00), + C(7af31199) + }, + { + C(ba87acef79d14f53), C(b3e0fcae63a11558), C(d5ac313a593a9f45), C(eea5f5a9f74af591), C(578710bcc36fbea2), C(7a8393432188931d), C(705cfc5ec7cc172), + C(eea5f5a9f74af591), C(578710bcc36fbea2), C(7a8393432188931d), C(705cfc5ec7cc172), + C(da85ebe5fc427976), C(bfa5c7a454df54c8), C(4632b72a81bf66d2), C(5dd72877db539ee2), + C(e341a9d6) + }, + { + C(bcd3957d5717dc3), C(2da746741b03a007), C(873816f4b1ece472), C(2b826f1a2c08c289), C(da50f56863b55e74), C(b18712f6b3eed83b), C(bdc7cc05ab4c685f), + C(2b826f1a2c08c289), C(da50f56863b55e74), C(b18712f6b3eed83b), C(bdc7cc05ab4c685f), + C(9e45fb833d1b0af), C(d7213081db29d82e), C(d2a6b6c6a09ed55e), C(98a7686cba323ca9), + C(ca24aeeb) + }, + { + C(61442ff55609168e), C(6447c5fc76e8c9cf), C(6a846de83ae15728), C(effc2663cffc777f), C(93214f8f463afbed), C(a156ef06066f4e4e), C(a407b6ed8769d51e), + C(effc2663cffc777f), C(93214f8f463afbed), C(a156ef06066f4e4e), C(a407b6ed8769d51e), + C(bb2f9ed29745c02a), C(981eecd435b36ad9), C(461a5a05fb9cdff4), C(bd6cb2a87b9f910c), + C(b2252b57) + }, + { + C(dbe4b1b2d174757f), C(506512da18712656), C(6857f3e0b8dd95f), C(5a4fc2728a9bb671), C(ebb971522ec38759), C(1a5a093e6cf1f72b), C(729b057fe784f504), + C(5a4fc2728a9bb671), C(ebb971522ec38759), C(1a5a093e6cf1f72b), C(729b057fe784f504), + C(71fcbf42a767f9cf), C(114cfe772da6cdd), C(60cdf9cb629d9d7a), C(e270d10ad088b24e), + C(72c81da1) + }, + { + C(531e8e77b363161c), C(eece0b43e2dae030), C(8294b82c78f34ed1), C(e777b1fd580582f2), C(7b880f58da112699), C(562c6b189a6333f4), C(139d64f88a611d4), + C(e777b1fd580582f2), C(7b880f58da112699), C(562c6b189a6333f4), C(139d64f88a611d4), + C(53d8ef17eda64fa4), C(bf3eded14dc60a04), C(2b5c559cf5ec07c5), C(8895f7339d03a48a), + C(6b9fce95) + }, + { + C(f71e9c926d711e2b), C(d77af2853a4ceaa1), C(9aa0d6d76a36fae7), C(dd16cd0fbc08393), C(29a414a5d8c58962), C(72793d8d1022b5b2), C(2e8e69cf7cbffdf0), + C(dd16cd0fbc08393), C(29a414a5d8c58962), C(72793d8d1022b5b2), C(2e8e69cf7cbffdf0), + C(3721c0473aa99c9a), C(1cff4ed9c31cd91c), C(4990735033cc482b), C(7fdf8c701c72f577), + C(19399857) + }, + { + C(cb20ac28f52df368), C(e6705ee7880996de), C(9b665cc3ec6972f2), C(4260e8c254e9924b), C(f197a6eb4591572d), C(8e867ff0fb7ab27c), C(f95502fb503efaf3), + C(4260e8c254e9924b), C(f197a6eb4591572d), C(8e867ff0fb7ab27c), C(f95502fb503efaf3), + C(30c41876b08e3e22), C(958e2419e3cd22f4), C(f0f3aa1fe119a107), C(481662310a379100), + C(3c57a994) + }, + { + C(e4a794b4acb94b55), C(89795358057b661b), C(9c4cdcec176d7a70), C(4890a83ee435bc8b), C(d8c1c00fceb00914), C(9e7111ba234f900f), C(eb8dbab364d8b604), + C(4890a83ee435bc8b), C(d8c1c00fceb00914), C(9e7111ba234f900f), C(eb8dbab364d8b604), + C(b3261452963eebb), C(6cf94b02792c4f95), C(d88fa815ef1e8fc), C(2d687af66604c73), + C(c053e729) + }, + { + C(cb942e91443e7208), C(e335de8125567c2a), C(d4d74d268b86df1f), C(8ba0fdd2ffc8b239), C(f413b366c1ffe02f), C(c05b2717c59a8a28), C(981188eab4fcc8fb), + C(8ba0fdd2ffc8b239), C(f413b366c1ffe02f), C(c05b2717c59a8a28), C(981188eab4fcc8fb), + C(e563f49a1d9072ba), C(3c6a3aa4a26367dc), C(ba0db13448653f34), C(31065d756074d7d6), + C(51cbbba7) + }, + { + C(ecca7563c203f7ba), C(177ae2423ef34bb2), C(f60b7243400c5731), C(cf1edbfe7330e94e), C(881945906bcb3cc6), C(4acf0293244855da), C(65ae042c1c2a28c2), + C(cf1edbfe7330e94e), C(881945906bcb3cc6), C(4acf0293244855da), C(65ae042c1c2a28c2), + C(b25fa0a1cab33559), C(d98e8daa28124131), C(fce17f50b9c351b3), C(3f995ccf7386864b), + C(1acde79a) + }, + { + C(1652cb940177c8b5), C(8c4fe7d85d2a6d6d), C(f6216ad097e54e72), C(f6521b912b368ae6), C(a9fe4eff81d03e73), C(d6f623629f80d1a3), C(2b9604f32cb7dc34), + C(f6521b912b368ae6), C(a9fe4eff81d03e73), C(d6f623629f80d1a3), C(2b9604f32cb7dc34), + C(2a43d84dcf59c7e2), C(d0a197c70c5dae0b), C(6e84d4bbc71d76a0), C(c7e94620378c6cb2), + C(2d160d13) + }, + { + C(31fed0fc04c13ce8), C(3d5d03dbf7ff240a), C(727c5c9b51581203), C(6b5ffc1f54fecb29), C(a8e8e7ad5b9a21d9), C(c4d5a32cd6aac22d), C(d7e274ad22d4a79a), + C(6b5ffc1f54fecb29), C(a8e8e7ad5b9a21d9), C(c4d5a32cd6aac22d), C(d7e274ad22d4a79a), + C(368841ea5731a112), C(feaf7bc2e73ca48f), C(636fb272e9ea1f6), C(5d9cb7580c3f6207), + C(787f5801) + }, + { + C(e7b668947590b9b3), C(baa41ad32938d3fa), C(abcbc8d4ca4b39e4), C(381ee1b7ea534f4e), C(da3759828e3de429), C(3e015d76729f9955), C(cbbec51a6485fbde), + C(381ee1b7ea534f4e), C(da3759828e3de429), C(3e015d76729f9955), C(cbbec51a6485fbde), + C(9b86605281f20727), C(fc6fcf508676982a), C(3b135f7a813a1040), C(d3a4706bea1db9c9), + C(c9629828) + }, + { + C(1de2119923e8ef3c), C(6ab27c096cf2fe14), C(8c3658edca958891), C(4cc8ed3ada5f0f2), C(4a496b77c1f1c04e), C(9085b0a862084201), C(a1894bde9e3dee21), + C(4cc8ed3ada5f0f2), C(4a496b77c1f1c04e), C(9085b0a862084201), C(a1894bde9e3dee21), + C(367fb472dc5b277d), C(7d39ccca16fc6745), C(763f988d70db9106), C(a8b66f7fecb70f02), + C(be139231) + }, + { + C(1269df1e69e14fa7), C(992f9d58ac5041b7), C(e97fcf695a7cbbb4), C(e5d0549802d15008), C(424c134ecd0db834), C(6fc44fd91be15c6c), C(a1a5ef95d50e537d), + C(e5d0549802d15008), C(424c134ecd0db834), C(6fc44fd91be15c6c), C(a1a5ef95d50e537d), + C(d1e3daf5d05f5308), C(4c7f81600eaa1327), C(109d1b8d1f9d0d2b), C(871e8699e0aeb862), + C(7df699ef) + }, + { + C(820826d7aba567ff), C(1f73d28e036a52f3), C(41c4c5a73f3b0893), C(aa0d74d4a98db89b), C(36fd486d07c56e1d), C(d0ad23cbb6660d8a), C(1264a84665b35e19), + C(aa0d74d4a98db89b), C(36fd486d07c56e1d), C(d0ad23cbb6660d8a), C(1264a84665b35e19), + C(789682bf7d781b33), C(6bfa6abd2fb5722d), C(6779cb3623d33900), C(435ca5214e1ee5f0), + C(8ce6b96d) + }, + { + C(ffe0547e4923cef9), C(3534ed49b9da5b02), C(548a273700fba03d), C(28ac84ca70958f7e), C(d8ae575a68faa731), C(2aaaee9b9dcffd4c), C(6c7faab5c285c6da), + C(28ac84ca70958f7e), C(d8ae575a68faa731), C(2aaaee9b9dcffd4c), C(6c7faab5c285c6da), + C(45d94235f99ba78f), C(ab5ea16f39497f5b), C(fb4d6c86fccbdca3), C(8104e6310a5fd2c7), + C(6f9ed99c) + }, + { + C(72da8d1b11d8bc8b), C(ba94b56b91b681c6), C(4e8cc51bd9b0fc8c), C(43505ed133be672a), C(e8f2f9d973c2774e), C(677b9b9c7cad6d97), C(4e1f5d56ef17b906), + C(43505ed133be672a), C(e8f2f9d973c2774e), C(677b9b9c7cad6d97), C(4e1f5d56ef17b906), + C(eea3a6038f983767), C(87109f077f86db01), C(ecc1ca41f74d61cc), C(34a87e86e83bed17), + C(e0244796) + }, + { + C(d62ab4e3f88fc797), C(ea86c7aeb6283ae4), C(b5b93e09a7fe465), C(4344a1a0134afe2), C(ff5c17f02b62341d), C(3214c6a587ce4644), C(a905e7ed0629d05c), + C(4344a1a0134afe2), C(ff5c17f02b62341d), C(3214c6a587ce4644), C(a905e7ed0629d05c), + C(b5c72690cd716e82), C(7c6097649e6ebe7b), C(7ceee8c6e56a4dcd), C(80ca849dc53eb9e4), + C(4ccf7e75) + }, + { + C(d0f06c28c7b36823), C(1008cb0874de4bb8), C(d6c7ff816c7a737b), C(489b697fe30aa65f), C(4da0fb621fdc7817), C(dc43583b82c58107), C(4b0261debdec3cd6), + C(489b697fe30aa65f), C(4da0fb621fdc7817), C(dc43583b82c58107), C(4b0261debdec3cd6), + C(a9748d7b6c0e016c), C(7e8828f7ba4b034b), C(da0fa54348a2512a), C(ebf9745c0962f9ad), + C(915cef86) + }, + { + C(99b7042460d72ec6), C(2a53e5e2b8e795c2), C(53a78132d9e1b3e3), C(c043e67e6fc64118), C(ff0abfe926d844d3), C(f2a9fe5db2e910fe), C(ce352cdc84a964dd), + C(c043e67e6fc64118), C(ff0abfe926d844d3), C(f2a9fe5db2e910fe), C(ce352cdc84a964dd), + C(b89bc028aa5e6063), C(a354e7fdac04459c), C(68d6547e6e980189), C(c968dddfd573773e), + C(5cb59482) + }, + { + C(4f4dfcfc0ec2bae5), C(841233148268a1b8), C(9248a76ab8be0d3), C(334c5a25b5903a8c), C(4c94fef443122128), C(743e7d8454655c40), C(1ab1e6d1452ae2cd), + C(334c5a25b5903a8c), C(4c94fef443122128), C(743e7d8454655c40), C(1ab1e6d1452ae2cd), + C(fec766de4a8e476c), C(cc0929da9567e71b), C(5f9ef5b5f150c35a), C(87659cabd649768f), + C(6ca3f532) + }, + { + C(fe86bf9d4422b9ae), C(ebce89c90641ef9c), C(1c84e2292c0b5659), C(8bde625a10a8c50d), C(eb8271ded1f79a0b), C(14dc6844f0de7a3c), C(f85b2f9541e7e6da), + C(8bde625a10a8c50d), C(eb8271ded1f79a0b), C(14dc6844f0de7a3c), C(f85b2f9541e7e6da), + C(2fe22cfd1683b961), C(ea1d75c5b7aa01ca), C(9eef60a44876bb95), C(950c818e505c6f7f), + C(e24f3859) + }, + { + C(a90d81060932dbb0), C(8acfaa88c5fbe92b), C(7c6f3447e90f7f3f), C(dd52fc14c8dd3143), C(1bc7508516e40628), C(3059730266ade626), C(ffa526822f391c2), + C(dd52fc14c8dd3143), C(1bc7508516e40628), C(3059730266ade626), C(ffa526822f391c2), + C(e25232d7afc8a406), C(d2b8a5a3f3b5f670), C(6630f33edb7dfe32), C(c71250ba68c4ea86), + C(adf5a9c7) + }, + { + C(17938a1b0e7f5952), C(22cadd2f56f8a4be), C(84b0d1183d5ed7c1), C(c1336b92fef91bf6), C(80332a3945f33fa9), C(a0f68b86f726ff92), C(a3db5282cf5f4c0b), + C(c1336b92fef91bf6), C(80332a3945f33fa9), C(a0f68b86f726ff92), C(a3db5282cf5f4c0b), + C(82640b6fc4916607), C(2dc2a3aa1a894175), C(8b4c852bdee7cc9), C(10b9d0a08b55ff83), + C(32264b75) + }, + { + C(de9e0cb0e16f6e6d), C(238e6283aa4f6594), C(4fb9c914c2f0a13b), C(497cb912b670f3b), C(d963a3f02ff4a5b6), C(4fccefae11b50391), C(42ba47db3f7672f), + C(497cb912b670f3b), C(d963a3f02ff4a5b6), C(4fccefae11b50391), C(42ba47db3f7672f), + C(1d6b655a1889feef), C(5f319abf8fafa19f), C(715c2e49deb14620), C(8d9153082ecdcea4), + C(a64b3376) + }, + { + C(6d4b876d9b146d1a), C(aab2d64ce8f26739), C(d315f93600e83fe5), C(2fe9fabdbe7fdd4), C(755db249a2d81a69), C(f27929f360446d71), C(79a1bf957c0c1b92), + C(2fe9fabdbe7fdd4), C(755db249a2d81a69), C(f27929f360446d71), C(79a1bf957c0c1b92), + C(3c8a28d4c936c9cd), C(df0d3d13b2c6a902), C(c76702dd97cd2edd), C(1aa220f7be16517), + C(d33890e) + }, + { + C(e698fa3f54e6ea22), C(bd28e20e7455358c), C(9ace161f6ea76e66), C(d53fb7e3c93a9e4), C(737ae71b051bf108), C(7ac71feb84c2df42), C(3d8075cd293a15b4), + C(d53fb7e3c93a9e4), C(737ae71b051bf108), C(7ac71feb84c2df42), C(3d8075cd293a15b4), + C(bf8cee5e095d8a7c), C(e7086b3c7608143a), C(e55b0c2fa938d70c), C(fffb5f58e643649c), + C(926d4b63) + }, + { + C(7bc0deed4fb349f7), C(1771aff25dc722fa), C(19ff0644d9681917), C(cf7d7f25bd70cd2c), C(9464ed9baeb41b4f), C(b9064f5c3cb11b71), C(237e39229b012b20), + C(cf7d7f25bd70cd2c), C(9464ed9baeb41b4f), C(b9064f5c3cb11b71), C(237e39229b012b20), + C(dd54d3f5d982dffe), C(7fc7562dbfc81dbf), C(5b0dd1924f70945), C(f1760537d8261135), + C(d51ba539) + }, + { + C(db4b15e88533f622), C(256d6d2419b41ce9), C(9d7c5378396765d5), C(9040e5b936b8661b), C(276e08fa53ac27fd), C(8c944d39c2bdd2cc), C(e2514c9802a5743c), + C(9040e5b936b8661b), C(276e08fa53ac27fd), C(8c944d39c2bdd2cc), C(e2514c9802a5743c), + C(e82107b11ac90386), C(7d6a22bc35055e6), C(fd6ea9d1c438d8ae), C(be6015149e981553), + C(7f37636d) + }, + { + C(922834735e86ecb2), C(363382685b88328e), C(e9c92960d7144630), C(8431b1bfd0a2379c), C(90383913aea283f9), C(a6163831eb4924d2), C(5f3921b4f9084aee), + C(8431b1bfd0a2379c), C(90383913aea283f9), C(a6163831eb4924d2), C(5f3921b4f9084aee), + C(7a70061a1473e579), C(5b19d80dcd2c6331), C(6196b97931faad27), C(869bf6828e237c3f), + C(b98026c0) + }, + { + C(30f1d72c812f1eb8), C(b567cd4a69cd8989), C(820b6c992a51f0bc), C(c54677a80367125e), C(3204fbdba462e606), C(8563278afc9eae69), C(262147dd4bf7e566), + C(c54677a80367125e), C(3204fbdba462e606), C(8563278afc9eae69), C(262147dd4bf7e566), + C(2178b63e7ee2d230), C(e9c61ad81f5bff26), C(9af7a81b3c501eca), C(44104a3859f0238f), + C(b877767e) + }, + { + C(168884267f3817e9), C(5b376e050f637645), C(1c18314abd34497a), C(9598f6ab0683fcc2), C(1c805abf7b80e1ee), C(dec9ac42ee0d0f32), C(8cd72e3912d24663), + C(9598f6ab0683fcc2), C(1c805abf7b80e1ee), C(dec9ac42ee0d0f32), C(8cd72e3912d24663), + C(1f025d405f1c1d87), C(bf7b6221e1668f8f), C(52316f64e692dbb0), C(7bf43df61ec51b39), + C(aefae77) + }, + { + C(82e78596ee3e56a7), C(25697d9c87f30d98), C(7600a8342834924d), C(6ba372f4b7ab268b), C(8c3237cf1fe243df), C(3833fc51012903df), C(8e31310108c5683f), + C(6ba372f4b7ab268b), C(8c3237cf1fe243df), C(3833fc51012903df), C(8e31310108c5683f), + C(126593715c2de429), C(48ca8f35a3f54b90), C(b9322b632f4f8b0), C(926bb169b7337693), + C(f686911) + }, + { + C(aa2d6cf22e3cc252), C(9b4dec4f5e179f16), C(76fb0fba1d99a99a), C(9a62af3dbba140da), C(27857ea044e9dfc1), C(33abce9da2272647), C(b22a7993aaf32556), + C(9a62af3dbba140da), C(27857ea044e9dfc1), C(33abce9da2272647), C(b22a7993aaf32556), + C(bf8f88f8019bedf0), C(ed2d7f01fb273905), C(6b45f15901b481cd), C(f88ebb413ba6a8d5), + C(3deadf12) + }, + { + C(7bf5ffd7f69385c7), C(fc077b1d8bc82879), C(9c04e36f9ed83a24), C(82065c62e6582188), C(8ef787fd356f5e43), C(2922e53e36e17dfa), C(9805f223d385010b), + C(82065c62e6582188), C(8ef787fd356f5e43), C(2922e53e36e17dfa), C(9805f223d385010b), + C(692154f3491b787d), C(e7e64700e414fbf), C(757d4d4ab65069a0), C(cd029446a8e348e2), + C(ccf02a4e) + }, + { + C(e89c8ff9f9c6e34b), C(f54c0f669a49f6c4), C(fc3e46f5d846adef), C(22f2aa3df2221cc), C(f66fea90f5d62174), C(b75defaeaa1dd2a7), C(9b994cd9a7214fd5), + C(22f2aa3df2221cc), C(f66fea90f5d62174), C(b75defaeaa1dd2a7), C(9b994cd9a7214fd5), + C(fac675a31804b773), C(98bcb3b820c50fc6), C(e14af64d28cf0885), C(27466fbd2b360eb5), + C(176c1722) + }, + { + C(a18fbcdccd11e1f4), C(8248216751dfd65e), C(40c089f208d89d7c), C(229b79ab69ae97d), C(a87aabc2ec26e582), C(be2b053721eb26d2), C(10febd7f0c3d6fcb), + C(229b79ab69ae97d), C(a87aabc2ec26e582), C(be2b053721eb26d2), C(10febd7f0c3d6fcb), + C(9cc5b9b2f6e3bf7b), C(655d8495fe624a86), C(6381a9f3d1f2bd7e), C(79ebabbfc25c83e2), + C(26f82ad) + }, + { + C(2d54f40cc4088b17), C(59d15633b0cd1399), C(a8cc04bb1bffd15b), C(d332cdb073d8dc46), C(272c56466868cb46), C(7e7fcbe35ca6c3f3), C(ee8f51e5a70399d4), + C(d332cdb073d8dc46), C(272c56466868cb46), C(7e7fcbe35ca6c3f3), C(ee8f51e5a70399d4), + C(16737a9c7581fe7b), C(ed04bf52f4b75dcb), C(9707ffb36bd30c1a), C(1390f236fdc0de3e), + C(b5244f42) + }, + { + C(69276946cb4e87c7), C(62bdbe6183be6fa9), C(3ba9773dac442a1a), C(702e2afc7f5a1825), C(8c49b11ea8151fdc), C(caf3fef61f5a86fa), C(ef0b2ee8649d7272), + C(702e2afc7f5a1825), C(8c49b11ea8151fdc), C(caf3fef61f5a86fa), C(ef0b2ee8649d7272), + C(9e34a4e08d9441e1), C(7bdc0cd64d5af533), C(a926b14d99e3d868), C(fca923a17788cce4), + C(49a689e5) + }, + { + C(668174a3f443df1d), C(407299392da1ce86), C(c2a3f7d7f2c5be28), C(a590b202a7a5807b), C(968d2593f7ccb54e), C(9dd8d669e3e95dec), C(ee0cc5dd58b6e93a), + C(a590b202a7a5807b), C(968d2593f7ccb54e), C(9dd8d669e3e95dec), C(ee0cc5dd58b6e93a), + C(ac65d5a9466fb483), C(221be538b2c9d806), C(5cbe9441784f9fd9), C(d4c7d5d6e3c122b8), + C(59fcdd3) + }, + { + C(5e29be847bd5046), C(b561c7f19c8f80c3), C(5e5abd5021ccaeaf), C(7432d63888e0c306), C(74bbceeed479cb71), C(6471586599575fdf), C(6a859ad23365cba2), + C(7432d63888e0c306), C(74bbceeed479cb71), C(6471586599575fdf), C(6a859ad23365cba2), + C(f9ceec84acd18dcc), C(74a242ff1907437c), C(f70890194e1ee913), C(777dfcb4bb01f0ba), + C(4f4b04e9) + }, + { + C(cd0d79f2164da014), C(4c386bb5c5d6ca0c), C(8e771b03647c3b63), C(69db23875cb0b715), C(ada8dd91504ae37f), C(46bf18dbf045ed6a), C(e1b5f67b0645ab63), + C(69db23875cb0b715), C(ada8dd91504ae37f), C(46bf18dbf045ed6a), C(e1b5f67b0645ab63), + C(877be8f5dcddff4), C(6d471b5f9ca2e2d1), C(802c86d6f495b9bb), C(a1f9b9b22b3be704), + C(8b00f891) + }, + { + C(e0e6fc0b1628af1d), C(29be5fb4c27a2949), C(1c3f781a604d3630), C(c4af7faf883033aa), C(9bd296c4e9453cac), C(ca45426c1f7e33f9), C(a6bbdcf7074d40c5), + C(c4af7faf883033aa), C(9bd296c4e9453cac), C(ca45426c1f7e33f9), C(a6bbdcf7074d40c5), + C(e13a005d7142733b), C(c02b7925c5eeefaf), C(d39119a60441e2d5), C(3c24c710df8f4d43), + C(16e114f3) + }, + { + C(2058927664adfd93), C(6e8f968c7963baa5), C(af3dced6fff7c394), C(42e34cf3d53c7876), C(9cddbb26424dc5e), C(64f6340a6d8eddad), C(2196e488eb2a3a4b), + C(42e34cf3d53c7876), C(9cddbb26424dc5e), C(64f6340a6d8eddad), C(2196e488eb2a3a4b), + C(c9e9da25911a16fd), C(e21b4683f3e196a8), C(cb80bf1a4c6fdbb4), C(53792e9b3c3e67f8), + C(d6b6dadc) + }, + { + C(dc107285fd8e1af7), C(a8641a0609321f3f), C(db06e89ffdc54466), C(bcc7a81ed5432429), C(b6d7bdc6ad2e81f1), C(93605ec471aa37db), C(a2a73f8a85a8e397), + C(bcc7a81ed5432429), C(b6d7bdc6ad2e81f1), C(93605ec471aa37db), C(a2a73f8a85a8e397), + C(10a012b8ca7ac24b), C(aac5fd63351595cf), C(5bb4c648a226dea0), C(9d11ecb2b5c05c5f), + C(897e20ac) + }, + { + C(fbba1afe2e3280f1), C(755a5f392f07fce), C(9e44a9a15402809a), C(6226a32e25099848), C(ea895661ecf53004), C(4d7e0158db2228b9), C(e5a7d82922f69842), + C(6226a32e25099848), C(ea895661ecf53004), C(4d7e0158db2228b9), C(e5a7d82922f69842), + C(2cea7713b69840ca), C(18de7b9ae938375b), C(f127cca08f3cc665), C(b1c22d727665ad2), + C(f996e05d) + }, + { + C(bfa10785ddc1011b), C(b6e1c4d2f670f7de), C(517d95604e4fcc1f), C(ca6552a0dfb82c73), C(b024cdf09e34ba07), C(66cd8c5a95d7393b), C(e3939acf790d4a74), + C(ca6552a0dfb82c73), C(b024cdf09e34ba07), C(66cd8c5a95d7393b), C(e3939acf790d4a74), + C(97827541a1ef051e), C(ac2fce47ebe6500c), C(b3f06d3bddf3bd6a), C(1d74afb25e1ce5fe), + C(c4306af6) + }, + { + C(534cc35f0ee1eb4e), C(b703820f1f3b3dce), C(884aa164cf22363), C(f14ef7f47d8a57a3), C(80d1f86f2e061d7c), C(401d6c2f151b5a62), C(e988460224108944), + C(f14ef7f47d8a57a3), C(80d1f86f2e061d7c), C(401d6c2f151b5a62), C(e988460224108944), + C(7804d4135f68cd19), C(5487b4b39e69fe8e), C(8cc5999015358a27), C(8f3729b61c2d5601), + C(6dcad433) + }, + { + C(7ca6e3933995dac), C(fd118c77daa8188), C(3aceb7b5e7da6545), C(c8389799445480db), C(5389f5df8aacd50d), C(d136581f22fab5f), C(c2f31f85991da417), + C(c8389799445480db), C(5389f5df8aacd50d), C(d136581f22fab5f), C(c2f31f85991da417), + C(aefbf9ff84035a43), C(8accbaf44adadd7c), C(e57f3657344b67f5), C(21490e5e8abdec51), + C(3c07374d) + }, + { + C(f0d6044f6efd7598), C(e044d6ba4369856e), C(91968e4f8c8a1a4c), C(70bd1968996bffc2), C(4c613de5d8ab32ac), C(fe1f4f97206f79d8), C(ac0434f2c4e213a9), + C(70bd1968996bffc2), C(4c613de5d8ab32ac), C(fe1f4f97206f79d8), C(ac0434f2c4e213a9), + C(7490e9d82cfe22ca), C(5fbbf7f987454238), C(c39e0dc8368ce949), C(22201d3894676c71), + C(f0f4602c) + }, + { + C(3d69e52049879d61), C(76610636ea9f74fe), C(e9bf5602f89310c0), C(8eeb177a86053c11), C(e390122c345f34a2), C(1e30e47afbaaf8d6), C(7b892f68e5f91732), + C(8eeb177a86053c11), C(e390122c345f34a2), C(1e30e47afbaaf8d6), C(7b892f68e5f91732), + C(b87922525fa44158), C(f440a1ee1a1a766b), C(ee8efad279d08c5c), C(421f910c5b60216e), + C(3e1ea071) + }, + { + C(79da242a16acae31), C(183c5f438e29d40), C(6d351710ae92f3de), C(27233b28b5b11e9b), C(c7dfe8988a942700), C(570ed11c4abad984), C(4b4c04632f48311a), + C(27233b28b5b11e9b), C(c7dfe8988a942700), C(570ed11c4abad984), C(4b4c04632f48311a), + C(12f33235442cbf9), C(a35315ca0b5b8cdb), C(d8abde62ead5506b), C(fc0fcf8478ad5266), + C(67580f0c) + }, + { + C(461c82656a74fb57), C(d84b491b275aa0f7), C(8f262cb29a6eb8b2), C(49fa3070bc7b06d0), C(f12ed446bd0c0539), C(6d43ac5d1dd4b240), C(7609524fe90bec93), + C(49fa3070bc7b06d0), C(f12ed446bd0c0539), C(6d43ac5d1dd4b240), C(7609524fe90bec93), + C(391c2b2e076ec241), C(f5e62deda7839f7b), C(3c7b3186a10d870f), C(77ef4f2cba4f1005), + C(4e109454) + }, + { + C(53c1a66d0b13003), C(731f060e6fe797fc), C(daa56811791371e3), C(57466046cf6896ed), C(8ac37e0e8b25b0c6), C(3e6074b52ad3cf18), C(aa491ce7b45db297), + C(57466046cf6896ed), C(8ac37e0e8b25b0c6), C(3e6074b52ad3cf18), C(aa491ce7b45db297), + C(f7a9227c5e5e22c3), C(3d92e0841e29ce28), C(2d30da5b2859e59d), C(ff37fa1c9cbfafc2), + C(88a474a7) + }, + { + C(d3a2efec0f047e9), C(1cabce58853e58ea), C(7a17b2eae3256be4), C(c2dcc9758c910171), C(cb5cddaeff4ddb40), C(5d7cc5869baefef1), C(9644c5853af9cfeb), + C(c2dcc9758c910171), C(cb5cddaeff4ddb40), C(5d7cc5869baefef1), C(9644c5853af9cfeb), + C(255c968184694ee1), C(4e4d726eda360927), C(7d27dd5b6d100377), C(9a300e2020ddea2c), + C(5b5bedd) + }, + { + C(43c64d7484f7f9b2), C(5da002b64aafaeb7), C(b576c1e45800a716), C(3ee84d3d5b4ca00b), C(5cbc6d701894c3f9), C(d9e946f5ae1ca95), C(24ca06e67f0b1833), + C(3ee84d3d5b4ca00b), C(5cbc6d701894c3f9), C(d9e946f5ae1ca95), C(24ca06e67f0b1833), + C(3413d46b4152650e), C(cbdfdbc2ab516f9c), C(2aad8acb739e0c6c), C(2bfc950d9f9fa977), + C(1aaddfa7) + }, + { + C(a7dec6ad81cf7fa1), C(180c1ab708683063), C(95e0fd7008d67cff), C(6b11c5073687208), C(7e0a57de0d453f3), C(e48c267d4f646867), C(2168e9136375f9cb), + C(6b11c5073687208), C(7e0a57de0d453f3), C(e48c267d4f646867), C(2168e9136375f9cb), + C(64da194aeeea7fdf), C(a3b9f01fa5885678), C(c316f8ee2eb2bd17), C(a7e4d80f83e4427f), + C(5be07fd8) + }, + { + C(5408a1df99d4aff), C(b9565e588740f6bd), C(abf241813b08006e), C(7da9e81d89fda7ad), C(274157cabe71440d), C(2c22d9a480b331f7), C(e835c8ac746472d5), + C(7da9e81d89fda7ad), C(274157cabe71440d), C(2c22d9a480b331f7), C(e835c8ac746472d5), + C(2038ce817a201ae4), C(46f3289dfe1c5e40), C(435578a42d4b7c56), C(f96d9f409fcf561), + C(cbca8606) + }, + { + C(a8b27a6bcaeeed4b), C(aec1eeded6a87e39), C(9daf246d6fed8326), C(d45a938b79f54e8f), C(366b219d6d133e48), C(5b14be3c25c49405), C(fdd791d48811a572), + C(d45a938b79f54e8f), C(366b219d6d133e48), C(5b14be3c25c49405), C(fdd791d48811a572), + C(3de67b8d9e95d335), C(903c01307cfbeed5), C(af7d65f32274f1d1), C(4dba141b5fc03c42), + C(bde64d01) + }, + { + C(9a952a8246fdc269), C(d0dcfcac74ef278c), C(250f7139836f0f1f), C(c83d3c5f4e5f0320), C(694e7adeb2bf32e5), C(7ad09538a3da27f5), C(2b5c18f934aa5303), + C(c83d3c5f4e5f0320), C(694e7adeb2bf32e5), C(7ad09538a3da27f5), C(2b5c18f934aa5303), + C(c4dad7703d34326e), C(825569e2bcdc6a25), C(b83d267709ca900d), C(44ed05151f5d74e6), + C(ee90cf33) + }, + { + C(c930841d1d88684f), C(5eb66eb18b7f9672), C(e455d413008a2546), C(bc271bc0df14d647), C(b071100a9ff2edbb), C(2b1a4c1cc31a119a), C(b5d7caa1bd946cef), + C(bc271bc0df14d647), C(b071100a9ff2edbb), C(2b1a4c1cc31a119a), C(b5d7caa1bd946cef), + C(e02623ae10f4aadd), C(d79f600389cd06fd), C(1e8da7965303e62b), C(86f50e10eeab0925), + C(4305c3ce) + }, + { + C(94dc6971e3cf071a), C(994c7003b73b2b34), C(ea16e85978694e5), C(336c1b59a1fc19f6), C(c173acaecc471305), C(db1267d24f3f3f36), C(e9a5ee98627a6e78), + C(336c1b59a1fc19f6), C(c173acaecc471305), C(db1267d24f3f3f36), C(e9a5ee98627a6e78), + C(718f334204305ae5), C(e3b53c148f98d22c), C(a184012df848926), C(6e96386127d51183), + C(4b3a1d76) + }, + { + C(7fc98006e25cac9), C(77fee0484cda86a7), C(376ec3d447060456), C(84064a6dcf916340), C(fbf55a26790e0ebb), C(2e7f84151c31a5c2), C(9f7f6d76b950f9bf), + C(84064a6dcf916340), C(fbf55a26790e0ebb), C(2e7f84151c31a5c2), C(9f7f6d76b950f9bf), + C(125e094fbee2b146), C(5706aa72b2eef7c2), C(1c4a2daa905ee66e), C(83d48029b5451694), + C(a8bb6d80) + }, + { + C(bd781c4454103f6), C(612197322f49c931), C(b9cf17fd7e5462d5), C(e38e526cd3324364), C(85f2b63a5b5e840a), C(485d7cef5aaadd87), C(d2b837a462f6db6d), + C(e38e526cd3324364), C(85f2b63a5b5e840a), C(485d7cef5aaadd87), C(d2b837a462f6db6d), + C(3e41cef031520d9a), C(82df73902d7f67e), C(3ba6fd54c15257cb), C(22f91f079be42d40), + C(1f9fa607) + }, + { + C(da60e6b14479f9df), C(3bdccf69ece16792), C(18ebf45c4fecfdc9), C(16818ee9d38c6664), C(5519fa9a1e35a329), C(cbd0001e4b08ed8), C(41a965e37a0c731b), + C(16818ee9d38c6664), C(5519fa9a1e35a329), C(cbd0001e4b08ed8), C(41a965e37a0c731b), + C(66e7b5dcca1ca28f), C(963b2d993614347d), C(9b6fc6f41d411106), C(aaaecaccf7848c0c), + C(8d0e4ed2) + }, + { + C(4ca56a348b6c4d3), C(60618537c3872514), C(2fbb9f0e65871b09), C(30278016830ddd43), C(f046646d9012e074), C(c62a5804f6e7c9da), C(98d51f5830e2bc1e), + C(30278016830ddd43), C(f046646d9012e074), C(c62a5804f6e7c9da), C(98d51f5830e2bc1e), + C(7b2cbe5d37e3f29e), C(7b8c3ed50bda4aa0), C(3ea60cc24639e038), C(f7706de9fb0b5801), + C(1bf31347) + }, + { + C(ebd22d4b70946401), C(6863602bf7139017), C(c0b1ac4e11b00666), C(7d2782b82bd494b6), C(97159ba1c26b304b), C(42b3b0fd431b2ac2), C(faa81f82691c830c), + C(7d2782b82bd494b6), C(97159ba1c26b304b), C(42b3b0fd431b2ac2), C(faa81f82691c830c), + C(7cc6449234c7e185), C(aeaa6fa643ca86a5), C(1412db1c0f2e0133), C(4df2fe3e4072934f), + C(1ae3fc5b) + }, + { + C(3cc4693d6cbcb0c), C(501689ea1c70ffa), C(10a4353e9c89e364), C(58c8aba7475e2d95), C(3e2f291698c9427a), C(e8710d19c9de9e41), C(65dda22eb04cf953), + C(58c8aba7475e2d95), C(3e2f291698c9427a), C(e8710d19c9de9e41), C(65dda22eb04cf953), + C(d7729c48c250cffa), C(ef76162b2ddfba4b), C(52371e17f4d51f6d), C(ddd002112ff0c833), + C(459c3930) + }, + { + C(38908e43f7ba5ef0), C(1ab035d4e7781e76), C(41d133e8c0a68ff7), C(d1090893afaab8bc), C(96c4fe6922772807), C(4522426c2b4205eb), C(efad99a1262e7e0d), + C(d1090893afaab8bc), C(96c4fe6922772807), C(4522426c2b4205eb), C(efad99a1262e7e0d), + C(c7696029abdb465e), C(4e18eaf03d517651), C(d006bced54c86ac8), C(4330326d1021860c), + C(e00c4184) + }, + { + C(34983ccc6aa40205), C(21802cad34e72bc4), C(1943e8fb3c17bb8), C(fc947167f69c0da5), C(ae79cfdb91b6f6c1), C(7b251d04c26cbda3), C(128a33a79060d25e), + C(fc947167f69c0da5), C(ae79cfdb91b6f6c1), C(7b251d04c26cbda3), C(128a33a79060d25e), + C(1eca842dbfe018dd), C(50a4cd2ee0ba9c63), C(c2f5c97d8399682f), C(3f929fc7cbe8ecbb), + C(ffc7a781) + }, + { + C(86215c45dcac9905), C(ea546afe851cae4b), C(d85b6457e489e374), C(b7609c8e70386d66), C(36e6ccc278d1636d), C(2f873307c08e6a1c), C(10f252a758505289), + C(b7609c8e70386d66), C(36e6ccc278d1636d), C(2f873307c08e6a1c), C(10f252a758505289), + C(c8977646e81ab4b6), C(8017b745cd80213b), C(960687db359bea0), C(ef4a470660799488), + C(6a125480) + }, + { + C(420fc255c38db175), C(d503cd0f3c1208d1), C(d4684e74c825a0bc), C(4c10537443152f3d), C(720451d3c895e25d), C(aff60c4d11f513fd), C(881e8d6d2d5fb953), + C(4c10537443152f3d), C(720451d3c895e25d), C(aff60c4d11f513fd), C(881e8d6d2d5fb953), + C(9dec034a043f1f55), C(e27a0c22e7bfb39d), C(2220b959128324), C(53240272152dbd8b), + C(88a1512b) + }, + { + C(1d7a31f5bc8fe2f9), C(4763991092dcf836), C(ed695f55b97416f4), C(f265edb0c1c411d7), C(30e1e9ec5262b7e6), C(c2c3ba061ce7957a), C(d975f93b89a16409), + C(f265edb0c1c411d7), C(30e1e9ec5262b7e6), C(c2c3ba061ce7957a), C(d975f93b89a16409), + C(e9d703123f43450a), C(41383fedfed67c82), C(6e9f43ecbbbd6004), C(c7ccd23a24e77b8), + C(549bbbe5) + }, + { + C(94129a84c376a26e), C(c245e859dc231933), C(1b8f74fecf917453), C(e9369d2e9007e74b), C(b1375915d1136052), C(926c2021fe1d2351), C(1d943addaaa2e7e6), + C(e9369d2e9007e74b), C(b1375915d1136052), C(926c2021fe1d2351), C(1d943addaaa2e7e6), + C(f5f515869c246738), C(7e309cd0e1c0f2a0), C(153c3c36cf523e3b), C(4931c66872ea6758), + C(c133d38c) + }, + { + C(1d3a9809dab05c8d), C(adddeb4f71c93e8), C(ef342eb36631edb), C(301d7a61c4b3dbca), C(861336c3f0552d61), C(12c6db947471300f), C(a679ef0ed761deb9), + C(301d7a61c4b3dbca), C(861336c3f0552d61), C(12c6db947471300f), C(a679ef0ed761deb9), + C(5f713b720efcd147), C(37ac330a333aa6b), C(3309dc9ec1616eef), C(52301d7a908026b5), + C(fcace348) + }, + { + C(90fa3ccbd60848da), C(dfa6e0595b569e11), C(e585d067a1f5135d), C(6cef866ec295abea), C(c486c0d9214beb2d), C(d6e490944d5fe100), C(59df3175d72c9f38), + C(6cef866ec295abea), C(c486c0d9214beb2d), C(d6e490944d5fe100), C(59df3175d72c9f38), + C(3f23aeb4c04d1443), C(9bf0515cd8d24770), C(958554f60ccaade2), C(5182863c90132fe8), + C(ed7b6f9a) + }, + { + C(2dbb4fc71b554514), C(9650e04b86be0f82), C(60f2304fba9274d3), C(fcfb9443e997cab), C(f13310d96dec2772), C(709cad2045251af2), C(afd0d30cc6376dad), + C(fcfb9443e997cab), C(f13310d96dec2772), C(709cad2045251af2), C(afd0d30cc6376dad), + C(59d4bed30d550d0d), C(58006d4e22d8aad1), C(eee12d2362d1f13b), C(35cf1d7faaf1d228), + C(6d907dda) + }, + { + C(b98bf4274d18374a), C(1b669fd4c7f9a19a), C(b1f5972b88ba2b7a), C(73119c99e6d508be), C(5d4036a187735385), C(8fa66e192fd83831), C(2abf64b6b592ed57), + C(73119c99e6d508be), C(5d4036a187735385), C(8fa66e192fd83831), C(2abf64b6b592ed57), + C(d4501f95dd84b08c), C(bf1552439c8bea02), C(4f56fe753ba7e0ba), C(4ca8d35cc058cfcd), + C(7a4d48d5) + }, + { + C(d6781d0b5e18eb68), C(b992913cae09b533), C(58f6021caaee3a40), C(aafcb77497b5a20b), C(411819e5e79b77a3), C(bd779579c51c77ce), C(58d11f5dcf5d075d), + C(aafcb77497b5a20b), C(411819e5e79b77a3), C(bd779579c51c77ce), C(58d11f5dcf5d075d), + C(9eae76cde1cb4233), C(32fe25a9bf657970), C(1c0c807948edb06a), C(b8f29a3dfaee254d), + C(e686f3db) + }, + { + C(226651cf18f4884c), C(595052a874f0f51c), C(c9b75162b23bab42), C(3f44f873be4812ec), C(427662c1dbfaa7b2), C(a207ff9638fb6558), C(a738d919e45f550f), + C(3f44f873be4812ec), C(427662c1dbfaa7b2), C(a207ff9638fb6558), C(a738d919e45f550f), + C(cb186ea05717e7d6), C(1ca7d68a5871fdc1), C(5d4c119ea8ef3750), C(72b6a10fa2ff9406), + C(cce7c55) + }, + { + C(a734fb047d3162d6), C(e523170d240ba3a5), C(125a6972809730e8), C(d396a297799c24a1), C(8fee992e3069bad5), C(2e3a01b0697ccf57), C(ee9c7390bd901cfa), + C(d396a297799c24a1), C(8fee992e3069bad5), C(2e3a01b0697ccf57), C(ee9c7390bd901cfa), + C(56f2d9da0af28af2), C(3fdd37b2fe8437cb), C(3d13eeeb60d6aec0), C(2432ae62e800a5ce), + C(f58b96b) + }, + { + C(c6df6364a24f75a3), C(c294e2c84c4f5df8), C(a88df65c6a89313b), C(895fe8443183da74), C(c7f2f6f895a67334), C(a0d6b6a506691d31), C(24f51712b459a9f0), + C(895fe8443183da74), C(c7f2f6f895a67334), C(a0d6b6a506691d31), C(24f51712b459a9f0), + C(173a699481b9e088), C(1dee9b77bcbf45d3), C(32b98a646a8667d0), C(3adcd4ee28f42a0e), + C(1bbf6f60) + }, + { + C(d8d1364c1fbcd10), C(2d7cc7f54832deaa), C(4e22c876a7c57625), C(a3d5d1137d30c4bd), C(1e7d706a49bdfb9e), C(c63282b20ad86db2), C(aec97fa07916bfd6), + C(a3d5d1137d30c4bd), C(1e7d706a49bdfb9e), C(c63282b20ad86db2), C(aec97fa07916bfd6), + C(7c9ba3e52d44f73e), C(af62fd245811185d), C(8a9d2dacd8737652), C(bd2cce277d5fbec0), + C(ce5e0cc2) + }, + { + C(aae06f9146db885f), C(3598736441e280d9), C(fba339b117083e55), C(b22bf08d9f8aecf7), C(c182730de337b922), C(2b9adc87a0450a46), C(192c29a9cfc00aad), + C(b22bf08d9f8aecf7), C(c182730de337b922), C(2b9adc87a0450a46), C(192c29a9cfc00aad), + C(9fd733f1d84a59d9), C(d86bd5c9839ace15), C(af20b57303172876), C(9f63cb7161b5364c), + C(584cfd6f) + }, + { + C(8955ef07631e3bcc), C(7d70965ea3926f83), C(39aed4134f8b2db6), C(882efc2561715a9c), C(ef8132a18a540221), C(b20a3c87a8c257c1), C(f541b8628fad6c23), + C(882efc2561715a9c), C(ef8132a18a540221), C(b20a3c87a8c257c1), C(f541b8628fad6c23), + C(9552aed57a6e0467), C(4d9fdd56867611a7), C(c330279bf23b9eab), C(44dbbaea2fcb8eba), + C(8f9bbc33) + }, + { + C(ad611c609cfbe412), C(d3c00b18bf253877), C(90b2172e1f3d0bfd), C(371a98b2cb084883), C(33a2886ee9f00663), C(be9568818ed6e6bd), C(f244a0fa2673469a), + C(371a98b2cb084883), C(33a2886ee9f00663), C(be9568818ed6e6bd), C(f244a0fa2673469a), + C(b447050bd3e559e9), C(d3b695dae7a13383), C(ded0bb65be471188), C(ca3c7a2b78922cae), + C(d7640d95) + }, + { + C(d5339adc295d5d69), C(b633cc1dcb8b586a), C(ee84184cf5b1aeaf), C(89f3aab99afbd636), C(f420e004f8148b9a), C(6818073faa797c7c), C(dd3b4e21cbbf42ca), + C(89f3aab99afbd636), C(f420e004f8148b9a), C(6818073faa797c7c), C(dd3b4e21cbbf42ca), + C(6a2b7db261164844), C(cbead63d1895852a), C(93d37e1eae05e2f9), C(5d06db2703fbc3ae), + C(3d12a2b) + }, + { + C(40d0aeff521375a8), C(77ba1ad7ecebd506), C(547c6f1a7d9df427), C(21c2be098327f49b), C(7e035065ac7bbef5), C(6d7348e63023fb35), C(9d427dc1b67c3830), + C(21c2be098327f49b), C(7e035065ac7bbef5), C(6d7348e63023fb35), C(9d427dc1b67c3830), + C(4e3d018a43858341), C(cf924bb44d6b43c5), C(4618b6a26e3446ae), C(54d3013fac3ed469), + C(aaeafed0) + }, + { + C(8b2d54ae1a3df769), C(11e7adaee3216679), C(3483781efc563e03), C(9d097dd3152ab107), C(51e21d24126e8563), C(cba56cac884a1354), C(39abb1b595f0a977), + C(9d097dd3152ab107), C(51e21d24126e8563), C(cba56cac884a1354), C(39abb1b595f0a977), + C(81e6dd1c1109848f), C(1644b209826d7b15), C(6ac67e4e4b4812f0), C(b3a9f5622c935bf7), + C(95b9b814) + }, + { + C(99c175819b4eae28), C(932e8ff9f7a40043), C(ec78dcab07ca9f7c), C(c1a78b82ba815b74), C(458cbdfc82eb322a), C(17f4a192376ed8d7), C(6f9e92968bc8ccef), + C(c1a78b82ba815b74), C(458cbdfc82eb322a), C(17f4a192376ed8d7), C(6f9e92968bc8ccef), + C(93e098c333b39905), C(d59b1cace44b7fdc), C(f7a64ed78c64c7c5), C(7c6eca5dd87ec1ce), + C(45fbe66e) + }, + { + C(2a418335779b82fc), C(af0295987849a76b), C(c12bc5ff0213f46e), C(5aeead8d6cb25bb9), C(739315f7743ec3ff), C(9ab48d27111d2dcc), C(5b87bd35a975929b), + C(5aeead8d6cb25bb9), C(739315f7743ec3ff), C(9ab48d27111d2dcc), C(5b87bd35a975929b), + C(c3dd8d6d95a46bb3), C(7bf9093215a4f483), C(cb557d6ed84285bd), C(daf58422f261fdb5), + C(b4baa7a8) + }, + { + C(3b1fc6a3d279e67d), C(70ea1e49c226396), C(25505adcf104697c), C(ba1ffba29f0367aa), C(a20bec1dd15a8b6c), C(e9bf61d2dab0f774), C(f4f35bf5870a049c), + C(ba1ffba29f0367aa), C(a20bec1dd15a8b6c), C(e9bf61d2dab0f774), C(f4f35bf5870a049c), + C(26787efa5b92385), C(3d9533590ce30b59), C(a4da3e40530a01d4), C(6395deaefb70067c), + C(83e962fe) + }, + { + C(d97eacdf10f1c3c9), C(b54f4654043a36e0), C(b128f6eb09d1234), C(d8ad7ec84a9c9aa2), C(e256cffed11f69e6), C(2cf65e4958ad5bda), C(cfbf9b03245989a7), + C(d8ad7ec84a9c9aa2), C(e256cffed11f69e6), C(2cf65e4958ad5bda), C(cfbf9b03245989a7), + C(9fa51e6686cf4444), C(9425c117a34609d5), C(b25f7e2c6f30e96), C(ea5477c3f2b5afd1), + C(aac3531c) + }, + { + C(293a5c1c4e203cd4), C(6b3329f1c130cefe), C(f2e32f8ec76aac91), C(361e0a62c8187bff), C(6089971bb84d7133), C(93df7741588dd50b), C(c2a9b6abcd1d80b1), + C(361e0a62c8187bff), C(6089971bb84d7133), C(93df7741588dd50b), C(c2a9b6abcd1d80b1), + C(4d2f86869d79bc59), C(85cd24d8aa570ff), C(b0dcf6ef0e94bbb5), C(2037c69aa7a78421), + C(2b1db7cc) + }, + { + C(4290e018ffaedde7), C(a14948545418eb5e), C(72d851b202284636), C(4ec02f3d2f2b23f2), C(ab3580708aa7c339), C(cdce066fbab3f65), C(d8ed3ecf3c7647b9), + C(4ec02f3d2f2b23f2), C(ab3580708aa7c339), C(cdce066fbab3f65), C(d8ed3ecf3c7647b9), + C(6d2204b3e31f344a), C(61a4d87f80ee61d7), C(446c43dbed4b728f), C(73130ac94f58747e), + C(cf00cd31) + }, + { + C(f919a59cbde8bf2f), C(a56d04203b2dc5a5), C(38b06753ac871e48), C(c2c9fc637dbdfcfa), C(292ab8306d149d75), C(7f436b874b9ffc07), C(a5b56b0129218b80), + C(c2c9fc637dbdfcfa), C(292ab8306d149d75), C(7f436b874b9ffc07), C(a5b56b0129218b80), + C(9188f7bdc47ec050), C(cfe9345d03a15ade), C(40b520fb2750c49e), C(c2e83d343968af2e), + C(7d3c43b8) + }, + { + C(1d70a3f5521d7fa4), C(fb97b3fdc5891965), C(299d49bbbe3535af), C(e1a8286a7d67946e), C(52bd956f047b298), C(cbd74332dd4204ac), C(12b5be7752721976), + C(e1a8286a7d67946e), C(52bd956f047b298), C(cbd74332dd4204ac), C(12b5be7752721976), + C(278426e27f6204b6), C(932ca7a7cd610181), C(41647321f0a5914d), C(48f4aa61a0ae80db), + C(cbd5fac6) + }, + { + C(6af98d7b656d0d7c), C(d2e99ae96d6b5c0c), C(f63bd1603ef80627), C(bde51033ac0413f8), C(bc0272f691aec629), C(6204332651bebc44), C(1cbf00de026ea9bd), + C(bde51033ac0413f8), C(bc0272f691aec629), C(6204332651bebc44), C(1cbf00de026ea9bd), + C(b9c7ed6a75f3ff1e), C(7e310b76a5808e4f), C(acbbd1aad5531885), C(fc245f2473adeb9c), + C(76d0fec4) + }, + { + C(395b7a8adb96ab75), C(582df7165b20f4a), C(e52bd30e9ff657f9), C(6c71064996cbec8b), C(352c535edeefcb89), C(ac7f0aba15cd5ecd), C(3aba1ca8353e5c60), + C(6c71064996cbec8b), C(352c535edeefcb89), C(ac7f0aba15cd5ecd), C(3aba1ca8353e5c60), + C(5c30a288a80ce646), C(c2940488b6617674), C(925f8cc66b370575), C(aa65d1283b9bb0ef), + C(405e3402) + }, + { + C(3822dd82c7df012f), C(b9029b40bd9f122b), C(fd25b988468266c4), C(43e47bd5bab1e0ef), C(4a71f363421f282f), C(880b2f32a2b4e289), C(1299d4eda9d3eadf), + C(43e47bd5bab1e0ef), C(4a71f363421f282f), C(880b2f32a2b4e289), C(1299d4eda9d3eadf), + C(d713a40226f5564), C(4d8d34fedc769406), C(a85001b29cd9cac3), C(cae92352a41fd2b0), + C(c732c481) + }, + { + C(79f7efe4a80b951a), C(dd3a3fddfc6c9c41), C(ab4c812f9e27aa40), C(832954ec9d0de333), C(94c390aa9bcb6b8a), C(f3b32afdc1f04f82), C(d229c3b72e4b9a74), + C(832954ec9d0de333), C(94c390aa9bcb6b8a), C(f3b32afdc1f04f82), C(d229c3b72e4b9a74), + C(1d11860d7ed624a6), C(cadee20b3441b984), C(75307079bf306f7b), C(87902aa3b9753ba4), + C(a8d123c9) + }, + { + C(ae6e59f5f055921a), C(e9d9b7bf68e82), C(5ce4e4a5b269cc59), C(4960111789727567), C(149b8a37c7125ab6), C(78c7a13ab9749382), C(1c61131260ca151a), + C(4960111789727567), C(149b8a37c7125ab6), C(78c7a13ab9749382), C(1c61131260ca151a), + C(1e93276b35c309a0), C(2618f56230acde58), C(af61130a18e4febf), C(7145deb18e89befe), + C(1e80ad7d) + }, + { + C(8959dbbf07387d36), C(b4658afce48ea35d), C(8f3f82437d8cb8d6), C(6566d74954986ba5), C(99d5235cc82519a7), C(257a23805c2d825), C(ad75ccb968e93403), + C(6566d74954986ba5), C(99d5235cc82519a7), C(257a23805c2d825), C(ad75ccb968e93403), + C(b45bd4cf78e11f7f), C(80c5536bdc487983), C(a4fd76ecbf018c8a), C(3b9dac78a7a70d43), + C(52aeb863) + }, + { + C(4739613234278a49), C(99ea5bcd340bf663), C(258640912e712b12), C(c8a2827404991402), C(7ee5e78550f02675), C(2ec53952db5ac662), C(1526405a9df6794b), + C(c8a2827404991402), C(7ee5e78550f02675), C(2ec53952db5ac662), C(1526405a9df6794b), + C(eddc6271170c5e1f), C(f5a85f986001d9d6), C(95427c677bf58d58), C(53ed666dfa85cb29), + C(ef7c0c18) + }, + { + C(420e6c926bc54841), C(96dbbf6f4e7c75cd), C(d8d40fa70c3c67bb), C(3edbc10e4bfee91b), C(f0d681304c28ef68), C(77ea602029aaaf9c), C(90f070bd24c8483c), + C(3edbc10e4bfee91b), C(f0d681304c28ef68), C(77ea602029aaaf9c), C(90f070bd24c8483c), + C(28bc8e41e08ceb86), C(1eb56e48a65691ef), C(9fea5301c9202f0e), C(3fcb65091aa9f135), + C(b6ad4b68) + }, + { + C(c8601bab561bc1b7), C(72b26272a0ff869a), C(56fdfc986d6bc3c4), C(83707730cad725d4), C(c9ca88c3a779674a), C(e1c696fbbd9aa933), C(723f3baab1c17a45), + C(83707730cad725d4), C(c9ca88c3a779674a), C(e1c696fbbd9aa933), C(723f3baab1c17a45), + C(f82abc7a1d851682), C(30683836818e857d), C(78bfa3e89a5ab23f), C(6928234482b31817), + C(c1e46b17) + }, + { + C(b2d294931a0e20eb), C(284ffd9a0815bc38), C(1f8a103aac9bbe6), C(1ef8e98e1ea57269), C(5971116272f45a8b), C(187ad68ce95d8eac), C(e94e93ee4e8ecaa6), + C(1ef8e98e1ea57269), C(5971116272f45a8b), C(187ad68ce95d8eac), C(e94e93ee4e8ecaa6), + C(a0ff2a58611838b5), C(b01e03849bfbae6f), C(d081e202e28ea3ab), C(51836bcee762bf13), + C(57b8df25) + }, + { + C(7966f53c37b6c6d7), C(8e6abcfb3aa2b88f), C(7f2e5e0724e5f345), C(3eeb60c3f5f8143d), C(a25aec05c422a24f), C(b026b03ad3cca4db), C(e6e030028cc02a02), + C(3eeb60c3f5f8143d), C(a25aec05c422a24f), C(b026b03ad3cca4db), C(e6e030028cc02a02), + C(16fe679338b34bfc), C(c1be385b5c8a9de4), C(65af5df6567530eb), C(ed3b303df4dc6335), + C(e9fa36d6) + }, + { + C(be9bb0abd03b7368), C(13bca93a3031be55), C(e864f4f52b55b472), C(36a8d13a2cbb0939), C(254ac73907413230), C(73520d1522315a70), C(8c9fdb5cf1e1a507), + C(36a8d13a2cbb0939), C(254ac73907413230), C(73520d1522315a70), C(8c9fdb5cf1e1a507), + C(b3640570b926886), C(fba2344ee87f7bab), C(de57341ab448df05), C(385612ee094fa977), + C(8f8daefc) + }, + { + C(a08d128c5f1649be), C(a8166c3dbbe19aad), C(cb9f914f829ec62c), C(5b2b7ca856fad1c3), C(8093022d682e375d), C(ea5d163ba7ea231f), C(d6181d012c0de641), + C(5b2b7ca856fad1c3), C(8093022d682e375d), C(ea5d163ba7ea231f), C(d6181d012c0de641), + C(e7d40d0ab8b08159), C(2e82320f51b3a67e), C(27c2e356ea0b63a3), C(58842d01a2b1d077), + C(6e1bb7e) + }, + { + C(7c386f0ffe0465ac), C(530419c9d843dbf3), C(7450e3a4f72b8d8c), C(48b218e3b721810d), C(d3757ac8609bc7fc), C(111ba02a88aefc8), C(e86343137d3bfc2a), + C(48b218e3b721810d), C(d3757ac8609bc7fc), C(111ba02a88aefc8), C(e86343137d3bfc2a), + C(44ad26b51661b507), C(db1268670274f51e), C(62a5e75beae875f3), C(e266e7a44c5f28c6), + C(fd0076f0) + }, + { + C(bb362094e7ef4f8), C(ff3c2a48966f9725), C(55152803acd4a7fe), C(15747d8c505ffd00), C(438a15f391312cd6), C(e46ca62c26d821f5), C(be78d74c9f79cb44), + C(15747d8c505ffd00), C(438a15f391312cd6), C(e46ca62c26d821f5), C(be78d74c9f79cb44), + C(a8aa19f3aa59f09a), C(effb3cddab2c9267), C(d78e41ad97cb16a5), C(ace6821513527d32), + C(899b17b6) + }, + { + C(cd80dea24321eea4), C(52b4fdc8130c2b15), C(f3ea100b154bfb82), C(d9ccef1d4be46988), C(5ede0c4e383a5e66), C(da69683716a54d1e), C(bfc3fdf02d242d24), + C(d9ccef1d4be46988), C(5ede0c4e383a5e66), C(da69683716a54d1e), C(bfc3fdf02d242d24), + C(20ed30274651b3f5), C(4c659824169e86c6), C(637226dae5b52a0e), C(7e050dbd1c71dc7f), + C(e3e84e31) + }, + { + C(d599a04125372c3a), C(313136c56a56f363), C(1e993c3677625832), C(2870a99c76a587a4), C(99f74cc0b182dda4), C(8a5e895b2f0ca7b6), C(3d78882d5e0bb1dc), + C(2870a99c76a587a4), C(99f74cc0b182dda4), C(8a5e895b2f0ca7b6), C(3d78882d5e0bb1dc), + C(f466123732a3e25e), C(aca5e59716a40e50), C(261d2e7383d0e686), C(ce9362d6a42c15a7), + C(eef79b6b) + }, + { + C(dbbf541e9dfda0a), C(1479fceb6db4f844), C(31ab576b59062534), C(a3335c417687cf3a), C(92ff114ac45cda75), C(c3b8a627384f13b5), C(c4f25de33de8b3f7), + C(a3335c417687cf3a), C(92ff114ac45cda75), C(c3b8a627384f13b5), C(c4f25de33de8b3f7), + C(eacbf520578c5964), C(4cb19c5ab24f3215), C(e7d8a6f67f0c6e7), C(325c2413eb770ada), + C(868e3315) + }, + { + C(c2ee3288be4fe2bf), C(c65d2f5ddf32b92), C(af6ecdf121ba5485), C(c7cd48f7abf1fe59), C(ce600656ace6f53a), C(8a94a4381b108b34), C(f9d1276c64bf59fb), + C(c7cd48f7abf1fe59), C(ce600656ace6f53a), C(8a94a4381b108b34), C(f9d1276c64bf59fb), + C(219ce70ff5a112a5), C(e6026c576e2d28d7), C(b8e467f25015e3a6), C(950cb904f37af710), + C(4639a426) + }, + { + C(d86603ced1ed4730), C(f9de718aaada7709), C(db8b9755194c6535), C(d803e1eead47604c), C(ad00f7611970a71b), C(bc50036b16ce71f5), C(afba96210a2ca7d6), + C(d803e1eead47604c), C(ad00f7611970a71b), C(bc50036b16ce71f5), C(afba96210a2ca7d6), + C(28f7a7be1d6765f0), C(97bd888b93938c68), C(6ad41d1b407ded49), C(b9bfec098dc543e4), + C(f3213646) + }, + { + C(915263c671b28809), C(a815378e7ad762fd), C(abec6dc9b669f559), C(d17c928c5342477f), C(745130b795254ad5), C(8c5db926fe88f8ba), C(742a95c953e6d974), + C(d17c928c5342477f), C(745130b795254ad5), C(8c5db926fe88f8ba), C(742a95c953e6d974), + C(279db8057b5d3e96), C(98168411565b4ec4), C(50a72c54fa1125fa), C(27766a635db73638), + C(17f148e9) + }, + { + C(2b67cdd38c307a5e), C(cb1d45bb5c9fe1c), C(800baf2a02ec18ad), C(6531c1fe32bcb417), C(8c970d8df8cdbeb4), C(917ba5fc67e72b40), C(4b65e4e263e0a426), + C(6531c1fe32bcb417), C(8c970d8df8cdbeb4), C(917ba5fc67e72b40), C(4b65e4e263e0a426), + C(e0de33ce88a8b3a9), C(f8ef98a437e16b08), C(a5162c0c7c5f7b62), C(dbdac43361b2b881), + C(bfd94880) + }, + { + C(2d107419073b9cd0), C(a96db0740cef8f54), C(ec41ee91b3ecdc1b), C(ffe319654c8e7ebc), C(6a67b8f13ead5a72), C(6dd10a34f80d532f), C(6e9cfaece9fbca4), + C(ffe319654c8e7ebc), C(6a67b8f13ead5a72), C(6dd10a34f80d532f), C(6e9cfaece9fbca4), + C(b4468eb6a30aa7e9), C(e87995bee483222a), C(d036c2c90c609391), C(853306e82fa32247), + C(bb1fa7f3) + }, + { + C(f3e9487ec0e26dfc), C(1ab1f63224e837fa), C(119983bb5a8125d8), C(8950cfcf4bdf622c), C(8847dca82efeef2f), C(646b75b026708169), C(21cab4b1687bd8b), + C(8950cfcf4bdf622c), C(8847dca82efeef2f), C(646b75b026708169), C(21cab4b1687bd8b), + C(243b489a9eae6231), C(5f3e634c4b779876), C(ff8abd1548eaf646), C(c7962f5f0151914b), + C(88816b1) + }, + { + C(1160987c8fe86f7d), C(879e6db1481eb91b), C(d7dcb802bfe6885d), C(14453b5cc3d82396), C(4ef700c33ed278bc), C(1639c72ffc00d12e), C(fb140ee6155f700d), + C(14453b5cc3d82396), C(4ef700c33ed278bc), C(1639c72ffc00d12e), C(fb140ee6155f700d), + C(2e6b5c96a6620862), C(a1f136998cbe19c), C(74e058a3b6c5a712), C(93dcf6bd33928b17), + C(5c2faeb3) + }, + { + C(eab8112c560b967b), C(97f550b58e89dbae), C(846ed506d304051f), C(276aa37744b5a028), C(8c10800ee90ea573), C(e6e57d2b33a1e0b7), C(91f83563cd3b9dda), + C(276aa37744b5a028), C(8c10800ee90ea573), C(e6e57d2b33a1e0b7), C(91f83563cd3b9dda), + C(afbb4739570738a1), C(440ba98da5d8f69), C(fde4e9b0eda20350), C(e67dfa5a2138fa1), + C(51b5fc6f) + }, + { + C(1addcf0386d35351), C(b5f436561f8f1484), C(85d38e22181c9bb1), C(ff5c03f003c1fefe), C(e1098670afe7ff6), C(ea445030cf86de19), C(f155c68b5c2967f8), + C(ff5c03f003c1fefe), C(e1098670afe7ff6), C(ea445030cf86de19), C(f155c68b5c2967f8), + C(95d31b145dbb2e9e), C(914fe1ca3deb3265), C(6066020b1358ccc1), C(c74bb7e2dee15036), + C(33d94752) + }, + { + C(d445ba84bf803e09), C(1216c2497038f804), C(2293216ea2237207), C(e2164451c651adfb), C(b2534e65477f9823), C(4d70691a69671e34), C(15be4963dbde8143), + C(e2164451c651adfb), C(b2534e65477f9823), C(4d70691a69671e34), C(15be4963dbde8143), + C(762e75c406c5e9a3), C(7b7579f7e0356841), C(480533eb066dfce5), C(90ae14ea6bfeb4ae), + C(b0c92948) + }, + { + C(37235a096a8be435), C(d9b73130493589c2), C(3b1024f59378d3be), C(ad159f542d81f04e), C(49626a97a946096), C(d8d3998bf09fd304), C(d127a411eae69459), + C(ad159f542d81f04e), C(49626a97a946096), C(d8d3998bf09fd304), C(d127a411eae69459), + C(8f3253c4eb785a7b), C(4049062f37e62397), C(b9fa04d3b670e5c1), C(1211a7967ac9350f), + C(c7171590) + }, + { + C(763ad6ea2fe1c99d), C(cf7af5368ac1e26b), C(4d5e451b3bb8d3d4), C(3712eb913d04e2f2), C(2f9500d319c84d89), C(4ac6eb21a8cf06f9), C(7d1917afcde42744), + C(3712eb913d04e2f2), C(2f9500d319c84d89), C(4ac6eb21a8cf06f9), C(7d1917afcde42744), + C(6b58604b5dd10903), C(c4288dfbc1e319fc), C(230f75ca96817c6e), C(8894cba3b763756c), + C(240a67fb) + }, + { + C(ea627fc84cd1b857), C(85e372494520071f), C(69ec61800845780b), C(a3c1c5ca1b0367), C(eb6933997272bb3d), C(76a72cb62692a655), C(140bb5531edf756e), + C(a3c1c5ca1b0367), C(eb6933997272bb3d), C(76a72cb62692a655), C(140bb5531edf756e), + C(8d0d8067d1c925f4), C(7b3fa56d8d77a10c), C(2bd00287b0946d88), C(f08c8e4bd65b8970), + C(e1843cd5) + }, + { + C(1f2ffd79f2cdc0c8), C(726a1bc31b337aaa), C(678b7f275ef96434), C(5aa82bfaa99d3978), C(c18f96cade5ce18d), C(38404491f9e34c03), C(891fb8926ba0418c), + C(5aa82bfaa99d3978), C(c18f96cade5ce18d), C(38404491f9e34c03), C(891fb8926ba0418c), + C(e5f69a6398114c15), C(7b8ded3623bc6b1d), C(2f3e5c5da5ff70e8), C(1ab142addea6a9ec), + C(fda1452b) + }, + { + C(39a9e146ec4b3210), C(f63f75802a78b1ac), C(e2e22539c94741c3), C(8b305d532e61226e), C(caeae80da2ea2e), C(88a6289a76ac684e), C(8ce5b5f9df1cbd85), + C(8b305d532e61226e), C(caeae80da2ea2e), C(88a6289a76ac684e), C(8ce5b5f9df1cbd85), + C(8ae1fc4798e00d57), C(e7164b8fb364fc46), C(6a978c9bd3a66943), C(ef10d5ae4dd08dc), + C(a2cad330) + }, + { + C(74cba303e2dd9d6d), C(692699b83289fad1), C(dfb9aa7874678480), C(751390a8a5c41bdc), C(6ee5fbf87605d34), C(6ca73f610f3a8f7c), C(e898b3c996570ad), + C(751390a8a5c41bdc), C(6ee5fbf87605d34), C(6ca73f610f3a8f7c), C(e898b3c996570ad), + C(98168a5858fc7110), C(6f987fa27aa0daa2), C(f25e3e180d4b36a3), C(d0b03495aeb1be8a), + C(53467e16) + }, + { + C(4cbc2b73a43071e0), C(56c5db4c4ca4e0b7), C(1b275a162f46bd3d), C(b87a326e413604bf), C(d8f9a5fa214b03ab), C(8a8bb8265771cf88), C(a655319054f6e70f), + C(b87a326e413604bf), C(d8f9a5fa214b03ab), C(8a8bb8265771cf88), C(a655319054f6e70f), + C(b499cb8e65a9af44), C(bee7fafcc8307491), C(5d2e55fa9b27cda2), C(63b120f5fb2d6ee5), + C(da14a8d0) + }, + { + C(875638b9715d2221), C(d9ba0615c0c58740), C(616d4be2dfe825aa), C(5df25f13ea7bc284), C(165edfaafd2598fb), C(af7215c5c718c696), C(e9f2f9ca655e769), + C(5df25f13ea7bc284), C(165edfaafd2598fb), C(af7215c5c718c696), C(e9f2f9ca655e769), + C(e459cfcb565d3d2d), C(41d032631be2418a), C(c505db05fd946f60), C(54990394a714f5de), + C(67333551) + }, + { + C(fb686b2782994a8d), C(edee60693756bb48), C(e6bc3cae0ded2ef5), C(58eb4d03b2c3ddf5), C(6d2542995f9189f1), C(c0beec58a5f5fea2), C(ed67436f42e2a78b), + C(58eb4d03b2c3ddf5), C(6d2542995f9189f1), C(c0beec58a5f5fea2), C(ed67436f42e2a78b), + C(dfec763cdb2b5193), C(724a8d5345bd2d6), C(94d4fd1b81457c23), C(28e87c50cdede453), + C(a0ebd66e) + }, + { + C(ab21d81a911e6723), C(4c31b07354852f59), C(835da384c9384744), C(7f759dddc6e8549a), C(616dd0ca022c8735), C(94717ad4bc15ceb3), C(f66c7be808ab36e), + C(7f759dddc6e8549a), C(616dd0ca022c8735), C(94717ad4bc15ceb3), C(f66c7be808ab36e), + C(af8286b550b2f4b7), C(745bd217d20a9f40), C(c73bfb9c5430f015), C(55e65922666e3fc2), + C(4b769593) + }, + { + C(33d013cc0cd46ecf), C(3de726423aea122c), C(116af51117fe21a9), C(f271ba474edc562d), C(e6596e67f9dd3ebd), C(c0a288edf808f383), C(b3def70681c6babc), + C(f271ba474edc562d), C(e6596e67f9dd3ebd), C(c0a288edf808f383), C(b3def70681c6babc), + C(7da7864e9989b095), C(bf2f8718693cd8a1), C(264a9144166da776), C(61ad90676870beb6), + C(6aa75624) + }, + { + C(8ca92c7cd39fae5d), C(317e620e1bf20f1), C(4f0b33bf2194b97f), C(45744afcf131dbee), C(97222392c2559350), C(498a19b280c6d6ed), C(83ac2c36acdb8d49), + C(45744afcf131dbee), C(97222392c2559350), C(498a19b280c6d6ed), C(83ac2c36acdb8d49), + C(7a69645c294daa62), C(abe9d2be8275b3d2), C(39542019de371085), C(7f4efac8488cd6ad), + C(602a3f96) + }, + { + C(fdde3b03f018f43e), C(38f932946c78660), C(c84084ce946851ee), C(b6dd09ba7851c7af), C(570de4e1bb13b133), C(c4e784eb97211642), C(8285a7fcdcc7c58d), + C(b6dd09ba7851c7af), C(570de4e1bb13b133), C(c4e784eb97211642), C(8285a7fcdcc7c58d), + C(d421f47990da899b), C(8aed409c997eaa13), C(7a045929c2e29ccf), C(b373682a6202c86b), + C(cd183c4d) + }, + { + C(9c8502050e9c9458), C(d6d2a1a69964beb9), C(1675766f480229b5), C(216e1d6c86cb524c), C(d01cf6fd4f4065c0), C(fffa4ec5b482ea0f), C(a0e20ee6a5404ac1), + C(216e1d6c86cb524c), C(d01cf6fd4f4065c0), C(fffa4ec5b482ea0f), C(a0e20ee6a5404ac1), + C(c1b037e4eebaf85e), C(634e3d7c3ebf89eb), C(bcda972358c67d1), C(fd1352181e5b8578), + C(960a4d07) + }, + { + C(348176ca2fa2fdd2), C(3a89c514cc360c2d), C(9f90b8afb318d6d0), C(bceee07c11a9ac30), C(2e2d47dff8e77eb7), C(11a394cd7b6d614a), C(1d7c41d54e15cb4a), + C(bceee07c11a9ac30), C(2e2d47dff8e77eb7), C(11a394cd7b6d614a), C(1d7c41d54e15cb4a), + C(15baa5ae7312b0fc), C(f398f596cc984635), C(8ab8fdf87a6788e8), C(b2b5c1234ab47e2), + C(9ae998c4) + }, + { + C(4a3d3dfbbaea130b), C(4e221c920f61ed01), C(553fd6cd1304531f), C(bd2b31b5608143fe), C(ab717a10f2554853), C(293857f04d194d22), C(d51be8fa86f254f0), + C(bd2b31b5608143fe), C(ab717a10f2554853), C(293857f04d194d22), C(d51be8fa86f254f0), + C(1eee39e07686907e), C(639039fe0e8d3052), C(d6ec1470cef97ff), C(370c82b860034f0f), + C(74e2179d) + }, + { + C(b371f768cdf4edb9), C(bdef2ace6d2de0f0), C(e05b4100f7f1baec), C(b9e0d415b4ebd534), C(c97c2a27efaa33d7), C(591cdb35f84ef9da), C(a57d02d0e8e3756c), + C(b9e0d415b4ebd534), C(c97c2a27efaa33d7), C(591cdb35f84ef9da), C(a57d02d0e8e3756c), + C(23f55f12d7c5c87b), C(4c7ca0fe23221101), C(dbc3020480334564), C(d985992f32c236b1), + C(ee9bae25) + }, + { + C(7a1d2e96934f61f), C(eb1760ae6af7d961), C(887eb0da063005df), C(2228d6725e31b8ab), C(9b98f7e4d0142e70), C(b6a8c2115b8e0fe7), C(b591e2f5ab9b94b1), + C(2228d6725e31b8ab), C(9b98f7e4d0142e70), C(b6a8c2115b8e0fe7), C(b591e2f5ab9b94b1), + C(6c1feaa8065318e0), C(4e7e2ca21c2e81fb), C(e9fe5d8ce7993c45), C(ee411fa2f12cf8df), + C(b66edf10) + }, + { + C(8be53d466d4728f2), C(86a5ac8e0d416640), C(984aa464cdb5c8bb), C(87049e68f5d38e59), C(7d8ce44ec6bd7751), C(cc28d08ab414839c), C(6c8f0bd34fe843e3), + C(87049e68f5d38e59), C(7d8ce44ec6bd7751), C(cc28d08ab414839c), C(6c8f0bd34fe843e3), + C(b8496dcdc01f3e47), C(2f03125c282ac26), C(82a8797ba3f5ef07), C(7c977a4d10bf52b8), + C(d6209737) + }, + { + C(829677eb03abf042), C(43cad004b6bc2c0), C(f2f224756803971a), C(98d0dbf796480187), C(fbcb5f3e1bef5742), C(5af2a0463bf6e921), C(ad9555bf0120b3a3), + C(98d0dbf796480187), C(fbcb5f3e1bef5742), C(5af2a0463bf6e921), C(ad9555bf0120b3a3), + C(283e39b3dc99f447), C(bedaa1a4a0250c28), C(9d50546624ff9a57), C(4abaf523d1c090f6), + C(b994a88) + }, + { + C(754435bae3496fc), C(5707fc006f094dcf), C(8951c86ab19d8e40), C(57c5208e8f021a77), C(f7653fbb69cd9276), C(a484410af21d75cb), C(f19b6844b3d627e8), + C(57c5208e8f021a77), C(f7653fbb69cd9276), C(a484410af21d75cb), C(f19b6844b3d627e8), + C(f37400fc3ffd9514), C(36ae0d821734edfd), C(5f37820af1f1f306), C(be637d40e6a5ad0), + C(a05d43c0) + }, + { + C(fda9877ea8e3805f), C(31e868b6ffd521b7), C(b08c90681fb6a0fd), C(68110a7f83f5d3ff), C(6d77e045901b85a8), C(84ef681113036d8b), C(3b9f8e3928f56160), + C(68110a7f83f5d3ff), C(6d77e045901b85a8), C(84ef681113036d8b), C(3b9f8e3928f56160), + C(fc8b7f56c130835), C(a11f3e800638e841), C(d9572267f5cf28c1), C(7897c8149803f2aa), + C(c79f73a8) + }, + { + C(2e36f523ca8f5eb5), C(8b22932f89b27513), C(331cd6ecbfadc1bb), C(d1bfe4df12b04cbf), C(f58c17243fd63842), C(3a453cdba80a60af), C(5737b2ca7470ea95), + C(d1bfe4df12b04cbf), C(f58c17243fd63842), C(3a453cdba80a60af), C(5737b2ca7470ea95), + C(54d44a3f4477030c), C(8168e02d4869aa7f), C(77f383a17778559d), C(95e1737d77a268fc), + C(a490aff5) + }, + { + C(21a378ef76828208), C(a5c13037fa841da2), C(506d22a53fbe9812), C(61c9c95d91017da5), C(16f7c83ba68f5279), C(9c0619b0808d05f7), C(83c117ce4e6b70a3), + C(61c9c95d91017da5), C(16f7c83ba68f5279), C(9c0619b0808d05f7), C(83c117ce4e6b70a3), + C(cfb4c8af7fd01413), C(fdef04e602e72296), C(ed6124d337889b1), C(4919c86707b830da), + C(dfad65b4) + }, + { + C(ccdd5600054b16ca), C(f78846e84204cb7b), C(1f9faec82c24eac9), C(58634004c7b2d19a), C(24bb5f51ed3b9073), C(46409de018033d00), C(4a9805eed5ac802e), + C(58634004c7b2d19a), C(24bb5f51ed3b9073), C(46409de018033d00), C(4a9805eed5ac802e), + C(e18de8db306baf82), C(46bbf75f1fa025ff), C(5faf2fb09be09487), C(3fbc62bd4e558fb3), + C(1d07dfb) + }, + { + C(7854468f4e0cabd0), C(3a3f6b4f098d0692), C(ae2423ec7799d30d), C(29c3529eb165eeba), C(443de3703b657c35), C(66acbce31ae1bc8d), C(1acc99effe1d547e), + C(29c3529eb165eeba), C(443de3703b657c35), C(66acbce31ae1bc8d), C(1acc99effe1d547e), + C(cf07f8a57906573d), C(31bafb0bbb9a86e7), C(40c69492702a9346), C(7df61fdaa0b858af), + C(416df9a0) + }, + { + C(7f88db5346d8f997), C(88eac9aacc653798), C(68a4d0295f8eefa1), C(ae59ca86f4c3323d), C(25906c09906d5c4c), C(8dd2aa0c0a6584ae), C(232a7d96b38f40e9), + C(ae59ca86f4c3323d), C(25906c09906d5c4c), C(8dd2aa0c0a6584ae), C(232a7d96b38f40e9), + C(8986ee00a2ed0042), C(c49ae7e428c8a7d1), C(b7dd8280713ac9c2), C(e018720aed1ebc28), + C(1f8fb9cc) + }, + { + C(bb3fb5fb01d60fcf), C(1b7cc0847a215eb6), C(1246c994437990a1), C(d4edc954c07cd8f3), C(224f47e7c00a30ab), C(d5ad7ad7f41ef0c6), C(59e089281d869fd7), + C(d4edc954c07cd8f3), C(224f47e7c00a30ab), C(d5ad7ad7f41ef0c6), C(59e089281d869fd7), + C(f29340d07a14b6f1), C(c87c5ef76d9c4ef3), C(463118794193a9a), C(2922dcb0540f0dbc), + C(7abf48e3) + }, + { + C(2e783e1761acd84d), C(39158042bac975a0), C(1cd21c5a8071188d), C(b1b7ec44f9302176), C(5cb476450dc0c297), C(dc5ef652521ef6a2), C(3cc79a9e334e1f84), + C(b1b7ec44f9302176), C(5cb476450dc0c297), C(dc5ef652521ef6a2), C(3cc79a9e334e1f84), + C(769e2a283dbcc651), C(9f24b105c8511d3f), C(c31c15575de2f27e), C(ecfecf32c3ae2d66), + C(dea4e3dd) + }, + { + C(392058251cf22acc), C(944ec4475ead4620), C(b330a10b5cb94166), C(54bc9bee7cbe1767), C(485820bdbe442431), C(54d6120ea2972e90), C(f437a0341f29b72a), + C(54bc9bee7cbe1767), C(485820bdbe442431), C(54d6120ea2972e90), C(f437a0341f29b72a), + C(8f30885c784d5704), C(aa95376b16c7906a), C(e826928cfaf93dc3), C(20e8f54d1c16d7d8), + C(c6064f22) + }, + { + C(adf5c1e5d6419947), C(2a9747bc659d28aa), C(95c5b8cb1f5d62c), C(80973ea532b0f310), C(a471829aa9c17dd9), C(c2ff3479394804ab), C(6bf44f8606753636), + C(80973ea532b0f310), C(a471829aa9c17dd9), C(c2ff3479394804ab), C(6bf44f8606753636), + C(5184d2973e6dd827), C(121b96369a332d9a), C(5c25d3475ab69e50), C(26d2961d62884168), + C(743bed9c) + }, + { + C(6bc1db2c2bee5aba), C(e63b0ed635307398), C(7b2eca111f30dbbc), C(230d2b3e47f09830), C(ec8624a821c1caf4), C(ea6ec411cdbf1cb1), C(5f38ae82af364e27), + C(230d2b3e47f09830), C(ec8624a821c1caf4), C(ea6ec411cdbf1cb1), C(5f38ae82af364e27), + C(a519ef515ea7187c), C(6bad5efa7ebae05f), C(748abacb11a74a63), C(a28eef963d1396eb), + C(fce254d5) + }, + { + C(b00f898229efa508), C(83b7590ad7f6985c), C(2780e70a0592e41d), C(7122413bdbc94035), C(e7f90fae33bf7763), C(4b6bd0fb30b12387), C(557359c0c44f48ca), + C(7122413bdbc94035), C(e7f90fae33bf7763), C(4b6bd0fb30b12387), C(557359c0c44f48ca), + C(d5656c3d6bc5f0d), C(983ff8e5e784da99), C(628479671b445bf), C(e179a1e27ce68f5d), + C(e47ec9d1) + }, + { + C(b56eb769ce0d9a8c), C(ce196117bfbcaf04), C(b26c3c3797d66165), C(5ed12338f630ab76), C(fab19fcb319116d), C(167f5f42b521724b), C(c4aa56c409568d74), + C(5ed12338f630ab76), C(fab19fcb319116d), C(167f5f42b521724b), C(c4aa56c409568d74), + C(75fff4b42f8e9778), C(94218f94710c1ea3), C(b7b05efb738b06a6), C(83fff2deabf9cd3), + C(334a145c) + }, + { + C(70c0637675b94150), C(259e1669305b0a15), C(46e1dd9fd387a58d), C(fca4e5bc9292788e), C(cd509dc1facce41c), C(bbba575a59d82fe), C(4e2e71c15b45d4d3), + C(fca4e5bc9292788e), C(cd509dc1facce41c), C(bbba575a59d82fe), C(4e2e71c15b45d4d3), + C(5dc54582ead999c), C(72612d1571963c6f), C(30318a9d2d3d1829), C(785dd00f4cc9c9a0), + C(adec1e3c) + }, + { + C(74c0b8a6821faafe), C(abac39d7491370e7), C(faf0b2a48a4e6aed), C(967e970df9673d2a), C(d465247cffa415c0), C(33a1df0ca1107722), C(49fc2a10adce4a32), + C(967e970df9673d2a), C(d465247cffa415c0), C(33a1df0ca1107722), C(49fc2a10adce4a32), + C(c5707e079a284308), C(573028266635dda6), C(f786f5eee6127fa0), C(b30d79cebfb51266), + C(f6a9fbf8) + }, + { + C(5fb5e48ac7b7fa4f), C(a96170f08f5acbc7), C(bbf5c63d4f52a1e5), C(6cc09e60700563e9), C(d18f23221e964791), C(ffc23eeef7af26eb), C(693a954a3622a315), + C(815308a32a9b0daf), C(efb2ab27bf6fd0bd), C(9f1ffc0986111118), C(f9a3aa1778ea3985), + C(698fe54b2b93933b), C(dacc2b28404d0f10), C(815308a32a9b0daf), C(efb2ab27bf6fd0bd), + C(5398210c) + }, }; -void Check(uint64 expected, uint64 actual) { - if (expected != actual) { - cerr << "ERROR: expected 0x" << hex << expected << ", but got 0x" << actual << "\n"; - ++errors; - } +void Check(uint64 expected, uint64 actual) +{ + if (expected != actual) + { + cerr << "ERROR: expected 0x" << hex << expected << ", but got 0x" << actual << "\n"; + ++errors; + } } -void Test(const uint64* expected, int offset, int len) { - const uint128 u = CityHash128(data + offset, len); - const uint128 v = CityHash128WithSeed(data + offset, len, kSeed128); - Check(expected[0], CityHash64(data + offset, len)); - Check(expected[15], CityHash32(data + offset, len)); - Check(expected[1], CityHash64WithSeed(data + offset, len, kSeed0)); - Check(expected[2], CityHash64WithSeeds(data + offset, len, kSeed0, kSeed1)); - Check(expected[3], Uint128Low64(u)); - Check(expected[4], Uint128High64(u)); - Check(expected[5], Uint128Low64(v)); - Check(expected[6], Uint128High64(v)); +void Test(const uint64 *expected, int offset, int len) +{ + const uint128 u = CityHash128(data + offset, len); + const uint128 v = CityHash128WithSeed(data + offset, len, kSeed128); + Check(expected[0], CityHash64(data + offset, len)); + Check(expected[15], CityHash32(data + offset, len)); + Check(expected[1], CityHash64WithSeed(data + offset, len, kSeed0)); + Check(expected[2], CityHash64WithSeeds(data + offset, len, kSeed0, kSeed1)); + Check(expected[3], Uint128Low64(u)); + Check(expected[4], Uint128High64(u)); + Check(expected[5], Uint128Low64(v)); + Check(expected[6], Uint128High64(v)); #ifdef __SSE4_2__ - const uint128 y = CityHashCrc128(data + offset, len); - const uint128 z = CityHashCrc128WithSeed(data + offset, len, kSeed128); - uint64 crc256_results[4]; - CityHashCrc256(data + offset, len, crc256_results); - Check(expected[7], Uint128Low64(y)); - Check(expected[8], Uint128High64(y)); - Check(expected[9], Uint128Low64(z)); - Check(expected[10], Uint128High64(z)); - for (int i = 0; i < 4; i++) { - Check(expected[11 + i], crc256_results[i]); - } + const uint128 y = CityHashCrc128(data + offset, len); + const uint128 z = CityHashCrc128WithSeed(data + offset, len, kSeed128); + uint64 crc256_results[4]; + CityHashCrc256(data + offset, len, crc256_results); + Check(expected[7], Uint128Low64(y)); + Check(expected[8], Uint128High64(y)); + Check(expected[9], Uint128Low64(z)); + Check(expected[10], Uint128High64(z)); + for (int i = 0; i < 4; i++) + { + Check(expected[11 + i], crc256_results[i]); + } #endif } #else #define Test(a, b, c) Dump((b), (c)) -void Dump(int offset, int len) { - const uint128 u = CityHash128(data + offset, len); - const uint128 v = CityHash128WithSeed(data + offset, len, kSeed128); - const uint128 y = CityHashCrc128(data + offset, len); - const uint128 z = CityHashCrc128WithSeed(data + offset, len, kSeed128); - uint64 crc256_results[4]; - CityHashCrc256(data + offset, len, crc256_results); - cout << hex - << "{C(" << CityHash64(data + offset, len) << "), " - << "C(" << CityHash64WithSeed(data + offset, len, kSeed0) << "), " - << "C(" << CityHash64WithSeeds(data + offset, len, kSeed0, kSeed1) << "), " - << "C(" << Uint128Low64(u) << "), " - << "C(" << Uint128High64(u) << "), " - << "C(" << Uint128Low64(v) << "), " - << "C(" << Uint128High64(v) << "),\n" - << "C(" << Uint128Low64(y) << "), " - << "C(" << Uint128High64(y) << "), " - << "C(" << Uint128Low64(z) << "), " - << "C(" << Uint128High64(z) << "),\n"; - for (int i = 0; i < 4; i++) { - cout << hex << "C(" << crc256_results[i] << (i == 3 ? "),\n" : "), "); - } - cout << "C(" << CityHash32(data + offset, len) << ")},\n"; +void Dump(int offset, int len) +{ + const uint128 u = CityHash128(data + offset, len); + const uint128 v = CityHash128WithSeed(data + offset, len, kSeed128); + const uint128 y = CityHashCrc128(data + offset, len); + const uint128 z = CityHashCrc128WithSeed(data + offset, len, kSeed128); + uint64 crc256_results[4]; + CityHashCrc256(data + offset, len, crc256_results); + cout << hex + << "{C(" << CityHash64(data + offset, len) << "), " + << "C(" << CityHash64WithSeed(data + offset, len, kSeed0) << "), " + << "C(" << CityHash64WithSeeds(data + offset, len, kSeed0, kSeed1) << "), " + << "C(" << Uint128Low64(u) << "), " + << "C(" << Uint128High64(u) << "), " + << "C(" << Uint128Low64(v) << "), " + << "C(" << Uint128High64(v) << "),\n" + << "C(" << Uint128Low64(y) << "), " + << "C(" << Uint128High64(y) << "), " + << "C(" << Uint128Low64(z) << "), " + << "C(" << Uint128High64(z) << "),\n"; + for (int i = 0; i < 4; i++) + { + cout << hex << "C(" << crc256_results[i] << (i == 3 ? "),\n" : "), "); + } + cout << "C(" << CityHash32(data + offset, len) << ")},\n"; } #endif -int main(int argc, char** argv) { - setup(); - int i = 0; - for ( ; i < kTestSize - 1; i++) { - Test(testdata[i], i * i, i); - } - Test(testdata[i], 0, kDataSize); - return errors > 0; +int main(int argc, char **argv) +{ + setup(); + int i = 0; + for ( ; i < kTestSize - 1; i++) + { + Test(testdata[i], i * i, i); + } + Test(testdata[i], 0, kDataSize); + return errors > 0; } diff --git a/client/c.cc b/client/c.cc index 2a49c556d..86794d37f 100644 --- a/client/c.cc +++ b/client/c.cc @@ -43,2317 +43,2314 @@ #define FAKE_STATUS hyperdex_client_returncode _status; hyperdex_client_returncode* status = &_status #define SIGNAL_PROTECT_ERR(X) \ - sigset_t old_sigs; \ - sigset_t all_sigs; \ - sigfillset(&all_sigs); \ - if (pthread_sigmask(SIG_BLOCK, &all_sigs, &old_sigs) < 0) \ - { \ - *status = HYPERDEX_CLIENT_INTERNAL; \ - return (X); \ - } \ - e::guard g = e::makeguard(pthread_sigmask, SIG_SETMASK, (sigset_t*)&old_sigs, (sigset_t*)NULL) + sigset_t old_sigs; \ + sigset_t all_sigs; \ + sigfillset(&all_sigs); \ + if (pthread_sigmask(SIG_BLOCK, &all_sigs, &old_sigs) < 0) \ + { \ + *status = HYPERDEX_CLIENT_INTERNAL; \ + return (X); \ + } \ + e::guard g = e::makeguard(pthread_sigmask, SIG_SETMASK, (sigset_t*)&old_sigs, (sigset_t*)NULL) #define SIGNAL_PROTECT SIGNAL_PROTECT_ERR(-1); inline void return_void() {} #define SIGNAL_PROTECT_VOID SIGNAL_PROTECT_ERR(return_void()); #define C_WRAP_EXCEPT(X) \ - hyperdex::client* cl = reinterpret_cast(_cl); \ - SIGNAL_PROTECT; \ - try \ - { \ - X \ - } \ - catch (std::bad_alloc& ba) \ - { \ - errno = ENOMEM; \ - *status = HYPERDEX_CLIENT_NOMEM; \ - cl->set_error_message("out of memory"); \ - return -1; \ - } \ - catch (...) \ - { \ - *status = HYPERDEX_CLIENT_EXCEPTION; \ - cl->set_error_message("unhandled exception was thrown"); \ - return -1; \ - } \ + hyperdex::client* cl = reinterpret_cast(_cl); \ + SIGNAL_PROTECT; \ + try \ + { \ + X \ + } \ + catch (std::bad_alloc& ba) \ + { \ + errno = ENOMEM; \ + *status = HYPERDEX_CLIENT_NOMEM; \ + cl->set_error_message("out of memory"); \ + return -1; \ + } \ + catch (...) \ + { \ + *status = HYPERDEX_CLIENT_EXCEPTION; \ + cl->set_error_message("unhandled exception was thrown"); \ + return -1; \ + } \ #ifdef __cplusplus -extern "C" -{ + extern "C" + { #endif // __cplusplus -HYPERDEX_API hyperdex_client* -hyperdex_client_create(const char* coordinator, uint16_t port) -{ - FAKE_STATUS; - SIGNAL_PROTECT_ERR(NULL); - try - { - return reinterpret_cast(new hyperdex::client(coordinator, port)); - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - return NULL; - } - catch (...) - { - return NULL; - } -} - -HYPERDEX_API hyperdex_client* -hyperdex_client_create_conn_str(const char* conn_str) -{ - FAKE_STATUS; - SIGNAL_PROTECT_ERR(NULL); - try - { - return reinterpret_cast(new hyperdex::client(conn_str)); - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - return NULL; - } - catch (...) - { - return NULL; - } -} - -HYPERDEX_API void -hyperdex_client_destroy(hyperdex_client* client) -{ - delete reinterpret_cast(client); -} - -HYPERDEX_API const char* -hyperdex_client_error_message(hyperdex_client* _cl) -{ - FAKE_STATUS; - SIGNAL_PROTECT_ERR(NULL); - hyperdex::client* cl = reinterpret_cast(_cl); - return cl->error_message(); -} - -HYPERDEX_API const char* -hyperdex_client_error_location(hyperdex_client* _cl) -{ - FAKE_STATUS; - SIGNAL_PROTECT_ERR(NULL); - hyperdex::client* cl = reinterpret_cast(_cl); - return cl->error_location(); -} - -HYPERDEX_API const char* -hyperdex_client_returncode_to_string(enum hyperdex_client_returncode stat) -{ - FAKE_STATUS; - SIGNAL_PROTECT_ERR(NULL); - switch (stat) - { - CSTRINGIFY(HYPERDEX_CLIENT_SUCCESS); - CSTRINGIFY(HYPERDEX_CLIENT_NOTFOUND); - CSTRINGIFY(HYPERDEX_CLIENT_SEARCHDONE); - CSTRINGIFY(HYPERDEX_CLIENT_CMPFAIL); - CSTRINGIFY(HYPERDEX_CLIENT_READONLY); - CSTRINGIFY(HYPERDEX_CLIENT_UNKNOWNSPACE); - CSTRINGIFY(HYPERDEX_CLIENT_COORDFAIL); - CSTRINGIFY(HYPERDEX_CLIENT_SERVERERROR); - CSTRINGIFY(HYPERDEX_CLIENT_POLLFAILED); - CSTRINGIFY(HYPERDEX_CLIENT_OVERFLOW); - CSTRINGIFY(HYPERDEX_CLIENT_RECONFIGURE); - CSTRINGIFY(HYPERDEX_CLIENT_TIMEOUT); - CSTRINGIFY(HYPERDEX_CLIENT_UNKNOWNATTR); - CSTRINGIFY(HYPERDEX_CLIENT_DUPEATTR); - CSTRINGIFY(HYPERDEX_CLIENT_NONEPENDING); - CSTRINGIFY(HYPERDEX_CLIENT_DONTUSEKEY); - CSTRINGIFY(HYPERDEX_CLIENT_WRONGTYPE); - CSTRINGIFY(HYPERDEX_CLIENT_NOMEM); - CSTRINGIFY(HYPERDEX_CLIENT_INTERRUPTED); - CSTRINGIFY(HYPERDEX_CLIENT_CLUSTER_JUMP); - CSTRINGIFY(HYPERDEX_CLIENT_OFFLINE); - CSTRINGIFY(HYPERDEX_CLIENT_UNAUTHORIZED); - CSTRINGIFY(HYPERDEX_CLIENT_INTERNAL); - CSTRINGIFY(HYPERDEX_CLIENT_EXCEPTION); - CSTRINGIFY(HYPERDEX_CLIENT_GARBAGE); - default: - return "unknown hyperdex_client_returncode"; - } -} - -HYPERDEX_API enum hyperdatatype -hyperdex_client_attribute_type(hyperdex_client* _cl, - const char* space, const char* name, - enum hyperdex_client_returncode* status) -{ - SIGNAL_PROTECT_ERR(HYPERDATATYPE_GARBAGE); - hyperdex::client* cl = reinterpret_cast(_cl); \ - - try - { - return cl->attribute_type(space, name, status); - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - *status = HYPERDEX_CLIENT_NOMEM; - cl->set_error_message("out of memory"); - return HYPERDATATYPE_GARBAGE; - } - catch (...) - { - *status = HYPERDEX_CLIENT_EXCEPTION; - cl->set_error_message("unhandled exception was thrown"); - return HYPERDATATYPE_GARBAGE; - } -} - -HYPERDEX_API void -hyperdex_client_destroy_attrs(const hyperdex_client_attribute* attrs, size_t /*attrs_sz*/) -{ - FAKE_STATUS; - SIGNAL_PROTECT_VOID; - if (attrs) { - free(const_cast(attrs)); - attrs = NULL; - } -} - -HYPERDEX_API void -hyperdex_client_clear_auth_context(struct hyperdex_client* _cl) -{ - FAKE_STATUS; - SIGNAL_PROTECT_VOID; - hyperdex::client* cl = reinterpret_cast(_cl); - cl->clear_auth_context(); -} - -HYPERDEX_API void -hyperdex_client_set_auth_context(struct hyperdex_client* _cl, - const char** macaroons, size_t macaroons_sz) -{ - FAKE_STATUS; - SIGNAL_PROTECT_VOID; - hyperdex::client* cl = reinterpret_cast(_cl); - cl->set_auth_context(macaroons, macaroons_sz); -} - -HYPERDEX_API struct hyperdex_client_microtransaction* -hyperdex_client_uxact_init(struct hyperdex_client* _cl, - const char* space, - enum hyperdex_client_returncode *status) -{ - - SIGNAL_PROTECT_ERR(NULL); - hyperdex::client *cl = reinterpret_cast(_cl); - hyperdex::microtransaction *tx = cl->uxact_init(space, status); - - return reinterpret_cast(tx); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_commit(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction *transaction, - const char* key, size_t key_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(transaction); - hyperdex_client_returncode *status = tx->status; - - C_WRAP_EXCEPT( - return cl->uxact_commit(tx, key, key_sz); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_group_commit(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction *transaction, - const hyperdex_client_attribute_check *chks, size_t chks_sz, - uint64_t *count) -{ - hyperdex::microtransaction* tx = reinterpret_cast(transaction); - hyperdex_client_returncode *status = tx->status; - - C_WRAP_EXCEPT( - return cl->uxact_group_commit(tx, chks, chks_sz, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_cond_commit(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction *transaction, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check *chks, size_t chks_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(transaction); - hyperdex_client_returncode *status = tx->status; - - C_WRAP_EXCEPT( - return cl->uxact_cond_commit(tx, key, key_sz, chks, chks_sz); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_get(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - enum hyperdex_client_returncode* status, - const struct hyperdex_client_attribute** attrs, size_t* attrs_sz) -{ - C_WRAP_EXCEPT( - return cl->get(space, key, key_sz, status, attrs, attrs_sz); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_get_partial(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const char** attrnames, size_t attrnames_sz, - enum hyperdex_client_returncode* status, - const struct hyperdex_client_attribute** attrs, size_t* attrs_sz) -{ - C_WRAP_EXCEPT( - return cl->get_partial(space, key, key_sz, attrnames, attrnames_sz, status, attrs, attrs_sz); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_put(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(put), strlen(XSTR(put))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_put(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(put), strlen(XSTR(put))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_put(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_put), strlen(XSTR(cond_put))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_put_or_create(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_put_or_create), strlen(XSTR(cond_put_or_create))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_put(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_put), strlen(XSTR(group_put))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_put_if_not_exist(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(put_if_not_exist), strlen(XSTR(put_if_not_exist))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_del(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(del), strlen(XSTR(del))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_del(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_del), strlen(XSTR(cond_del))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_del(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_del), strlen(XSTR(group_del))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_atomic_add(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_add), strlen(XSTR(atomic_add))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_atomic_add(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_add), strlen(XSTR(atomic_add))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_atomic_add(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_add), strlen(XSTR(cond_atomic_add))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_atomic_add(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_add), strlen(XSTR(group_atomic_add))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_atomic_sub(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_sub), strlen(XSTR(atomic_sub))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_atomic_sub(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_sub), strlen(XSTR(atomic_sub))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_atomic_sub(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_sub), strlen(XSTR(cond_atomic_sub))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_atomic_sub(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_sub), strlen(XSTR(group_atomic_sub))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_atomic_mul(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_mul), strlen(XSTR(atomic_mul))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_atomic_mul(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_mul), strlen(XSTR(atomic_mul))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_atomic_mul(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_mul), strlen(XSTR(cond_atomic_mul))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_atomic_mul(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_mul), strlen(XSTR(group_atomic_mul))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_atomic_div(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_div), strlen(XSTR(atomic_div))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_atomic_div(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_div), strlen(XSTR(atomic_div))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_atomic_div(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_div), strlen(XSTR(cond_atomic_div))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_atomic_div(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_div), strlen(XSTR(group_atomic_div))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_atomic_mod(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_mod), strlen(XSTR(atomic_mod))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_atomic_mod(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_mod), strlen(XSTR(cond_atomic_mod))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_atomic_mod(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_mod), strlen(XSTR(group_atomic_mod))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_atomic_and(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_and), strlen(XSTR(atomic_and))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_atomic_and(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_and), strlen(XSTR(atomic_and))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_atomic_and(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_and), strlen(XSTR(cond_atomic_and))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_atomic_and(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_and), strlen(XSTR(group_atomic_and))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_atomic_or(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_or), strlen(XSTR(atomic_or))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_atomic_or(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_or), strlen(XSTR(atomic_or))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_atomic_or(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_or), strlen(XSTR(cond_atomic_or))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_atomic_or(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_or), strlen(XSTR(group_atomic_or))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_atomic_xor(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_xor), strlen(XSTR(atomic_xor))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_atomic_xor(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_xor), strlen(XSTR(cond_atomic_xor))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_atomic_xor(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_xor), strlen(XSTR(group_atomic_xor))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_atomic_min(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_min), strlen(XSTR(atomic_min))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_atomic_min(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_min), strlen(XSTR(cond_atomic_min))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_atomic_min(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_min), strlen(XSTR(group_atomic_min))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_atomic_max(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_max), strlen(XSTR(atomic_max))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_atomic_max(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_max), strlen(XSTR(cond_atomic_max))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_atomic_max(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_max), strlen(XSTR(group_atomic_max))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_string_prepend(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_prepend), strlen(XSTR(string_prepend))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_string_prepend(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_prepend), strlen(XSTR(string_prepend))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_string_prepend(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_string_prepend), strlen(XSTR(cond_string_prepend))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_string_prepend(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_string_prepend), strlen(XSTR(group_string_prepend))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_string_append(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_append), strlen(XSTR(string_append))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_string_append(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_append), strlen(XSTR(string_append))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_string_append(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_string_append), strlen(XSTR(cond_string_append))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_string_append(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_string_append), strlen(XSTR(group_string_append))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_string_ltrim(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_ltrim), strlen(XSTR(string_ltrim))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_string_ltrim(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_ltrim), strlen(XSTR(string_ltrim))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_string_ltrim(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_string_ltrim), strlen(XSTR(cond_string_ltrim))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_string_ltrim(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_string_ltrim), strlen(XSTR(group_string_ltrim))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_string_rtrim(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_rtrim), strlen(XSTR(string_rtrim))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_string_rtrim(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_rtrim), strlen(XSTR(string_rtrim))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_string_rtrim(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_string_rtrim), strlen(XSTR(cond_string_rtrim))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_string_rtrim(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_string_rtrim), strlen(XSTR(group_string_rtrim))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_list_lpush(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(list_lpush), strlen(XSTR(list_lpush))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_list_lpush(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(list_lpush), strlen(XSTR(list_lpush))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_list_lpush(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_list_lpush), strlen(XSTR(cond_list_lpush))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_list_lpush(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_list_lpush), strlen(XSTR(group_list_lpush))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_list_rpush(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(list_rpush), strlen(XSTR(list_rpush))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_list_rpush(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(list_rpush), strlen(XSTR(list_rpush))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_list_rpush(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_list_rpush), strlen(XSTR(cond_list_rpush))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_list_rpush(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_list_rpush), strlen(XSTR(group_list_rpush))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_set_add(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(set_add), strlen(XSTR(set_add))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_set_add(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_set_add), strlen(XSTR(cond_set_add))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_set_add(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_set_add), strlen(XSTR(group_set_add))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_set_remove(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(set_remove), strlen(XSTR(set_remove))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_set_remove(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_set_remove), strlen(XSTR(cond_set_remove))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_set_remove(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_set_remove), strlen(XSTR(group_set_remove))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_set_intersect(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(set_intersect), strlen(XSTR(set_intersect))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_set_intersect(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_set_intersect), strlen(XSTR(cond_set_intersect))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_set_intersect(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_set_intersect), strlen(XSTR(group_set_intersect))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_set_union(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(set_union), strlen(XSTR(set_union))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_set_union(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_set_union), strlen(XSTR(cond_set_union))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_set_union(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_set_union), strlen(XSTR(group_set_union))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_document_rename(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(document_rename), strlen(XSTR(document_rename))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_document_rename(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(document_rename), strlen(XSTR(document_rename))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_document_rename(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_document_rename), strlen(XSTR(cond_document_rename))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_document_rename(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_document_rename), strlen(XSTR(group_document_rename))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_document_unset(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(document_unset), strlen(XSTR(document_unset))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_document_unset(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(document_unset), strlen(XSTR(document_unset))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_document_unset(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_document_unset), strlen(XSTR(cond_document_unset))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_document_unset(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_document_unset), strlen(XSTR(group_document_unset))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_map_add(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_add), strlen(XSTR(map_add))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_map_add(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_add), strlen(XSTR(cond_map_add))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_map_add(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_add), strlen(XSTR(group_map_add))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_map_remove(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_remove), strlen(XSTR(map_remove))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_map_remove(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_remove), strlen(XSTR(cond_map_remove))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_map_remove(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_remove), strlen(XSTR(group_map_remove))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_map_atomic_add(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_add), strlen(XSTR(map_atomic_add))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_map_atomic_add(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_add), strlen(XSTR(cond_map_atomic_add))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_map_atomic_add(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_add), strlen(XSTR(group_map_atomic_add))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_map_atomic_sub(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_sub), strlen(XSTR(map_atomic_sub))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_map_atomic_sub(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_sub), strlen(XSTR(cond_map_atomic_sub))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_map_atomic_sub(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_sub), strlen(XSTR(group_map_atomic_sub))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_map_atomic_mul(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_mul), strlen(XSTR(map_atomic_mul))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_map_atomic_mul(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_mul), strlen(XSTR(cond_map_atomic_mul))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_map_atomic_mul(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_mul), strlen(XSTR(group_map_atomic_mul))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_map_atomic_div(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_div), strlen(XSTR(map_atomic_div))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_map_atomic_div(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_div), strlen(XSTR(cond_map_atomic_div))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_map_atomic_div(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_div), strlen(XSTR(group_map_atomic_div))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_map_atomic_mod(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_mod), strlen(XSTR(map_atomic_mod))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_map_atomic_mod(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_mod), strlen(XSTR(cond_map_atomic_mod))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_map_atomic_mod(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_mod), strlen(XSTR(group_map_atomic_mod))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_map_atomic_and(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_and), strlen(XSTR(map_atomic_and))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_map_atomic_and(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_and), strlen(XSTR(cond_map_atomic_and))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_map_atomic_and(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_and), strlen(XSTR(group_map_atomic_and))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_map_atomic_or(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_or), strlen(XSTR(map_atomic_or))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_map_atomic_or(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_or), strlen(XSTR(cond_map_atomic_or))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_map_atomic_or(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_or), strlen(XSTR(group_map_atomic_or))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_map_atomic_xor(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_xor), strlen(XSTR(map_atomic_xor))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_map_atomic_xor(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_xor), strlen(XSTR(cond_map_atomic_xor))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_map_atomic_xor(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_xor), strlen(XSTR(group_map_atomic_xor))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_map_string_prepend(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_string_prepend), strlen(XSTR(map_string_prepend))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_map_string_prepend(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_string_prepend), strlen(XSTR(cond_map_string_prepend))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_map_string_prepend(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_string_prepend), strlen(XSTR(group_map_string_prepend))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_map_string_append(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_string_append), strlen(XSTR(map_string_append))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_map_string_append(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_string_append), strlen(XSTR(cond_map_string_append))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_map_string_append(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_string_append), strlen(XSTR(group_map_string_append))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_map_atomic_min(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_min), strlen(XSTR(map_atomic_min))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_map_atomic_min(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_min), strlen(XSTR(cond_map_atomic_min))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_map_atomic_min(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_min), strlen(XSTR(group_map_atomic_min))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_atomic_min(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_min), strlen(XSTR(atomic_min))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_map_atomic_max(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_max), strlen(XSTR(map_atomic_max))); - return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_cond_map_atomic_max(struct hyperdex_client* _cl, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_max), strlen(XSTR(cond_map_atomic_max))); - return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_group_map_atomic_max(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_max), strlen(XSTR(group_map_atomic_max))); - return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_uxact_atomic_max(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz) -{ - hyperdex::microtransaction* tx = reinterpret_cast(microtransaction); - hyperdex_client_returncode *status = tx->status; - C_WRAP_EXCEPT( - const hyperdex_client_keyop_info* opinfo; - opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_max), strlen(XSTR(atomic_max))); - return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_search(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - enum hyperdex_client_returncode* status, - const struct hyperdex_client_attribute** attrs, size_t* attrs_sz) -{ - C_WRAP_EXCEPT( - return cl->search(space, checks, checks_sz, status, attrs, attrs_sz); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_search_describe(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - enum hyperdex_client_returncode* status, - const char** description) -{ - C_WRAP_EXCEPT( - return cl->search_describe(space, checks, checks_sz, status, description); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_sorted_search(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const char* sort_by, - uint64_t limit, - int maxmin, - enum hyperdex_client_returncode* status, - const struct hyperdex_client_attribute** attrs, size_t* attrs_sz) -{ - C_WRAP_EXCEPT( - return cl->sorted_search(space, checks, checks_sz, sort_by, limit, maxmin, status, attrs, attrs_sz); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_count(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - enum hyperdex_client_returncode* status, - uint64_t* count) -{ - C_WRAP_EXCEPT( - return cl->count(space, checks, checks_sz, status, count); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_sum(struct hyperdex_client* _cl, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const char* sum_key, - enum hyperdex_client_returncode* status, - uint64_t* total) -{ - C_WRAP_EXCEPT( - return cl->sum(space, checks, checks_sz, sum_key, status, total); - ); -} - -HYPERDEX_API int64_t -hyperdex_client_loop(hyperdex_client* _cl, int timeout, - hyperdex_client_returncode* status) -{ - C_WRAP_EXCEPT( - return cl->loop(timeout, status); - ); -} - -HYPERDEX_API int -hyperdex_client_poll_fd(hyperdex_client* _cl) -{ - FAKE_STATUS; - C_WRAP_EXCEPT( - return cl->poll_fd(); - ); -} - -HYPERDEX_API int -hyperdex_client_block(hyperdex_client* _cl, int timeout) -{ - FAKE_STATUS; - C_WRAP_EXCEPT( - return cl->block(timeout); - ); -} - -HYPERDEX_API void -hyperdex_client_set_type_conversion(hyperdex_client* _cl, bool enabled) -{ - hyperdex::client* cl = reinterpret_cast(_cl); - cl->set_type_conversion(enabled); -} + HYPERDEX_API hyperdex_client * + hyperdex_client_create(const char *coordinator, uint16_t port) + { + FAKE_STATUS; + SIGNAL_PROTECT_ERR(NULL); + try + { + return reinterpret_cast(new hyperdex::client(coordinator, port)); + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + return NULL; + } + catch (...) + { + return NULL; + } + } + + HYPERDEX_API hyperdex_client * + hyperdex_client_create_conn_str(const char *conn_str) + { + FAKE_STATUS; + SIGNAL_PROTECT_ERR(NULL); + try + { + return reinterpret_cast(new hyperdex::client(conn_str)); + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + return NULL; + } + catch (...) + { + return NULL; + } + } + + HYPERDEX_API void + hyperdex_client_destroy(hyperdex_client *client) + { + delete reinterpret_cast(client); + } + + HYPERDEX_API const char * + hyperdex_client_error_message(hyperdex_client *_cl) + { + FAKE_STATUS; + SIGNAL_PROTECT_ERR(NULL); + hyperdex::client *cl = reinterpret_cast(_cl); + return cl->error_message(); + } + + HYPERDEX_API const char * + hyperdex_client_error_location(hyperdex_client *_cl) + { + FAKE_STATUS; + SIGNAL_PROTECT_ERR(NULL); + hyperdex::client *cl = reinterpret_cast(_cl); + return cl->error_location(); + } + + HYPERDEX_API const char * + hyperdex_client_returncode_to_string(enum hyperdex_client_returncode stat) + { + FAKE_STATUS; + SIGNAL_PROTECT_ERR(NULL); + switch (stat) + { + CSTRINGIFY(HYPERDEX_CLIENT_SUCCESS); + CSTRINGIFY(HYPERDEX_CLIENT_NOTFOUND); + CSTRINGIFY(HYPERDEX_CLIENT_SEARCHDONE); + CSTRINGIFY(HYPERDEX_CLIENT_CMPFAIL); + CSTRINGIFY(HYPERDEX_CLIENT_READONLY); + CSTRINGIFY(HYPERDEX_CLIENT_UNKNOWNSPACE); + CSTRINGIFY(HYPERDEX_CLIENT_COORDFAIL); + CSTRINGIFY(HYPERDEX_CLIENT_SERVERERROR); + CSTRINGIFY(HYPERDEX_CLIENT_POLLFAILED); + CSTRINGIFY(HYPERDEX_CLIENT_OVERFLOW); + CSTRINGIFY(HYPERDEX_CLIENT_RECONFIGURE); + CSTRINGIFY(HYPERDEX_CLIENT_TIMEOUT); + CSTRINGIFY(HYPERDEX_CLIENT_UNKNOWNATTR); + CSTRINGIFY(HYPERDEX_CLIENT_DUPEATTR); + CSTRINGIFY(HYPERDEX_CLIENT_NONEPENDING); + CSTRINGIFY(HYPERDEX_CLIENT_DONTUSEKEY); + CSTRINGIFY(HYPERDEX_CLIENT_WRONGTYPE); + CSTRINGIFY(HYPERDEX_CLIENT_NOMEM); + CSTRINGIFY(HYPERDEX_CLIENT_INTERRUPTED); + CSTRINGIFY(HYPERDEX_CLIENT_CLUSTER_JUMP); + CSTRINGIFY(HYPERDEX_CLIENT_OFFLINE); + CSTRINGIFY(HYPERDEX_CLIENT_UNAUTHORIZED); + CSTRINGIFY(HYPERDEX_CLIENT_INTERNAL); + CSTRINGIFY(HYPERDEX_CLIENT_EXCEPTION); + CSTRINGIFY(HYPERDEX_CLIENT_GARBAGE); + default: + return "unknown hyperdex_client_returncode"; + } + } + + HYPERDEX_API enum hyperdatatype + hyperdex_client_attribute_type(hyperdex_client *_cl, + const char *space, const char *name, + enum hyperdex_client_returncode *status) + { + SIGNAL_PROTECT_ERR(HYPERDATATYPE_GARBAGE); + hyperdex::client *cl = reinterpret_cast(_cl); + \ + + try + { + return cl->attribute_type(space, name, status); + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + *status = HYPERDEX_CLIENT_NOMEM; + cl->set_error_message("out of memory"); + return HYPERDATATYPE_GARBAGE; + } + catch (...) + { + *status = HYPERDEX_CLIENT_EXCEPTION; + cl->set_error_message("unhandled exception was thrown"); + return HYPERDATATYPE_GARBAGE; + } + } + + HYPERDEX_API void + hyperdex_client_destroy_attrs(const hyperdex_client_attribute *attrs, size_t /*attrs_sz*/) + { + FAKE_STATUS; + SIGNAL_PROTECT_VOID; + if (attrs) + { + free(const_cast(attrs)); + attrs = NULL; + } + } + + HYPERDEX_API void + hyperdex_client_clear_auth_context(struct hyperdex_client *_cl) + { + FAKE_STATUS; + SIGNAL_PROTECT_VOID; + hyperdex::client *cl = reinterpret_cast(_cl); + cl->clear_auth_context(); + } + + HYPERDEX_API void + hyperdex_client_set_auth_context(struct hyperdex_client *_cl, + const char **macaroons, size_t macaroons_sz) + { + FAKE_STATUS; + SIGNAL_PROTECT_VOID; + hyperdex::client *cl = reinterpret_cast(_cl); + cl->set_auth_context(macaroons, macaroons_sz); + } + + HYPERDEX_API struct hyperdex_client_microtransaction * + hyperdex_client_uxact_init(struct hyperdex_client *_cl, + const char *space, + enum hyperdex_client_returncode *status) + { + SIGNAL_PROTECT_ERR(NULL); + hyperdex::client *cl = reinterpret_cast(_cl); + hyperdex::microtransaction *tx = cl->uxact_init(space, status); + return reinterpret_cast(tx); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_commit(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *transaction, + const char *key, size_t key_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(transaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + return cl->uxact_commit(tx, key, key_sz); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_group_commit(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *transaction, + const hyperdex_client_attribute_check *chks, size_t chks_sz, + uint64_t *count) + { + hyperdex::microtransaction *tx = reinterpret_cast(transaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + return cl->uxact_group_commit(tx, chks, chks_sz, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_cond_commit(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *transaction, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *chks, size_t chks_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(transaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + return cl->uxact_cond_commit(tx, key, key_sz, chks, chks_sz); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_get(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + enum hyperdex_client_returncode *status, + const struct hyperdex_client_attribute **attrs, size_t *attrs_sz) + { + C_WRAP_EXCEPT( + return cl->get(space, key, key_sz, status, attrs, attrs_sz); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_get_partial(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const char **attrnames, size_t attrnames_sz, + enum hyperdex_client_returncode *status, + const struct hyperdex_client_attribute **attrs, size_t *attrs_sz) + { + C_WRAP_EXCEPT( + return cl->get_partial(space, key, key_sz, attrnames, attrnames_sz, status, attrs, attrs_sz); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_put(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(put), strlen(XSTR(put))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_put(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(put), strlen(XSTR(put))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_put(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_put), strlen(XSTR(cond_put))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_put_or_create(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_put_or_create), strlen(XSTR(cond_put_or_create))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_put(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_put), strlen(XSTR(group_put))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_put_if_not_exist(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(put_if_not_exist), strlen(XSTR(put_if_not_exist))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_del(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(del), strlen(XSTR(del))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_del(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_del), strlen(XSTR(cond_del))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_del(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_del), strlen(XSTR(group_del))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_atomic_add(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_add), strlen(XSTR(atomic_add))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_atomic_add(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_add), strlen(XSTR(atomic_add))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_atomic_add(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_add), strlen(XSTR(cond_atomic_add))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_atomic_add(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_add), strlen(XSTR(group_atomic_add))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_atomic_sub(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_sub), strlen(XSTR(atomic_sub))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_atomic_sub(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_sub), strlen(XSTR(atomic_sub))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_atomic_sub(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_sub), strlen(XSTR(cond_atomic_sub))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_atomic_sub(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_sub), strlen(XSTR(group_atomic_sub))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_atomic_mul(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_mul), strlen(XSTR(atomic_mul))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_atomic_mul(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_mul), strlen(XSTR(atomic_mul))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_atomic_mul(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_mul), strlen(XSTR(cond_atomic_mul))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_atomic_mul(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_mul), strlen(XSTR(group_atomic_mul))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_atomic_div(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_div), strlen(XSTR(atomic_div))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_atomic_div(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_div), strlen(XSTR(atomic_div))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_atomic_div(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_div), strlen(XSTR(cond_atomic_div))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_atomic_div(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_div), strlen(XSTR(group_atomic_div))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_atomic_mod(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_mod), strlen(XSTR(atomic_mod))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_atomic_mod(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_mod), strlen(XSTR(cond_atomic_mod))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_atomic_mod(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_mod), strlen(XSTR(group_atomic_mod))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_atomic_and(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_and), strlen(XSTR(atomic_and))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_atomic_and(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_and), strlen(XSTR(atomic_and))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_atomic_and(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_and), strlen(XSTR(cond_atomic_and))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_atomic_and(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_and), strlen(XSTR(group_atomic_and))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_atomic_or(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_or), strlen(XSTR(atomic_or))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_atomic_or(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_or), strlen(XSTR(atomic_or))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_atomic_or(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_or), strlen(XSTR(cond_atomic_or))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_atomic_or(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_or), strlen(XSTR(group_atomic_or))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_atomic_xor(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_xor), strlen(XSTR(atomic_xor))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_atomic_xor(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_xor), strlen(XSTR(cond_atomic_xor))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_atomic_xor(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_xor), strlen(XSTR(group_atomic_xor))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_atomic_min(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_min), strlen(XSTR(atomic_min))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_atomic_min(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_min), strlen(XSTR(cond_atomic_min))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_atomic_min(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_min), strlen(XSTR(group_atomic_min))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_atomic_max(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_max), strlen(XSTR(atomic_max))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_atomic_max(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_atomic_max), strlen(XSTR(cond_atomic_max))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_atomic_max(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_atomic_max), strlen(XSTR(group_atomic_max))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_string_prepend(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_prepend), strlen(XSTR(string_prepend))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_string_prepend(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_prepend), strlen(XSTR(string_prepend))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_string_prepend(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_string_prepend), strlen(XSTR(cond_string_prepend))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_string_prepend(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_string_prepend), strlen(XSTR(group_string_prepend))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_string_append(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_append), strlen(XSTR(string_append))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_string_append(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_append), strlen(XSTR(string_append))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_string_append(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_string_append), strlen(XSTR(cond_string_append))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_string_append(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_string_append), strlen(XSTR(group_string_append))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_string_ltrim(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_ltrim), strlen(XSTR(string_ltrim))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_string_ltrim(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_ltrim), strlen(XSTR(string_ltrim))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_string_ltrim(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_string_ltrim), strlen(XSTR(cond_string_ltrim))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_string_ltrim(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_string_ltrim), strlen(XSTR(group_string_ltrim))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_string_rtrim(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_rtrim), strlen(XSTR(string_rtrim))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_string_rtrim(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(string_rtrim), strlen(XSTR(string_rtrim))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_string_rtrim(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_string_rtrim), strlen(XSTR(cond_string_rtrim))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_string_rtrim(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_string_rtrim), strlen(XSTR(group_string_rtrim))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_list_lpush(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(list_lpush), strlen(XSTR(list_lpush))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_list_lpush(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(list_lpush), strlen(XSTR(list_lpush))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_list_lpush(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_list_lpush), strlen(XSTR(cond_list_lpush))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_list_lpush(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_list_lpush), strlen(XSTR(group_list_lpush))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_list_rpush(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(list_rpush), strlen(XSTR(list_rpush))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_list_rpush(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(list_rpush), strlen(XSTR(list_rpush))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_list_rpush(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_list_rpush), strlen(XSTR(cond_list_rpush))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_list_rpush(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_list_rpush), strlen(XSTR(group_list_rpush))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_set_add(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(set_add), strlen(XSTR(set_add))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_set_add(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_set_add), strlen(XSTR(cond_set_add))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_set_add(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_set_add), strlen(XSTR(group_set_add))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_set_remove(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(set_remove), strlen(XSTR(set_remove))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_set_remove(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_set_remove), strlen(XSTR(cond_set_remove))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_set_remove(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_set_remove), strlen(XSTR(group_set_remove))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_set_intersect(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(set_intersect), strlen(XSTR(set_intersect))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_set_intersect(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_set_intersect), strlen(XSTR(cond_set_intersect))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_set_intersect(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_set_intersect), strlen(XSTR(group_set_intersect))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_set_union(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(set_union), strlen(XSTR(set_union))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_set_union(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_set_union), strlen(XSTR(cond_set_union))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_set_union(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_set_union), strlen(XSTR(group_set_union))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_document_rename(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(document_rename), strlen(XSTR(document_rename))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_document_rename(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(document_rename), strlen(XSTR(document_rename))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_document_rename(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_document_rename), strlen(XSTR(cond_document_rename))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_document_rename(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_document_rename), strlen(XSTR(group_document_rename))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_document_unset(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(document_unset), strlen(XSTR(document_unset))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_document_unset(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(document_unset), strlen(XSTR(document_unset))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_document_unset(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_document_unset), strlen(XSTR(cond_document_unset))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_document_unset(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_document_unset), strlen(XSTR(group_document_unset))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_map_add(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_add), strlen(XSTR(map_add))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_map_add(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_add), strlen(XSTR(cond_map_add))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_map_add(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_add), strlen(XSTR(group_map_add))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_map_remove(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_remove), strlen(XSTR(map_remove))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_map_remove(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_remove), strlen(XSTR(cond_map_remove))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, NULL, 0, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_map_remove(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_remove), strlen(XSTR(group_map_remove))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, attrs, attrs_sz, NULL, 0, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_map_atomic_add(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_add), strlen(XSTR(map_atomic_add))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_map_atomic_add(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_add), strlen(XSTR(cond_map_atomic_add))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_map_atomic_add(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_add), strlen(XSTR(group_map_atomic_add))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_map_atomic_sub(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_sub), strlen(XSTR(map_atomic_sub))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_map_atomic_sub(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_sub), strlen(XSTR(cond_map_atomic_sub))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_map_atomic_sub(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_sub), strlen(XSTR(group_map_atomic_sub))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_map_atomic_mul(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_mul), strlen(XSTR(map_atomic_mul))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_map_atomic_mul(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_mul), strlen(XSTR(cond_map_atomic_mul))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_map_atomic_mul(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_mul), strlen(XSTR(group_map_atomic_mul))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_map_atomic_div(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_div), strlen(XSTR(map_atomic_div))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_map_atomic_div(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_div), strlen(XSTR(cond_map_atomic_div))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_map_atomic_div(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_div), strlen(XSTR(group_map_atomic_div))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_map_atomic_mod(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_mod), strlen(XSTR(map_atomic_mod))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_map_atomic_mod(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_mod), strlen(XSTR(cond_map_atomic_mod))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_map_atomic_mod(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_mod), strlen(XSTR(group_map_atomic_mod))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_map_atomic_and(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_and), strlen(XSTR(map_atomic_and))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_map_atomic_and(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_and), strlen(XSTR(cond_map_atomic_and))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_map_atomic_and(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_and), strlen(XSTR(group_map_atomic_and))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_map_atomic_or(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_or), strlen(XSTR(map_atomic_or))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_map_atomic_or(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_or), strlen(XSTR(cond_map_atomic_or))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_map_atomic_or(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_or), strlen(XSTR(group_map_atomic_or))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_map_atomic_xor(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_xor), strlen(XSTR(map_atomic_xor))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_map_atomic_xor(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_xor), strlen(XSTR(cond_map_atomic_xor))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_map_atomic_xor(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_xor), strlen(XSTR(group_map_atomic_xor))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_map_string_prepend(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_string_prepend), strlen(XSTR(map_string_prepend))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_map_string_prepend(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_string_prepend), strlen(XSTR(cond_map_string_prepend))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_map_string_prepend(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_string_prepend), strlen(XSTR(group_map_string_prepend))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_map_string_append(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_string_append), strlen(XSTR(map_string_append))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_map_string_append(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_string_append), strlen(XSTR(cond_map_string_append))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_map_string_append(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_string_append), strlen(XSTR(group_map_string_append))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_map_atomic_min(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_min), strlen(XSTR(map_atomic_min))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_map_atomic_min(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_min), strlen(XSTR(cond_map_atomic_min))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_map_atomic_min(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_min), strlen(XSTR(group_map_atomic_min))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_atomic_min(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_min), strlen(XSTR(atomic_min))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_map_atomic_max(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(map_atomic_max), strlen(XSTR(map_atomic_max))); + return cl->perform_funcall(opinfo, space, key, key_sz, NULL, 0, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_cond_map_atomic_max(struct hyperdex_client *_cl, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(cond_map_atomic_max), strlen(XSTR(cond_map_atomic_max))); + return cl->perform_funcall(opinfo, space, key, key_sz, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_group_map_atomic_max(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(group_map_atomic_max), strlen(XSTR(group_map_atomic_max))); + return cl->perform_group_funcall(opinfo, space, checks, checks_sz, NULL, 0, mapattrs, mapattrs_sz, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_uxact_atomic_max(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz) + { + hyperdex::microtransaction *tx = reinterpret_cast(microtransaction); + hyperdex_client_returncode *status = tx->status; + C_WRAP_EXCEPT( + const hyperdex_client_keyop_info * opinfo; + opinfo = hyperdex_client_keyop_info_lookup(XSTR(atomic_max), strlen(XSTR(atomic_max))); + return cl->uxact_add_funcall(tx, opinfo, attrs, attrs_sz, NULL, 0); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_search(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + enum hyperdex_client_returncode *status, + const struct hyperdex_client_attribute **attrs, size_t *attrs_sz) + { + C_WRAP_EXCEPT( + return cl->search(space, checks, checks_sz, status, attrs, attrs_sz); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_search_describe(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + enum hyperdex_client_returncode *status, + const char **description) + { + C_WRAP_EXCEPT( + return cl->search_describe(space, checks, checks_sz, status, description); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_sorted_search(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const char *sort_by, + uint64_t limit, + int maxmin, + enum hyperdex_client_returncode *status, + const struct hyperdex_client_attribute **attrs, size_t *attrs_sz) + { + C_WRAP_EXCEPT( + return cl->sorted_search(space, checks, checks_sz, sort_by, limit, maxmin, status, attrs, attrs_sz); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_count(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + enum hyperdex_client_returncode *status, + uint64_t *count) + { + C_WRAP_EXCEPT( + return cl->count(space, checks, checks_sz, status, count); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_sum(struct hyperdex_client *_cl, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const char *sum_key, + enum hyperdex_client_returncode *status, + uint64_t *total) + { + C_WRAP_EXCEPT( + return cl->sum(space, checks, checks_sz, sum_key, status, total); + ); + } + + HYPERDEX_API int64_t + hyperdex_client_loop(hyperdex_client *_cl, int timeout, + hyperdex_client_returncode *status) + { + C_WRAP_EXCEPT( + return cl->loop(timeout, status); + ); + } + + HYPERDEX_API int + hyperdex_client_poll_fd(hyperdex_client *_cl) + { + FAKE_STATUS; + C_WRAP_EXCEPT( + return cl->poll_fd(); + ); + } + + HYPERDEX_API int + hyperdex_client_block(hyperdex_client *_cl, int timeout) + { + FAKE_STATUS; + C_WRAP_EXCEPT( + return cl->block(timeout); + ); + } + + HYPERDEX_API void + hyperdex_client_set_type_conversion(hyperdex_client *_cl, bool enabled) + { + hyperdex::client *cl = reinterpret_cast(_cl); + cl->set_type_conversion(enabled); + } #ifdef __cplusplus -} // extern "C" + } // extern "C" #endif // __cplusplus diff --git a/client/client.cc b/client/client.cc index c1df93d03..3aae4ad80 100644 --- a/client/client.cc +++ b/client/client.cc @@ -63,1518 +63,1345 @@ #include "client/pending_sorted_search.h" #define ERROR(CODE) \ - *status = HYPERDEX_CLIENT_ ## CODE; \ - m_last_error.set_loc(__FILE__, __LINE__); \ - m_last_error.set_msg() + *status = HYPERDEX_CLIENT_ ## CODE; \ + m_last_error.set_loc(__FILE__, __LINE__); \ + m_last_error.set_msg() #define _BUSYBEE_ERROR(BBRC) \ - case BUSYBEE_ ## BBRC: \ - ERROR(INTERNAL) << "internal error: BusyBee unexpectedly returned " XSTR(BBRC) << ": please file a bug" + case BUSYBEE_ ## BBRC: \ + ERROR(INTERNAL) << "internal error: BusyBee unexpectedly returned " XSTR(BBRC) << ": please file a bug" #define BUSYBEE_ERROR_CASE(BBRC) \ - _BUSYBEE_ERROR(BBRC); \ - return -1; + _BUSYBEE_ERROR(BBRC); \ + return -1; #define BUSYBEE_ERROR_CASE_FALSE(BBRC) \ - _BUSYBEE_ERROR(BBRC); \ - return false; + _BUSYBEE_ERROR(BBRC); \ + return false; using hyperdex::client; using hyperdex::microtransaction; -client :: client(const char* coordinator, uint16_t port) - : m_coord(replicant_client_create(coordinator, port)) - , m_busybee_mapper(&m_config) - , m_busybee(&m_busybee_mapper, 0) - , m_config() - , m_config_id(-1) - , m_config_status() - , m_config_state(0) - , m_config_data(NULL) - , m_config_data_sz(0) - , m_next_client_id(1) - , m_next_server_nonce(1) - , m_flagfd() - , m_pending_ops() - , m_failed() - , m_yieldable() - , m_yielding() - , m_yielded() - , m_last_error() - , m_macaroons(NULL) - , m_macaroons_sz(0) - , m_convert_types(true) +client :: client(const char *coordinator, uint16_t port) + : m_coord(replicant_client_create(coordinator, port)) + , m_busybee_mapper(&m_config) + , m_busybee(&m_busybee_mapper, 0) + , m_config() + , m_config_id(-1) + , m_config_status() + , m_config_state(0) + , m_config_data(NULL) + , m_config_data_sz(0) + , m_next_client_id(1) + , m_next_server_nonce(1) + , m_flagfd() + , m_pending_ops() + , m_failed() + , m_yieldable() + , m_yielding() + , m_yielded() + , m_last_error() + , m_macaroons(NULL) + , m_macaroons_sz(0) + , m_convert_types(true) { - if (!m_coord) - { - throw std::bad_alloc(); - } - - m_busybee.set_external_fd(replicant_client_poll_fd(m_coord)); - m_busybee.set_external_fd(m_flagfd.poll_fd()); + if (!m_coord) + { + throw std::bad_alloc(); + } + m_busybee.set_external_fd(replicant_client_poll_fd(m_coord)); + m_busybee.set_external_fd(m_flagfd.poll_fd()); } -client :: client(const char* conn_str) - : m_coord(replicant_client_create_conn_str(conn_str)) - , m_busybee_mapper(&m_config) - , m_busybee(&m_busybee_mapper, 0) - , m_config() - , m_config_id(-1) - , m_config_status() - , m_config_state(0) - , m_config_data(NULL) - , m_config_data_sz(0) - , m_next_client_id(1) - , m_next_server_nonce(1) - , m_flagfd() - , m_pending_ops() - , m_failed() - , m_yieldable() - , m_yielding() - , m_yielded() - , m_last_error() - , m_macaroons(NULL) - , m_macaroons_sz(0) - , m_convert_types(true) +client :: client(const char *conn_str) + : m_coord(replicant_client_create_conn_str(conn_str)) + , m_busybee_mapper(&m_config) + , m_busybee(&m_busybee_mapper, 0) + , m_config() + , m_config_id(-1) + , m_config_status() + , m_config_state(0) + , m_config_data(NULL) + , m_config_data_sz(0) + , m_next_client_id(1) + , m_next_server_nonce(1) + , m_flagfd() + , m_pending_ops() + , m_failed() + , m_yieldable() + , m_yielding() + , m_yielded() + , m_last_error() + , m_macaroons(NULL) + , m_macaroons_sz(0) + , m_convert_types(true) { - if (!m_coord) - { - throw std::bad_alloc(); - } - - m_busybee.set_external_fd(replicant_client_poll_fd(m_coord)); - m_busybee.set_external_fd(m_flagfd.poll_fd()); + if (!m_coord) + { + throw std::bad_alloc(); + } + m_busybee.set_external_fd(replicant_client_poll_fd(m_coord)); + m_busybee.set_external_fd(m_flagfd.poll_fd()); } client :: ~client() throw () { - replicant_client_destroy(m_coord); + replicant_client_destroy(m_coord); } int64_t -client :: get(const char* space, const char* _key, size_t _key_sz, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz) +client :: get(const char *space, const char *_key, size_t _key_sz, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - const schema* sc = m_config.get_schema(space); - - if (!sc) - { - ERROR(UNKNOWNSPACE) << "space \"" << e::strescape(space) << "\" does not exist"; - return -1; - } - - datatype_info* di = datatype_info::lookup(sc->attrs[0].type); - assert(di); - e::slice key(_key, _key_sz); - - if (!di->validate(key)) - { - ERROR(WRONGTYPE) << "key must be type " << sc->attrs[0].type; - return -1; - } - - e::intrusive_ptr op; - op = new pending_get(m_next_client_id++, status, attrs, attrs_sz); - size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ + pack_size(key); - auth_wallet aw(m_macaroons, m_macaroons_sz); - - if (m_macaroons_sz) - { - sz += pack_size(aw); - } - - std::auto_ptr msg(e::buffer::create(sz)); - e::packer pa = msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << key; - - if (m_macaroons_sz) - { - pa = pa << aw; - } - - return send_keyop(space, key, REQ_GET, msg, op, status); + if (!maintain_coord_connection(status)) + { + return -1; + } + const schema *sc = m_config.get_schema(space); + if (!sc) + { + ERROR(UNKNOWNSPACE) << "space \"" << e::strescape(space) << "\" does not exist"; + return -1; + } + datatype_info *di = datatype_info::lookup(sc->attrs[0].type); + assert(di); + e::slice key(_key, _key_sz); + if (!di->validate(key)) + { + ERROR(WRONGTYPE) << "key must be type " << sc->attrs[0].type; + return -1; + } + e::intrusive_ptr op; + op = new pending_get(m_next_client_id++, status, attrs, attrs_sz); + size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ + pack_size(key); + auth_wallet aw(m_macaroons, m_macaroons_sz); + if (m_macaroons_sz) + { + sz += pack_size(aw); + } + std::auto_ptr msg(e::buffer::create(sz)); + e::packer pa = msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << key; + if (m_macaroons_sz) + { + pa = pa << aw; + } + return send_keyop(space, key, REQ_GET, msg, op, status); } int64_t -client :: get_partial(const char* space, const char* _key, size_t _key_sz, - const char** attrnames, size_t attrnames_sz, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz) +client :: get_partial(const char *space, const char *_key, size_t _key_sz, + const char **attrnames, size_t attrnames_sz, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - const schema* sc = m_config.get_schema(space); - - if (!sc) - { - ERROR(UNKNOWNSPACE) << "space \"" << e::strescape(space) << "\" does not exist"; - return -1; - } - - std::vector attrnums; - - for (size_t i = 0; i < attrnames_sz; ++i) - { - uint16_t attr = sc->lookup_attr(attrnames[i]); - - if (attr == UINT16_MAX) - { - ERROR(UNKNOWNATTR) << "attribute \"" << e::strescape(attrnames[i]) - << "\" is not an attribute in space \"" - << e::strescape(space) << "\""; - return -1; - } - - if (attr == 0) - { - ERROR(DONTUSEKEY) << "don't specify the key (\"" << e::strescape(attrnames[i]) - << "\") when doing get_partial on space \"" - << e::strescape(space) << "\""; - return -1; - } - - attrnums.push_back(attr); - } - - datatype_info* di = datatype_info::lookup(sc->attrs[0].type); - assert(di); - e::slice key(_key, _key_sz); - - if (!di->validate(key)) - { - ERROR(WRONGTYPE) << "key must be type " << sc->attrs[0].type; - return -1; - } - - e::intrusive_ptr op; - op = new pending_get_partial(m_next_client_id++, status, attrs, attrs_sz); - size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ - + pack_size(key) - + sizeof(uint64_t) + attrnums.size() * sizeof(uint16_t); - auth_wallet aw(m_macaroons, m_macaroons_sz); - - if (m_macaroons_sz) - { - sz += pack_size(aw); - } - - std::auto_ptr msg(e::buffer::create(sz)); - e::packer pa = msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ); - pa = pa << key << attrnums; - - if (m_macaroons_sz) - { - pa = pa << aw; - } - - return send_keyop(space, key, REQ_GET_PARTIAL, msg, op, status); + if (!maintain_coord_connection(status)) + { + return -1; + } + const schema *sc = m_config.get_schema(space); + if (!sc) + { + ERROR(UNKNOWNSPACE) << "space \"" << e::strescape(space) << "\" does not exist"; + return -1; + } + std::vector attrnums; + for (size_t i = 0; i < attrnames_sz; ++i) + { + uint16_t attr = sc->lookup_attr(attrnames[i]); + if (attr == UINT16_MAX) + { + ERROR(UNKNOWNATTR) << "attribute \"" << e::strescape(attrnames[i]) + << "\" is not an attribute in space \"" + << e::strescape(space) << "\""; + return -1; + } + if (attr == 0) + { + ERROR(DONTUSEKEY) << "don't specify the key (\"" << e::strescape(attrnames[i]) + << "\") when doing get_partial on space \"" + << e::strescape(space) << "\""; + return -1; + } + attrnums.push_back(attr); + } + datatype_info *di = datatype_info::lookup(sc->attrs[0].type); + assert(di); + e::slice key(_key, _key_sz); + if (!di->validate(key)) + { + ERROR(WRONGTYPE) << "key must be type " << sc->attrs[0].type; + return -1; + } + e::intrusive_ptr op; + op = new pending_get_partial(m_next_client_id++, status, attrs, attrs_sz); + size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ + + pack_size(key) + + sizeof(uint64_t) + attrnums.size() * sizeof(uint16_t); + auth_wallet aw(m_macaroons, m_macaroons_sz); + if (m_macaroons_sz) + { + sz += pack_size(aw); + } + std::auto_ptr msg(e::buffer::create(sz)); + e::packer pa = msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ); + pa = pa << key << attrnums; + if (m_macaroons_sz) + { + pa = pa << aw; + } + return send_keyop(space, key, REQ_GET_PARTIAL, msg, op, status); } #define SEARCH_BOILERPLATE \ - if (!maintain_coord_connection(status)) \ - { \ - return -1; \ - } \ - const schema* sc = m_config.get_schema(space); \ - if (!sc) \ - { \ - ERROR(UNKNOWNSPACE) << "space \"" << e::strescape(space) << "\" does not exist"; \ - return -1; \ - } \ - std::vector checks; \ - std::vector servers; \ - e::arena memory; \ - int64_t ret = prepare_searchop(*sc, space, chks, chks_sz, &memory, status, &checks, &servers); \ - if (ret < 0) \ - { \ - return ret; \ - } + if (!maintain_coord_connection(status)) \ + { \ + return -1; \ + } \ + const schema* sc = m_config.get_schema(space); \ + if (!sc) \ + { \ + ERROR(UNKNOWNSPACE) << "space \"" << e::strescape(space) << "\" does not exist"; \ + return -1; \ + } \ + std::vector checks; \ + std::vector servers; \ + e::arena memory; \ + int64_t ret = prepare_searchop(*sc, space, chks, chks_sz, &memory, status, &checks, &servers); \ + if (ret < 0) \ + { \ + return ret; \ + } int64_t -client :: search(const char* space, - const hyperdex_client_attribute_check* chks, size_t chks_sz, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz) +client :: search(const char *space, + const hyperdex_client_attribute_check *chks, size_t chks_sz, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz) { - SEARCH_BOILERPLATE - int64_t client_id = m_next_client_id++; - e::intrusive_ptr op; - op = new pending_search(client_id, status, attrs, attrs_sz); - size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ - + sizeof(uint64_t) - + pack_size(checks); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << client_id << checks; - return perform_aggregation(servers, op, REQ_SEARCH_START, msg, status); + SEARCH_BOILERPLATE + int64_t client_id = m_next_client_id++; + e::intrusive_ptr op; + op = new pending_search(client_id, status, attrs, attrs_sz); + size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ + + sizeof(uint64_t) + + pack_size(checks); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << client_id << checks; + return perform_aggregation(servers, op, REQ_SEARCH_START, msg, status); } int64_t -client :: search_describe(const char* space, - const hyperdex_client_attribute_check* chks, size_t chks_sz, - hyperdex_client_returncode* status, const char** description) +client :: search_describe(const char *space, + const hyperdex_client_attribute_check *chks, size_t chks_sz, + hyperdex_client_returncode *status, const char **description) { - SEARCH_BOILERPLATE - int64_t client_id = m_next_client_id++; - e::intrusive_ptr op; - op = new pending_search_describe(client_id, status, description); - size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ - + pack_size(checks); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << checks; - return perform_aggregation(servers, op, REQ_SEARCH_DESCRIBE, msg, status); + SEARCH_BOILERPLATE + int64_t client_id = m_next_client_id++; + e::intrusive_ptr op; + op = new pending_search_describe(client_id, status, description); + size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ + + pack_size(checks); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << checks; + return perform_aggregation(servers, op, REQ_SEARCH_DESCRIBE, msg, status); } int64_t -client :: sorted_search(const char* space, - const hyperdex_client_attribute_check* chks, size_t chks_sz, - const char* sort_by, +client :: sorted_search(const char *space, + const hyperdex_client_attribute_check *chks, size_t chks_sz, + const char *sort_by, uint64_t limit, bool maximize, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz) + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz) { - SEARCH_BOILERPLATE - uint16_t sort_by_num = sc->lookup_attr(sort_by); - - if (sort_by_num == sc->attrs_sz) - { - ERROR(UNKNOWNATTR) << "\"" << e::strescape(sort_by) - << "\" is not an attribute of space \"" - << e::strescape(space) << "\""; - return -1 - chks_sz; - } - - datatype_info* di = datatype_info::lookup(sc->attrs[sort_by_num].type); - - if (!di->comparable()) - { - ERROR(WRONGTYPE) << "cannot sort by attribute \"" - << e::strescape(sort_by) - << "\": it is not comparable"; - return -1 - chks_sz; - } - - int64_t client_id = m_next_client_id++; - e::intrusive_ptr op; - op = new pending_sorted_search(this, client_id, maximize, limit, sort_by_num, di, status, attrs, attrs_sz); - int8_t max = maximize ? 1 : 0; - size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ - + pack_size(checks) - + sizeof(limit) - + sizeof(sort_by_num) - + sizeof(max); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << checks << limit << sort_by_num << max; - return perform_aggregation(servers, op, REQ_SORTED_SEARCH, msg, status); + SEARCH_BOILERPLATE + uint16_t sort_by_num = sc->lookup_attr(sort_by); + if (sort_by_num == sc->attrs_sz) + { + ERROR(UNKNOWNATTR) << "\"" << e::strescape(sort_by) + << "\" is not an attribute of space \"" + << e::strescape(space) << "\""; + return -1 - chks_sz; + } + datatype_info *di = datatype_info::lookup(sc->attrs[sort_by_num].type); + if (!di->comparable()) + { + ERROR(WRONGTYPE) << "cannot sort by attribute \"" + << e::strescape(sort_by) + << "\": it is not comparable"; + return -1 - chks_sz; + } + int64_t client_id = m_next_client_id++; + e::intrusive_ptr op; + op = new pending_sorted_search(this, client_id, maximize, limit, sort_by_num, di, status, attrs, attrs_sz); + int8_t max = maximize ? 1 : 0; + size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ + + pack_size(checks) + + sizeof(limit) + + sizeof(sort_by_num) + + sizeof(max); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << checks << limit << sort_by_num << max; + return perform_aggregation(servers, op, REQ_SORTED_SEARCH, msg, status); } int64_t -client :: count(const char* space, - const hyperdex_client_attribute_check* chks, size_t chks_sz, - hyperdex_client_returncode* status, - uint64_t* result) +client :: count(const char *space, + const hyperdex_client_attribute_check *chks, size_t chks_sz, + hyperdex_client_returncode *status, + uint64_t *result) { - SEARCH_BOILERPLATE - int64_t client_id = m_next_client_id++; - e::intrusive_ptr op; - op = new pending_count(client_id, status, result); - size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ - + pack_size(checks); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << checks; - return perform_aggregation(servers, op, REQ_COUNT, msg, status); + SEARCH_BOILERPLATE + int64_t client_id = m_next_client_id++; + e::intrusive_ptr op; + op = new pending_count(client_id, status, result); + size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ + + pack_size(checks); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << checks; + return perform_aggregation(servers, op, REQ_COUNT, msg, status); } int64_t -client :: sum(const char* space, - const hyperdex_client_attribute_check* chks, size_t chks_sz, - const char* sum_key, - hyperdex_client_returncode* status, - uint64_t* result) +client :: sum(const char *space, + const hyperdex_client_attribute_check *chks, size_t chks_sz, + const char *sum_key, + hyperdex_client_returncode *status, + uint64_t *result) { - SEARCH_BOILERPLATE - uint16_t sum_idx = sc->lookup_attr(sum_key); - - if (sum_idx== sc->attrs_sz) - { - ERROR(UNKNOWNATTR) << "\"" << e::strescape(sum_key) - << "\" is not an attribute of space \"" - << e::strescape(space) << "\""; - return -1 - chks_sz; - } - - datatype_info* di = datatype_info::lookup(sc->attrs[sum_idx].type); - - if (!di->comparable()) - { - ERROR(WRONGTYPE) << "cannot sort by attribute \"" - << e::strescape(sum_key) - << "\": it is not comparable"; - return -1 - chks_sz; - } - - int64_t client_id = m_next_client_id++; - e::intrusive_ptr op; - op = new pending_sum(client_id, sum_idx, di, status, result); - size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ - + pack_size(checks) - + sizeof(sum_idx); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << checks << sum_idx; - return perform_aggregation(servers, op, REQ_SUM, msg, status); + SEARCH_BOILERPLATE + uint16_t sum_idx = sc->lookup_attr(sum_key); + if (sum_idx == sc->attrs_sz) + { + ERROR(UNKNOWNATTR) << "\"" << e::strescape(sum_key) + << "\" is not an attribute of space \"" + << e::strescape(space) << "\""; + return -1 - chks_sz; + } + datatype_info *di = datatype_info::lookup(sc->attrs[sum_idx].type); + if (!di->comparable()) + { + ERROR(WRONGTYPE) << "cannot sort by attribute \"" + << e::strescape(sum_key) + << "\": it is not comparable"; + return -1 - chks_sz; + } + int64_t client_id = m_next_client_id++; + e::intrusive_ptr op; + op = new pending_sum(client_id, sum_idx, di, status, result); + size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ + + pack_size(checks) + + sizeof(sum_idx); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << checks << sum_idx; + return perform_aggregation(servers, op, REQ_SUM, msg, status); } int64_t -client :: perform_funcall(const hyperdex_client_keyop_info* opinfo, - const char* space, const char* _key, size_t _key_sz, - const hyperdex_client_attribute_check* chks, size_t chks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) +client :: perform_funcall(const hyperdex_client_keyop_info *opinfo, + const char *space, const char *_key, size_t _key_sz, + const hyperdex_client_attribute_check *chks, size_t chks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) { - if (!maintain_coord_connection(status)) - { - return -1; - } - - const schema* sc = m_config.get_schema(space); - - if (!sc) - { - ERROR(UNKNOWNSPACE) << "space \"" << e::strescape(space) << "\" does not exist"; - return -1; - } - - datatype_info* di = datatype_info::lookup(sc->attrs[0].type); - assert(di); - e::slice key(_key, _key_sz); - - if (!di->validate(key)) - { - ERROR(WRONGTYPE) << "key must be type " << sc->attrs[0].type; - return -1; - } - - e::intrusive_ptr op; - op = new pending_atomic(m_next_client_id++, status); - std::auto_ptr msg; - auth_wallet aw(m_macaroons, m_macaroons_sz); - size_t header_sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ - + pack_size(key); - size_t footer_sz = 0; - - if (m_macaroons_sz) - { - footer_sz += pack_size(aw); - } - - int64_t ret = perform_funcall(space, sc, opinfo, - chks, chks_sz, - attrs, attrs_sz, - mapattrs, mapattrs_sz, - header_sz, footer_sz, - status, &msg); - - if (ret < 0) - { - return ret; - } - - msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << key; - - if (m_macaroons_sz) - { - msg->pack_at(msg->capacity() - footer_sz) << aw; - } - - return send_keyop(space, key, REQ_ATOMIC, msg, op, status); + if (!maintain_coord_connection(status)) + { + return -1; + } + const schema *sc = m_config.get_schema(space); + if (!sc) + { + ERROR(UNKNOWNSPACE) << "space \"" << e::strescape(space) << "\" does not exist"; + return -1; + } + datatype_info *di = datatype_info::lookup(sc->attrs[0].type); + assert(di); + e::slice key(_key, _key_sz); + if (!di->validate(key)) + { + ERROR(WRONGTYPE) << "key must be type " << sc->attrs[0].type; + return -1; + } + e::intrusive_ptr op; + op = new pending_atomic(m_next_client_id++, status); + std::auto_ptr msg; + auth_wallet aw(m_macaroons, m_macaroons_sz); + size_t header_sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ + + pack_size(key); + size_t footer_sz = 0; + if (m_macaroons_sz) + { + footer_sz += pack_size(aw); + } + int64_t ret = perform_funcall(space, sc, opinfo, + chks, chks_sz, + attrs, attrs_sz, + mapattrs, mapattrs_sz, + header_sz, footer_sz, + status, &msg); + if (ret < 0) + { + return ret; + } + msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << key; + if (m_macaroons_sz) + { + msg->pack_at(msg->capacity() - footer_sz) << aw; + } + return send_keyop(space, key, REQ_ATOMIC, msg, op, status); } int64_t -client :: perform_group_funcall(const hyperdex_client_keyop_info* opinfo, - const char* space, - const hyperdex_client_attribute_check* chks, size_t chks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* update_count) +client :: perform_group_funcall(const hyperdex_client_keyop_info *opinfo, + const char *space, + const hyperdex_client_attribute_check *chks, size_t chks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *update_count) { - SEARCH_BOILERPLATE - int64_t client_id = m_next_client_id++; - e::intrusive_ptr op; - op = new pending_group_atomic(client_id, status, update_count); - std::auto_ptr inner_msg; - ret = perform_funcall(space, sc, opinfo, - chks, chks_sz, - attrs, attrs_sz, - mapattrs, mapattrs_sz, - 0, 0, status, &inner_msg); - - if (ret < 0) - { - return ret; - } - - size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ - + sizeof(uint64_t) - + pack_size(checks) - + inner_msg->size(); - std::auto_ptr msg(e::buffer::create(sz)); - e::packer pa = msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ); - e::slice ims = inner_msg->as_slice(); - pa = pa << checks << e::pack_memmove(ims.data(), ims.size()); - return perform_aggregation(servers, op, REQ_GROUP_ATOMIC, msg, status); + SEARCH_BOILERPLATE + int64_t client_id = m_next_client_id++; + e::intrusive_ptr op; + op = new pending_group_atomic(client_id, status, update_count); + std::auto_ptr inner_msg; + ret = perform_funcall(space, sc, opinfo, + chks, chks_sz, + attrs, attrs_sz, + mapattrs, mapattrs_sz, + 0, 0, status, &inner_msg); + if (ret < 0) + { + return ret; + } + size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ + + sizeof(uint64_t) + + pack_size(checks) + + inner_msg->size(); + std::auto_ptr msg(e::buffer::create(sz)); + e::packer pa = msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ); + e::slice ims = inner_msg->as_slice(); + pa = pa << checks << e::pack_memmove(ims.data(), ims.size()); + return perform_aggregation(servers, op, REQ_GROUP_ATOMIC, msg, status); } int64_t -client :: loop(int timeout, hyperdex_client_returncode* status) +client :: loop(int timeout, hyperdex_client_returncode *status) { - *status = HYPERDEX_CLIENT_SUCCESS; - m_last_error = e::error(); - - while (m_yielding || - !m_failed.empty() || - !m_yieldable.empty() || - !m_pending_ops.empty()) - { - if (m_yielding) - { - if (!m_yielding->can_yield()) - { - m_yielding = NULL; - continue; - } - - if (!m_yielding->yield(status, &m_last_error)) - { - return -1; - } - - int64_t client_id = m_yielding->client_visible_id(); - m_last_error = m_yielding->error(); - - if (!m_yielding->can_yield()) - { - m_yielded = m_yielding; - m_yielding = NULL; - } - - return client_id; - } - else if (!m_yieldable.empty()) - { - m_yielding = m_yieldable.front(); - m_yieldable.pop_front(); - continue; - } - else if (!m_failed.empty()) - { - const pending_server_pair& psp(m_failed.front()); - psp.op->handle_failure(psp.si, psp.vsi); - m_yielding = psp.op; - m_failed.pop_front(); - continue; - } - - m_flagfd.clear(); - m_yielded = NULL; - assert(!m_pending_ops.empty()); - - if (!maintain_coord_connection(status)) - { - return -1; - } - - uint64_t sid_num; - std::auto_ptr msg; - m_busybee.set_timeout(timeout); - busybee_returncode rc = m_busybee.recv(&sid_num, &msg); - server_id id(sid_num); - - switch (rc) - { - case BUSYBEE_SUCCESS: - break; - case BUSYBEE_INTERRUPTED: - ERROR(INTERRUPTED) << "signal received"; - return -1; - case BUSYBEE_TIMEOUT: - ERROR(TIMEOUT) << "operation timed out"; - return -1; - case BUSYBEE_DISRUPTED: - handle_disruption(id); - continue; - case BUSYBEE_EXTERNAL: - continue; - BUSYBEE_ERROR_CASE(POLLFAILED); - BUSYBEE_ERROR_CASE(ADDFDFAIL); - BUSYBEE_ERROR_CASE(SHUTDOWN); - default: - ERROR(INTERNAL) << "internal error: BusyBee unexpectedly returned " - << (unsigned) rc << ": please file a bug"; - return -1; - } - - e::unpacker up = msg->unpack_from(BUSYBEE_HEADER_SIZE); - uint8_t mt; - virtual_server_id vfrom; - int64_t nonce; - up = up >> mt >> vfrom >> nonce; - - if (up.error()) - { - ERROR(SERVERERROR) << "communication error: server " - << sid_num << " sent message=" - << msg->as_slice().hex() - << " with invalid header"; - return -1; - } - - network_msgtype msg_type = static_cast(mt); - pending_map_t::iterator it = m_pending_ops.find(nonce); - - if (it == m_pending_ops.end()) - { - continue; - } - - const pending_server_pair psp(it->second); - e::intrusive_ptr op = psp.op; - m_pending_ops.erase(it); - - if (msg_type == CONFIGMISMATCH) - { - m_failed.push_back(psp); - continue; - } - - if (vfrom == psp.vsi && - id == psp.si && - m_config.get_server_id(vfrom) == id) - { - if (!op->handle_message(this, id, vfrom, msg_type, msg, up, status, &m_last_error)) - { - return -1; - } - - m_yielding = psp.op; - } - else - { - ERROR(SERVERERROR) << "wrong server replied for nonce=" << nonce - << ": expected it to come from " - << psp.vsi << "/" << psp.si - << "; it came from " - << vfrom << "/" << id - << "; our config says that virtual_id should map to " - << m_config.get_server_id(vfrom); - return -1; - } - } - - uint64_t sid_num; - m_busybee.set_timeout(0); - busybee_returncode rc = m_busybee.recv_no_msg(&sid_num); - - switch (rc) - { - case BUSYBEE_SUCCESS: - case BUSYBEE_TIMEOUT: - break; - case BUSYBEE_INTERRUPTED: - ERROR(INTERRUPTED) << "signal received"; - return -1; - case BUSYBEE_DISRUPTED: - handle_disruption(server_id(sid_num)); - break; - case BUSYBEE_EXTERNAL: - if (!maintain_coord_connection(status)) - { - return -1; - } - break; - BUSYBEE_ERROR_CASE(POLLFAILED); - BUSYBEE_ERROR_CASE(ADDFDFAIL); - BUSYBEE_ERROR_CASE(SHUTDOWN); - default: - ERROR(INTERNAL) << "internal error: BusyBee unexpectedly returned " - << (unsigned) rc << ": please file a bug"; - return -1; - } - - ERROR(NONEPENDING) << "no outstanding operations to process"; - return -1; + *status = HYPERDEX_CLIENT_SUCCESS; + m_last_error = e::error(); + while (m_yielding || + !m_failed.empty() || + !m_yieldable.empty() || + !m_pending_ops.empty()) + { + if (m_yielding) + { + if (!m_yielding->can_yield()) + { + m_yielding = NULL; + continue; + } + if (!m_yielding->yield(status, &m_last_error)) + { + return -1; + } + int64_t client_id = m_yielding->client_visible_id(); + m_last_error = m_yielding->error(); + if (!m_yielding->can_yield()) + { + m_yielded = m_yielding; + m_yielding = NULL; + } + return client_id; + } + else if (!m_yieldable.empty()) + { + m_yielding = m_yieldable.front(); + m_yieldable.pop_front(); + continue; + } + else if (!m_failed.empty()) + { + const pending_server_pair &psp(m_failed.front()); + psp.op->handle_failure(psp.si, psp.vsi); + m_yielding = psp.op; + m_failed.pop_front(); + continue; + } + m_flagfd.clear(); + m_yielded = NULL; + assert(!m_pending_ops.empty()); + if (!maintain_coord_connection(status)) + { + return -1; + } + uint64_t sid_num; + std::auto_ptr msg; + m_busybee.set_timeout(timeout); + busybee_returncode rc = m_busybee.recv(&sid_num, &msg); + server_id id(sid_num); + switch (rc) + { + case BUSYBEE_SUCCESS: + break; + case BUSYBEE_INTERRUPTED: + ERROR(INTERRUPTED) << "signal received"; + return -1; + case BUSYBEE_TIMEOUT: + ERROR(TIMEOUT) << "operation timed out"; + return -1; + case BUSYBEE_DISRUPTED: + handle_disruption(id); + continue; + case BUSYBEE_EXTERNAL: + continue; + BUSYBEE_ERROR_CASE(POLLFAILED); + BUSYBEE_ERROR_CASE(ADDFDFAIL); + BUSYBEE_ERROR_CASE(SHUTDOWN); + default: + ERROR(INTERNAL) << "internal error: BusyBee unexpectedly returned " + << (unsigned) rc << ": please file a bug"; + return -1; + } + e::unpacker up = msg->unpack_from(BUSYBEE_HEADER_SIZE); + uint8_t mt; + virtual_server_id vfrom; + int64_t nonce; + up = up >> mt >> vfrom >> nonce; + if (up.error()) + { + ERROR(SERVERERROR) << "communication error: server " + << sid_num << " sent message=" + << msg->as_slice().hex() + << " with invalid header"; + return -1; + } + network_msgtype msg_type = static_cast(mt); + pending_map_t::iterator it = m_pending_ops.find(nonce); + if (it == m_pending_ops.end()) + { + continue; + } + const pending_server_pair psp(it->second); + e::intrusive_ptr op = psp.op; + m_pending_ops.erase(it); + if (msg_type == CONFIGMISMATCH) + { + m_failed.push_back(psp); + continue; + } + if (vfrom == psp.vsi && + id == psp.si && + m_config.get_server_id(vfrom) == id) + { + if (!op->handle_message(this, id, vfrom, msg_type, msg, up, status, &m_last_error)) + { + return -1; + } + m_yielding = psp.op; + } + else + { + ERROR(SERVERERROR) << "wrong server replied for nonce=" << nonce + << ": expected it to come from " + << psp.vsi << "/" << psp.si + << "; it came from " + << vfrom << "/" << id + << "; our config says that virtual_id should map to " + << m_config.get_server_id(vfrom); + return -1; + } + } + uint64_t sid_num; + m_busybee.set_timeout(0); + busybee_returncode rc = m_busybee.recv_no_msg(&sid_num); + switch (rc) + { + case BUSYBEE_SUCCESS: + case BUSYBEE_TIMEOUT: + break; + case BUSYBEE_INTERRUPTED: + ERROR(INTERRUPTED) << "signal received"; + return -1; + case BUSYBEE_DISRUPTED: + handle_disruption(server_id(sid_num)); + break; + case BUSYBEE_EXTERNAL: + if (!maintain_coord_connection(status)) + { + return -1; + } + break; + BUSYBEE_ERROR_CASE(POLLFAILED); + BUSYBEE_ERROR_CASE(ADDFDFAIL); + BUSYBEE_ERROR_CASE(SHUTDOWN); + default: + ERROR(INTERNAL) << "internal error: BusyBee unexpectedly returned " + << (unsigned) rc << ": please file a bug"; + return -1; + } + ERROR(NONEPENDING) << "no outstanding operations to process"; + return -1; } int client :: poll_fd() { - return m_busybee.poll_fd(); + return m_busybee.poll_fd(); } void client :: adjust_flagfd() { - if (!m_failed.empty() || - !m_yieldable.empty() || - m_yielding.get()) - { - m_flagfd.set(); - } - - assert(m_yieldable.empty() || m_flagfd.isset()); + if (!m_failed.empty() || + !m_yieldable.empty() || + m_yielding.get()) + { + m_flagfd.set(); + } + assert(m_yieldable.empty() || m_flagfd.isset()); } int client :: block(int timeout) { - pollfd pfd; - pfd.fd = m_busybee.poll_fd(); - pfd.events = POLLIN|POLLHUP; - pfd.revents = 0; - return ::poll(&pfd, 1, timeout) >= 0 ? 0 : -1; + pollfd pfd; + pfd.fd = m_busybee.poll_fd(); + pfd.events = POLLIN | POLLHUP; + pfd.revents = 0; + return ::poll(&pfd, 1, timeout) >= 0 ? 0 : -1; } -const char* +const char * client :: error_message() { - return m_last_error.msg(); + return m_last_error.msg(); } -const char* +const char * client :: error_location() { - return m_last_error.loc(); + return m_last_error.loc(); } void -client :: set_error_message(const char* msg) +client :: set_error_message(const char *msg) { - m_last_error = e::error(); - m_last_error.set_loc(__FILE__, __LINE__); - m_last_error.set_msg() << msg; + m_last_error = e::error(); + m_last_error.set_loc(__FILE__, __LINE__); + m_last_error.set_msg() << msg; } hyperdatatype -client :: attribute_type(const char* space, const char* name, - hyperdex_client_returncode* status) +client :: attribute_type(const char *space, const char *name, + hyperdex_client_returncode *status) { - if (maintain_coord_connection(status) < 0) - { - return HYPERDATATYPE_GARBAGE; - } - - const hyperdex::schema* sc = m_config.get_schema(space); - - if (!sc) - { - ERROR(UNKNOWNSPACE) << "space \"" << e::strescape(space) << "\" does not exist"; - return HYPERDATATYPE_GARBAGE; - } - - uint16_t attrnum = sc->lookup_attr(name); - - if (attrnum == sc->attrs_sz) - { - ERROR(UNKNOWNATTR) << "\"" << e::strescape(name) - << "\" is not an attribute of space \"" - << e::strescape(space) << "\""; - return HYPERDATATYPE_GARBAGE; - } - - return sc->attrs[attrnum].type; + if (maintain_coord_connection(status) < 0) + { + return HYPERDATATYPE_GARBAGE; + } + const hyperdex::schema *sc = m_config.get_schema(space); + if (!sc) + { + ERROR(UNKNOWNSPACE) << "space \"" << e::strescape(space) << "\" does not exist"; + return HYPERDATATYPE_GARBAGE; + } + uint16_t attrnum = sc->lookup_attr(name); + if (attrnum == sc->attrs_sz) + { + ERROR(UNKNOWNATTR) << "\"" << e::strescape(name) + << "\" is not an attribute of space \"" + << e::strescape(space) << "\""; + return HYPERDATATYPE_GARBAGE; + } + return sc->attrs[attrnum].type; } size_t -client :: prepare_checks(const char* space, const schema& sc, - const hyperdex_client_attribute_check* chks, size_t chks_sz, - e::arena* memory, - hyperdex_client_returncode* status, - std::vector* checks) +client :: prepare_checks(const char *space, const schema &sc, + const hyperdex_client_attribute_check *chks, size_t chks_sz, + e::arena *memory, + hyperdex_client_returncode *status, + std::vector *checks) { - checks->reserve(checks->size() + chks_sz); - - for (size_t i = 0; i < chks_sz; ++i) - { - std::string scratch; - const char* attr; - const char* path; - parse_document_path(chks[i].attr, &attr, &path, &scratch); - uint16_t attrnum = sc.lookup_attr(attr); - - if (attrnum >= sc.attrs_sz) - { - ERROR(UNKNOWNATTR) << "\"" << e::strescape(attr) - << "\" is not an attribute of space \"" - << e::strescape(space) << "\""; - return i; - } - - hyperdatatype datatype = chks[i].datatype; - - if (datatype == CONTAINER_TYPE(datatype) && - CONTAINER_TYPE(datatype) == CONTAINER_TYPE(sc.attrs[attrnum].type) && - (chks[i].value_sz == 0 || datatype == HYPERDATATYPE_TIMESTAMP_GENERIC)) - { - datatype = sc.attrs[attrnum].type; - } - - attribute_check c; - c.attr = attrnum; - c.value = e::slice(chks[i].value, chks[i].value_sz); - c.datatype = datatype; - c.predicate = chks[i].predicate; - datatype_info* vtype = datatype_info::lookup(c.datatype); - - if (!vtype->client_to_server(c.value, memory, &c.value)) - { - ERROR(WRONGTYPE) << "check[" << i << "], which is on attribute \"" - << e::strescape(sc.attrs[attrnum].name) - << "\", does not meet the constraints of its type"; - return i; - } - - if (!path && datatype == HYPERDATATYPE_DOCUMENT) - { - // Document datatype always requires a path. Empty means root. - path = ""; - } - - if (path) - { - size_t path_sz = strlen(path) + 1; - size_t sz = path_sz + c.value.size(); - unsigned char* tmp = NULL; - memory->allocate(path_sz + c.value.size(), &tmp); - memmove(tmp, path, path_sz); - memmove(tmp + path_sz, c.value.data(), c.value.size()); - - c.value = e::slice(tmp, sz); - } - - if (!validate_attribute_check(sc.attrs[attrnum].type, c)) - { - ERROR(WRONGTYPE) << "invalid predicate on \"" - << e::strescape(attr) << "\""; - return i; - } - - checks->push_back(c); - } - - return chks_sz; + checks->reserve(checks->size() + chks_sz); + for (size_t i = 0; i < chks_sz; ++i) + { + std::string scratch; + const char *attr; + const char *path; + parse_document_path(chks[i].attr, &attr, &path, &scratch); + uint16_t attrnum = sc.lookup_attr(attr); + if (attrnum >= sc.attrs_sz) + { + ERROR(UNKNOWNATTR) << "\"" << e::strescape(attr) + << "\" is not an attribute of space \"" + << e::strescape(space) << "\""; + return i; + } + hyperdatatype datatype = chks[i].datatype; + if (datatype == CONTAINER_TYPE(datatype) && + CONTAINER_TYPE(datatype) == CONTAINER_TYPE(sc.attrs[attrnum].type) && + (chks[i].value_sz == 0 || datatype == HYPERDATATYPE_TIMESTAMP_GENERIC)) + { + datatype = sc.attrs[attrnum].type; + } + attribute_check c; + c.attr = attrnum; + c.value = e::slice(chks[i].value, chks[i].value_sz); + c.datatype = datatype; + c.predicate = chks[i].predicate; + datatype_info *vtype = datatype_info::lookup(c.datatype); + if (!vtype->client_to_server(c.value, memory, &c.value)) + { + ERROR(WRONGTYPE) << "check[" << i << "], which is on attribute \"" + << e::strescape(sc.attrs[attrnum].name) + << "\", does not meet the constraints of its type"; + return i; + } + if (!path && datatype == HYPERDATATYPE_DOCUMENT) + { + // Document datatype always requires a path. Empty means root. + path = ""; + } + if (path) + { + size_t path_sz = strlen(path) + 1; + size_t sz = path_sz + c.value.size(); + unsigned char *tmp = NULL; + memory->allocate(path_sz + c.value.size(), &tmp); + memmove(tmp, path, path_sz); + memmove(tmp + path_sz, c.value.data(), c.value.size()); + c.value = e::slice(tmp, sz); + } + if (!validate_attribute_check(sc.attrs[attrnum].type, c)) + { + ERROR(WRONGTYPE) << "invalid predicate on \"" + << e::strescape(attr) << "\""; + return i; + } + checks->push_back(c); + } + return chks_sz; } size_t -client :: prepare_funcs(const char* space, const schema& sc, - const hyperdex_client_keyop_info* opinfo, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - e::arena* memory, - hyperdex_client_returncode* status, - std::vector* funcs) +client :: prepare_funcs(const char *space, const schema &sc, + const hyperdex_client_keyop_info *opinfo, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + e::arena *memory, + hyperdex_client_returncode *status, + std::vector *funcs) { - funcs->reserve(funcs->size() + attrs_sz); - - for (size_t i = 0; i < attrs_sz; ++i) - { - std::string scratch; - const char* attr; - const char* path; - parse_document_path(attrs[i].attr, &attr, &path, &scratch); - uint16_t attrnum = sc.lookup_attr(attr); - - if (attrnum == sc.attrs_sz) - { - ERROR(UNKNOWNATTR) << "\"" << e::strescape(attr) - << "\" is not an attribute of space \"" - << e::strescape(space) << "\""; - return i; - } - - if (attrnum == 0) - { - ERROR(DONTUSEKEY) << "attribute \"" - << e::strescape(attrs[i].attr) - << "\" is the key and cannot be changed"; - return i; - } - - hyperdatatype datatype = attrs[i].datatype; - - if (datatype == CONTAINER_TYPE(datatype) && - CONTAINER_TYPE(datatype) == CONTAINER_TYPE(sc.attrs[attrnum].type) && - (attrs[i].value_sz == 0 || datatype == HYPERDATATYPE_TIMESTAMP_GENERIC)) - { - datatype = sc.attrs[attrnum].type; - } - - if (sc.attrs[attrnum].type == HYPERDATATYPE_MACAROON_SECRET) - { - datatype = HYPERDATATYPE_MACAROON_SECRET; - } - - funcall o; - o.attr = attrnum; - o.name = opinfo->fname; - o.arg1 = e::slice(attrs[i].value, attrs[i].value_sz); - o.arg1_datatype = datatype; - datatype_info* type = datatype_info::lookup(sc.attrs[attrnum].type); - datatype_info* a1type = datatype_info::lookup(o.arg1_datatype); - - if (m_convert_types) - { - if (!a1type->client_to_server(o.arg1, memory, &o.arg1)) - { - ERROR(WRONGTYPE) << "attribute \"" - << e::strescape(attrs[i].attr) - << "\" does not meet the constraints of its type"; - return i; - } - } - - if (path != NULL) - { - o.arg2 = e::slice(path, strlen(path) + 1); - o.arg2_datatype = HYPERDATATYPE_STRING; - } - - if (!type->check_args(o)) - { - ERROR(WRONGTYPE) << "invalid attribute \"" - << e::strescape(attrs[i].attr) - << "\": attribute has the wrong type"; - return i; - } - - funcs->push_back(o); - } - - return attrs_sz; + funcs->reserve(funcs->size() + attrs_sz); + for (size_t i = 0; i < attrs_sz; ++i) + { + std::string scratch; + const char *attr; + const char *path; + parse_document_path(attrs[i].attr, &attr, &path, &scratch); + uint16_t attrnum = sc.lookup_attr(attr); + if (attrnum == sc.attrs_sz) + { + ERROR(UNKNOWNATTR) << "\"" << e::strescape(attr) + << "\" is not an attribute of space \"" + << e::strescape(space) << "\""; + return i; + } + if (attrnum == 0) + { + ERROR(DONTUSEKEY) << "attribute \"" + << e::strescape(attrs[i].attr) + << "\" is the key and cannot be changed"; + return i; + } + hyperdatatype datatype = attrs[i].datatype; + if (datatype == CONTAINER_TYPE(datatype) && + CONTAINER_TYPE(datatype) == CONTAINER_TYPE(sc.attrs[attrnum].type) && + (attrs[i].value_sz == 0 || datatype == HYPERDATATYPE_TIMESTAMP_GENERIC)) + { + datatype = sc.attrs[attrnum].type; + } + if (sc.attrs[attrnum].type == HYPERDATATYPE_MACAROON_SECRET) + { + datatype = HYPERDATATYPE_MACAROON_SECRET; + } + funcall o; + o.attr = attrnum; + o.name = opinfo->fname; + o.arg1 = e::slice(attrs[i].value, attrs[i].value_sz); + o.arg1_datatype = datatype; + datatype_info *type = datatype_info::lookup(sc.attrs[attrnum].type); + datatype_info *a1type = datatype_info::lookup(o.arg1_datatype); + if (m_convert_types) + { + if (!a1type->client_to_server(o.arg1, memory, &o.arg1)) + { + ERROR(WRONGTYPE) << "attribute \"" + << e::strescape(attrs[i].attr) + << "\" does not meet the constraints of its type"; + return i; + } + } + if (path != NULL) + { + o.arg2 = e::slice(path, strlen(path) + 1); + o.arg2_datatype = HYPERDATATYPE_STRING; + } + if (!type->check_args(o)) + { + ERROR(WRONGTYPE) << "invalid attribute \"" + << e::strescape(attrs[i].attr) + << "\": attribute has the wrong type"; + return i; + } + funcs->push_back(o); + } + return attrs_sz; } size_t -client :: prepare_funcs(const char* space, const schema& sc, - const hyperdex_client_keyop_info* opinfo, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - e::arena* memory, - hyperdex_client_returncode* status, - std::vector* funcs) +client :: prepare_funcs(const char *space, const schema &sc, + const hyperdex_client_keyop_info *opinfo, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + e::arena *memory, + hyperdex_client_returncode *status, + std::vector *funcs) { - funcs->reserve(funcs->size() + mapattrs_sz); - - for (size_t i = 0; i < mapattrs_sz; ++i) - { - uint16_t attrnum = sc.lookup_attr(mapattrs[i].attr); - - if (attrnum == sc.attrs_sz) - { - ERROR(UNKNOWNATTR) << "\"" << e::strescape(mapattrs[i].attr) - << "\" is not an attribute of space \"" - << e::strescape(space) << "\""; - return i; - } - - if (attrnum == 0) - { - ERROR(DONTUSEKEY) << "attribute \"" - << e::strescape(mapattrs[i].attr) - << "\" is the key and cannot be changed"; - return i; - } - - hyperdatatype k_datatype = mapattrs[i].map_key_datatype; - - if (k_datatype == CONTAINER_TYPE(k_datatype) && - CONTAINER_TYPE(k_datatype) == CONTAINER_TYPE(sc.attrs[attrnum].type) && - mapattrs[i].value_sz == 0) - { - k_datatype = sc.attrs[attrnum].type; - } - - hyperdatatype v_datatype = mapattrs[i].value_datatype; - - if (v_datatype == CONTAINER_TYPE(v_datatype) && - CONTAINER_TYPE(v_datatype) == CONTAINER_TYPE(sc.attrs[attrnum].type) && - mapattrs[i].value_sz == 0) - { - v_datatype = sc.attrs[attrnum].type; - } - - funcall o; - o.attr = attrnum; - o.name = opinfo->fname; - o.arg2 = e::slice(mapattrs[i].map_key, mapattrs[i].map_key_sz); - o.arg2_datatype = k_datatype; - o.arg1 = e::slice(mapattrs[i].value, mapattrs[i].value_sz); - o.arg1_datatype = v_datatype; - datatype_info* type = datatype_info::lookup(sc.attrs[attrnum].type); - datatype_info* ktype = datatype_info::lookup(k_datatype); - datatype_info* vtype = datatype_info::lookup(k_datatype); - - if (!ktype->client_to_server(o.arg2, memory, &o.arg2)) - { - ERROR(WRONGTYPE) << "key of [" << i << "], which modifies attribute \"" - << e::strescape(mapattrs[i].attr) - << "\", does not meet the constraints of its type"; - return i; - } - - if (!vtype->client_to_server(o.arg1, memory, &o.arg1)) - { - ERROR(WRONGTYPE) << "value of [" << i << "], which modifies attribute \"" - << e::strescape(mapattrs[i].attr) - << "\", does not meet the constraints of its type"; - return i; - } - - if (!type->check_args(o)) - { - ERROR(WRONGTYPE) << "invalid attribute \"" - << e::strescape(mapattrs[i].attr) - << "\": attribute has the wrong type"; - return i; - } - - funcs->push_back(o); - } - - return mapattrs_sz; + funcs->reserve(funcs->size() + mapattrs_sz); + for (size_t i = 0; i < mapattrs_sz; ++i) + { + uint16_t attrnum = sc.lookup_attr(mapattrs[i].attr); + if (attrnum == sc.attrs_sz) + { + ERROR(UNKNOWNATTR) << "\"" << e::strescape(mapattrs[i].attr) + << "\" is not an attribute of space \"" + << e::strescape(space) << "\""; + return i; + } + if (attrnum == 0) + { + ERROR(DONTUSEKEY) << "attribute \"" + << e::strescape(mapattrs[i].attr) + << "\" is the key and cannot be changed"; + return i; + } + hyperdatatype k_datatype = mapattrs[i].map_key_datatype; + if (k_datatype == CONTAINER_TYPE(k_datatype) && + CONTAINER_TYPE(k_datatype) == CONTAINER_TYPE(sc.attrs[attrnum].type) && + mapattrs[i].value_sz == 0) + { + k_datatype = sc.attrs[attrnum].type; + } + hyperdatatype v_datatype = mapattrs[i].value_datatype; + if (v_datatype == CONTAINER_TYPE(v_datatype) && + CONTAINER_TYPE(v_datatype) == CONTAINER_TYPE(sc.attrs[attrnum].type) && + mapattrs[i].value_sz == 0) + { + v_datatype = sc.attrs[attrnum].type; + } + funcall o; + o.attr = attrnum; + o.name = opinfo->fname; + o.arg2 = e::slice(mapattrs[i].map_key, mapattrs[i].map_key_sz); + o.arg2_datatype = k_datatype; + o.arg1 = e::slice(mapattrs[i].value, mapattrs[i].value_sz); + o.arg1_datatype = v_datatype; + datatype_info *type = datatype_info::lookup(sc.attrs[attrnum].type); + datatype_info *ktype = datatype_info::lookup(k_datatype); + datatype_info *vtype = datatype_info::lookup(k_datatype); + if (!ktype->client_to_server(o.arg2, memory, &o.arg2)) + { + ERROR(WRONGTYPE) << "key of [" << i << "], which modifies attribute \"" + << e::strescape(mapattrs[i].attr) + << "\", does not meet the constraints of its type"; + return i; + } + if (!vtype->client_to_server(o.arg1, memory, &o.arg1)) + { + ERROR(WRONGTYPE) << "value of [" << i << "], which modifies attribute \"" + << e::strescape(mapattrs[i].attr) + << "\", does not meet the constraints of its type"; + return i; + } + if (!type->check_args(o)) + { + ERROR(WRONGTYPE) << "invalid attribute \"" + << e::strescape(mapattrs[i].attr) + << "\": attribute has the wrong type"; + return i; + } + funcs->push_back(o); + } + return mapattrs_sz; } size_t -client :: prepare_searchop(const schema& sc, - const char* space, - const hyperdex_client_attribute_check* chks, size_t chks_sz, - e::arena* memory, - hyperdex_client_returncode* status, - std::vector* checks, - std::vector* servers) +client :: prepare_searchop(const schema &sc, + const char *space, + const hyperdex_client_attribute_check *chks, size_t chks_sz, + e::arena *memory, + hyperdex_client_returncode *status, + std::vector *checks, + std::vector *servers) { - size_t num_checks = prepare_checks(space, sc, chks, chks_sz, memory, status, checks); - - if (num_checks != chks_sz) - { - return -1 - num_checks; - } - - std::stable_sort(checks->begin(), checks->end()); - m_config.lookup_search(space, *checks, servers); // XXX search guaranteed empty vs. search encounters offline server - - if (servers->empty()) - { - // XXX NOCOMMIT - ERROR(INTERNAL) << "there are no servers for the search"; - *status = HYPERDEX_CLIENT_INTERNAL; - return -1; - } - - return 0; + size_t num_checks = prepare_checks(space, sc, chks, chks_sz, memory, status, checks); + if (num_checks != chks_sz) + { + return -1 - num_checks; + } + std::stable_sort(checks->begin(), checks->end()); + m_config.lookup_search(space, *checks, servers); // XXX search guaranteed empty vs. search encounters offline server + if (servers->empty()) + { + // XXX NOCOMMIT + ERROR(INTERNAL) << "there are no servers for the search"; + *status = HYPERDEX_CLIENT_INTERNAL; + return -1; + } + return 0; } int64_t -client :: perform_funcall(const char* space, const schema* sc, - const hyperdex_client_keyop_info* opinfo, - const hyperdex_client_attribute_check* chks, size_t chks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, +client :: perform_funcall(const char *space, const schema *sc, + const hyperdex_client_keyop_info *opinfo, + const hyperdex_client_attribute_check *chks, size_t chks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, size_t header_sz, size_t footer_sz, - hyperdex_client_returncode* status, - std::auto_ptr* msg) + hyperdex_client_returncode *status, + std::auto_ptr *msg) { - std::vector checks; - std::vector funcs; - size_t idx = 0; - e::arena memory; - - // Prepare the checks - idx = prepare_checks(space, *sc, chks, chks_sz, &memory, status, &checks); - - if (idx < chks_sz) - { - return -2 - idx; - } - - // Prepare the attrs - idx = prepare_funcs(space, *sc, opinfo, attrs, attrs_sz, &memory, status, &funcs); - - if (idx < attrs_sz) - { - return -2 - chks_sz - idx; - } - - // Prepare the mapattrs - idx = prepare_funcs(space, *sc, opinfo, mapattrs, mapattrs_sz, &memory, status, &funcs); - - if (idx < mapattrs_sz) - { - return -2 - chks_sz - attrs_sz - idx; - } - - std::stable_sort(checks.begin(), checks.end()); - std::stable_sort(funcs.begin(), funcs.end()); - size_t sz = header_sz + footer_sz - + sizeof(uint8_t) - + pack_size(checks) - + pack_size(funcs); - msg->reset(e::buffer::create(sz)); - uint8_t flags = (opinfo->fail_if_not_found ? 1 : 0) - | (opinfo->fail_if_found ? 2 : 0) - | (opinfo->erase ? 0 : 128) - | (m_macaroons_sz ? 64 : 0); - (*msg)->pack_at(header_sz) << flags << checks << funcs; - return 0; + std::vector checks; + std::vector funcs; + size_t idx = 0; + e::arena memory; + // Prepare the checks + idx = prepare_checks(space, *sc, chks, chks_sz, &memory, status, &checks); + if (idx < chks_sz) + { + return -2 - idx; + } + // Prepare the attrs + idx = prepare_funcs(space, *sc, opinfo, attrs, attrs_sz, &memory, status, &funcs); + if (idx < attrs_sz) + { + return -2 - chks_sz - idx; + } + // Prepare the mapattrs + idx = prepare_funcs(space, *sc, opinfo, mapattrs, mapattrs_sz, &memory, status, &funcs); + if (idx < mapattrs_sz) + { + return -2 - chks_sz - attrs_sz - idx; + } + std::stable_sort(checks.begin(), checks.end()); + std::stable_sort(funcs.begin(), funcs.end()); + size_t sz = header_sz + footer_sz + + sizeof(uint8_t) + + pack_size(checks) + + pack_size(funcs); + msg->reset(e::buffer::create(sz)); + uint8_t flags = (opinfo->fail_if_not_found ? 1 : 0) + | (opinfo->fail_if_found ? 2 : 0) + | (opinfo->erase ? 0 : 128) + | (m_macaroons_sz ? 64 : 0); + (*msg)->pack_at(header_sz) << flags << checks << funcs; + return 0; } int64_t -client :: perform_aggregation(const std::vector& servers, +client :: perform_aggregation(const std::vector &servers, e::intrusive_ptr _op, network_msgtype mt, std::auto_ptr msg, - hyperdex_client_returncode* status) + hyperdex_client_returncode *status) { - e::intrusive_ptr op(_op.get()); - - for (size_t i = 0; i < servers.size(); ++i) - { - uint64_t nonce = m_next_server_nonce++; - pending_server_pair psp(m_config.get_server_id(servers[i]), servers[i], op); - std::auto_ptr msg_copy(msg->copy()); - - if (!send(mt, psp.vsi, nonce, msg_copy, op, status)) - { - m_failed.push_back(psp); - } - } - - return op->client_visible_id(); + e::intrusive_ptr op(_op.get()); + for (size_t i = 0; i < servers.size(); ++i) + { + uint64_t nonce = m_next_server_nonce++; + pending_server_pair psp(m_config.get_server_id(servers[i]), servers[i], op); + std::auto_ptr msg_copy(msg->copy()); + if (!send(mt, psp.vsi, nonce, msg_copy, op, status)) + { + m_failed.push_back(psp); + } + } + return op->client_visible_id(); } bool -client :: maintain_coord_connection(hyperdex_client_returncode* status) +client :: maintain_coord_connection(hyperdex_client_returncode *status) { - if (m_config_status != REPLICANT_SUCCESS) - { - replicant_client_kill(m_coord, m_config_id); - m_config_id = -1; - } - - replicant_returncode rc; - - if (m_config_id < 0) - { - m_config_status = REPLICANT_SUCCESS; - m_config_id = replicant_client_cond_follow(m_coord, "hyperdex", "config", - &m_config_status, &m_config_state, - &m_config_data, &m_config_data_sz); - if (replicant_client_wait(m_coord, m_config_id, -1, &rc) < 0) - { - ERROR(COORDFAIL) << "coordinator failure: " << replicant_client_error_message(m_coord); - return false; - } - } - - if (replicant_client_loop(m_coord, 0, &rc) < 0) - { - if (rc == REPLICANT_INTERRUPTED) - { - ERROR(INTERRUPTED) << "interrupted by a signal"; - return false; - } - else if (rc != REPLICANT_NONE_PENDING && rc != REPLICANT_TIMEOUT) - { - ERROR(COORDFAIL) << "coordinator failure: " << replicant_client_error_message(m_coord); - return false; - } - } - - if (m_config.version() < m_config_state) - { - configuration new_config; - e::unpacker up(m_config_data, m_config_data_sz); - up = up >> new_config; - - if (!up.error()) - { - m_config = new_config; - } - - pending_map_t::iterator it = m_pending_ops.begin(); - - while (it != m_pending_ops.end()) - { - // If the mapping that was true when the operation started is no - // longer true, we fail the operation with a RECONFIGURE. - if (m_config.get_server_id(it->second.vsi) != it->second.si) - { - m_failed.push_back(it->second); - m_pending_ops.erase(it); - it = m_pending_ops.begin(); - } - else - { - ++it; - } - } - } - - return true; + if (m_config_status != REPLICANT_SUCCESS) + { + replicant_client_kill(m_coord, m_config_id); + m_config_id = -1; + } + replicant_returncode rc; + if (m_config_id < 0) + { + m_config_status = REPLICANT_SUCCESS; + m_config_id = replicant_client_cond_follow(m_coord, "hyperdex", "config", + &m_config_status, &m_config_state, + &m_config_data, &m_config_data_sz); + if (replicant_client_wait(m_coord, m_config_id, -1, &rc) < 0) + { + ERROR(COORDFAIL) << "coordinator failure: " << replicant_client_error_message(m_coord); + return false; + } + } + if (replicant_client_loop(m_coord, 0, &rc) < 0) + { + if (rc == REPLICANT_INTERRUPTED) + { + ERROR(INTERRUPTED) << "interrupted by a signal"; + return false; + } + else if (rc != REPLICANT_NONE_PENDING && rc != REPLICANT_TIMEOUT) + { + ERROR(COORDFAIL) << "coordinator failure: " << replicant_client_error_message(m_coord); + return false; + } + } + if (m_config.version() < m_config_state) + { + configuration new_config; + e::unpacker up(m_config_data, m_config_data_sz); + up = up >> new_config; + if (!up.error()) + { + m_config = new_config; + } + pending_map_t::iterator it = m_pending_ops.begin(); + while (it != m_pending_ops.end()) + { + // If the mapping that was true when the operation started is no + // longer true, we fail the operation with a RECONFIGURE. + if (m_config.get_server_id(it->second.vsi) != it->second.si) + { + m_failed.push_back(it->second); + m_pending_ops.erase(it); + it = m_pending_ops.begin(); + } + else + { + ++it; + } + } + } + return true; } bool client :: send(network_msgtype mt, - const virtual_server_id& to, + const virtual_server_id &to, uint64_t nonce, std::auto_ptr msg, e::intrusive_ptr op, - hyperdex_client_returncode* status) + hyperdex_client_returncode *status) { - const uint8_t type = static_cast(mt); - const uint8_t flags = 0; - const uint64_t version = m_config.version(); - msg->pack_at(BUSYBEE_HEADER_SIZE) - << type << flags << version << to << nonce; - server_id id = m_config.get_server_id(to); - m_busybee.set_timeout(-1); - busybee_returncode rc = m_busybee.send(id.get(), msg); - - switch (rc) - { - case BUSYBEE_SUCCESS: - op->handle_sent_to(id, to); - m_pending_ops.insert(std::make_pair(nonce, pending_server_pair(id, to, op))); - return true; - case BUSYBEE_DISRUPTED: - handle_disruption(id); - ERROR(SERVERERROR) << "server " << id.get() << " had a communication disruption"; - return false; - BUSYBEE_ERROR_CASE_FALSE(SHUTDOWN); - BUSYBEE_ERROR_CASE_FALSE(POLLFAILED); - BUSYBEE_ERROR_CASE_FALSE(ADDFDFAIL); - BUSYBEE_ERROR_CASE_FALSE(TIMEOUT); - BUSYBEE_ERROR_CASE_FALSE(EXTERNAL); - BUSYBEE_ERROR_CASE_FALSE(INTERRUPTED); - default: - ERROR(INTERNAL) << "internal error: BusyBee unexpectedly returned " - << (unsigned) rc << ": please file a bug"; - return false; - } + const uint8_t type = static_cast(mt); + const uint8_t flags = 0; + const uint64_t version = m_config.version(); + msg->pack_at(BUSYBEE_HEADER_SIZE) + << type << flags << version << to << nonce; + server_id id = m_config.get_server_id(to); + m_busybee.set_timeout(-1); + busybee_returncode rc = m_busybee.send(id.get(), msg); + switch (rc) + { + case BUSYBEE_SUCCESS: + op->handle_sent_to(id, to); + m_pending_ops.insert(std::make_pair(nonce, pending_server_pair(id, to, op))); + return true; + case BUSYBEE_DISRUPTED: + handle_disruption(id); + ERROR(SERVERERROR) << "server " << id.get() << " had a communication disruption"; + return false; + BUSYBEE_ERROR_CASE_FALSE(SHUTDOWN); + BUSYBEE_ERROR_CASE_FALSE(POLLFAILED); + BUSYBEE_ERROR_CASE_FALSE(ADDFDFAIL); + BUSYBEE_ERROR_CASE_FALSE(TIMEOUT); + BUSYBEE_ERROR_CASE_FALSE(EXTERNAL); + BUSYBEE_ERROR_CASE_FALSE(INTERRUPTED); + default: + ERROR(INTERNAL) << "internal error: BusyBee unexpectedly returned " + << (unsigned) rc << ": please file a bug"; + return false; + } } int64_t -client :: send_keyop(const char* space, - const e::slice& key, +client :: send_keyop(const char *space, + const e::slice &key, network_msgtype mt, std::auto_ptr msg, e::intrusive_ptr op, - hyperdex_client_returncode* status) + hyperdex_client_returncode *status) { - virtual_server_id vsi = m_config.point_leader(space, key); - - if (vsi == virtual_server_id()) - { - ERROR(OFFLINE) << "all servers for key \"" - << e::strescape(std::string(reinterpret_cast(key.data()), key.size())) - << "\" in space \"" << e::strescape(space) - << "\" are offline: bring one or more online to remedy the issue"; - return -1; - } - - int64_t nonce = m_next_server_nonce++; - - if (send(mt, vsi, nonce, msg, op, status)) - { - return op->client_visible_id(); - } - else - { - ERROR(RECONFIGURE) << "could not send " << mt << " to " << vsi; - return -1; - } + virtual_server_id vsi = m_config.point_leader(space, key); + if (vsi == virtual_server_id()) + { + ERROR(OFFLINE) << "all servers for key \"" + << e::strescape(std::string(reinterpret_cast(key.data()), key.size())) + << "\" in space \"" << e::strescape(space) + << "\" are offline: bring one or more online to remedy the issue"; + return -1; + } + int64_t nonce = m_next_server_nonce++; + if (send(mt, vsi, nonce, msg, op, status)) + { + return op->client_visible_id(); + } + else + { + ERROR(RECONFIGURE) << "could not send " << mt << " to " << vsi; + return -1; + } } void -client :: handle_disruption(const server_id& si) +client :: handle_disruption(const server_id &si) { - pending_map_t::iterator it = m_pending_ops.begin(); - - while (it != m_pending_ops.end()) - { - if (it->second.si == si) - { - m_failed.push_back(it->second); - pending_map_t::iterator tmp = it; - ++it; - m_pending_ops.erase(tmp); - } - else - { - ++it; - } - } - - m_busybee.drop(si.get()); + pending_map_t::iterator it = m_pending_ops.begin(); + while (it != m_pending_ops.end()) + { + if (it->second.si == si) + { + m_failed.push_back(it->second); + pending_map_t::iterator tmp = it; + ++it; + m_pending_ops.erase(tmp); + } + else + { + ++it; + } + } + m_busybee.drop(si.get()); } -microtransaction* client::uxact_init(const char* space, hyperdex_client_returncode *status) +microtransaction *client::uxact_init(const char *space, hyperdex_client_returncode *status) { - if (!maintain_coord_connection(status)) - { - return NULL; - } - - const schema* sc = m_config.get_schema(space); - - if (!sc) - { - ERROR(UNKNOWNSPACE) << "space \"" << e::strescape(space) << "\" does not exist"; - return NULL; - } - - return new microtransaction(space, *sc, status); + if (!maintain_coord_connection(status)) + { + return NULL; + } + const schema *sc = m_config.get_schema(space); + if (!sc) + { + ERROR(UNKNOWNSPACE) << "space \"" << e::strescape(space) << "\" does not exist"; + return NULL; + } + return new microtransaction(space, *sc, status); } int64_t client::uxact_add_funcall(microtransaction *transaction, - const hyperdex_client_keyop_info* opinfo, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz) + const hyperdex_client_keyop_info *opinfo, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz) { - size_t idx = 0; - - // Prepare the attrs - idx = prepare_funcs(transaction->space, transaction->sc, opinfo, attrs, attrs_sz, &transaction->memory, transaction->status, &transaction->funcalls); - - if (idx < attrs_sz) - { - return -2 - idx; - } - - // Prepare the mapattrs - idx = prepare_funcs(transaction->space, transaction->sc, opinfo, mapattrs, mapattrs_sz, &transaction->memory, transaction->status, &transaction->funcalls); - - if (idx < mapattrs_sz) - { - return -2 - attrs_sz - idx; - } - - return 0; + size_t idx = 0; + // Prepare the attrs + idx = prepare_funcs(transaction->space, transaction->sc, opinfo, attrs, attrs_sz, &transaction->memory, transaction->status, &transaction->funcalls); + if (idx < attrs_sz) + { + return -2 - idx; + } + // Prepare the mapattrs + idx = prepare_funcs(transaction->space, transaction->sc, opinfo, mapattrs, mapattrs_sz, &transaction->memory, transaction->status, &transaction->funcalls); + if (idx < mapattrs_sz) + { + return -2 - attrs_sz - idx; + } + return 0; } int64_t client::uxact_commit(microtransaction *transaction, - const char* _key, size_t _key_sz) + const char *_key, size_t _key_sz) { - hyperdex_client_returncode *status = transaction->status; - - datatype_info* di = datatype_info::lookup(transaction->sc.attrs[0].type); - assert(di); - e::slice key(_key, _key_sz); - - if (!di->validate(key)) - { - ERROR(WRONGTYPE) << "key must be type " << transaction->sc.attrs[0].type; - return -1; - } - - e::intrusive_ptr op; - op = new pending_atomic(m_next_client_id++, status); - std::auto_ptr msg; - auth_wallet aw(m_macaroons, m_macaroons_sz); - size_t header_sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ - + pack_size(key); - size_t footer_sz = 0; - - if (m_macaroons_sz) - { - footer_sz += pack_size(aw); - } - - const std::vector checks; - int ret = transaction->generate_message(header_sz, footer_sz, checks, &msg); - - if (ret < 0) - { - return ret; - } - - msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << key; - - if (m_macaroons_sz) - { - msg->pack_at(msg->capacity() - footer_sz) << aw; - } - - int64_t result = send_keyop(transaction->space, key, REQ_ATOMIC, msg, op, status); - delete transaction; - return result; + hyperdex_client_returncode *status = transaction->status; + datatype_info *di = datatype_info::lookup(transaction->sc.attrs[0].type); + assert(di); + e::slice key(_key, _key_sz); + if (!di->validate(key)) + { + ERROR(WRONGTYPE) << "key must be type " << transaction->sc.attrs[0].type; + return -1; + } + e::intrusive_ptr op; + op = new pending_atomic(m_next_client_id++, status); + std::auto_ptr msg; + auth_wallet aw(m_macaroons, m_macaroons_sz); + size_t header_sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ + + pack_size(key); + size_t footer_sz = 0; + if (m_macaroons_sz) + { + footer_sz += pack_size(aw); + } + const std::vector checks; + int ret = transaction->generate_message(header_sz, footer_sz, checks, &msg); + if (ret < 0) + { + return ret; + } + msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << key; + if (m_macaroons_sz) + { + msg->pack_at(msg->capacity() - footer_sz) << aw; + } + int64_t result = send_keyop(transaction->space, key, REQ_ATOMIC, msg, op, status); + delete transaction; + return result; } int64_t client :: uxact_cond_commit(microtransaction *transaction, - const char* _key, size_t _key_sz, - const hyperdex_client_attribute_check* chks, size_t chks_sz) + const char *_key, size_t _key_sz, + const hyperdex_client_attribute_check *chks, size_t chks_sz) { - hyperdex_client_returncode *status = transaction->status; - - datatype_info* di = datatype_info::lookup(transaction->sc.attrs[0].type); - assert(di); - e::slice key(_key, _key_sz); - - if (!di->validate(key)) - { - ERROR(WRONGTYPE) << "key must be type " << transaction->sc.attrs[0].type; - return -2; - } - - e::intrusive_ptr op; - op = new pending_atomic(m_next_client_id++, status); - std::auto_ptr msg; - auth_wallet aw(m_macaroons, m_macaroons_sz); - size_t header_sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ - + pack_size(key); - size_t footer_sz = 0; - - if (m_macaroons_sz) - { - footer_sz += pack_size(aw); - } - - // Prepare the checks - std::vector checks; - uint64_t idx = prepare_checks(transaction->space, transaction->sc, chks, chks_sz, &transaction->memory, status, &checks); - - if (idx < chks_sz) - { - return -2 - idx; - } - - int ret = transaction->generate_message(header_sz, footer_sz, checks, &msg); - - if (ret < 0) - { - return ret; - } - - msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << key; - - if (m_macaroons_sz) - { - msg->pack_at(msg->capacity() - footer_sz) << aw; - } - - int64_t result = send_keyop(transaction->space, key, REQ_ATOMIC, msg, op, status); - delete transaction; - return result; + hyperdex_client_returncode *status = transaction->status; + datatype_info *di = datatype_info::lookup(transaction->sc.attrs[0].type); + assert(di); + e::slice key(_key, _key_sz); + if (!di->validate(key)) + { + ERROR(WRONGTYPE) << "key must be type " << transaction->sc.attrs[0].type; + return -2; + } + e::intrusive_ptr op; + op = new pending_atomic(m_next_client_id++, status); + std::auto_ptr msg; + auth_wallet aw(m_macaroons, m_macaroons_sz); + size_t header_sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ + + pack_size(key); + size_t footer_sz = 0; + if (m_macaroons_sz) + { + footer_sz += pack_size(aw); + } + // Prepare the checks + std::vector checks; + uint64_t idx = prepare_checks(transaction->space, transaction->sc, chks, chks_sz, &transaction->memory, status, &checks); + if (idx < chks_sz) + { + return -2 - idx; + } + int ret = transaction->generate_message(header_sz, footer_sz, checks, &msg); + if (ret < 0) + { + return ret; + } + msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << key; + if (m_macaroons_sz) + { + msg->pack_at(msg->capacity() - footer_sz) << aw; + } + int64_t result = send_keyop(transaction->space, key, REQ_ATOMIC, msg, op, status); + delete transaction; + return result; } int64_t client :: uxact_group_commit(microtransaction *transaction, - const hyperdex_client_attribute_check* chks, size_t chks_sz, - uint64_t *update_count) + const hyperdex_client_attribute_check *chks, size_t chks_sz, + uint64_t *update_count) { - hyperdex_client_returncode *status = transaction->status; - const char *space = transaction->space; - - SEARCH_BOILERPLATE - - int64_t client_id = m_next_client_id++; - e::intrusive_ptr op; - op = new pending_group_atomic(client_id, status, update_count); - - std::auto_ptr inner_msg; - const std::vector checks_; - ret = transaction->generate_message(0, 0, checks_, &inner_msg); - - if (ret < 0) - { - return ret; - } - - size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ - + sizeof(uint64_t) - + pack_size(checks) - + inner_msg->size(); - std::auto_ptr msg(e::buffer::create(sz)); - e::packer pa = msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ); - e::slice ims = inner_msg->as_slice(); - pa = pa << checks << e::pack_memmove(ims.data(), ims.size()); - - int64_t result = perform_aggregation(servers, op, REQ_GROUP_ATOMIC, msg, status); - delete transaction; - return result; + hyperdex_client_returncode *status = transaction->status; + const char *space = transaction->space; + SEARCH_BOILERPLATE + int64_t client_id = m_next_client_id++; + e::intrusive_ptr op; + op = new pending_group_atomic(client_id, status, update_count); + std::auto_ptr inner_msg; + const std::vector checks_; + ret = transaction->generate_message(0, 0, checks_, &inner_msg); + if (ret < 0) + { + return ret; + } + size_t sz = HYPERDEX_CLIENT_HEADER_SIZE_REQ + + sizeof(uint64_t) + + pack_size(checks) + + inner_msg->size(); + std::auto_ptr msg(e::buffer::create(sz)); + e::packer pa = msg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ); + e::slice ims = inner_msg->as_slice(); + pa = pa << checks << e::pack_memmove(ims.data(), ims.size()); + int64_t result = perform_aggregation(servers, op, REQ_GROUP_ATOMIC, msg, status); + delete transaction; + return result; } -HYPERDEX_API std::ostream& -operator << (std::ostream& lhs, hyperdex_client_returncode rhs) +HYPERDEX_API std::ostream & +operator << (std::ostream &lhs, hyperdex_client_returncode rhs) { - switch (rhs) - { - STRINGIFY(HYPERDEX_CLIENT_SUCCESS); - STRINGIFY(HYPERDEX_CLIENT_NOTFOUND); - STRINGIFY(HYPERDEX_CLIENT_SEARCHDONE); - STRINGIFY(HYPERDEX_CLIENT_CMPFAIL); - STRINGIFY(HYPERDEX_CLIENT_READONLY); - STRINGIFY(HYPERDEX_CLIENT_UNKNOWNSPACE); - STRINGIFY(HYPERDEX_CLIENT_COORDFAIL); - STRINGIFY(HYPERDEX_CLIENT_SERVERERROR); - STRINGIFY(HYPERDEX_CLIENT_POLLFAILED); - STRINGIFY(HYPERDEX_CLIENT_OVERFLOW); - STRINGIFY(HYPERDEX_CLIENT_RECONFIGURE); - STRINGIFY(HYPERDEX_CLIENT_TIMEOUT); - STRINGIFY(HYPERDEX_CLIENT_UNKNOWNATTR); - STRINGIFY(HYPERDEX_CLIENT_DUPEATTR); - STRINGIFY(HYPERDEX_CLIENT_NONEPENDING); - STRINGIFY(HYPERDEX_CLIENT_DONTUSEKEY); - STRINGIFY(HYPERDEX_CLIENT_WRONGTYPE); - STRINGIFY(HYPERDEX_CLIENT_NOMEM); - STRINGIFY(HYPERDEX_CLIENT_INTERRUPTED); - STRINGIFY(HYPERDEX_CLIENT_CLUSTER_JUMP); - STRINGIFY(HYPERDEX_CLIENT_OFFLINE); - STRINGIFY(HYPERDEX_CLIENT_UNAUTHORIZED); - STRINGIFY(HYPERDEX_CLIENT_INTERNAL); - STRINGIFY(HYPERDEX_CLIENT_EXCEPTION); - STRINGIFY(HYPERDEX_CLIENT_GARBAGE); - default: - lhs << "unknown hyperdex_client_returncode"; - return lhs; - } - - return lhs; + switch (rhs) + { + STRINGIFY(HYPERDEX_CLIENT_SUCCESS); + STRINGIFY(HYPERDEX_CLIENT_NOTFOUND); + STRINGIFY(HYPERDEX_CLIENT_SEARCHDONE); + STRINGIFY(HYPERDEX_CLIENT_CMPFAIL); + STRINGIFY(HYPERDEX_CLIENT_READONLY); + STRINGIFY(HYPERDEX_CLIENT_UNKNOWNSPACE); + STRINGIFY(HYPERDEX_CLIENT_COORDFAIL); + STRINGIFY(HYPERDEX_CLIENT_SERVERERROR); + STRINGIFY(HYPERDEX_CLIENT_POLLFAILED); + STRINGIFY(HYPERDEX_CLIENT_OVERFLOW); + STRINGIFY(HYPERDEX_CLIENT_RECONFIGURE); + STRINGIFY(HYPERDEX_CLIENT_TIMEOUT); + STRINGIFY(HYPERDEX_CLIENT_UNKNOWNATTR); + STRINGIFY(HYPERDEX_CLIENT_DUPEATTR); + STRINGIFY(HYPERDEX_CLIENT_NONEPENDING); + STRINGIFY(HYPERDEX_CLIENT_DONTUSEKEY); + STRINGIFY(HYPERDEX_CLIENT_WRONGTYPE); + STRINGIFY(HYPERDEX_CLIENT_NOMEM); + STRINGIFY(HYPERDEX_CLIENT_INTERRUPTED); + STRINGIFY(HYPERDEX_CLIENT_CLUSTER_JUMP); + STRINGIFY(HYPERDEX_CLIENT_OFFLINE); + STRINGIFY(HYPERDEX_CLIENT_UNAUTHORIZED); + STRINGIFY(HYPERDEX_CLIENT_INTERNAL); + STRINGIFY(HYPERDEX_CLIENT_EXCEPTION); + STRINGIFY(HYPERDEX_CLIENT_GARBAGE); + default: + lhs << "unknown hyperdex_client_returncode"; + return lhs; + } + return lhs; } // enable or disable type conversion on the client-side void client :: set_type_conversion(bool enabled) { - m_convert_types = enabled; + m_convert_types = enabled; } int64_t microtransaction::generate_message(size_t header_sz, size_t footer_sz, - const std::vector& checks, - std::auto_ptr* msg) + const std::vector &checks, + std::auto_ptr *msg) { - const bool fail_if_not_found = false; - const bool fail_if_found = false; - const bool erase = false; - - std::stable_sort(funcalls.begin(), funcalls.end()); - size_t sz = header_sz + footer_sz - + sizeof(uint8_t) - + pack_size(checks) - + pack_size(funcalls); - msg->reset(e::buffer::create(sz)); - uint8_t flags = (fail_if_not_found ? 1 : 0) - | (fail_if_found ? 2 : 0) - | (erase ? 0 : 128); - (*msg)->pack_at(header_sz) << flags << checks << funcalls; - return 0; + const bool fail_if_not_found = false; + const bool fail_if_found = false; + const bool erase = false; + std::stable_sort(funcalls.begin(), funcalls.end()); + size_t sz = header_sz + footer_sz + + sizeof(uint8_t) + + pack_size(checks) + + pack_size(funcalls); + msg->reset(e::buffer::create(sz)); + uint8_t flags = (fail_if_not_found ? 1 : 0) + | (fail_if_found ? 2 : 0) + | (erase ? 0 : 128); + (*msg)->pack_at(header_sz) << flags << checks << funcalls; + return 0; } diff --git a/client/client.h b/client/client.h index c7b8154ec..a3c6c8115 100644 --- a/client/client.h +++ b/client/client.h @@ -53,238 +53,238 @@ BEGIN_HYPERDEX_NAMESPACE struct microtransaction { - microtransaction(const char* space_, const schema& sc_, - hyperdex_client_returncode *status_) - : space(space_), sc(sc_), status(status_), funcalls(), memory() - {} + microtransaction(const char *space_, const schema &sc_, + hyperdex_client_returncode *status_) + : space(space_), sc(sc_), status(status_), funcalls(), memory() + {} - int64_t generate_message(size_t header_sz, size_t footer_sz, - const std::vector& checks, - std::auto_ptr* msg); + int64_t generate_message(size_t header_sz, size_t footer_sz, + const std::vector &checks, + std::auto_ptr *msg); - const char* space; - const schema& sc; - hyperdex_client_returncode* status; - std::vector funcalls; - e::arena memory; + const char *space; + const schema ≻ + hyperdex_client_returncode *status; + std::vector funcalls; + e::arena memory; - private: - microtransaction(const microtransaction&); - microtransaction& operator = (const microtransaction&); +private: + microtransaction(const microtransaction &); + microtransaction &operator = (const microtransaction &); }; class client { - public: - client(const char* coordinator, uint16_t port); - client(const char* conn_str); - ~client() throw (); +public: + client(const char *coordinator, uint16_t port); + client(const char *conn_str); + ~client() throw (); - public: - void clear_auth_context() { m_macaroons = NULL; m_macaroons_sz = 0; } - void set_auth_context(const char** macaroons, size_t macaroons_sz) - { m_macaroons = macaroons; m_macaroons_sz = macaroons_sz; } +public: + void clear_auth_context() { m_macaroons = NULL; m_macaroons_sz = 0; } + void set_auth_context(const char **macaroons, size_t macaroons_sz) + { m_macaroons = macaroons; m_macaroons_sz = macaroons_sz; } - public: - // specific calls - int64_t get(const char* space, const char* key, size_t key_sz, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz); - int64_t get_partial(const char* space, const char* key, size_t key_sz, - const char** attrnames, size_t attrnames_sz, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz); - int64_t search(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz); - int64_t search_describe(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - hyperdex_client_returncode* status, const char** description); - int64_t sorted_search(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const char* sort_by, - uint64_t limit, - bool maximize, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz); - int64_t group_del(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - hyperdex_client_returncode* status); - int64_t count(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - hyperdex_client_returncode* status, uint64_t* result); - int64_t sum(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const char* sum_key, hyperdex_client_returncode* status, uint64_t* result); +public: + // specific calls + int64_t get(const char *space, const char *key, size_t key_sz, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz); + int64_t get_partial(const char *space, const char *key, size_t key_sz, + const char **attrnames, size_t attrnames_sz, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz); + int64_t search(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz); + int64_t search_describe(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + hyperdex_client_returncode *status, const char **description); + int64_t sorted_search(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const char *sort_by, + uint64_t limit, + bool maximize, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz); + int64_t group_del(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + hyperdex_client_returncode *status); + int64_t count(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + hyperdex_client_returncode *status, uint64_t *result); + int64_t sum(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const char *sum_key, hyperdex_client_returncode *status, uint64_t *result); - // General keyop call - // This will be called by the bindings from c.cc - int64_t perform_funcall(const hyperdex_client_keyop_info* opinfo, - const char* space, const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status); + // General keyop call + // This will be called by the bindings from c.cc + int64_t perform_funcall(const hyperdex_client_keyop_info *opinfo, + const char *space, const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status); - // General keyop call for group operations - // This will be called by the bindings from c.cc - int64_t perform_group_funcall(const hyperdex_client_keyop_info* opinfo, - const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* update_count); + // General keyop call for group operations + // This will be called by the bindings from c.cc + int64_t perform_group_funcall(const hyperdex_client_keyop_info *opinfo, + const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *update_count); - // Initiate a microtransaction - // Status and transaction object must remain valid until the operation has completed - microtransaction *uxact_init(const char* space, - hyperdex_client_returncode *status); + // Initiate a microtransaction + // Status and transaction object must remain valid until the operation has completed + microtransaction *uxact_init(const char *space, + hyperdex_client_returncode *status); - // Add a new funcall to the microstransaction - int64_t uxact_add_funcall(microtransaction *transaction, - const hyperdex_client_keyop_info* opinfo, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz); + // Add a new funcall to the microstransaction + int64_t uxact_add_funcall(microtransaction *transaction, + const hyperdex_client_keyop_info *opinfo, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz); - // Issue a microtransaction to a specific key - int64_t uxact_commit(microtransaction *transaction, - const char* key, size_t key_sz); + // Issue a microtransaction to a specific key + int64_t uxact_commit(microtransaction *transaction, + const char *key, size_t key_sz); - // Issue a microtransaction to a specific key only if checks passs - int64_t uxact_cond_commit(microtransaction *transaction, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz); + // Issue a microtransaction to a specific key only if checks passs + int64_t uxact_cond_commit(microtransaction *transaction, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz); - // Issue a mircotransaction to a all entries matching the checks - int64_t uxact_group_commit(microtransaction *transaction, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - uint64_t *update_count); + // Issue a mircotransaction to a all entries matching the checks + int64_t uxact_group_commit(microtransaction *transaction, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + uint64_t *update_count); - // looping/polling - int64_t loop(int timeout, hyperdex_client_returncode* status); - // Return the fildescriptor that hyperdex uses for networking - int poll_fd(); - // Ensure the flagfd is set correctly - void adjust_flagfd(); - // Block unitl there is incoming data or the timeout is reached - int block(int timeout); - // error handling - const char* error_message(); - const char* error_location(); - void set_error_message(const char* msg); - // helpers for bindings - hyperdatatype attribute_type(const char* space, const char* name, - hyperdex_client_returncode* status); - // enable or disable type conversion on the client-side - void set_type_conversion(bool enabled); + // looping/polling + int64_t loop(int timeout, hyperdex_client_returncode *status); + // Return the fildescriptor that hyperdex uses for networking + int poll_fd(); + // Ensure the flagfd is set correctly + void adjust_flagfd(); + // Block unitl there is incoming data or the timeout is reached + int block(int timeout); + // error handling + const char *error_message(); + const char *error_location(); + void set_error_message(const char *msg); + // helpers for bindings + hyperdatatype attribute_type(const char *space, const char *name, + hyperdex_client_returncode *status); + // enable or disable type conversion on the client-side + void set_type_conversion(bool enabled); - private: - struct pending_server_pair - { - pending_server_pair() - : si(), vsi(), op() {} - pending_server_pair(const server_id& s, - const virtual_server_id& v, - const e::intrusive_ptr& o) - : si(s), vsi(v), op(o) {} - ~pending_server_pair() throw () {} - server_id si; - virtual_server_id vsi; - e::intrusive_ptr op; - }; - typedef std::map pending_map_t; - typedef std::list pending_queue_t; - friend class pending_get; - friend class pending_get_partial; - friend class pending_search; - friend class pending_sorted_search; +private: + struct pending_server_pair + { + pending_server_pair() + : si(), vsi(), op() {} + pending_server_pair(const server_id &s, + const virtual_server_id &v, + const e::intrusive_ptr &o) + : si(s), vsi(v), op(o) {} + ~pending_server_pair() throw () {} + server_id si; + virtual_server_id vsi; + e::intrusive_ptr op; + }; + typedef std::map pending_map_t; + typedef std::list pending_queue_t; + friend class pending_get; + friend class pending_get_partial; + friend class pending_search; + friend class pending_sorted_search; - private: - size_t prepare_checks(const char* space, const schema& sc, - const hyperdex_client_attribute_check* chks, size_t chks_sz, - e::arena* memory, - hyperdex_client_returncode* status, - std::vector* checks); - size_t prepare_funcs(const char* space, const schema& sc, - const hyperdex_client_keyop_info* opinfo, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - e::arena* memory, - hyperdex_client_returncode* status, - std::vector* funcs); - size_t prepare_funcs(const char* space, const schema& sc, - const hyperdex_client_keyop_info* opinfo, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - e::arena* memory, - hyperdex_client_returncode* status, - std::vector* funcs); - size_t prepare_searchop(const schema& sc, - const char* space, - const hyperdex_client_attribute_check* chks, size_t chks_sz, - e::arena* memory, - hyperdex_client_returncode* status, - std::vector* checks, - std::vector* servers); - int64_t perform_funcall(const char* space, const schema* sc, - const hyperdex_client_keyop_info* opinfo, - const hyperdex_client_attribute_check* chks, size_t chks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - size_t header_sz, - size_t footer_sz, - hyperdex_client_returncode* status, - std::auto_ptr* msg); - int64_t perform_aggregation(const std::vector& servers, - e::intrusive_ptr op, - network_msgtype mt, - std::auto_ptr msg, - hyperdex_client_returncode* status); - bool maintain_coord_connection(hyperdex_client_returncode* status); - bool send(network_msgtype mt, - const virtual_server_id& to, - uint64_t nonce, - std::auto_ptr msg, - e::intrusive_ptr op, - hyperdex_client_returncode* status); - int64_t send_keyop(const char* space, - const e::slice& key, - network_msgtype mt, - std::auto_ptr msg, - e::intrusive_ptr op, - hyperdex_client_returncode* status); - void handle_disruption(const server_id& si); +private: + size_t prepare_checks(const char *space, const schema &sc, + const hyperdex_client_attribute_check *chks, size_t chks_sz, + e::arena *memory, + hyperdex_client_returncode *status, + std::vector *checks); + size_t prepare_funcs(const char *space, const schema &sc, + const hyperdex_client_keyop_info *opinfo, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + e::arena *memory, + hyperdex_client_returncode *status, + std::vector *funcs); + size_t prepare_funcs(const char *space, const schema &sc, + const hyperdex_client_keyop_info *opinfo, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + e::arena *memory, + hyperdex_client_returncode *status, + std::vector *funcs); + size_t prepare_searchop(const schema &sc, + const char *space, + const hyperdex_client_attribute_check *chks, size_t chks_sz, + e::arena *memory, + hyperdex_client_returncode *status, + std::vector *checks, + std::vector *servers); + int64_t perform_funcall(const char *space, const schema *sc, + const hyperdex_client_keyop_info *opinfo, + const hyperdex_client_attribute_check *chks, size_t chks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + size_t header_sz, + size_t footer_sz, + hyperdex_client_returncode *status, + std::auto_ptr *msg); + int64_t perform_aggregation(const std::vector &servers, + e::intrusive_ptr op, + network_msgtype mt, + std::auto_ptr msg, + hyperdex_client_returncode *status); + bool maintain_coord_connection(hyperdex_client_returncode *status); + bool send(network_msgtype mt, + const virtual_server_id &to, + uint64_t nonce, + std::auto_ptr msg, + e::intrusive_ptr op, + hyperdex_client_returncode *status); + int64_t send_keyop(const char *space, + const e::slice &key, + network_msgtype mt, + std::auto_ptr msg, + e::intrusive_ptr op, + hyperdex_client_returncode *status); + void handle_disruption(const server_id &si); - private: - replicant_client* m_coord; - mapper m_busybee_mapper; - busybee_st m_busybee; - // configuration - configuration m_config; - int64_t m_config_id; - replicant_returncode m_config_status; - uint64_t m_config_state; - char* m_config_data; - size_t m_config_data_sz; - // nonces - int64_t m_next_client_id; - uint64_t m_next_server_nonce; - e::flagfd m_flagfd; - // operations - pending_map_t m_pending_ops; - pending_queue_t m_failed; - std::list > m_yieldable; - e::intrusive_ptr m_yielding; - e::intrusive_ptr m_yielded; - // misc - e::error m_last_error; - const char** m_macaroons; - size_t m_macaroons_sz; - bool m_convert_types; +private: + replicant_client *m_coord; + mapper m_busybee_mapper; + busybee_st m_busybee; + // configuration + configuration m_config; + int64_t m_config_id; + replicant_returncode m_config_status; + uint64_t m_config_state; + char *m_config_data; + size_t m_config_data_sz; + // nonces + int64_t m_next_client_id; + uint64_t m_next_server_nonce; + e::flagfd m_flagfd; + // operations + pending_map_t m_pending_ops; + pending_queue_t m_failed; + std::list > m_yieldable; + e::intrusive_ptr m_yielding; + e::intrusive_ptr m_yielded; + // misc + e::error m_last_error; + const char **m_macaroons; + size_t m_macaroons_sz; + bool m_convert_types; - private: - client(const client&); - client& operator = (const client&); +private: + client(const client &); + client &operator = (const client &); }; END_HYPERDEX_NAMESPACE diff --git a/client/constants.h b/client/constants.h index 5589f33c3..df7157157 100644 --- a/client/constants.h +++ b/client/constants.h @@ -32,14 +32,14 @@ #include #define HYPERDEX_CLIENT_HEADER_SIZE_REQ (BUSYBEE_HEADER_SIZE \ - + sizeof(uint8_t) /*mt*/ \ - + sizeof(uint8_t) /*flags*/ \ - + sizeof(uint64_t) /*version*/ \ - + sizeof(uint64_t) /*vidt*/ \ - + sizeof(uint64_t) /*nonce*/) + + sizeof(uint8_t) /*mt*/ \ + + sizeof(uint8_t) /*flags*/ \ + + sizeof(uint64_t) /*version*/ \ + + sizeof(uint64_t) /*vidt*/ \ + + sizeof(uint64_t) /*nonce*/) #define HYPERDEX_CLIENT_HEADER_SIZE_RESP (BUSYBEE_HEADER_SIZE \ - + sizeof(uint8_t) /*mt*/ \ - + sizeof(uint64_t) /*vidt*/ \ - + sizeof(uint64_t) /*nonce*/) + + sizeof(uint8_t) /*mt*/ \ + + sizeof(uint64_t) /*vidt*/ \ + + sizeof(uint64_t) /*nonce*/) #endif // hyperdex_client_constants_h_ diff --git a/client/datastructures.cc b/client/datastructures.cc index dcae0d20e..ab0dea324 100644 --- a/client/datastructures.cc +++ b/client/datastructures.cc @@ -52,194 +52,189 @@ using hyperdex::datatype_info; class hyperdex_ds_arena { - public: - hyperdex_ds_arena(); - ~hyperdex_ds_arena() throw (); - - public: - void* allocate(size_t bytes); - hyperdex_ds_list* allocate_list(); - hyperdex_ds_set* allocate_set(); - hyperdex_ds_map* allocate_map(); - - private: - std::list m_voids; - std::list m_lists; - std::list m_sets; - std::list m_maps; +public: + hyperdex_ds_arena(); + ~hyperdex_ds_arena() throw (); + +public: + void *allocate(size_t bytes); + hyperdex_ds_list *allocate_list(); + hyperdex_ds_set *allocate_set(); + hyperdex_ds_map *allocate_map(); + +private: + std::list m_voids; + std::list m_lists; + std::list m_sets; + std::list m_maps; }; class hyperdex_ds_list { - public: - hyperdex_ds_list(); - ~hyperdex_ds_list() throw (); +public: + hyperdex_ds_list(); + ~hyperdex_ds_list() throw (); - public: - hyperdatatype type; - std::string elems; +public: + hyperdatatype type; + std::string elems; }; class hyperdex_ds_set { - public: - hyperdex_ds_set(); - ~hyperdex_ds_set() throw (); +public: + hyperdex_ds_set(); + ~hyperdex_ds_set() throw (); - public: - hyperdatatype type; - std::string elems; +public: + hyperdatatype type; + std::string elems; }; class hyperdex_ds_map { - public: - hyperdex_ds_map(); - ~hyperdex_ds_map() throw (); - - public: - hyperdatatype type; - std::string pairs; - enum { EXPECT_KEY, EXPECT_VAL } state; +public: + hyperdex_ds_map(); + ~hyperdex_ds_map() throw (); + +public: + hyperdatatype type; + std::string pairs; + enum { EXPECT_KEY, EXPECT_VAL } state; }; hyperdex_ds_arena :: hyperdex_ds_arena() - : m_voids() - , m_lists() - , m_sets() - , m_maps() + : m_voids() + , m_lists() + , m_sets() + , m_maps() { } hyperdex_ds_arena :: ~hyperdex_ds_arena() throw () { - for (std::list::iterator it = m_voids.begin(); - it != m_voids.end(); ++it) - { - if (*it) - { - free(*it); - } - } - - for (std::list::iterator it = m_lists.begin(); - it != m_lists.end(); ++it) - { - if (*it) - { - delete *it; - } - } - - for (std::list::iterator it = m_sets.begin(); - it != m_sets.end(); ++it) - { - if (*it) - { - delete *it; - } - } - - for (std::list::iterator it = m_maps.begin(); - it != m_maps.end(); ++it) - { - if (*it) - { - delete *it; - } - } + for (std::list::iterator it = m_voids.begin(); + it != m_voids.end(); ++it) + { + if (*it) + { + free(*it); + } + } + for (std::list::iterator it = m_lists.begin(); + it != m_lists.end(); ++it) + { + if (*it) + { + delete *it; + } + } + for (std::list::iterator it = m_sets.begin(); + it != m_sets.end(); ++it) + { + if (*it) + { + delete *it; + } + } + for (std::list::iterator it = m_maps.begin(); + it != m_maps.end(); ++it) + { + if (*it) + { + delete *it; + } + } } -void* +void * hyperdex_ds_arena :: allocate(size_t bytes) { - try - { - m_voids.push_back(NULL); - m_voids.back() = malloc(bytes); - - if (m_voids.back() == NULL) - { - m_voids.pop_back(); - return NULL; - } - - return m_voids.back(); - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - return NULL; - } - catch (...) - { - abort(); - } + try + { + m_voids.push_back(NULL); + m_voids.back() = malloc(bytes); + if (m_voids.back() == NULL) + { + m_voids.pop_back(); + return NULL; + } + return m_voids.back(); + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + return NULL; + } + catch (...) + { + abort(); + } } -hyperdex_ds_list* +hyperdex_ds_list * hyperdex_ds_arena :: allocate_list() { - try - { - std::auto_ptr list(new hyperdex_ds_list()); - m_lists.push_back(list.get()); - return list.release(); - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - return NULL; - } - catch (...) - { - abort(); - } + try + { + std::auto_ptr list(new hyperdex_ds_list()); + m_lists.push_back(list.get()); + return list.release(); + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + return NULL; + } + catch (...) + { + abort(); + } } -hyperdex_ds_set* +hyperdex_ds_set * hyperdex_ds_arena :: allocate_set() { - try - { - std::auto_ptr set(new hyperdex_ds_set()); - m_sets.push_back(set.get()); - return set.release(); - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - return NULL; - } - catch (...) - { - abort(); - } + try + { + std::auto_ptr set(new hyperdex_ds_set()); + m_sets.push_back(set.get()); + return set.release(); + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + return NULL; + } + catch (...) + { + abort(); + } } -hyperdex_ds_map* +hyperdex_ds_map * hyperdex_ds_arena :: allocate_map() { - try - { - std::auto_ptr map(new hyperdex_ds_map()); - m_maps.push_back(map.get()); - return map.release(); - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - return NULL; - } - catch (...) - { - abort(); - } + try + { + std::auto_ptr map(new hyperdex_ds_map()); + m_maps.push_back(map.get()); + return map.release(); + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + return NULL; + } + catch (...) + { + abort(); + } } hyperdex_ds_list :: hyperdex_ds_list() - : type(HYPERDATATYPE_LIST_GENERIC) - , elems() + : type(HYPERDATATYPE_LIST_GENERIC) + , elems() { } @@ -248,8 +243,8 @@ hyperdex_ds_list :: ~hyperdex_ds_list() throw () } hyperdex_ds_set :: hyperdex_ds_set() - : type(HYPERDATATYPE_SET_GENERIC) - , elems() + : type(HYPERDATATYPE_SET_GENERIC) + , elems() { } @@ -258,9 +253,9 @@ hyperdex_ds_set :: ~hyperdex_ds_set() throw () } hyperdex_ds_map :: hyperdex_ds_map() - : type(HYPERDATATYPE_MAP_GENERIC) - , pairs() - , state(EXPECT_KEY) + : type(HYPERDATATYPE_MAP_GENERIC) + , pairs() + , state(EXPECT_KEY) { } @@ -275,1328 +270,1227 @@ hyperdex_ds_map :: ~hyperdex_ds_map() throw () extern "C" { -///////////////////////////////////// Arena //////////////////////////////////// - -HYPERDEX_API struct hyperdex_ds_arena* -hyperdex_ds_arena_create() -{ - return new (std::nothrow) hyperdex_ds_arena(); -} - -HYPERDEX_API void -hyperdex_ds_arena_destroy(struct hyperdex_ds_arena* arena) -{ - if (arena) - { - delete arena; - } -} - -HYPERDEX_API void* -hyperdex_ds_malloc(struct hyperdex_ds_arena* arena, size_t sz) -{ - return reinterpret_cast(arena->allocate(sz)); -} - -//////////////////////////////// Client Structs //////////////////////////////// - -HYPERDEX_API struct hyperdex_client_attribute* -hyperdex_ds_allocate_attribute(struct hyperdex_ds_arena* arena, size_t sz) -{ - size_t bytes = sizeof(struct hyperdex_client_attribute) * sz; - return reinterpret_cast(arena->allocate(bytes)); -} - -HYPERDEX_API struct hyperdex_client_attribute_check* -hyperdex_ds_allocate_attribute_check(struct hyperdex_ds_arena* arena, size_t sz) -{ - size_t bytes = sizeof(struct hyperdex_client_attribute_check) * sz; - return reinterpret_cast(arena->allocate(bytes)); -} - -HYPERDEX_API struct hyperdex_client_map_attribute* -hyperdex_ds_allocate_map_attribute(struct hyperdex_ds_arena* arena, size_t sz) -{ - size_t bytes = sizeof(struct hyperdex_client_map_attribute) * sz; - return reinterpret_cast(arena->allocate(bytes)); -} - -//////////////////////////// pack/unpack ints/floats /////////////////////////// - -HYPERDEX_API void -hyperdex_ds_pack_int(int64_t num, char* buf) -{ - e::pack64le(num, buf); -} - -HYPERDEX_API int -hyperdex_ds_unpack_int(const char* value, size_t value_sz, int64_t* num) -{ - if (value_sz == 0) - { - *num = 0; - return 0; - } - else if (value_sz != sizeof(int64_t)) - { - return -1; - } - - e::unpack64le(value, num); - return 0; -} - -HYPERDEX_API void -hyperdex_ds_pack_float(double num, char* buf) -{ - e::packdoublele(num, buf); -} - -HYPERDEX_API int -hyperdex_ds_unpack_float(const char* value, size_t value_sz, double* num) -{ - if (value_sz == 0) - { - *num = 0; - return 0; - } - else if (value_sz != sizeof(double)) - { - return -1; - } - - e::unpackdoublele(value, num); - return 0; -} - -HYPERDEX_API int -hyperdex_ds_copy_string(struct hyperdex_ds_arena* arena, - const char* str, size_t str_sz, - enum hyperdex_ds_returncode* status, - const char** value, size_t* value_sz) -{ - char* x = reinterpret_cast(arena->allocate(str_sz)); - - if (!x) - { - *status = HYPERDEX_DS_NOMEM; - return -1; - } - - memmove(x, str, str_sz); - *value = x; - *value_sz = str_sz; - *status = HYPERDEX_DS_SUCCESS; - return 0; -} - -HYPERDEX_API int -hyperdex_ds_copy_int(struct hyperdex_ds_arena* arena, int64_t num, - enum hyperdex_ds_returncode* status, - const char** value, size_t* value_sz) -{ - char* x = reinterpret_cast(arena->allocate(sizeof(int64_t))); - - if (!x) - { - *status = HYPERDEX_DS_NOMEM; - return -1; - } - - e::pack64le(num, x); - *value = x; - *value_sz = sizeof(int64_t); - *status = HYPERDEX_DS_SUCCESS; - return 0; -} - -HYPERDEX_API int -hyperdex_ds_copy_float(struct hyperdex_ds_arena* arena, double num, - enum hyperdex_ds_returncode* status, - const char** value, size_t* value_sz) -{ - char* x = reinterpret_cast(arena->allocate(sizeof(double))); - - if (!x) - { - *status = HYPERDEX_DS_NOMEM; - return -1; - } - - e::packdoublele(num, x); - *value = x; - *value_sz = sizeof(double); - *status = HYPERDEX_DS_SUCCESS; - return 0; -} - -////////////////////////////////// pack lists ////////////////////////////////// - -HYPERDEX_API struct hyperdex_ds_list* -hyperdex_ds_allocate_list(struct hyperdex_ds_arena* arena) -{ - return arena->allocate_list(); -} - -HYPERDEX_API int -hyperdex_ds_list_append_string(struct hyperdex_ds_list* list, - const char* str, size_t str_sz, - enum hyperdex_ds_returncode* status) -{ - try - { - if (list->type == HYPERDATATYPE_LIST_GENERIC) - { - list->type = HYPERDATATYPE_LIST_STRING; - } - else if (list->type != HYPERDATATYPE_LIST_STRING) - { - *status = HYPERDEX_DS_MIXED_TYPES; - return -1; - } - - if (str_sz >= UINT32_MAX) - { - *status = HYPERDEX_DS_STRING_TOO_LONG; - return -1; - } - - char buf[sizeof(uint32_t)]; - e::pack32le(str_sz, buf); - list->elems += std::string(buf, sizeof(uint32_t)); - list->elems += std::string(str, str_sz); - *status = HYPERDEX_DS_SUCCESS; - return 0; - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - *status = HYPERDEX_DS_NOMEM; - return -1; - } - catch (...) - { - abort(); - } -} - -HYPERDEX_API int -hyperdex_ds_list_append_int(struct hyperdex_ds_list* list, - int64_t num, - enum hyperdex_ds_returncode* status) -{ - try - { - if (list->type == HYPERDATATYPE_LIST_GENERIC) - { - list->type = HYPERDATATYPE_LIST_INT64; - } - else if (list->type != HYPERDATATYPE_LIST_INT64) - { - *status = HYPERDEX_DS_MIXED_TYPES; - return -1; - } - - char buf[sizeof(int64_t)]; - e::pack64le(num, buf); - list->elems += std::string(buf, buf + sizeof(int64_t)); - *status = HYPERDEX_DS_SUCCESS; - return 0; - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - *status = HYPERDEX_DS_NOMEM; - return -1; - } - catch (...) - { - abort(); - } -} - -HYPERDEX_API int -hyperdex_ds_list_append_float(struct hyperdex_ds_list* list, - double num, - enum hyperdex_ds_returncode* status) -{ - try - { - if (list->type == HYPERDATATYPE_LIST_GENERIC) - { - list->type = HYPERDATATYPE_LIST_FLOAT; - } - else if (list->type != HYPERDATATYPE_LIST_FLOAT) - { - *status = HYPERDEX_DS_MIXED_TYPES; - return -1; - } - - char buf[sizeof(double)]; - e::packdoublele(num, buf); - list->elems += std::string(buf, buf + sizeof(double)); - *status = HYPERDEX_DS_SUCCESS; - return 0; - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - *status = HYPERDEX_DS_NOMEM; - return -1; - } - catch (...) - { - abort(); - } -} - -HYPERDEX_API int -hyperdex_ds_list_finalize(struct hyperdex_ds_list* list, - enum hyperdex_ds_returncode* status, - const char** value, size_t* value_sz, - enum hyperdatatype* datatype) -{ - *status = HYPERDEX_DS_SUCCESS; - *value = list->elems.data(); - *value_sz = list->elems.size(); - *datatype = list->type; - return 0; -} - -/////////////////////////////////// pack sets ////////////////////////////////// - -HYPERDEX_API struct hyperdex_ds_set* -hyperdex_ds_allocate_set(struct hyperdex_ds_arena* arena) -{ - return arena->allocate_set(); -} - -HYPERDEX_API int -hyperdex_ds_set_insert_string(struct hyperdex_ds_set* set, - const char* str, size_t str_sz, - enum hyperdex_ds_returncode* status) -{ - try - { - if (set->type == HYPERDATATYPE_SET_GENERIC) - { - set->type = HYPERDATATYPE_SET_STRING; - } - else if (set->type != HYPERDATATYPE_SET_STRING) - { - *status = HYPERDEX_DS_MIXED_TYPES; - return -1; - } - - if (str_sz >= UINT32_MAX) - { - *status = HYPERDEX_DS_STRING_TOO_LONG; - return -1; - } - - char buf[sizeof(uint32_t)]; - e::pack32le(str_sz, buf); - set->elems += std::string(buf, sizeof(uint32_t)); - set->elems += std::string(str, str_sz); - *status = HYPERDEX_DS_SUCCESS; - return 0; - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - *status = HYPERDEX_DS_NOMEM; - return -1; - } - catch (...) - { - abort(); - } -} - -HYPERDEX_API int -hyperdex_ds_set_insert_int(struct hyperdex_ds_set* set, int64_t num, - enum hyperdex_ds_returncode* status) -{ - try - { - if (set->type == HYPERDATATYPE_SET_GENERIC) - { - set->type = HYPERDATATYPE_SET_INT64; - } - else if (set->type != HYPERDATATYPE_SET_INT64) - { - *status = HYPERDEX_DS_MIXED_TYPES; - return -1; - } - - char buf[sizeof(int64_t)]; - e::pack64le(num, buf); - set->elems += std::string(buf, buf + sizeof(int64_t)); - *status = HYPERDEX_DS_SUCCESS; - return 0; - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - *status = HYPERDEX_DS_NOMEM; - return -1; - } - catch (...) - { - abort(); - } -} - -HYPERDEX_API int -hyperdex_ds_set_insert_float(struct hyperdex_ds_set* set, double num, - enum hyperdex_ds_returncode* status) -{ - try - { - if (set->type == HYPERDATATYPE_SET_GENERIC) - { - set->type = HYPERDATATYPE_SET_FLOAT; - } - else if (set->type != HYPERDATATYPE_SET_FLOAT) - { - *status = HYPERDEX_DS_MIXED_TYPES; - return -1; - } - - char buf[sizeof(double)]; - e::packdoublele(num, buf); - set->elems += std::string(buf, buf + sizeof(double)); - *status = HYPERDEX_DS_SUCCESS; - return 0; - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - *status = HYPERDEX_DS_NOMEM; - return -1; - } - catch (...) - { - abort(); - } -} - -HYPERDEX_API int -hyperdex_ds_set_finalize(struct hyperdex_ds_set* set, - enum hyperdex_ds_returncode* status, - const char** value, size_t* value_sz, - enum hyperdatatype* datatype) -{ - if (set->type == HYPERDATATYPE_SET_GENERIC) - { - assert(set->elems.empty()); - *status = HYPERDEX_DS_SUCCESS; - *value = set->elems.data(); - *value_sz = set->elems.size(); - *datatype = set->type; - return 0; - } - - datatype_info* di = datatype_info::lookup(CONTAINER_ELEM(set->type)); - assert(di); - const uint8_t* ptr = reinterpret_cast(set->elems.data()); - const uint8_t* end = ptr + set->elems.size(); - e::slice elem; - std::vector elems; - - while (ptr < end) - { - bool stepped = di->step(&ptr, end, &elem); - assert(stepped); - elems.push_back(elem); - } - - assert(ptr == end); - std::sort(elems.begin(), elems.end(), di->compare_less()); - std::vector tmp(set->elems.size()); - uint8_t* wr = reinterpret_cast(&tmp[0]); - - for (size_t i = 0; i < elems.size(); ++i) - { - wr = di->write(elems[i], wr); - } - - set->elems = std::string(tmp.begin(), tmp.end()); - *status = HYPERDEX_DS_SUCCESS; - *value = set->elems.data(); - *value_sz = set->elems.size(); - *datatype = set->type; - return 0; -} - -/////////////////////////////////// pack maps ////////////////////////////////// - -HYPERDEX_API struct hyperdex_ds_map* -hyperdex_ds_allocate_map(struct hyperdex_ds_arena* arena) -{ - return arena->allocate_map(); -} - -HYPERDEX_API int -hyperdex_ds_map_insert_key_string(struct hyperdex_ds_map* map, - const char* str, size_t str_sz, - enum hyperdex_ds_returncode* status) -{ - if (map->state != hyperdex_ds_map::EXPECT_KEY) - { - *status = HYPERDEX_DS_WRONG_STATE; - return -1; - } - - try - { - if (CONTAINER_KEY(map->type) == HYPERDATATYPE_GENERIC) - { - map->type = HYPERDATATYPE_MAP_STRING_KEYONLY; - } - else if (CONTAINER_KEY(map->type) != HYPERDATATYPE_STRING) - { - *status = HYPERDEX_DS_MIXED_TYPES; - return -1; - } - - if (str_sz >= UINT32_MAX) - { - *status = HYPERDEX_DS_STRING_TOO_LONG; - return -1; - } - - char buf[sizeof(uint32_t)]; - e::pack32le(str_sz, buf); - map->pairs += std::string(buf, sizeof(uint32_t)); - map->pairs += std::string(str, str_sz); - *status = HYPERDEX_DS_SUCCESS; - map->state = hyperdex_ds_map::EXPECT_VAL; - return 0; - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - *status = HYPERDEX_DS_NOMEM; - return -1; - } - catch (...) - { - abort(); - } -} - -HYPERDEX_API int -hyperdex_ds_map_insert_val_string(struct hyperdex_ds_map* map, - const char* str, size_t str_sz, - enum hyperdex_ds_returncode* status) -{ - if (map->state != hyperdex_ds_map::EXPECT_VAL) - { - *status = HYPERDEX_DS_WRONG_STATE; - return -1; - } - - try - { - if (CONTAINER_VAL(map->type) == HYPERDATATYPE_GENERIC) - { - map->type = RESTRICT_CONTAINER(map->type, HYPERDATATYPE_STRING); - } - else if (CONTAINER_VAL(map->type) != HYPERDATATYPE_STRING) - { - *status = HYPERDEX_DS_MIXED_TYPES; - return -1; - } - - if (str_sz >= UINT32_MAX) - { - *status = HYPERDEX_DS_STRING_TOO_LONG; - return -1; - } - - char buf[sizeof(uint32_t)]; - e::pack32le(str_sz, buf); - map->pairs += std::string(buf, sizeof(uint32_t)); - map->pairs += std::string(str, str_sz); - *status = HYPERDEX_DS_SUCCESS; - map->state = hyperdex_ds_map::EXPECT_KEY; - return 0; - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - *status = HYPERDEX_DS_NOMEM; - return -1; - } - catch (...) - { - abort(); - } -} - -HYPERDEX_API int -hyperdex_ds_map_insert_key_int(struct hyperdex_ds_map* map, int64_t num, - enum hyperdex_ds_returncode* status) -{ - if (map->state != hyperdex_ds_map::EXPECT_KEY) - { - *status = HYPERDEX_DS_WRONG_STATE; - return -1; - } - - try - { - if (CONTAINER_KEY(map->type) == HYPERDATATYPE_GENERIC) - { - map->type = HYPERDATATYPE_MAP_INT64_KEYONLY; - } - else if (CONTAINER_KEY(map->type) != HYPERDATATYPE_INT64) - { - *status = HYPERDEX_DS_MIXED_TYPES; - return -1; - } - - char buf[sizeof(int64_t)]; - e::pack64le(num, buf); - map->pairs += std::string(buf, buf + sizeof(int64_t)); - *status = HYPERDEX_DS_SUCCESS; - map->state = hyperdex_ds_map::EXPECT_VAL; - return 0; - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - *status = HYPERDEX_DS_NOMEM; - return -1; - } - catch (...) - { - abort(); - } -} - -HYPERDEX_API int -hyperdex_ds_map_insert_val_int(struct hyperdex_ds_map* map, int64_t num, - enum hyperdex_ds_returncode* status) -{ - if (map->state != hyperdex_ds_map::EXPECT_VAL) - { - *status = HYPERDEX_DS_WRONG_STATE; - return -1; - } - - try - { - if (CONTAINER_VAL(map->type) == HYPERDATATYPE_GENERIC) - { - map->type = RESTRICT_CONTAINER(map->type, HYPERDATATYPE_INT64); - } - else if (CONTAINER_VAL(map->type) != HYPERDATATYPE_INT64) - { - *status = HYPERDEX_DS_MIXED_TYPES; - return -1; - } - - char buf[sizeof(int64_t)]; - e::pack64le(num, buf); - map->pairs += std::string(buf, buf + sizeof(int64_t)); - *status = HYPERDEX_DS_SUCCESS; - map->state = hyperdex_ds_map::EXPECT_KEY; - return 0; - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - *status = HYPERDEX_DS_NOMEM; - return -1; - } - catch (...) - { - abort(); - } -} - -HYPERDEX_API int -hyperdex_ds_map_insert_key_float(struct hyperdex_ds_map* map, double num, - enum hyperdex_ds_returncode* status) -{ - if (map->state != hyperdex_ds_map::EXPECT_KEY) - { - *status = HYPERDEX_DS_WRONG_STATE; - return -1; - } - - try - { - if (CONTAINER_KEY(map->type) == HYPERDATATYPE_GENERIC) - { - map->type = HYPERDATATYPE_MAP_FLOAT_KEYONLY; - } - else if (CONTAINER_KEY(map->type) != HYPERDATATYPE_FLOAT) - { - *status = HYPERDEX_DS_MIXED_TYPES; - return -1; - } - - char buf[sizeof(double)]; - e::packdoublele(num, buf); - map->pairs += std::string(buf, buf + sizeof(double)); - *status = HYPERDEX_DS_SUCCESS; - map->state = hyperdex_ds_map::EXPECT_VAL; - return 0; - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - *status = HYPERDEX_DS_NOMEM; - return -1; - } - catch (...) - { - abort(); - } -} - -HYPERDEX_API int -hyperdex_ds_map_insert_val_float(struct hyperdex_ds_map* map, double num, - enum hyperdex_ds_returncode* status) -{ - if (map->state != hyperdex_ds_map::EXPECT_VAL) - { - *status = HYPERDEX_DS_WRONG_STATE; - return -1; - } - - try - { - if (CONTAINER_VAL(map->type) == HYPERDATATYPE_GENERIC) - { - map->type = RESTRICT_CONTAINER(map->type, HYPERDATATYPE_FLOAT); - } - else if (CONTAINER_VAL(map->type) != HYPERDATATYPE_FLOAT) - { - *status = HYPERDEX_DS_MIXED_TYPES; - return -1; - } - - char buf[sizeof(double)]; - e::packdoublele(num, buf); - map->pairs += std::string(buf, buf + sizeof(double)); - *status = HYPERDEX_DS_SUCCESS; - map->state = hyperdex_ds_map::EXPECT_KEY; - return 0; - } - catch (std::bad_alloc& ba) - { - errno = ENOMEM; - *status = HYPERDEX_DS_NOMEM; - return -1; - } - catch (...) - { - abort(); - } -} - -namespace -{ - -class map_comparator -{ - public: - map_comparator(datatype_info* di) : m_di(di) {} - map_comparator(const map_comparator& other) : m_di(other.m_di) {} - - public: - map_comparator& operator = (const map_comparator& rhs) - { m_di = rhs.m_di; return *this; } - bool operator () (const std::pair& lhs, - const std::pair& rhs) - { return m_di->compare_less()(lhs.first, rhs.first); } - - private: - datatype_info* m_di; -}; - -} // namespace - -HYPERDEX_API int -hyperdex_ds_map_finalize(struct hyperdex_ds_map* map, - enum hyperdex_ds_returncode* status, - const char** value, size_t* value_sz, - enum hyperdatatype* datatype) -{ - if (map->state != hyperdex_ds_map::EXPECT_KEY) - { - *status = HYPERDEX_DS_WRONG_STATE; - return -1; - } - if (map->type == HYPERDATATYPE_MAP_GENERIC) - { - assert(map->pairs.empty()); - *status = HYPERDEX_DS_SUCCESS; - *value = map->pairs.data(); - *value_sz = map->pairs.size(); - *datatype = map->type; - return 0; - } - - datatype_info* dik = datatype_info::lookup(CONTAINER_KEY(map->type)); - datatype_info* div = datatype_info::lookup(CONTAINER_VAL(map->type)); - assert(dik); - assert(div); - const uint8_t* ptr = reinterpret_cast(map->pairs.data()); - const uint8_t* end = ptr + map->pairs.size(); - e::slice key; - e::slice val; - std::vector > pairs; - - while (ptr < end) - { - bool stepped; - stepped = dik->step(&ptr, end, &key); - assert(stepped); - stepped = div->step(&ptr, end, &val); - assert(stepped); - pairs.push_back(std::make_pair(key, val)); - } - - assert(ptr == end); - std::sort(pairs.begin(), pairs.end(), map_comparator(dik)); - std::vector tmp(map->pairs.size()); - uint8_t* wr = reinterpret_cast(&tmp[0]); - - for (size_t i = 0; i < pairs.size(); ++i) - { - wr = dik->write(pairs[i].first, wr); - wr = div->write(pairs[i].second, wr); - } - - map->pairs = std::string(tmp.begin(), tmp.end()); - *status = HYPERDEX_DS_SUCCESS; - *value = map->pairs.data(); - *value_sz = map->pairs.size(); - *datatype = map->type; - return 0; -} - -HYPERDEX_API void -hyperdex_ds_iterator_init(struct hyperdex_ds_iterator* iter, - enum hyperdatatype datatype, - const char* value, - size_t value_sz) -{ - iter->datatype = datatype; - iter->value = value; - iter->value_end = value + value_sz; - iter->progress = value; -} - -HYPERDEX_API int -hyperdex_ds_iterate_list_string_next(struct hyperdex_ds_iterator* iter, - const char** str, size_t* str_sz) -{ - if (iter->datatype != HYPERDATATYPE_LIST_STRING) - { - return -1; - } - - datatype_info* di = datatype_info::lookup(HYPERDATATYPE_STRING); - e::slice elem; - - if (iter->progress < iter->value_end) - { - if (!di->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &elem)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - *str = reinterpret_cast(elem.data()); - *str_sz = elem.size(); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} - -HYPERDEX_API int -hyperdex_ds_iterate_list_int_next(struct hyperdex_ds_iterator* iter, int64_t* num) -{ - if (iter->datatype != HYPERDATATYPE_LIST_INT64) - { - return -1; - } - - datatype_info* di = datatype_info::lookup(HYPERDATATYPE_INT64); - e::slice elem; - - if (iter->progress < iter->value_end) - { - if (!di->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &elem) || - elem.size() != sizeof(int64_t)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - e::unpack64le(elem.data(), num); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} - -HYPERDEX_API int -hyperdex_ds_iterate_list_float_next(struct hyperdex_ds_iterator* iter, double* num) -{ - if (iter->datatype != HYPERDATATYPE_LIST_FLOAT) - { - return -1; - } - - datatype_info* di = datatype_info::lookup(HYPERDATATYPE_FLOAT); - e::slice elem; - - if (iter->progress < iter->value_end) - { - if (!di->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &elem) || - elem.size() != sizeof(double)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - e::unpackdoublele(elem.data(), num); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} - -HYPERDEX_API int -hyperdex_ds_iterate_set_string_next(struct hyperdex_ds_iterator* iter, - const char** str, size_t* str_sz) -{ - if (iter->datatype != HYPERDATATYPE_SET_STRING) - { - return -1; - } - - datatype_info* di = datatype_info::lookup(HYPERDATATYPE_STRING); - e::slice elem; - - if (iter->progress < iter->value_end) - { - if (!di->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &elem)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - *str = reinterpret_cast(elem.data()); - *str_sz = elem.size(); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} - -HYPERDEX_API int -hyperdex_ds_iterate_set_int_next(struct hyperdex_ds_iterator* iter, int64_t* num) -{ - if (iter->datatype != HYPERDATATYPE_SET_INT64) - { - return -1; - } - - datatype_info* di = datatype_info::lookup(HYPERDATATYPE_INT64); - e::slice elem; - - if (iter->progress < iter->value_end) - { - if (!di->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &elem) || - elem.size() != sizeof(int64_t)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - e::unpack64le(elem.data(), num); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} - -HYPERDEX_API int -hyperdex_ds_iterate_set_float_next(struct hyperdex_ds_iterator* iter, double* num) -{ - if (iter->datatype != HYPERDATATYPE_SET_FLOAT) - { - return -1; - } - - datatype_info* di = datatype_info::lookup(HYPERDATATYPE_FLOAT); - e::slice elem; - - if (iter->progress < iter->value_end) - { - if (!di->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &elem) || - elem.size() != sizeof(double)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - e::unpackdoublele(elem.data(), num); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} - -HYPERDEX_API int -hyperdex_ds_iterate_map_string_string_next(struct hyperdex_ds_iterator* iter, - const char** key, size_t* key_sz, - const char** val, size_t* val_sz) -{ - if (iter->datatype != HYPERDATATYPE_MAP_STRING_STRING) - { - return -1; - } - - datatype_info* dik = datatype_info::lookup(HYPERDATATYPE_STRING); - datatype_info* div = datatype_info::lookup(HYPERDATATYPE_STRING); - e::slice mkey; - e::slice mval; - - if (iter->progress < iter->value_end) - { - if (!dik->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mkey) || - !div->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mval)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - *key = reinterpret_cast(mkey.data()); - *key_sz = mkey.size(); - *val = reinterpret_cast(mval.data()); - *val_sz = mval.size(); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} - -HYPERDEX_API int -hyperdex_ds_iterate_map_string_int_next(struct hyperdex_ds_iterator* iter, - const char** key, size_t* key_sz, - int64_t* val) -{ - if (iter->datatype != HYPERDATATYPE_MAP_STRING_INT64) - { - return -1; - } - - datatype_info* dik = datatype_info::lookup(HYPERDATATYPE_STRING); - datatype_info* div = datatype_info::lookup(HYPERDATATYPE_INT64); - e::slice mkey; - e::slice mval; - - if (iter->progress < iter->value_end) - { - if (!dik->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mkey) || - !div->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mval) || - mval.size() != sizeof(int64_t)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - *key = reinterpret_cast(mkey.data()); - *key_sz = mkey.size(); - e::unpack64le(mval.data(), val); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} - -HYPERDEX_API int -hyperdex_ds_iterate_map_string_float_next(struct hyperdex_ds_iterator* iter, - const char** key, size_t* key_sz, - double* val) -{ - if (iter->datatype != HYPERDATATYPE_MAP_STRING_FLOAT) - { - return -1; - } - - datatype_info* dik = datatype_info::lookup(HYPERDATATYPE_STRING); - datatype_info* div = datatype_info::lookup(HYPERDATATYPE_FLOAT); - e::slice mkey; - e::slice mval; - - if (iter->progress < iter->value_end) - { - if (!dik->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mkey) || - !div->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mval) || - mval.size() != sizeof(double)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - *key = reinterpret_cast(mkey.data()); - *key_sz = mkey.size(); - e::unpackdoublele(mval.data(), val); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} - -HYPERDEX_API int -hyperdex_ds_iterate_map_int_string_next(struct hyperdex_ds_iterator* iter, - int64_t* key, const char** val, size_t* val_sz) -{ - if (iter->datatype != HYPERDATATYPE_MAP_INT64_STRING) - { - return -1; - } - - datatype_info* dik = datatype_info::lookup(HYPERDATATYPE_INT64); - datatype_info* div = datatype_info::lookup(HYPERDATATYPE_STRING); - e::slice mkey; - e::slice mval; - - if (iter->progress < iter->value_end) - { - if (!dik->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mkey) || - !div->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mval) || - mkey.size() != sizeof(int64_t)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - e::unpack64le(mkey.data(), key); - *val = reinterpret_cast(mval.data()); - *val_sz = mval.size(); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} - -HYPERDEX_API int -hyperdex_ds_iterate_map_int_int_next(struct hyperdex_ds_iterator* iter, - int64_t* key, int64_t* val) -{ - if (iter->datatype != HYPERDATATYPE_MAP_INT64_INT64) - { - return -1; - } - - datatype_info* dik = datatype_info::lookup(HYPERDATATYPE_INT64); - datatype_info* div = datatype_info::lookup(HYPERDATATYPE_INT64); - e::slice mkey; - e::slice mval; - - if (iter->progress < iter->value_end) - { - if (!dik->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mkey) || - !div->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mval) || - mkey.size() != sizeof(int64_t) || - mval.size() != sizeof(int64_t)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - e::unpack64le(mkey.data(), key); - e::unpack64le(mval.data(), val); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} - -HYPERDEX_API int -hyperdex_ds_iterate_map_int_float_next(struct hyperdex_ds_iterator* iter, - int64_t* key, double* val) -{ - if (iter->datatype != HYPERDATATYPE_MAP_INT64_FLOAT) - { - return -1; - } - - datatype_info* dik = datatype_info::lookup(HYPERDATATYPE_INT64); - datatype_info* div = datatype_info::lookup(HYPERDATATYPE_FLOAT); - e::slice mkey; - e::slice mval; - - if (iter->progress < iter->value_end) - { - if (!dik->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mkey) || - !div->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mval) || - mkey.size() != sizeof(int64_t) || - mval.size() != sizeof(double)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - e::unpack64le(mkey.data(), key); - e::unpackdoublele(mval.data(), val); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} - -HYPERDEX_API int -hyperdex_ds_iterate_map_float_string_next(struct hyperdex_ds_iterator* iter, - double* key, const char** val, size_t* val_sz) -{ - if (iter->datatype != HYPERDATATYPE_MAP_FLOAT_STRING) - { - return -1; - } - - datatype_info* dik = datatype_info::lookup(HYPERDATATYPE_FLOAT); - datatype_info* div = datatype_info::lookup(HYPERDATATYPE_STRING); - e::slice mkey; - e::slice mval; - - if (iter->progress < iter->value_end) - { - if (!dik->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mkey) || - !div->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mval) || - mkey.size() != sizeof(double)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - e::unpackdoublele(mkey.data(), key); - *val = reinterpret_cast(mval.data()); - *val_sz = mval.size(); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} - -HYPERDEX_API int -hyperdex_ds_iterate_map_float_int_next(struct hyperdex_ds_iterator* iter, - double* key, int64_t* val) -{ - if (iter->datatype != HYPERDATATYPE_MAP_FLOAT_INT64) - { - return -1; - } - - datatype_info* dik = datatype_info::lookup(HYPERDATATYPE_FLOAT); - datatype_info* div = datatype_info::lookup(HYPERDATATYPE_INT64); - e::slice mkey; - e::slice mval; - - if (iter->progress < iter->value_end) - { - if (!dik->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mkey) || - !div->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mval) || - mkey.size() != sizeof(double) || - mval.size() != sizeof(int64_t)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - e::unpackdoublele(mkey.data(), key); - e::unpack64le(mval.data(), val); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} - -HYPERDEX_API int -hyperdex_ds_iterate_map_float_float_next(struct hyperdex_ds_iterator* iter, - double* key, double* val) -{ - if (iter->datatype != HYPERDATATYPE_MAP_FLOAT_FLOAT) - { - return -1; - } - - datatype_info* dik = datatype_info::lookup(HYPERDATATYPE_FLOAT); - datatype_info* div = datatype_info::lookup(HYPERDATATYPE_FLOAT); - e::slice mkey; - e::slice mval; - - if (iter->progress < iter->value_end) - { - if (!dik->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mkey) || - !div->step(reinterpret_cast(&iter->progress), - reinterpret_cast(iter->value_end), &mval) || - mkey.size() != sizeof(double) || - mval.size() != sizeof(double)) - { - iter->progress = iter->value_end + 1; - return -1; - } - - e::unpackdoublele(mkey.data(), key); - e::unpackdoublele(mval.data(), val); - return 1; - } - - return iter->progress == iter->value_end ? 0 : -1; -} + ///////////////////////////////////// Arena //////////////////////////////////// + + HYPERDEX_API struct hyperdex_ds_arena * + hyperdex_ds_arena_create() + { + return new (std::nothrow) hyperdex_ds_arena(); + } + + HYPERDEX_API void + hyperdex_ds_arena_destroy(struct hyperdex_ds_arena *arena) + { + if (arena) + { + delete arena; + } + } + + HYPERDEX_API void * + hyperdex_ds_malloc(struct hyperdex_ds_arena *arena, size_t sz) + { + return reinterpret_cast(arena->allocate(sz)); + } + + //////////////////////////////// Client Structs //////////////////////////////// + + HYPERDEX_API struct hyperdex_client_attribute * + hyperdex_ds_allocate_attribute(struct hyperdex_ds_arena *arena, size_t sz) + { + size_t bytes = sizeof(struct hyperdex_client_attribute) * sz; + return reinterpret_cast(arena->allocate(bytes)); + } + + HYPERDEX_API struct hyperdex_client_attribute_check * + hyperdex_ds_allocate_attribute_check(struct hyperdex_ds_arena *arena, size_t sz) + { + size_t bytes = sizeof(struct hyperdex_client_attribute_check) * sz; + return reinterpret_cast(arena->allocate(bytes)); + } + + HYPERDEX_API struct hyperdex_client_map_attribute * + hyperdex_ds_allocate_map_attribute(struct hyperdex_ds_arena *arena, size_t sz) + { + size_t bytes = sizeof(struct hyperdex_client_map_attribute) * sz; + return reinterpret_cast(arena->allocate(bytes)); + } + + //////////////////////////// pack/unpack ints/floats /////////////////////////// + + HYPERDEX_API void + hyperdex_ds_pack_int(int64_t num, char *buf) + { + e::pack64le(num, buf); + } + + HYPERDEX_API int + hyperdex_ds_unpack_int(const char *value, size_t value_sz, int64_t *num) + { + if (value_sz == 0) + { + *num = 0; + return 0; + } + else if (value_sz != sizeof(int64_t)) + { + return -1; + } + e::unpack64le(value, num); + return 0; + } + + HYPERDEX_API void + hyperdex_ds_pack_float(double num, char *buf) + { + e::packdoublele(num, buf); + } + + HYPERDEX_API int + hyperdex_ds_unpack_float(const char *value, size_t value_sz, double *num) + { + if (value_sz == 0) + { + *num = 0; + return 0; + } + else if (value_sz != sizeof(double)) + { + return -1; + } + e::unpackdoublele(value, num); + return 0; + } + + HYPERDEX_API int + hyperdex_ds_copy_string(struct hyperdex_ds_arena *arena, + const char *str, size_t str_sz, + enum hyperdex_ds_returncode *status, + const char **value, size_t *value_sz) + { + char *x = reinterpret_cast(arena->allocate(str_sz)); + if (!x) + { + *status = HYPERDEX_DS_NOMEM; + return -1; + } + memmove(x, str, str_sz); + *value = x; + *value_sz = str_sz; + *status = HYPERDEX_DS_SUCCESS; + return 0; + } + + HYPERDEX_API int + hyperdex_ds_copy_int(struct hyperdex_ds_arena *arena, int64_t num, + enum hyperdex_ds_returncode *status, + const char **value, size_t *value_sz) + { + char *x = reinterpret_cast(arena->allocate(sizeof(int64_t))); + if (!x) + { + *status = HYPERDEX_DS_NOMEM; + return -1; + } + e::pack64le(num, x); + *value = x; + *value_sz = sizeof(int64_t); + *status = HYPERDEX_DS_SUCCESS; + return 0; + } + + HYPERDEX_API int + hyperdex_ds_copy_float(struct hyperdex_ds_arena *arena, double num, + enum hyperdex_ds_returncode *status, + const char **value, size_t *value_sz) + { + char *x = reinterpret_cast(arena->allocate(sizeof(double))); + if (!x) + { + *status = HYPERDEX_DS_NOMEM; + return -1; + } + e::packdoublele(num, x); + *value = x; + *value_sz = sizeof(double); + *status = HYPERDEX_DS_SUCCESS; + return 0; + } + + ////////////////////////////////// pack lists ////////////////////////////////// + + HYPERDEX_API struct hyperdex_ds_list * + hyperdex_ds_allocate_list(struct hyperdex_ds_arena *arena) + { + return arena->allocate_list(); + } + + HYPERDEX_API int + hyperdex_ds_list_append_string(struct hyperdex_ds_list *list, + const char *str, size_t str_sz, + enum hyperdex_ds_returncode *status) + { + try + { + if (list->type == HYPERDATATYPE_LIST_GENERIC) + { + list->type = HYPERDATATYPE_LIST_STRING; + } + else if (list->type != HYPERDATATYPE_LIST_STRING) + { + *status = HYPERDEX_DS_MIXED_TYPES; + return -1; + } + if (str_sz >= UINT32_MAX) + { + *status = HYPERDEX_DS_STRING_TOO_LONG; + return -1; + } + char buf[sizeof(uint32_t)]; + e::pack32le(str_sz, buf); + list->elems += std::string(buf, sizeof(uint32_t)); + list->elems += std::string(str, str_sz); + *status = HYPERDEX_DS_SUCCESS; + return 0; + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + *status = HYPERDEX_DS_NOMEM; + return -1; + } + catch (...) + { + abort(); + } + } + + HYPERDEX_API int + hyperdex_ds_list_append_int(struct hyperdex_ds_list *list, + int64_t num, + enum hyperdex_ds_returncode *status) + { + try + { + if (list->type == HYPERDATATYPE_LIST_GENERIC) + { + list->type = HYPERDATATYPE_LIST_INT64; + } + else if (list->type != HYPERDATATYPE_LIST_INT64) + { + *status = HYPERDEX_DS_MIXED_TYPES; + return -1; + } + char buf[sizeof(int64_t)]; + e::pack64le(num, buf); + list->elems += std::string(buf, buf + sizeof(int64_t)); + *status = HYPERDEX_DS_SUCCESS; + return 0; + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + *status = HYPERDEX_DS_NOMEM; + return -1; + } + catch (...) + { + abort(); + } + } + + HYPERDEX_API int + hyperdex_ds_list_append_float(struct hyperdex_ds_list *list, + double num, + enum hyperdex_ds_returncode *status) + { + try + { + if (list->type == HYPERDATATYPE_LIST_GENERIC) + { + list->type = HYPERDATATYPE_LIST_FLOAT; + } + else if (list->type != HYPERDATATYPE_LIST_FLOAT) + { + *status = HYPERDEX_DS_MIXED_TYPES; + return -1; + } + char buf[sizeof(double)]; + e::packdoublele(num, buf); + list->elems += std::string(buf, buf + sizeof(double)); + *status = HYPERDEX_DS_SUCCESS; + return 0; + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + *status = HYPERDEX_DS_NOMEM; + return -1; + } + catch (...) + { + abort(); + } + } + + HYPERDEX_API int + hyperdex_ds_list_finalize(struct hyperdex_ds_list *list, + enum hyperdex_ds_returncode *status, + const char **value, size_t *value_sz, + enum hyperdatatype *datatype) + { + *status = HYPERDEX_DS_SUCCESS; + *value = list->elems.data(); + *value_sz = list->elems.size(); + *datatype = list->type; + return 0; + } + + /////////////////////////////////// pack sets ////////////////////////////////// + + HYPERDEX_API struct hyperdex_ds_set * + hyperdex_ds_allocate_set(struct hyperdex_ds_arena *arena) + { + return arena->allocate_set(); + } + + HYPERDEX_API int + hyperdex_ds_set_insert_string(struct hyperdex_ds_set *set, + const char *str, size_t str_sz, + enum hyperdex_ds_returncode *status) + { + try + { + if (set->type == HYPERDATATYPE_SET_GENERIC) + { + set->type = HYPERDATATYPE_SET_STRING; + } + else if (set->type != HYPERDATATYPE_SET_STRING) + { + *status = HYPERDEX_DS_MIXED_TYPES; + return -1; + } + if (str_sz >= UINT32_MAX) + { + *status = HYPERDEX_DS_STRING_TOO_LONG; + return -1; + } + char buf[sizeof(uint32_t)]; + e::pack32le(str_sz, buf); + set->elems += std::string(buf, sizeof(uint32_t)); + set->elems += std::string(str, str_sz); + *status = HYPERDEX_DS_SUCCESS; + return 0; + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + *status = HYPERDEX_DS_NOMEM; + return -1; + } + catch (...) + { + abort(); + } + } + + HYPERDEX_API int + hyperdex_ds_set_insert_int(struct hyperdex_ds_set *set, int64_t num, + enum hyperdex_ds_returncode *status) + { + try + { + if (set->type == HYPERDATATYPE_SET_GENERIC) + { + set->type = HYPERDATATYPE_SET_INT64; + } + else if (set->type != HYPERDATATYPE_SET_INT64) + { + *status = HYPERDEX_DS_MIXED_TYPES; + return -1; + } + char buf[sizeof(int64_t)]; + e::pack64le(num, buf); + set->elems += std::string(buf, buf + sizeof(int64_t)); + *status = HYPERDEX_DS_SUCCESS; + return 0; + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + *status = HYPERDEX_DS_NOMEM; + return -1; + } + catch (...) + { + abort(); + } + } + + HYPERDEX_API int + hyperdex_ds_set_insert_float(struct hyperdex_ds_set *set, double num, + enum hyperdex_ds_returncode *status) + { + try + { + if (set->type == HYPERDATATYPE_SET_GENERIC) + { + set->type = HYPERDATATYPE_SET_FLOAT; + } + else if (set->type != HYPERDATATYPE_SET_FLOAT) + { + *status = HYPERDEX_DS_MIXED_TYPES; + return -1; + } + char buf[sizeof(double)]; + e::packdoublele(num, buf); + set->elems += std::string(buf, buf + sizeof(double)); + *status = HYPERDEX_DS_SUCCESS; + return 0; + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + *status = HYPERDEX_DS_NOMEM; + return -1; + } + catch (...) + { + abort(); + } + } + + HYPERDEX_API int + hyperdex_ds_set_finalize(struct hyperdex_ds_set *set, + enum hyperdex_ds_returncode *status, + const char **value, size_t *value_sz, + enum hyperdatatype *datatype) + { + if (set->type == HYPERDATATYPE_SET_GENERIC) + { + assert(set->elems.empty()); + *status = HYPERDEX_DS_SUCCESS; + *value = set->elems.data(); + *value_sz = set->elems.size(); + *datatype = set->type; + return 0; + } + datatype_info *di = datatype_info::lookup(CONTAINER_ELEM(set->type)); + assert(di); + const uint8_t *ptr = reinterpret_cast(set->elems.data()); + const uint8_t *end = ptr + set->elems.size(); + e::slice elem; + std::vector elems; + while (ptr < end) + { + bool stepped = di->step(&ptr, end, &elem); + assert(stepped); + elems.push_back(elem); + } + assert(ptr == end); + std::sort(elems.begin(), elems.end(), di->compare_less()); + std::vector tmp(set->elems.size()); + uint8_t *wr = reinterpret_cast(&tmp[0]); + for (size_t i = 0; i < elems.size(); ++i) + { + wr = di->write(elems[i], wr); + } + set->elems = std::string(tmp.begin(), tmp.end()); + *status = HYPERDEX_DS_SUCCESS; + *value = set->elems.data(); + *value_sz = set->elems.size(); + *datatype = set->type; + return 0; + } + + /////////////////////////////////// pack maps ////////////////////////////////// + + HYPERDEX_API struct hyperdex_ds_map * + hyperdex_ds_allocate_map(struct hyperdex_ds_arena *arena) + { + return arena->allocate_map(); + } + + HYPERDEX_API int + hyperdex_ds_map_insert_key_string(struct hyperdex_ds_map *map, + const char *str, size_t str_sz, + enum hyperdex_ds_returncode *status) + { + if (map->state != hyperdex_ds_map::EXPECT_KEY) + { + *status = HYPERDEX_DS_WRONG_STATE; + return -1; + } + try + { + if (CONTAINER_KEY(map->type) == HYPERDATATYPE_GENERIC) + { + map->type = HYPERDATATYPE_MAP_STRING_KEYONLY; + } + else if (CONTAINER_KEY(map->type) != HYPERDATATYPE_STRING) + { + *status = HYPERDEX_DS_MIXED_TYPES; + return -1; + } + if (str_sz >= UINT32_MAX) + { + *status = HYPERDEX_DS_STRING_TOO_LONG; + return -1; + } + char buf[sizeof(uint32_t)]; + e::pack32le(str_sz, buf); + map->pairs += std::string(buf, sizeof(uint32_t)); + map->pairs += std::string(str, str_sz); + *status = HYPERDEX_DS_SUCCESS; + map->state = hyperdex_ds_map::EXPECT_VAL; + return 0; + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + *status = HYPERDEX_DS_NOMEM; + return -1; + } + catch (...) + { + abort(); + } + } + + HYPERDEX_API int + hyperdex_ds_map_insert_val_string(struct hyperdex_ds_map *map, + const char *str, size_t str_sz, + enum hyperdex_ds_returncode *status) + { + if (map->state != hyperdex_ds_map::EXPECT_VAL) + { + *status = HYPERDEX_DS_WRONG_STATE; + return -1; + } + try + { + if (CONTAINER_VAL(map->type) == HYPERDATATYPE_GENERIC) + { + map->type = RESTRICT_CONTAINER(map->type, HYPERDATATYPE_STRING); + } + else if (CONTAINER_VAL(map->type) != HYPERDATATYPE_STRING) + { + *status = HYPERDEX_DS_MIXED_TYPES; + return -1; + } + if (str_sz >= UINT32_MAX) + { + *status = HYPERDEX_DS_STRING_TOO_LONG; + return -1; + } + char buf[sizeof(uint32_t)]; + e::pack32le(str_sz, buf); + map->pairs += std::string(buf, sizeof(uint32_t)); + map->pairs += std::string(str, str_sz); + *status = HYPERDEX_DS_SUCCESS; + map->state = hyperdex_ds_map::EXPECT_KEY; + return 0; + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + *status = HYPERDEX_DS_NOMEM; + return -1; + } + catch (...) + { + abort(); + } + } + + HYPERDEX_API int + hyperdex_ds_map_insert_key_int(struct hyperdex_ds_map *map, int64_t num, + enum hyperdex_ds_returncode *status) + { + if (map->state != hyperdex_ds_map::EXPECT_KEY) + { + *status = HYPERDEX_DS_WRONG_STATE; + return -1; + } + try + { + if (CONTAINER_KEY(map->type) == HYPERDATATYPE_GENERIC) + { + map->type = HYPERDATATYPE_MAP_INT64_KEYONLY; + } + else if (CONTAINER_KEY(map->type) != HYPERDATATYPE_INT64) + { + *status = HYPERDEX_DS_MIXED_TYPES; + return -1; + } + char buf[sizeof(int64_t)]; + e::pack64le(num, buf); + map->pairs += std::string(buf, buf + sizeof(int64_t)); + *status = HYPERDEX_DS_SUCCESS; + map->state = hyperdex_ds_map::EXPECT_VAL; + return 0; + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + *status = HYPERDEX_DS_NOMEM; + return -1; + } + catch (...) + { + abort(); + } + } + + HYPERDEX_API int + hyperdex_ds_map_insert_val_int(struct hyperdex_ds_map *map, int64_t num, + enum hyperdex_ds_returncode *status) + { + if (map->state != hyperdex_ds_map::EXPECT_VAL) + { + *status = HYPERDEX_DS_WRONG_STATE; + return -1; + } + try + { + if (CONTAINER_VAL(map->type) == HYPERDATATYPE_GENERIC) + { + map->type = RESTRICT_CONTAINER(map->type, HYPERDATATYPE_INT64); + } + else if (CONTAINER_VAL(map->type) != HYPERDATATYPE_INT64) + { + *status = HYPERDEX_DS_MIXED_TYPES; + return -1; + } + char buf[sizeof(int64_t)]; + e::pack64le(num, buf); + map->pairs += std::string(buf, buf + sizeof(int64_t)); + *status = HYPERDEX_DS_SUCCESS; + map->state = hyperdex_ds_map::EXPECT_KEY; + return 0; + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + *status = HYPERDEX_DS_NOMEM; + return -1; + } + catch (...) + { + abort(); + } + } + + HYPERDEX_API int + hyperdex_ds_map_insert_key_float(struct hyperdex_ds_map *map, double num, + enum hyperdex_ds_returncode *status) + { + if (map->state != hyperdex_ds_map::EXPECT_KEY) + { + *status = HYPERDEX_DS_WRONG_STATE; + return -1; + } + try + { + if (CONTAINER_KEY(map->type) == HYPERDATATYPE_GENERIC) + { + map->type = HYPERDATATYPE_MAP_FLOAT_KEYONLY; + } + else if (CONTAINER_KEY(map->type) != HYPERDATATYPE_FLOAT) + { + *status = HYPERDEX_DS_MIXED_TYPES; + return -1; + } + char buf[sizeof(double)]; + e::packdoublele(num, buf); + map->pairs += std::string(buf, buf + sizeof(double)); + *status = HYPERDEX_DS_SUCCESS; + map->state = hyperdex_ds_map::EXPECT_VAL; + return 0; + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + *status = HYPERDEX_DS_NOMEM; + return -1; + } + catch (...) + { + abort(); + } + } + + HYPERDEX_API int + hyperdex_ds_map_insert_val_float(struct hyperdex_ds_map *map, double num, + enum hyperdex_ds_returncode *status) + { + if (map->state != hyperdex_ds_map::EXPECT_VAL) + { + *status = HYPERDEX_DS_WRONG_STATE; + return -1; + } + try + { + if (CONTAINER_VAL(map->type) == HYPERDATATYPE_GENERIC) + { + map->type = RESTRICT_CONTAINER(map->type, HYPERDATATYPE_FLOAT); + } + else if (CONTAINER_VAL(map->type) != HYPERDATATYPE_FLOAT) + { + *status = HYPERDEX_DS_MIXED_TYPES; + return -1; + } + char buf[sizeof(double)]; + e::packdoublele(num, buf); + map->pairs += std::string(buf, buf + sizeof(double)); + *status = HYPERDEX_DS_SUCCESS; + map->state = hyperdex_ds_map::EXPECT_KEY; + return 0; + } + catch (std::bad_alloc &ba) + { + errno = ENOMEM; + *status = HYPERDEX_DS_NOMEM; + return -1; + } + catch (...) + { + abort(); + } + } + + namespace + { + + class map_comparator + { + public: + map_comparator(datatype_info *di) : m_di(di) {} + map_comparator(const map_comparator &other) : m_di(other.m_di) {} + + public: + map_comparator &operator = (const map_comparator &rhs) + { m_di = rhs.m_di; return *this; } + bool operator () (const std::pair &lhs, + const std::pair &rhs) + { return m_di->compare_less()(lhs.first, rhs.first); } + + private: + datatype_info *m_di; + }; + + } // namespace + + HYPERDEX_API int + hyperdex_ds_map_finalize(struct hyperdex_ds_map *map, + enum hyperdex_ds_returncode *status, + const char **value, size_t *value_sz, + enum hyperdatatype *datatype) + { + if (map->state != hyperdex_ds_map::EXPECT_KEY) + { + *status = HYPERDEX_DS_WRONG_STATE; + return -1; + } + if (map->type == HYPERDATATYPE_MAP_GENERIC) + { + assert(map->pairs.empty()); + *status = HYPERDEX_DS_SUCCESS; + *value = map->pairs.data(); + *value_sz = map->pairs.size(); + *datatype = map->type; + return 0; + } + datatype_info *dik = datatype_info::lookup(CONTAINER_KEY(map->type)); + datatype_info *div = datatype_info::lookup(CONTAINER_VAL(map->type)); + assert(dik); + assert(div); + const uint8_t *ptr = reinterpret_cast(map->pairs.data()); + const uint8_t *end = ptr + map->pairs.size(); + e::slice key; + e::slice val; + std::vector > pairs; + while (ptr < end) + { + bool stepped; + stepped = dik->step(&ptr, end, &key); + assert(stepped); + stepped = div->step(&ptr, end, &val); + assert(stepped); + pairs.push_back(std::make_pair(key, val)); + } + assert(ptr == end); + std::sort(pairs.begin(), pairs.end(), map_comparator(dik)); + std::vector tmp(map->pairs.size()); + uint8_t *wr = reinterpret_cast(&tmp[0]); + for (size_t i = 0; i < pairs.size(); ++i) + { + wr = dik->write(pairs[i].first, wr); + wr = div->write(pairs[i].second, wr); + } + map->pairs = std::string(tmp.begin(), tmp.end()); + *status = HYPERDEX_DS_SUCCESS; + *value = map->pairs.data(); + *value_sz = map->pairs.size(); + *datatype = map->type; + return 0; + } + + HYPERDEX_API void + hyperdex_ds_iterator_init(struct hyperdex_ds_iterator *iter, + enum hyperdatatype datatype, + const char *value, + size_t value_sz) + { + iter->datatype = datatype; + iter->value = value; + iter->value_end = value + value_sz; + iter->progress = value; + } + + HYPERDEX_API int + hyperdex_ds_iterate_list_string_next(struct hyperdex_ds_iterator *iter, + const char **str, size_t *str_sz) + { + if (iter->datatype != HYPERDATATYPE_LIST_STRING) + { + return -1; + } + datatype_info *di = datatype_info::lookup(HYPERDATATYPE_STRING); + e::slice elem; + if (iter->progress < iter->value_end) + { + if (!di->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &elem)) + { + iter->progress = iter->value_end + 1; + return -1; + } + *str = reinterpret_cast(elem.data()); + *str_sz = elem.size(); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } + + HYPERDEX_API int + hyperdex_ds_iterate_list_int_next(struct hyperdex_ds_iterator *iter, int64_t *num) + { + if (iter->datatype != HYPERDATATYPE_LIST_INT64) + { + return -1; + } + datatype_info *di = datatype_info::lookup(HYPERDATATYPE_INT64); + e::slice elem; + if (iter->progress < iter->value_end) + { + if (!di->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &elem) || + elem.size() != sizeof(int64_t)) + { + iter->progress = iter->value_end + 1; + return -1; + } + e::unpack64le(elem.data(), num); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } + + HYPERDEX_API int + hyperdex_ds_iterate_list_float_next(struct hyperdex_ds_iterator *iter, double *num) + { + if (iter->datatype != HYPERDATATYPE_LIST_FLOAT) + { + return -1; + } + datatype_info *di = datatype_info::lookup(HYPERDATATYPE_FLOAT); + e::slice elem; + if (iter->progress < iter->value_end) + { + if (!di->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &elem) || + elem.size() != sizeof(double)) + { + iter->progress = iter->value_end + 1; + return -1; + } + e::unpackdoublele(elem.data(), num); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } + + HYPERDEX_API int + hyperdex_ds_iterate_set_string_next(struct hyperdex_ds_iterator *iter, + const char **str, size_t *str_sz) + { + if (iter->datatype != HYPERDATATYPE_SET_STRING) + { + return -1; + } + datatype_info *di = datatype_info::lookup(HYPERDATATYPE_STRING); + e::slice elem; + if (iter->progress < iter->value_end) + { + if (!di->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &elem)) + { + iter->progress = iter->value_end + 1; + return -1; + } + *str = reinterpret_cast(elem.data()); + *str_sz = elem.size(); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } + + HYPERDEX_API int + hyperdex_ds_iterate_set_int_next(struct hyperdex_ds_iterator *iter, int64_t *num) + { + if (iter->datatype != HYPERDATATYPE_SET_INT64) + { + return -1; + } + datatype_info *di = datatype_info::lookup(HYPERDATATYPE_INT64); + e::slice elem; + if (iter->progress < iter->value_end) + { + if (!di->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &elem) || + elem.size() != sizeof(int64_t)) + { + iter->progress = iter->value_end + 1; + return -1; + } + e::unpack64le(elem.data(), num); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } + + HYPERDEX_API int + hyperdex_ds_iterate_set_float_next(struct hyperdex_ds_iterator *iter, double *num) + { + if (iter->datatype != HYPERDATATYPE_SET_FLOAT) + { + return -1; + } + datatype_info *di = datatype_info::lookup(HYPERDATATYPE_FLOAT); + e::slice elem; + if (iter->progress < iter->value_end) + { + if (!di->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &elem) || + elem.size() != sizeof(double)) + { + iter->progress = iter->value_end + 1; + return -1; + } + e::unpackdoublele(elem.data(), num); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } + + HYPERDEX_API int + hyperdex_ds_iterate_map_string_string_next(struct hyperdex_ds_iterator *iter, + const char **key, size_t *key_sz, + const char **val, size_t *val_sz) + { + if (iter->datatype != HYPERDATATYPE_MAP_STRING_STRING) + { + return -1; + } + datatype_info *dik = datatype_info::lookup(HYPERDATATYPE_STRING); + datatype_info *div = datatype_info::lookup(HYPERDATATYPE_STRING); + e::slice mkey; + e::slice mval; + if (iter->progress < iter->value_end) + { + if (!dik->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mkey) || + !div->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mval)) + { + iter->progress = iter->value_end + 1; + return -1; + } + *key = reinterpret_cast(mkey.data()); + *key_sz = mkey.size(); + *val = reinterpret_cast(mval.data()); + *val_sz = mval.size(); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } + + HYPERDEX_API int + hyperdex_ds_iterate_map_string_int_next(struct hyperdex_ds_iterator *iter, + const char **key, size_t *key_sz, + int64_t *val) + { + if (iter->datatype != HYPERDATATYPE_MAP_STRING_INT64) + { + return -1; + } + datatype_info *dik = datatype_info::lookup(HYPERDATATYPE_STRING); + datatype_info *div = datatype_info::lookup(HYPERDATATYPE_INT64); + e::slice mkey; + e::slice mval; + if (iter->progress < iter->value_end) + { + if (!dik->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mkey) || + !div->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mval) || + mval.size() != sizeof(int64_t)) + { + iter->progress = iter->value_end + 1; + return -1; + } + *key = reinterpret_cast(mkey.data()); + *key_sz = mkey.size(); + e::unpack64le(mval.data(), val); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } + + HYPERDEX_API int + hyperdex_ds_iterate_map_string_float_next(struct hyperdex_ds_iterator *iter, + const char **key, size_t *key_sz, + double *val) + { + if (iter->datatype != HYPERDATATYPE_MAP_STRING_FLOAT) + { + return -1; + } + datatype_info *dik = datatype_info::lookup(HYPERDATATYPE_STRING); + datatype_info *div = datatype_info::lookup(HYPERDATATYPE_FLOAT); + e::slice mkey; + e::slice mval; + if (iter->progress < iter->value_end) + { + if (!dik->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mkey) || + !div->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mval) || + mval.size() != sizeof(double)) + { + iter->progress = iter->value_end + 1; + return -1; + } + *key = reinterpret_cast(mkey.data()); + *key_sz = mkey.size(); + e::unpackdoublele(mval.data(), val); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } + + HYPERDEX_API int + hyperdex_ds_iterate_map_int_string_next(struct hyperdex_ds_iterator *iter, + int64_t *key, const char **val, size_t *val_sz) + { + if (iter->datatype != HYPERDATATYPE_MAP_INT64_STRING) + { + return -1; + } + datatype_info *dik = datatype_info::lookup(HYPERDATATYPE_INT64); + datatype_info *div = datatype_info::lookup(HYPERDATATYPE_STRING); + e::slice mkey; + e::slice mval; + if (iter->progress < iter->value_end) + { + if (!dik->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mkey) || + !div->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mval) || + mkey.size() != sizeof(int64_t)) + { + iter->progress = iter->value_end + 1; + return -1; + } + e::unpack64le(mkey.data(), key); + *val = reinterpret_cast(mval.data()); + *val_sz = mval.size(); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } + + HYPERDEX_API int + hyperdex_ds_iterate_map_int_int_next(struct hyperdex_ds_iterator *iter, + int64_t *key, int64_t *val) + { + if (iter->datatype != HYPERDATATYPE_MAP_INT64_INT64) + { + return -1; + } + datatype_info *dik = datatype_info::lookup(HYPERDATATYPE_INT64); + datatype_info *div = datatype_info::lookup(HYPERDATATYPE_INT64); + e::slice mkey; + e::slice mval; + if (iter->progress < iter->value_end) + { + if (!dik->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mkey) || + !div->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mval) || + mkey.size() != sizeof(int64_t) || + mval.size() != sizeof(int64_t)) + { + iter->progress = iter->value_end + 1; + return -1; + } + e::unpack64le(mkey.data(), key); + e::unpack64le(mval.data(), val); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } + + HYPERDEX_API int + hyperdex_ds_iterate_map_int_float_next(struct hyperdex_ds_iterator *iter, + int64_t *key, double *val) + { + if (iter->datatype != HYPERDATATYPE_MAP_INT64_FLOAT) + { + return -1; + } + datatype_info *dik = datatype_info::lookup(HYPERDATATYPE_INT64); + datatype_info *div = datatype_info::lookup(HYPERDATATYPE_FLOAT); + e::slice mkey; + e::slice mval; + if (iter->progress < iter->value_end) + { + if (!dik->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mkey) || + !div->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mval) || + mkey.size() != sizeof(int64_t) || + mval.size() != sizeof(double)) + { + iter->progress = iter->value_end + 1; + return -1; + } + e::unpack64le(mkey.data(), key); + e::unpackdoublele(mval.data(), val); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } + + HYPERDEX_API int + hyperdex_ds_iterate_map_float_string_next(struct hyperdex_ds_iterator *iter, + double *key, const char **val, size_t *val_sz) + { + if (iter->datatype != HYPERDATATYPE_MAP_FLOAT_STRING) + { + return -1; + } + datatype_info *dik = datatype_info::lookup(HYPERDATATYPE_FLOAT); + datatype_info *div = datatype_info::lookup(HYPERDATATYPE_STRING); + e::slice mkey; + e::slice mval; + if (iter->progress < iter->value_end) + { + if (!dik->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mkey) || + !div->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mval) || + mkey.size() != sizeof(double)) + { + iter->progress = iter->value_end + 1; + return -1; + } + e::unpackdoublele(mkey.data(), key); + *val = reinterpret_cast(mval.data()); + *val_sz = mval.size(); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } + + HYPERDEX_API int + hyperdex_ds_iterate_map_float_int_next(struct hyperdex_ds_iterator *iter, + double *key, int64_t *val) + { + if (iter->datatype != HYPERDATATYPE_MAP_FLOAT_INT64) + { + return -1; + } + datatype_info *dik = datatype_info::lookup(HYPERDATATYPE_FLOAT); + datatype_info *div = datatype_info::lookup(HYPERDATATYPE_INT64); + e::slice mkey; + e::slice mval; + if (iter->progress < iter->value_end) + { + if (!dik->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mkey) || + !div->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mval) || + mkey.size() != sizeof(double) || + mval.size() != sizeof(int64_t)) + { + iter->progress = iter->value_end + 1; + return -1; + } + e::unpackdoublele(mkey.data(), key); + e::unpack64le(mval.data(), val); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } + + HYPERDEX_API int + hyperdex_ds_iterate_map_float_float_next(struct hyperdex_ds_iterator *iter, + double *key, double *val) + { + if (iter->datatype != HYPERDATATYPE_MAP_FLOAT_FLOAT) + { + return -1; + } + datatype_info *dik = datatype_info::lookup(HYPERDATATYPE_FLOAT); + datatype_info *div = datatype_info::lookup(HYPERDATATYPE_FLOAT); + e::slice mkey; + e::slice mval; + if (iter->progress < iter->value_end) + { + if (!dik->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mkey) || + !div->step(reinterpret_cast(&iter->progress), + reinterpret_cast(iter->value_end), &mval) || + mkey.size() != sizeof(double) || + mval.size() != sizeof(double)) + { + iter->progress = iter->value_end + 1; + return -1; + } + e::unpackdoublele(mkey.data(), key); + e::unpackdoublele(mval.data(), val); + return 1; + } + return iter->progress == iter->value_end ? 0 : -1; + } } // extern "C" -HYPERDEX_API std::ostream& -operator << (std::ostream& lhs, hyperdex_ds_returncode rhs) -{ - switch (rhs) - { - STRINGIFY(HYPERDEX_DS_SUCCESS); - STRINGIFY(HYPERDEX_DS_NOMEM); - STRINGIFY(HYPERDEX_DS_MIXED_TYPES); - STRINGIFY(HYPERDEX_DS_WRONG_STATE); - STRINGIFY(HYPERDEX_DS_STRING_TOO_LONG); - default: - lhs << "unknown hyperdex_ds_returncode"; - break; - } - - return lhs; +HYPERDEX_API std::ostream & +operator << (std::ostream &lhs, hyperdex_ds_returncode rhs) +{ + switch (rhs) + { + STRINGIFY(HYPERDEX_DS_SUCCESS); + STRINGIFY(HYPERDEX_DS_NOMEM); + STRINGIFY(HYPERDEX_DS_MIXED_TYPES); + STRINGIFY(HYPERDEX_DS_WRONG_STATE); + STRINGIFY(HYPERDEX_DS_STRING_TOO_LONG); + default: + lhs << "unknown hyperdex_ds_returncode"; + break; + } + return lhs; } diff --git a/client/keyop_info.h b/client/keyop_info.h index e3a3a45b6..775d75976 100644 --- a/client/keyop_info.h +++ b/client/keyop_info.h @@ -38,14 +38,14 @@ // This corresponds to the values given in keyop_info.gperf struct hyperdex_client_keyop_info { - int name; // hash of the function name - bool erase; - bool fail_if_not_found; - bool fail_if_found; - hyperdex::funcall_t fname; + int name; // hash of the function name + bool erase; + bool fail_if_not_found; + bool fail_if_found; + hyperdex::funcall_t fname; }; -const struct hyperdex_client_keyop_info* -hyperdex_client_keyop_info_lookup(const char* str, unsigned int len); +const struct hyperdex_client_keyop_info * +hyperdex_client_keyop_info_lookup(const char *str, unsigned int len); #endif // hyperdex_client_keyop_info_h_ diff --git a/client/pending.cc b/client/pending.cc index 5956329e5..63ee6a317 100644 --- a/client/pending.cc +++ b/client/pending.cc @@ -30,11 +30,11 @@ using hyperdex::pending; -pending :: pending(uint64_t id, hyperdex_client_returncode* status) - : m_ref(0) - , m_client_visible_id(id) - , m_status(status) - , m_error() +pending :: pending(uint64_t id, hyperdex_client_returncode *status) + : m_ref(0) + , m_client_visible_id(id) + , m_status(status) + , m_error() { } @@ -42,15 +42,15 @@ pending :: ~pending() throw () { } -std::ostream& -pending :: error(const char* file, size_t line) +std::ostream & +pending :: error(const char *file, size_t line) { - m_error.set_loc(file, line); - return m_error.set_msg(); + m_error.set_loc(file, line); + return m_error.set_msg(); } void -pending :: set_error(const e::error& err) +pending :: set_error(const e::error &err) { - m_error = err; + m_error = err; } diff --git a/client/pending.h b/client/pending.h index dc1dbb6df..efe2701c3 100644 --- a/client/pending.h +++ b/client/pending.h @@ -47,62 +47,62 @@ class client; class pending { - public: - pending(uint64_t client_visible_id, - hyperdex_client_returncode* status); - virtual ~pending() throw (); - - public: - int64_t client_visible_id() const { return m_client_visible_id; } - void set_status(hyperdex_client_returncode status) { *m_status = status; } - e::error error() const { return m_error; } - - // return to client - public: - virtual bool can_yield() = 0; - virtual bool yield(hyperdex_client_returncode* status, e::error* error) = 0; - - // events - public: - virtual void handle_sent_to(const server_id& si, - const virtual_server_id& vsi) = 0; - virtual void handle_failure(const server_id& si, - const virtual_server_id& vsi) = 0; - virtual bool handle_message(client* cl, - const server_id& si, - const virtual_server_id& vsi, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_client_returncode* status, - e::error* error) = 0; - - // refcount - protected: - friend class e::intrusive_ptr; - void inc() { ++m_ref; } - void dec() { if (--m_ref == 0) delete this; } - size_t m_ref; - - protected: - std::ostream& error(const char* file, size_t line); - void set_error(const e::error& err); - - // noncopyable - private: - pending(const pending& other); - pending& operator = (const pending& rhs); - - // operation state - private: - int64_t m_client_visible_id; - hyperdex_client_returncode* m_status; - e::error m_error; +public: + pending(uint64_t client_visible_id, + hyperdex_client_returncode *status); + virtual ~pending() throw (); + +public: + int64_t client_visible_id() const { return m_client_visible_id; } + void set_status(hyperdex_client_returncode status) { *m_status = status; } + e::error error() const { return m_error; } + + // return to client +public: + virtual bool can_yield() = 0; + virtual bool yield(hyperdex_client_returncode *status, e::error *error) = 0; + + // events +public: + virtual void handle_sent_to(const server_id &si, + const virtual_server_id &vsi) = 0; + virtual void handle_failure(const server_id &si, + const virtual_server_id &vsi) = 0; + virtual bool handle_message(client *cl, + const server_id &si, + const virtual_server_id &vsi, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_client_returncode *status, + e::error *error) = 0; + + // refcount +protected: + friend class e::intrusive_ptr; + void inc() { ++m_ref; } + void dec() { if (--m_ref == 0) delete this; } + size_t m_ref; + +protected: + std::ostream &error(const char *file, size_t line); + void set_error(const e::error &err); + + // noncopyable +private: + pending(const pending &other); + pending &operator = (const pending &rhs); + + // operation state +private: + int64_t m_client_visible_id; + hyperdex_client_returncode *m_status; + e::error m_error; }; #define PENDING_ERROR(CODE) \ - this->set_status(HYPERDEX_CLIENT_ ## CODE); \ - this->error(__FILE__, __LINE__) + this->set_status(HYPERDEX_CLIENT_ ## CODE); \ + this->error(__FILE__, __LINE__) END_HYPERDEX_NAMESPACE diff --git a/client/pending_aggregation.cc b/client/pending_aggregation.cc index 505a16341..533dc5719 100644 --- a/client/pending_aggregation.cc +++ b/client/pending_aggregation.cc @@ -31,9 +31,9 @@ using hyperdex::pending_aggregation; pending_aggregation :: pending_aggregation(uint64_t id, - hyperdex_client_returncode* status) - : pending(id, status) - , m_outstanding() + hyperdex_client_returncode *status) + : pending(id, status) + , m_outstanding() { } @@ -44,55 +44,53 @@ pending_aggregation :: ~pending_aggregation() throw () bool pending_aggregation :: aggregation_done() { - return m_outstanding.empty(); + return m_outstanding.empty(); } void -pending_aggregation :: handle_sent_to(const server_id& si, - const virtual_server_id& vsi) +pending_aggregation :: handle_sent_to(const server_id &si, + const virtual_server_id &vsi) { - m_outstanding.push_back(std::make_pair(si, vsi)); + m_outstanding.push_back(std::make_pair(si, vsi)); } void -pending_aggregation :: handle_failure(const server_id& si, - const virtual_server_id& vsi) +pending_aggregation :: handle_failure(const server_id &si, + const virtual_server_id &vsi) { - remove(si, vsi); + remove(si, vsi); } bool -pending_aggregation :: handle_message(client*, - const server_id& si, - const virtual_server_id& vsi, +pending_aggregation :: handle_message(client *, + const server_id &si, + const virtual_server_id &vsi, network_msgtype, std::auto_ptr, e::unpacker, - hyperdex_client_returncode*, - e::error*) + hyperdex_client_returncode *, + e::error *) { - remove(si, vsi); - return true; + remove(si, vsi); + return true; } void -pending_aggregation :: remove(const server_id& si, - const virtual_server_id& vsi) +pending_aggregation :: remove(const server_id &si, + const virtual_server_id &vsi) { - for (size_t i = 0; i < m_outstanding.size(); ++i) - { - if (m_outstanding[i].first != si || - m_outstanding[i].second != vsi) - { - continue; - } - - for (size_t j = i; j + 1 < m_outstanding.size(); ++j) - { - m_outstanding[j] = m_outstanding[j + 1]; - } - - m_outstanding.pop_back(); - return; - } + for (size_t i = 0; i < m_outstanding.size(); ++i) + { + if (m_outstanding[i].first != si || + m_outstanding[i].second != vsi) + { + continue; + } + for (size_t j = i; j + 1 < m_outstanding.size(); ++j) + { + m_outstanding[j] = m_outstanding[j + 1]; + } + m_outstanding.pop_back(); + return; + } } diff --git a/client/pending_aggregation.h b/client/pending_aggregation.h index 8984a3ce9..f82130104 100644 --- a/client/pending_aggregation.h +++ b/client/pending_aggregation.h @@ -40,46 +40,46 @@ BEGIN_HYPERDEX_NAMESPACE class pending_aggregation : public pending { - public: - pending_aggregation(uint64_t client_visible_id, - hyperdex_client_returncode* status); - virtual ~pending_aggregation() throw (); +public: + pending_aggregation(uint64_t client_visible_id, + hyperdex_client_returncode *status); + virtual ~pending_aggregation() throw (); - // handle aggregation across servers; must call handle_* messages from - // subclasses for this to work - public: - bool aggregation_done(); + // handle aggregation across servers; must call handle_* messages from + // subclasses for this to work +public: + bool aggregation_done(); - // events - public: - virtual void handle_sent_to(const server_id& si, - const virtual_server_id& vsi); - virtual void handle_failure(const server_id& si, - const virtual_server_id& vsi); - // pass NULL for msg; we don't need it - virtual bool handle_message(client*, - const server_id& si, - const virtual_server_id& vsi, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_client_returncode* status, - e::error* error); + // events +public: + virtual void handle_sent_to(const server_id &si, + const virtual_server_id &vsi); + virtual void handle_failure(const server_id &si, + const virtual_server_id &vsi); + // pass NULL for msg; we don't need it + virtual bool handle_message(client *, + const server_id &si, + const virtual_server_id &vsi, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_client_returncode *status, + e::error *error); - // refcount - protected: - friend class e::intrusive_ptr; + // refcount +protected: + friend class e::intrusive_ptr; - // noncopyable - private: - pending_aggregation(const pending_aggregation& other); - pending_aggregation& operator = (const pending_aggregation& rhs); + // noncopyable +private: + pending_aggregation(const pending_aggregation &other); + pending_aggregation &operator = (const pending_aggregation &rhs); - private: - virtual void remove(const server_id& si, const virtual_server_id& vsi); +private: + virtual void remove(const server_id &si, const virtual_server_id &vsi); - private: - std::vector > m_outstanding; +private: + std::vector > m_outstanding; }; END_HYPERDEX_NAMESPACE diff --git a/client/pending_atomic.cc b/client/pending_atomic.cc index 7ce2859e2..d5a21ac49 100644 --- a/client/pending_atomic.cc +++ b/client/pending_atomic.cc @@ -32,9 +32,9 @@ using hyperdex::pending_atomic; pending_atomic :: pending_atomic(uint64_t id, - hyperdex_client_returncode* status) - : pending(id, status) - , m_state(INITIALIZED) + hyperdex_client_returncode *status) + : pending(id, status) + , m_state(INITIALIZED) { } @@ -45,114 +45,110 @@ pending_atomic :: ~pending_atomic() throw () bool pending_atomic :: can_yield() { - assert(m_state == RECV || m_state == YIELDED); - return m_state == RECV; + assert(m_state == RECV || m_state == YIELDED); + return m_state == RECV; } bool -pending_atomic :: yield(hyperdex_client_returncode* status, e::error* err) +pending_atomic :: yield(hyperdex_client_returncode *status, e::error *err) { - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - m_state = YIELDED; - return true; + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + m_state = YIELDED; + return true; } void -pending_atomic :: handle_sent_to(const server_id&, - const virtual_server_id&) +pending_atomic :: handle_sent_to(const server_id &, + const virtual_server_id &) { - assert(m_state == INITIALIZED); - m_state = SENT; + assert(m_state == INITIALIZED); + m_state = SENT; } void -pending_atomic :: handle_failure(const server_id& si, - const virtual_server_id& vsi) +pending_atomic :: handle_failure(const server_id &si, + const virtual_server_id &vsi) { - assert(m_state == SENT); - m_state = RECV; - PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " - << vsi << "/" << si; + assert(m_state == SENT); + m_state = RECV; + PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " + << vsi << "/" << si; } bool -pending_atomic :: handle_message(client*, - const server_id& si, - const virtual_server_id& vsi, +pending_atomic :: handle_message(client *, + const server_id &si, + const virtual_server_id &vsi, network_msgtype mt, std::auto_ptr msg, e::unpacker up, - hyperdex_client_returncode* status, - e::error* err) + hyperdex_client_returncode *status, + e::error *err) { - m_state = RECV; - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - - if (mt != RESP_ATOMIC) - { - PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to ATOMIC with " << mt; - return true; - } - - uint16_t response; - up = up >> response; - - if (up.error()) - { - PENDING_ERROR(SERVERERROR) << "communication error: server " - << vsi << " sent corrupt message=" - << msg->as_slice().hex() - << " in response to an ATOMIC"; - return true; - } - - switch (static_cast(response)) - { - case NET_SUCCESS: - set_status(HYPERDEX_CLIENT_SUCCESS); - set_error(e::error()); - return true; - case NET_NOTFOUND: - set_status(HYPERDEX_CLIENT_NOTFOUND); - set_error(e::error()); - return true; - case NET_CMPFAIL: - set_status(HYPERDEX_CLIENT_CMPFAIL); - set_error(e::error()); - return true; - case NET_BADDIMSPEC: - PENDING_ERROR(SERVERERROR) << "server " << si - << " reports that our request was invalid;" - << " check its log for details"; - return true; - case NET_NOTUS: - PENDING_ERROR(RECONFIGURE) << "server " << si - << " reports that it is no longer reponsible" - << " for the requested object"; - return true; - case NET_OVERFLOW: - PENDING_ERROR(OVERFLOW) << "server " << si - << " reports that the operation would" - << " cause a number overflow"; - return true; - case NET_READONLY: - PENDING_ERROR(READONLY) << "cluster is in read-only mode"; - return true; - case NET_SERVERERROR: - PENDING_ERROR(SERVERERROR) << "server " << si - << " reports a server error;" - << " check its log for details"; - return true; - case NET_UNAUTHORIZED: - PENDING_ERROR(UNAUTHORIZED) << "server " << si - << " denied the request because it is unauthorized"; - return true; - default: - PENDING_ERROR(SERVERERROR) << "server " << si - << " returned non-sensical returncode " - << response; - return true; - } + m_state = RECV; + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + if (mt != RESP_ATOMIC) + { + PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to ATOMIC with " << mt; + return true; + } + uint16_t response; + up = up >> response; + if (up.error()) + { + PENDING_ERROR(SERVERERROR) << "communication error: server " + << vsi << " sent corrupt message=" + << msg->as_slice().hex() + << " in response to an ATOMIC"; + return true; + } + switch (static_cast(response)) + { + case NET_SUCCESS: + set_status(HYPERDEX_CLIENT_SUCCESS); + set_error(e::error()); + return true; + case NET_NOTFOUND: + set_status(HYPERDEX_CLIENT_NOTFOUND); + set_error(e::error()); + return true; + case NET_CMPFAIL: + set_status(HYPERDEX_CLIENT_CMPFAIL); + set_error(e::error()); + return true; + case NET_BADDIMSPEC: + PENDING_ERROR(SERVERERROR) << "server " << si + << " reports that our request was invalid;" + << " check its log for details"; + return true; + case NET_NOTUS: + PENDING_ERROR(RECONFIGURE) << "server " << si + << " reports that it is no longer reponsible" + << " for the requested object"; + return true; + case NET_OVERFLOW: + PENDING_ERROR(OVERFLOW) << "server " << si + << " reports that the operation would" + << " cause a number overflow"; + return true; + case NET_READONLY: + PENDING_ERROR(READONLY) << "cluster is in read-only mode"; + return true; + case NET_SERVERERROR: + PENDING_ERROR(SERVERERROR) << "server " << si + << " reports a server error;" + << " check its log for details"; + return true; + case NET_UNAUTHORIZED: + PENDING_ERROR(UNAUTHORIZED) << "server " << si + << " denied the request because it is unauthorized"; + return true; + default: + PENDING_ERROR(SERVERERROR) << "server " << si + << " returned non-sensical returncode " + << response; + return true; + } } diff --git a/client/pending_atomic.h b/client/pending_atomic.h index cd53d9ec4..3508690d6 100644 --- a/client/pending_atomic.h +++ b/client/pending_atomic.h @@ -36,33 +36,33 @@ BEGIN_HYPERDEX_NAMESPACE class pending_atomic : public pending { - public: - pending_atomic(uint64_t client_visible_id, - hyperdex_client_returncode* status); - virtual ~pending_atomic() throw (); +public: + pending_atomic(uint64_t client_visible_id, + hyperdex_client_returncode *status); + virtual ~pending_atomic() throw (); - // return to client - public: - virtual bool can_yield(); - virtual bool yield(hyperdex_client_returncode* status, e::error* error); + // return to client +public: + virtual bool can_yield(); + virtual bool yield(hyperdex_client_returncode *status, e::error *error); - // events - public: - virtual void handle_sent_to(const server_id& si, - const virtual_server_id& vsi); - virtual void handle_failure(const server_id& si, - const virtual_server_id& vsi); - virtual bool handle_message(client*, - const server_id& si, - const virtual_server_id& vsi, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_client_returncode* status, - e::error* error); + // events +public: + virtual void handle_sent_to(const server_id &si, + const virtual_server_id &vsi); + virtual void handle_failure(const server_id &si, + const virtual_server_id &vsi); + virtual bool handle_message(client *, + const server_id &si, + const virtual_server_id &vsi, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_client_returncode *status, + e::error *error); - private: - enum { INITIALIZED, SENT, RECV, YIELDED } m_state; +private: + enum { INITIALIZED, SENT, RECV, YIELDED } m_state; }; END_HYPERDEX_NAMESPACE diff --git a/client/pending_count.cc b/client/pending_count.cc index 57265bb07..66e8bd185 100644 --- a/client/pending_count.cc +++ b/client/pending_count.cc @@ -31,14 +31,14 @@ using hyperdex::pending_count; pending_count :: pending_count(uint64_t id, - hyperdex_client_returncode* status, - uint64_t* count) - : pending_aggregation(id, status) - , m_count(count) - , m_done(false) + hyperdex_client_returncode *status, + uint64_t *count) + : pending_aggregation(id, status) + , m_count(count) + , m_done(false) { - set_status(HYPERDEX_CLIENT_SUCCESS); - set_error(e::error()); + set_status(HYPERDEX_CLIENT_SUCCESS); + set_error(e::error()); } pending_count :: ~pending_count() throw () @@ -48,64 +48,59 @@ pending_count :: ~pending_count() throw () bool pending_count :: can_yield() { - return this->aggregation_done() && !m_done; + return this->aggregation_done() && !m_done; } bool -pending_count :: yield(hyperdex_client_returncode* status, e::error* err) +pending_count :: yield(hyperdex_client_returncode *status, e::error *err) { - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - assert(this->can_yield()); - m_done = true; - return true; + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + assert(this->can_yield()); + m_done = true; + return true; } void -pending_count :: handle_failure(const server_id& si, - const virtual_server_id& vsi) +pending_count :: handle_failure(const server_id &si, + const virtual_server_id &vsi) { - PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " - << vsi << "/" << si; - return pending_aggregation::handle_failure(si, vsi); + PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " + << vsi << "/" << si; + return pending_aggregation::handle_failure(si, vsi); } bool -pending_count :: handle_message(client* cl, - const server_id& si, - const virtual_server_id& vsi, +pending_count :: handle_message(client *cl, + const server_id &si, + const virtual_server_id &vsi, network_msgtype mt, std::auto_ptr msg, e::unpacker up, - hyperdex_client_returncode* status, - e::error* err) + hyperdex_client_returncode *status, + e::error *err) { - bool handled = pending_aggregation::handle_message(cl, si, vsi, mt, std::auto_ptr(), up, status, err); - assert(handled); - - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - - if (mt != RESP_COUNT) - { - PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to COUNT with " << mt; - return true; - } - - uint64_t local_count; - up = up >> local_count; - - if (up.error()) - { - PENDING_ERROR(SERVERERROR) << "communication error: server " - << vsi << " sent corrupt message=" - << msg->as_slice().hex() - << " in response to a COUNT"; - return true; - } - - *m_count += local_count; - // Don't set the status or error so that errors will carry through. It was - // set to the success state in the constructor - return true; + bool handled = pending_aggregation::handle_message(cl, si, vsi, mt, std::auto_ptr(), up, status, err); + assert(handled); + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + if (mt != RESP_COUNT) + { + PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to COUNT with " << mt; + return true; + } + uint64_t local_count; + up = up >> local_count; + if (up.error()) + { + PENDING_ERROR(SERVERERROR) << "communication error: server " + << vsi << " sent corrupt message=" + << msg->as_slice().hex() + << " in response to a COUNT"; + return true; + } + *m_count += local_count; + // Don't set the status or error so that errors will carry through. It was + // set to the success state in the constructor + return true; } diff --git a/client/pending_count.h b/client/pending_count.h index 0819b0bef..fb9a9449b 100644 --- a/client/pending_count.h +++ b/client/pending_count.h @@ -36,38 +36,38 @@ BEGIN_HYPERDEX_NAMESPACE class pending_count : public pending_aggregation { - public: - pending_count(uint64_t client_visible_id, - hyperdex_client_returncode* status, - uint64_t* count); - virtual ~pending_count() throw (); +public: + pending_count(uint64_t client_visible_id, + hyperdex_client_returncode *status, + uint64_t *count); + virtual ~pending_count() throw (); - // return to client - public: - virtual bool can_yield(); - virtual bool yield(hyperdex_client_returncode* status, e::error* error); + // return to client +public: + virtual bool can_yield(); + virtual bool yield(hyperdex_client_returncode *status, e::error *error); - // events - public: - virtual void handle_failure(const server_id& si, - const virtual_server_id& vsi); - virtual bool handle_message(client*, - const server_id& si, - const virtual_server_id& vsi, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_client_returncode* status, - e::error* error); + // events +public: + virtual void handle_failure(const server_id &si, + const virtual_server_id &vsi); + virtual bool handle_message(client *, + const server_id &si, + const virtual_server_id &vsi, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_client_returncode *status, + e::error *error); - // noncopyable - private: - pending_count(const pending_count& other); - pending_count& operator = (const pending_count& rhs); + // noncopyable +private: + pending_count(const pending_count &other); + pending_count &operator = (const pending_count &rhs); - private: - uint64_t* m_count; - bool m_done; +private: + uint64_t *m_count; + bool m_done; }; END_HYPERDEX_NAMESPACE diff --git a/client/pending_get.cc b/client/pending_get.cc index 41ad8b7e5..72a6ff5f7 100644 --- a/client/pending_get.cc +++ b/client/pending_get.cc @@ -34,13 +34,13 @@ using hyperdex::pending_get; pending_get :: pending_get(uint64_t id, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, - size_t* attrs_sz) - : pending(id, status) - , m_state(INITIALIZED) - , m_attrs(attrs) - , m_attrs_sz(attrs_sz) + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, + size_t *attrs_sz) + : pending(id, status) + , m_state(INITIALIZED) + , m_attrs(attrs) + , m_attrs_sz(attrs_sz) { } @@ -51,143 +51,134 @@ pending_get :: ~pending_get() throw () bool pending_get :: can_yield() { - assert(m_state == RECV || m_state == YIELDED); - return m_state == RECV; + assert(m_state == RECV || m_state == YIELDED); + return m_state == RECV; } bool -pending_get :: yield(hyperdex_client_returncode* status, e::error* err) +pending_get :: yield(hyperdex_client_returncode *status, e::error *err) { - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - m_state = YIELDED; - return true; + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + m_state = YIELDED; + return true; } void -pending_get :: handle_sent_to(const server_id&, - const virtual_server_id&) +pending_get :: handle_sent_to(const server_id &, + const virtual_server_id &) { - assert(m_state == INITIALIZED); - m_state = SENT; + assert(m_state == INITIALIZED); + m_state = SENT; } void -pending_get :: handle_failure(const server_id& si, - const virtual_server_id& vsi) +pending_get :: handle_failure(const server_id &si, + const virtual_server_id &vsi) { - assert(m_state == SENT); - m_state = RECV; - PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " - << vsi << "/" << si; + assert(m_state == SENT); + m_state = RECV; + PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " + << vsi << "/" << si; } bool -pending_get :: handle_message(client* cl, - const server_id& si, - const virtual_server_id& vsi, +pending_get :: handle_message(client *cl, + const server_id &si, + const virtual_server_id &vsi, network_msgtype mt, std::auto_ptr msg, e::unpacker up, - hyperdex_client_returncode* status, - e::error* err) + hyperdex_client_returncode *status, + e::error *err) { - m_state = RECV; - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - - if (mt != RESP_GET) - { - PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to GET with " << mt; - return true; - } - - uint16_t response; - up = up >> response; - - if (up.error()) - { - PENDING_ERROR(SERVERERROR) << "communication error: server " - << vsi << " sent corrupt message=" - << msg->as_slice().hex() - << " in response to a GET"; - return true; - } - - switch (static_cast(response)) - { - case NET_SUCCESS: - break; - case NET_NOTFOUND: - set_status(HYPERDEX_CLIENT_NOTFOUND); - set_error(e::error()); - return true; - case NET_BADDIMSPEC: - PENDING_ERROR(SERVERERROR) << "server " << si - << " reports that our request was invalid;" - << " check its log for details"; - return true; - case NET_NOTUS: - PENDING_ERROR(RECONFIGURE) << "server " << si - << " reports that it is no longer reponsible" - << " for the requested object"; - return true; - case NET_READONLY: - PENDING_ERROR(READONLY) << "cluster is in read-only mode, but this was a read:" - << " please file a bug"; - return true; - case NET_SERVERERROR: - PENDING_ERROR(SERVERERROR) << "server " << si - << " reports a server error;" - << " check its log for details"; - return true; - case NET_CMPFAIL: - PENDING_ERROR(SERVERERROR) << "server " << si - << " unexpectedly reports that a comparison failed;" - << " check its log for details"; - return true; - case NET_OVERFLOW: - PENDING_ERROR(OVERFLOW) << "server " << si - << " reports that the operation would" - << " cause a number overflow"; - return true; - case NET_UNAUTHORIZED: - PENDING_ERROR(UNAUTHORIZED) << "server " << si - << " denied the request because it is unauthorized"; - return true; - default: - PENDING_ERROR(SERVERERROR) << "server " << si - << " returned non-sensical returncode" - << response; - return true; - } - - std::vector value; - up = up >> value; - - if (up.error()) - { - PENDING_ERROR(SERVERERROR) << "communication error: server " - << vsi << " sent corrupt message=" - << msg->as_slice().hex() - << " in response to a GET"; - return true; - } - - hyperdex_client_returncode op_status; - e::error op_error; - - if (!value_to_attributes(cl->m_config, - cl->m_config.get_region_id(vsi), - NULL, 0, value, &op_status, &op_error, - m_attrs, m_attrs_sz, cl->m_convert_types)) - { - set_status(op_status); - set_error(op_error); - return true; - } - - set_status(HYPERDEX_CLIENT_SUCCESS); - set_error(e::error()); - return true; + m_state = RECV; + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + if (mt != RESP_GET) + { + PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to GET with " << mt; + return true; + } + uint16_t response; + up = up >> response; + if (up.error()) + { + PENDING_ERROR(SERVERERROR) << "communication error: server " + << vsi << " sent corrupt message=" + << msg->as_slice().hex() + << " in response to a GET"; + return true; + } + switch (static_cast(response)) + { + case NET_SUCCESS: + break; + case NET_NOTFOUND: + set_status(HYPERDEX_CLIENT_NOTFOUND); + set_error(e::error()); + return true; + case NET_BADDIMSPEC: + PENDING_ERROR(SERVERERROR) << "server " << si + << " reports that our request was invalid;" + << " check its log for details"; + return true; + case NET_NOTUS: + PENDING_ERROR(RECONFIGURE) << "server " << si + << " reports that it is no longer reponsible" + << " for the requested object"; + return true; + case NET_READONLY: + PENDING_ERROR(READONLY) << "cluster is in read-only mode, but this was a read:" + << " please file a bug"; + return true; + case NET_SERVERERROR: + PENDING_ERROR(SERVERERROR) << "server " << si + << " reports a server error;" + << " check its log for details"; + return true; + case NET_CMPFAIL: + PENDING_ERROR(SERVERERROR) << "server " << si + << " unexpectedly reports that a comparison failed;" + << " check its log for details"; + return true; + case NET_OVERFLOW: + PENDING_ERROR(OVERFLOW) << "server " << si + << " reports that the operation would" + << " cause a number overflow"; + return true; + case NET_UNAUTHORIZED: + PENDING_ERROR(UNAUTHORIZED) << "server " << si + << " denied the request because it is unauthorized"; + return true; + default: + PENDING_ERROR(SERVERERROR) << "server " << si + << " returned non-sensical returncode" + << response; + return true; + } + std::vector value; + up = up >> value; + if (up.error()) + { + PENDING_ERROR(SERVERERROR) << "communication error: server " + << vsi << " sent corrupt message=" + << msg->as_slice().hex() + << " in response to a GET"; + return true; + } + hyperdex_client_returncode op_status; + e::error op_error; + if (!value_to_attributes(cl->m_config, + cl->m_config.get_region_id(vsi), + NULL, 0, value, &op_status, &op_error, + m_attrs, m_attrs_sz, cl->m_convert_types)) + { + set_status(op_status); + set_error(op_error); + return true; + } + set_status(HYPERDEX_CLIENT_SUCCESS); + set_error(e::error()); + return true; } diff --git a/client/pending_get.h b/client/pending_get.h index 9c5159f75..7567cc383 100644 --- a/client/pending_get.h +++ b/client/pending_get.h @@ -36,41 +36,41 @@ BEGIN_HYPERDEX_NAMESPACE class pending_get : public pending { - public: - pending_get(uint64_t client_visible_id, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz); - virtual ~pending_get() throw (); +public: + pending_get(uint64_t client_visible_id, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz); + virtual ~pending_get() throw (); - // return to client - public: - virtual bool can_yield(); - virtual bool yield(hyperdex_client_returncode* status, e::error* error); + // return to client +public: + virtual bool can_yield(); + virtual bool yield(hyperdex_client_returncode *status, e::error *error); - // events - public: - virtual void handle_sent_to(const server_id& si, - const virtual_server_id& vsi); - virtual void handle_failure(const server_id& si, - const virtual_server_id& vsi); - virtual bool handle_message(client*, - const server_id& si, - const virtual_server_id& vsi, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_client_returncode* status, - e::error* error); + // events +public: + virtual void handle_sent_to(const server_id &si, + const virtual_server_id &vsi); + virtual void handle_failure(const server_id &si, + const virtual_server_id &vsi); + virtual bool handle_message(client *, + const server_id &si, + const virtual_server_id &vsi, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_client_returncode *status, + e::error *error); - // noncopyable - private: - pending_get(const pending_get& other); - pending_get& operator = (const pending_get& rhs); + // noncopyable +private: + pending_get(const pending_get &other); + pending_get &operator = (const pending_get &rhs); - private: - enum { INITIALIZED, SENT, RECV, YIELDED } m_state; - const hyperdex_client_attribute** m_attrs; - size_t* m_attrs_sz; +private: + enum { INITIALIZED, SENT, RECV, YIELDED } m_state; + const hyperdex_client_attribute **m_attrs; + size_t *m_attrs_sz; }; END_HYPERDEX_NAMESPACE diff --git a/client/pending_get_partial.cc b/client/pending_get_partial.cc index f35fa03a9..2baf87100 100644 --- a/client/pending_get_partial.cc +++ b/client/pending_get_partial.cc @@ -34,13 +34,13 @@ using hyperdex::pending_get_partial; pending_get_partial :: pending_get_partial(uint64_t id, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, - size_t* attrs_sz) - : pending(id, status) - , m_state(INITIALIZED) - , m_attrs(attrs) - , m_attrs_sz(attrs_sz) + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, + size_t *attrs_sz) + : pending(id, status) + , m_state(INITIALIZED) + , m_attrs(attrs) + , m_attrs_sz(attrs_sz) { } @@ -51,150 +51,140 @@ pending_get_partial :: ~pending_get_partial() throw () bool pending_get_partial :: can_yield() { - assert(m_state == RECV || m_state == YIELDED); - return m_state == RECV; + assert(m_state == RECV || m_state == YIELDED); + return m_state == RECV; } bool -pending_get_partial :: yield(hyperdex_client_returncode* status, e::error* err) +pending_get_partial :: yield(hyperdex_client_returncode *status, e::error *err) { - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - m_state = YIELDED; - return true; + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + m_state = YIELDED; + return true; } void -pending_get_partial :: handle_sent_to(const server_id&, - const virtual_server_id&) +pending_get_partial :: handle_sent_to(const server_id &, + const virtual_server_id &) { - assert(m_state == INITIALIZED); - m_state = SENT; + assert(m_state == INITIALIZED); + m_state = SENT; } void -pending_get_partial :: handle_failure(const server_id& si, - const virtual_server_id& vsi) +pending_get_partial :: handle_failure(const server_id &si, + const virtual_server_id &vsi) { - assert(m_state == SENT); - m_state = RECV; - PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " - << vsi << "/" << si; + assert(m_state == SENT); + m_state = RECV; + PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " + << vsi << "/" << si; } bool -pending_get_partial :: handle_message(client* cl, - const server_id& si, - const virtual_server_id& vsi, +pending_get_partial :: handle_message(client *cl, + const server_id &si, + const virtual_server_id &vsi, network_msgtype mt, std::auto_ptr msg, e::unpacker up, - hyperdex_client_returncode* status, - e::error* err) + hyperdex_client_returncode *status, + e::error *err) { - m_state = RECV; - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - - if (mt != RESP_GET_PARTIAL) - { - PENDING_ERROR(SERVERERROR) << "server vsi responded to GET with " << mt; - return true; - } - - uint16_t response; - up = up >> response; - - if (up.error()) - { - PENDING_ERROR(SERVERERROR) << "communication error: server " - << vsi << " sent corrupt message=" - << msg->as_slice().hex() - << " in response to a GET"; - return true; - } - - switch (static_cast(response)) - { - case NET_SUCCESS: - break; - case NET_NOTFOUND: - set_status(HYPERDEX_CLIENT_NOTFOUND); - set_error(e::error()); - return true; - case NET_BADDIMSPEC: - PENDING_ERROR(SERVERERROR) << "server " << si - << " reports that our request was invalid;" - << " check its log for details"; - return true; - case NET_NOTUS: - PENDING_ERROR(RECONFIGURE) << "server " << si - << " reports that it is no longer reponsible" - << " for the requested object"; - return true; - case NET_READONLY: - PENDING_ERROR(READONLY) << "cluster is in read-only mode, but this was a read:" - << " please file a bug"; - return true; - case NET_SERVERERROR: - PENDING_ERROR(SERVERERROR) << "server " << si - << " reports a server error;" - << " check its log for details"; - return true; - case NET_CMPFAIL: - PENDING_ERROR(SERVERERROR) << "server " << si - << " unexpectedly reports that a comparison failed;" - << " check its log for details"; - return true; - case NET_OVERFLOW: - PENDING_ERROR(OVERFLOW) << "server " << si - << " reports that the operation would" - << " cause a number overflow"; - return true; - case NET_UNAUTHORIZED: - PENDING_ERROR(UNAUTHORIZED) << "server " << si - << " denied the request because it is unauthorized"; - return true; - default: - PENDING_ERROR(SERVERERROR) << "server " << si - << " returned non-sensical returncode" - << response; - return true; - } - - std::vector > value; - - while (up.remain() && !up.error()) - { - uint16_t attr_n; - e::slice attr_s; - up = up >> attr_n >> attr_s; - value.push_back(std::make_pair(attr_n, attr_s)); - } - - if (up.error()) - { - PENDING_ERROR(SERVERERROR) << "communication error: server " - << vsi << " sent corrupt message=" - << msg->as_slice().hex() - << " in response to a GET_PARTIAL"; - return true; - } - - hyperdex_client_returncode op_status; - e::error op_error; - - if (!value_to_attributes(cl->m_config, - cl->m_config.get_region_id(vsi), - value, &op_status, &op_error, - m_attrs, m_attrs_sz, cl->m_convert_types)) - { - set_status(op_status); - set_error(op_error); - return true; - } - - set_status(HYPERDEX_CLIENT_SUCCESS); - set_error(e::error()); - return true; + m_state = RECV; + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + if (mt != RESP_GET_PARTIAL) + { + PENDING_ERROR(SERVERERROR) << "server vsi responded to GET with " << mt; + return true; + } + uint16_t response; + up = up >> response; + if (up.error()) + { + PENDING_ERROR(SERVERERROR) << "communication error: server " + << vsi << " sent corrupt message=" + << msg->as_slice().hex() + << " in response to a GET"; + return true; + } + switch (static_cast(response)) + { + case NET_SUCCESS: + break; + case NET_NOTFOUND: + set_status(HYPERDEX_CLIENT_NOTFOUND); + set_error(e::error()); + return true; + case NET_BADDIMSPEC: + PENDING_ERROR(SERVERERROR) << "server " << si + << " reports that our request was invalid;" + << " check its log for details"; + return true; + case NET_NOTUS: + PENDING_ERROR(RECONFIGURE) << "server " << si + << " reports that it is no longer reponsible" + << " for the requested object"; + return true; + case NET_READONLY: + PENDING_ERROR(READONLY) << "cluster is in read-only mode, but this was a read:" + << " please file a bug"; + return true; + case NET_SERVERERROR: + PENDING_ERROR(SERVERERROR) << "server " << si + << " reports a server error;" + << " check its log for details"; + return true; + case NET_CMPFAIL: + PENDING_ERROR(SERVERERROR) << "server " << si + << " unexpectedly reports that a comparison failed;" + << " check its log for details"; + return true; + case NET_OVERFLOW: + PENDING_ERROR(OVERFLOW) << "server " << si + << " reports that the operation would" + << " cause a number overflow"; + return true; + case NET_UNAUTHORIZED: + PENDING_ERROR(UNAUTHORIZED) << "server " << si + << " denied the request because it is unauthorized"; + return true; + default: + PENDING_ERROR(SERVERERROR) << "server " << si + << " returned non-sensical returncode" + << response; + return true; + } + std::vector > value; + while (up.remain() && !up.error()) + { + uint16_t attr_n; + e::slice attr_s; + up = up >> attr_n >> attr_s; + value.push_back(std::make_pair(attr_n, attr_s)); + } + if (up.error()) + { + PENDING_ERROR(SERVERERROR) << "communication error: server " + << vsi << " sent corrupt message=" + << msg->as_slice().hex() + << " in response to a GET_PARTIAL"; + return true; + } + hyperdex_client_returncode op_status; + e::error op_error; + if (!value_to_attributes(cl->m_config, + cl->m_config.get_region_id(vsi), + value, &op_status, &op_error, + m_attrs, m_attrs_sz, cl->m_convert_types)) + { + set_status(op_status); + set_error(op_error); + return true; + } + set_status(HYPERDEX_CLIENT_SUCCESS); + set_error(e::error()); + return true; } diff --git a/client/pending_get_partial.h b/client/pending_get_partial.h index 792c47914..bedd30e41 100644 --- a/client/pending_get_partial.h +++ b/client/pending_get_partial.h @@ -36,41 +36,41 @@ BEGIN_HYPERDEX_NAMESPACE class pending_get_partial : public pending { - public: - pending_get_partial(uint64_t client_visible_id, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz); - virtual ~pending_get_partial() throw (); +public: + pending_get_partial(uint64_t client_visible_id, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz); + virtual ~pending_get_partial() throw (); - // return to client - public: - virtual bool can_yield(); - virtual bool yield(hyperdex_client_returncode* status, e::error* error); + // return to client +public: + virtual bool can_yield(); + virtual bool yield(hyperdex_client_returncode *status, e::error *error); - // events - public: - virtual void handle_sent_to(const server_id& si, - const virtual_server_id& vsi); - virtual void handle_failure(const server_id& si, - const virtual_server_id& vsi); - virtual bool handle_message(client*, - const server_id& si, - const virtual_server_id& vsi, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_client_returncode* status, - e::error* error); + // events +public: + virtual void handle_sent_to(const server_id &si, + const virtual_server_id &vsi); + virtual void handle_failure(const server_id &si, + const virtual_server_id &vsi); + virtual bool handle_message(client *, + const server_id &si, + const virtual_server_id &vsi, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_client_returncode *status, + e::error *error); - // noncopyable - private: - pending_get_partial(const pending_get_partial& other); - pending_get_partial& operator = (const pending_get_partial& rhs); + // noncopyable +private: + pending_get_partial(const pending_get_partial &other); + pending_get_partial &operator = (const pending_get_partial &rhs); - private: - enum { INITIALIZED, SENT, RECV, YIELDED } m_state; - const hyperdex_client_attribute** m_attrs; - size_t* m_attrs_sz; +private: + enum { INITIALIZED, SENT, RECV, YIELDED } m_state; + const hyperdex_client_attribute **m_attrs; + size_t *m_attrs_sz; }; END_HYPERDEX_NAMESPACE diff --git a/client/pending_group_atomic.cc b/client/pending_group_atomic.cc index 72254d3fa..60a0c4a00 100644 --- a/client/pending_group_atomic.cc +++ b/client/pending_group_atomic.cc @@ -32,13 +32,13 @@ using hyperdex::pending_group_atomic; pending_group_atomic :: pending_group_atomic(uint64_t id, - hyperdex_client_returncode* status, - uint64_t* update_count) - : pending_aggregation(id, status) - , m_state(INITIALIZED) - , m_update_count(update_count) + hyperdex_client_returncode *status, + uint64_t *update_count) + : pending_aggregation(id, status) + , m_state(INITIALIZED) + , m_update_count(update_count) { - *m_update_count = 0; + *m_update_count = 0; } pending_group_atomic :: ~pending_group_atomic() throw () @@ -48,84 +48,76 @@ pending_group_atomic :: ~pending_group_atomic() throw () bool pending_group_atomic :: can_yield() { - return m_state == DONE || m_state == FAILURE; + return m_state == DONE || m_state == FAILURE; } bool -pending_group_atomic :: yield(hyperdex_client_returncode* status, e::error* err) +pending_group_atomic :: yield(hyperdex_client_returncode *status, e::error *err) { - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - assert(this->can_yield()); - m_state = YIELDED; - return true; + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + assert(this->can_yield()); + m_state = YIELDED; + return true; } void -pending_group_atomic :: handle_sent_to(const server_id& sid, - const virtual_server_id& vid) +pending_group_atomic :: handle_sent_to(const server_id &sid, + const virtual_server_id &vid) { - pending_aggregation::handle_sent_to(sid, vid); - - // We could already have received something - if(m_state == INITIALIZED) - { - m_state = SENT; - } + pending_aggregation::handle_sent_to(sid, vid); + // We could already have received something + if (m_state == INITIALIZED) + { + m_state = SENT; + } } void -pending_group_atomic :: handle_failure(const server_id& si, - const virtual_server_id& vsi) +pending_group_atomic :: handle_failure(const server_id &si, + const virtual_server_id &vsi) { - pending_aggregation::handle_failure(si, vsi); - - assert(m_state == SENT); - m_state = RECV; - PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " - << vsi << "/" << si; + pending_aggregation::handle_failure(si, vsi); + assert(m_state == SENT); + m_state = RECV; + PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " + << vsi << "/" << si; } bool -pending_group_atomic :: handle_message(client* cl, - const server_id& si, - const virtual_server_id& vsi, +pending_group_atomic :: handle_message(client *cl, + const server_id &si, + const virtual_server_id &vsi, network_msgtype mt, std::auto_ptr msg, e::unpacker up, - hyperdex_client_returncode* status, - e::error* err) + hyperdex_client_returncode *status, + e::error *err) { - bool handled = pending_aggregation::handle_message(cl, si, vsi, mt, std::auto_ptr(), up, status, err); - assert(handled); - - if (mt != RESP_GROUP_ATOMIC) - { - PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to GROUP_ATOMIC with " << mt; - return true; - } - - uint64_t response; - up = up >> response; - - // Remember how many fields we updated - *m_update_count += response; - - if (up.error()) - { - PENDING_ERROR(SERVERERROR) << "communication error: server " - << vsi << " sent corrupt message=" - << msg->as_slice().hex() - << " in response to a GROUP_ATOMIC"; - return true; - } - - if(this->aggregation_done()) - { - m_state = DONE; - set_status(HYPERDEX_CLIENT_SUCCESS); - set_error(e::error()); - } - - return true; + bool handled = pending_aggregation::handle_message(cl, si, vsi, mt, std::auto_ptr(), up, status, err); + assert(handled); + if (mt != RESP_GROUP_ATOMIC) + { + PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to GROUP_ATOMIC with " << mt; + return true; + } + uint64_t response; + up = up >> response; + // Remember how many fields we updated + *m_update_count += response; + if (up.error()) + { + PENDING_ERROR(SERVERERROR) << "communication error: server " + << vsi << " sent corrupt message=" + << msg->as_slice().hex() + << " in response to a GROUP_ATOMIC"; + return true; + } + if (this->aggregation_done()) + { + m_state = DONE; + set_status(HYPERDEX_CLIENT_SUCCESS); + set_error(e::error()); + } + return true; } diff --git a/client/pending_group_atomic.h b/client/pending_group_atomic.h index ffe468e82..c0f5d8b01 100644 --- a/client/pending_group_atomic.h +++ b/client/pending_group_atomic.h @@ -36,39 +36,39 @@ BEGIN_HYPERDEX_NAMESPACE class pending_group_atomic : public pending_aggregation { - public: - pending_group_atomic(uint64_t client_visible_id, - hyperdex_client_returncode* status, - uint64_t* update_count); - virtual ~pending_group_atomic() throw (); +public: + pending_group_atomic(uint64_t client_visible_id, + hyperdex_client_returncode *status, + uint64_t *update_count); + virtual ~pending_group_atomic() throw (); - // return to client - public: - virtual bool can_yield(); - virtual bool yield(hyperdex_client_returncode* status, e::error* error); + // return to client +public: + virtual bool can_yield(); + virtual bool yield(hyperdex_client_returncode *status, e::error *error); - // events - public: - virtual void handle_sent_to(const server_id& si, - const virtual_server_id& vsi); - virtual void handle_failure(const server_id& si, - const virtual_server_id& vsi); - virtual bool handle_message(client*, - const server_id& si, - const virtual_server_id& vsi, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_client_returncode* status, - e::error* error); + // events +public: + virtual void handle_sent_to(const server_id &si, + const virtual_server_id &vsi); + virtual void handle_failure(const server_id &si, + const virtual_server_id &vsi); + virtual bool handle_message(client *, + const server_id &si, + const virtual_server_id &vsi, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_client_returncode *status, + e::error *error); - private: - enum { INITIALIZED, SENT, RECV, DONE, FAILURE, YIELDED } m_state; - uint64_t* m_update_count; +private: + enum { INITIALIZED, SENT, RECV, DONE, FAILURE, YIELDED } m_state; + uint64_t *m_update_count; - private: - pending_group_atomic(const pending_group_atomic&); - pending_group_atomic& operator = (const pending_group_atomic&); +private: + pending_group_atomic(const pending_group_atomic &); + pending_group_atomic &operator = (const pending_group_atomic &); }; END_HYPERDEX_NAMESPACE diff --git a/client/pending_search.cc b/client/pending_search.cc index 155eea855..9baa9f69a 100644 --- a/client/pending_search.cc +++ b/client/pending_search.cc @@ -34,16 +34,16 @@ using hyperdex::pending_search; pending_search :: pending_search(uint64_t id, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz) - : pending_aggregation(id, status) - , m_attrs(attrs) - , m_attrs_sz(attrs_sz) - , m_yield(false) - , m_done(false) + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz) + : pending_aggregation(id, status) + , m_attrs(attrs) + , m_attrs_sz(attrs_sz) + , m_yield(false) + , m_done(false) { - *m_attrs = NULL; - *m_attrs_sz = 0; + *m_attrs = NULL; + *m_attrs_sz = 0; } pending_search :: ~pending_search() throw () @@ -53,112 +53,100 @@ pending_search :: ~pending_search() throw () bool pending_search :: can_yield() { - return m_yield; + return m_yield; } bool -pending_search :: yield(hyperdex_client_returncode* status, e::error* err) +pending_search :: yield(hyperdex_client_returncode *status, e::error *err) { - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - m_yield = false; - - if (this->aggregation_done() && !m_done) - { - m_yield = true; - m_done = true; - } - else if (m_done) - { - set_status(HYPERDEX_CLIENT_SEARCHDONE); - } - - return true; + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + m_yield = false; + if (this->aggregation_done() && !m_done) + { + m_yield = true; + m_done = true; + } + else if (m_done) + { + set_status(HYPERDEX_CLIENT_SEARCHDONE); + } + return true; } void -pending_search :: handle_failure(const server_id& si, - const virtual_server_id& vsi) +pending_search :: handle_failure(const server_id &si, + const virtual_server_id &vsi) { - m_yield = true; - PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " - << vsi << "/" << si; - return pending_aggregation::handle_failure(si, vsi); + m_yield = true; + PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " + << vsi << "/" << si; + return pending_aggregation::handle_failure(si, vsi); } bool -pending_search :: handle_message(client* cl, - const server_id& si, - const virtual_server_id& vsi, +pending_search :: handle_message(client *cl, + const server_id &si, + const virtual_server_id &vsi, network_msgtype mt, std::auto_ptr msg, e::unpacker up, - hyperdex_client_returncode* status, - e::error* err) + hyperdex_client_returncode *status, + e::error *err) { - bool handled = pending_aggregation::handle_message(cl, si, vsi, mt, std::auto_ptr(), up, status, err); - assert(handled); - - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - - if (mt == RESP_SEARCH_DONE) - { - if (this->aggregation_done()) - { - m_yield = true; - m_done = true; - } - - return true; - } - else if (mt != RESP_SEARCH_ITEM) - { - PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to SEARCH with " << mt; - m_yield = true; - return true; - } - - e::slice key; - std::vector value; - up = up >> key >> value; - - if (up.error()) - { - PENDING_ERROR(SERVERERROR) << "communication error: server " - << vsi << " sent corrupt message=" - << msg->as_slice().hex() - << " in response to a SEARCH"; - m_yield = true; - return true; - } - - hyperdex_client_returncode op_status; - e::error op_error; - - if (!value_to_attributes(cl->m_config, - cl->m_config.get_region_id(vsi), - key.data(), key.size(), value, - &op_status, &op_error, m_attrs, m_attrs_sz, cl->m_convert_types)) - { - set_status(op_status); - set_error(op_error); - m_yield = true; - return true; - } - - std::auto_ptr smsg(e::buffer::create(HYPERDEX_CLIENT_HEADER_SIZE_REQ + sizeof(uint64_t))); - smsg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << static_cast(client_visible_id()); - - if (!cl->send(REQ_SEARCH_NEXT, vsi, cl->m_next_server_nonce++, smsg, this, status)) - { - PENDING_ERROR(RECONFIGURE) << "could not send SEARCH_NEXT to " << vsi; - m_yield = true; - return true; - } - - set_status(HYPERDEX_CLIENT_SUCCESS); - set_error(e::error()); - m_yield = true; - return true; + bool handled = pending_aggregation::handle_message(cl, si, vsi, mt, std::auto_ptr(), up, status, err); + assert(handled); + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + if (mt == RESP_SEARCH_DONE) + { + if (this->aggregation_done()) + { + m_yield = true; + m_done = true; + } + return true; + } + else if (mt != RESP_SEARCH_ITEM) + { + PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to SEARCH with " << mt; + m_yield = true; + return true; + } + e::slice key; + std::vector value; + up = up >> key >> value; + if (up.error()) + { + PENDING_ERROR(SERVERERROR) << "communication error: server " + << vsi << " sent corrupt message=" + << msg->as_slice().hex() + << " in response to a SEARCH"; + m_yield = true; + return true; + } + hyperdex_client_returncode op_status; + e::error op_error; + if (!value_to_attributes(cl->m_config, + cl->m_config.get_region_id(vsi), + key.data(), key.size(), value, + &op_status, &op_error, m_attrs, m_attrs_sz, cl->m_convert_types)) + { + set_status(op_status); + set_error(op_error); + m_yield = true; + return true; + } + std::auto_ptr smsg(e::buffer::create(HYPERDEX_CLIENT_HEADER_SIZE_REQ + sizeof(uint64_t))); + smsg->pack_at(HYPERDEX_CLIENT_HEADER_SIZE_REQ) << static_cast(client_visible_id()); + if (!cl->send(REQ_SEARCH_NEXT, vsi, cl->m_next_server_nonce++, smsg, this, status)) + { + PENDING_ERROR(RECONFIGURE) << "could not send SEARCH_NEXT to " << vsi; + m_yield = true; + return true; + } + set_status(HYPERDEX_CLIENT_SUCCESS); + set_error(e::error()); + m_yield = true; + return true; } diff --git a/client/pending_search.h b/client/pending_search.h index 5a965d018..fa7b06480 100644 --- a/client/pending_search.h +++ b/client/pending_search.h @@ -36,40 +36,40 @@ BEGIN_HYPERDEX_NAMESPACE class pending_search : public pending_aggregation { - public: - pending_search(uint64_t client_visible_id, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz); - virtual ~pending_search() throw (); +public: + pending_search(uint64_t client_visible_id, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz); + virtual ~pending_search() throw (); - // return to client - public: - virtual bool can_yield(); - virtual bool yield(hyperdex_client_returncode* status, e::error* error); + // return to client +public: + virtual bool can_yield(); + virtual bool yield(hyperdex_client_returncode *status, e::error *error); - // events - public: - virtual void handle_failure(const server_id& si, - const virtual_server_id& vsi); - virtual bool handle_message(client*, - const server_id& si, - const virtual_server_id& vsi, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_client_returncode* status, - e::error* error); + // events +public: + virtual void handle_failure(const server_id &si, + const virtual_server_id &vsi); + virtual bool handle_message(client *, + const server_id &si, + const virtual_server_id &vsi, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_client_returncode *status, + e::error *error); - // noncopyable - private: - pending_search(const pending_search& other); - pending_search& operator = (const pending_search& rhs); + // noncopyable +private: + pending_search(const pending_search &other); + pending_search &operator = (const pending_search &rhs); - private: - const hyperdex_client_attribute** m_attrs; - size_t* m_attrs_sz; - bool m_yield; - bool m_done; +private: + const hyperdex_client_attribute **m_attrs; + size_t *m_attrs_sz; + bool m_yield; + bool m_done; }; END_HYPERDEX_NAMESPACE diff --git a/client/pending_search_describe.cc b/client/pending_search_describe.cc index 2315e5293..ffd61ae4b 100644 --- a/client/pending_search_describe.cc +++ b/client/pending_search_describe.cc @@ -31,13 +31,13 @@ using hyperdex::pending_search_describe; pending_search_describe :: pending_search_describe(uint64_t id, - hyperdex_client_returncode* status, - const char** description) - : pending_aggregation(id, status) - , m_description(description) - , m_done(false) - , m_msgs() - , m_text() + hyperdex_client_returncode *status, + const char **description) + : pending_aggregation(id, status) + , m_description(description) + , m_done(false) + , m_msgs() + , m_text() { } @@ -48,83 +48,78 @@ pending_search_describe :: ~pending_search_describe() throw () bool pending_search_describe :: can_yield() { - return this->aggregation_done() && !m_done; + return this->aggregation_done() && !m_done; } bool -pending_search_describe :: yield(hyperdex_client_returncode* status, e::error* err) +pending_search_describe :: yield(hyperdex_client_returncode *status, e::error *err) { - std::ostringstream ostr; - - for (size_t i = 0; i < m_msgs.size(); ++i) - { - ostr << m_msgs[i].first << " " << m_msgs[i].second << "\n"; - } - - m_text = ostr.str(); - *status = HYPERDEX_CLIENT_SUCCESS; - *m_description = m_text.c_str(); - *err = e::error(); - assert(this->can_yield()); - m_done = true; - set_status(HYPERDEX_CLIENT_SUCCESS); - set_error(e::error()); - return true; + std::ostringstream ostr; + for (size_t i = 0; i < m_msgs.size(); ++i) + { + ostr << m_msgs[i].first << " " << m_msgs[i].second << "\n"; + } + m_text = ostr.str(); + *status = HYPERDEX_CLIENT_SUCCESS; + *m_description = m_text.c_str(); + *err = e::error(); + assert(this->can_yield()); + m_done = true; + set_status(HYPERDEX_CLIENT_SUCCESS); + set_error(e::error()); + return true; } void -pending_search_describe :: handle_sent_to(const server_id& si, - const virtual_server_id& vsi) +pending_search_describe :: handle_sent_to(const server_id &si, + const virtual_server_id &vsi) { - add_text(vsi, "touched by search"); - return pending_aggregation::handle_sent_to(si, vsi); + add_text(vsi, "touched by search"); + return pending_aggregation::handle_sent_to(si, vsi); } void -pending_search_describe :: handle_failure(const server_id& si, - const virtual_server_id& vsi) +pending_search_describe :: handle_failure(const server_id &si, + const virtual_server_id &vsi) { - add_text(vsi, "failed"); - return pending_aggregation::handle_sent_to(si, vsi); + add_text(vsi, "failed"); + return pending_aggregation::handle_sent_to(si, vsi); } bool -pending_search_describe :: handle_message(client* cl, - const server_id& si, - const virtual_server_id& vsi, +pending_search_describe :: handle_message(client *cl, + const server_id &si, + const virtual_server_id &vsi, network_msgtype mt, std::auto_ptr, e::unpacker up, - hyperdex_client_returncode* status, - e::error* err) + hyperdex_client_returncode *status, + e::error *err) { - bool handled = pending_aggregation::handle_message(cl, si, vsi, mt, std::auto_ptr(), up, status, err); - assert(handled); - - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - - if (mt != RESP_SEARCH_DESCRIBE) - { - add_text(vsi, "sent non-RESP_SEARCH_DESCRIBE message"); - return true; - } - - e::slice text = up.remainder(); - add_text(vsi, text); - return true; + bool handled = pending_aggregation::handle_message(cl, si, vsi, mt, std::auto_ptr(), up, status, err); + assert(handled); + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + if (mt != RESP_SEARCH_DESCRIBE) + { + add_text(vsi, "sent non-RESP_SEARCH_DESCRIBE message"); + return true; + } + e::slice text = up.remainder(); + add_text(vsi, text); + return true; } void -pending_search_describe :: add_text(const hyperdex::virtual_server_id& vid, - const e::slice& text) +pending_search_describe :: add_text(const hyperdex::virtual_server_id &vid, + const e::slice &text) { - m_msgs.push_back(std::make_pair(vid, std::string(reinterpret_cast(text.data()), text.size()))); + m_msgs.push_back(std::make_pair(vid, std::string(reinterpret_cast(text.data()), text.size()))); } void -pending_search_describe :: add_text(const hyperdex::virtual_server_id& vid, - const char* text) +pending_search_describe :: add_text(const hyperdex::virtual_server_id &vid, + const char *text) { - m_msgs.push_back(std::make_pair(vid, std::string(text))); + m_msgs.push_back(std::make_pair(vid, std::string(text))); } diff --git a/client/pending_search_describe.h b/client/pending_search_describe.h index 1add91fd5..a79e6b1f2 100644 --- a/client/pending_search_describe.h +++ b/client/pending_search_describe.h @@ -36,47 +36,47 @@ BEGIN_HYPERDEX_NAMESPACE class pending_search_describe : public pending_aggregation { - public: - pending_search_describe(uint64_t client_visible_id, - hyperdex_client_returncode* status, - const char** description); - virtual ~pending_search_describe() throw (); +public: + pending_search_describe(uint64_t client_visible_id, + hyperdex_client_returncode *status, + const char **description); + virtual ~pending_search_describe() throw (); - // return to client - public: - virtual bool can_yield(); - virtual bool yield(hyperdex_client_returncode* status, e::error* error); + // return to client +public: + virtual bool can_yield(); + virtual bool yield(hyperdex_client_returncode *status, e::error *error); - // events - public: - virtual void handle_sent_to(const server_id& si, - const virtual_server_id& vsi); - virtual void handle_failure(const server_id& si, - const virtual_server_id& vsi); - virtual bool handle_message(client*, - const server_id& si, - const virtual_server_id& vsi, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_client_returncode* status, - e::error* error); + // events +public: + virtual void handle_sent_to(const server_id &si, + const virtual_server_id &vsi); + virtual void handle_failure(const server_id &si, + const virtual_server_id &vsi); + virtual bool handle_message(client *, + const server_id &si, + const virtual_server_id &vsi, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_client_returncode *status, + e::error *error); - // add text to description - private: - void add_text(const hyperdex::virtual_server_id& vid, const e::slice& text); - void add_text(const hyperdex::virtual_server_id& vid, const char* text); + // add text to description +private: + void add_text(const hyperdex::virtual_server_id &vid, const e::slice &text); + void add_text(const hyperdex::virtual_server_id &vid, const char *text); - // noncopyable - private: - pending_search_describe(const pending_search_describe& other); - pending_search_describe& operator = (const pending_search_describe& rhs); + // noncopyable +private: + pending_search_describe(const pending_search_describe &other); + pending_search_describe &operator = (const pending_search_describe &rhs); - private: - const char** m_description; - bool m_done; - std::vector > m_msgs; - std::string m_text; +private: + const char **m_description; + bool m_done; + std::vector > m_msgs; + std::string m_text; }; END_HYPERDEX_NAMESPACE diff --git a/client/pending_sorted_search.cc b/client/pending_sorted_search.cc index 121170880..545bd7681 100644 --- a/client/pending_sorted_search.cc +++ b/client/pending_sorted_search.cc @@ -37,27 +37,27 @@ using hyperdex::datatype_info; using hyperdex::pending_sorted_search; -pending_sorted_search :: pending_sorted_search(client* cl, +pending_sorted_search :: pending_sorted_search(client *cl, uint64_t id, bool maximize, uint64_t limit, uint16_t sort_by_idx, - datatype_info* sort_by_di, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, - size_t* attrs_sz) - : pending_aggregation(id, status) - , m_cl(cl) - , m_yield(false) - , m_ri() - , m_maximize(maximize) - , m_limit(limit) - , m_sort_by_idx(sort_by_idx) - , m_sort_by_di(sort_by_di) - , m_attrs(attrs) - , m_attrs_sz(attrs_sz) - , m_results() - , m_results_idx(0) + datatype_info *sort_by_di, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, + size_t *attrs_sz) + : pending_aggregation(id, status) + , m_cl(cl) + , m_yield(false) + , m_ri() + , m_maximize(maximize) + , m_limit(limit) + , m_sort_by_idx(sort_by_idx) + , m_sort_by_di(sort_by_di) + , m_attrs(attrs) + , m_attrs_sz(attrs_sz) + , m_results() + , m_results_idx(0) { } @@ -68,232 +68,206 @@ pending_sorted_search :: ~pending_sorted_search() throw () bool pending_sorted_search :: can_yield() { - return m_yield; + return m_yield; } bool -pending_sorted_search :: yield(hyperdex_client_returncode* status, e::error* err) +pending_sorted_search :: yield(hyperdex_client_returncode *status, e::error *err) { - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - m_yield = false; - - if (this->aggregation_done() && m_results_idx >= m_results.size()) - { - set_status(HYPERDEX_CLIENT_SEARCHDONE); - set_error(e::error()); - return true; - } - - m_yield = true; - - hyperdex_client_returncode op_status; - e::error op_error; - const e::slice& key(m_results[m_results_idx].key); - const std::vector& value(m_results[m_results_idx].value); - ++m_results_idx; - - if (!value_to_attributes(m_cl->m_config, m_ri, key.data(), key.size(), - value, &op_status, &op_error, m_attrs, m_attrs_sz, m_cl->m_convert_types)) - { - set_status(op_status); - set_error(op_error); - return true; - } - - set_status(HYPERDEX_CLIENT_SUCCESS); - set_error(e::error()); - return true; + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + m_yield = false; + if (this->aggregation_done() && m_results_idx >= m_results.size()) + { + set_status(HYPERDEX_CLIENT_SEARCHDONE); + set_error(e::error()); + return true; + } + m_yield = true; + hyperdex_client_returncode op_status; + e::error op_error; + const e::slice &key(m_results[m_results_idx].key); + const std::vector &value(m_results[m_results_idx].value); + ++m_results_idx; + if (!value_to_attributes(m_cl->m_config, m_ri, key.data(), key.size(), + value, &op_status, &op_error, m_attrs, m_attrs_sz, m_cl->m_convert_types)) + { + set_status(op_status); + set_error(op_error); + return true; + } + set_status(HYPERDEX_CLIENT_SUCCESS); + set_error(e::error()); + return true; } void -pending_sorted_search :: handle_sent_to(const server_id& si, - const virtual_server_id& vsi) +pending_sorted_search :: handle_sent_to(const server_id &si, + const virtual_server_id &vsi) { - if (m_ri == region_id()) - { - m_ri = m_cl->m_config.get_region_id(vsi); - } - - return pending_aggregation::handle_sent_to(si, vsi); + if (m_ri == region_id()) + { + m_ri = m_cl->m_config.get_region_id(vsi); + } + return pending_aggregation::handle_sent_to(si, vsi); } void -pending_sorted_search :: handle_failure(const server_id& si, - const virtual_server_id& vsi) +pending_sorted_search :: handle_failure(const server_id &si, + const virtual_server_id &vsi) { - m_yield = true; - PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " - << vsi << "/" << si; - return pending_aggregation::handle_failure(si, vsi); + m_yield = true; + PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " + << vsi << "/" << si; + return pending_aggregation::handle_failure(si, vsi); } -namespace hyperdex +namespace hyperdex { bool -operator < (const pending_sorted_search::item& lhs, const pending_sorted_search::item& rhs) +operator < (const pending_sorted_search::item &lhs, const pending_sorted_search::item &rhs) { - assert(lhs.ssc_ptr == rhs.ssc_ptr); - const sorted_search_comparator* ssc_ptr = lhs.ssc_ptr; - - if (ssc_ptr->m_sort_by_idx > lhs.value.size() || - ssc_ptr->m_sort_by_idx > rhs.value.size() || - lhs.value.size() != rhs.value.size()) - { - return false; - } - - int cmp = 0; - - if (ssc_ptr->m_sort_by_idx == 0) - { - cmp = ssc_ptr->m_sort_by_di->compare(lhs.key, rhs.key); - } - else - { + assert(lhs.ssc_ptr == rhs.ssc_ptr); + const sorted_search_comparator *ssc_ptr = lhs.ssc_ptr; + if (ssc_ptr->m_sort_by_idx > lhs.value.size() || + ssc_ptr->m_sort_by_idx > rhs.value.size() || + lhs.value.size() != rhs.value.size()) + { + return false; + } + int cmp = 0; + if (ssc_ptr->m_sort_by_idx == 0) + { + cmp = ssc_ptr->m_sort_by_di->compare(lhs.key, rhs.key); + } + else + { cmp = ssc_ptr->m_sort_by_di->compare(lhs.value[ssc_ptr->m_sort_by_idx - 1], rhs.value[ssc_ptr->m_sort_by_idx - 1]); - } - - if (ssc_ptr->m_maximize) - { - return cmp < 0; - } - else - { - return cmp > 0; - } + } + if (ssc_ptr->m_maximize) + { + return cmp < 0; + } + else + { + return cmp > 0; + } } bool -operator > (const pending_sorted_search::item& lhs, const pending_sorted_search::item& rhs) +operator > (const pending_sorted_search::item &lhs, const pending_sorted_search::item &rhs) { - assert(lhs.ssc_ptr == rhs.ssc_ptr); - const sorted_search_comparator* ssc_ptr = lhs.ssc_ptr; - - if (ssc_ptr->m_sort_by_idx > lhs.value.size() || - ssc_ptr->m_sort_by_idx > rhs.value.size() || - lhs.value.size() != rhs.value.size()) - { - return false; - } - - int cmp = 0; - - if (ssc_ptr->m_sort_by_idx == 0) - { - cmp = ssc_ptr->m_sort_by_di->compare(lhs.key, rhs.key); - } - else - { + assert(lhs.ssc_ptr == rhs.ssc_ptr); + const sorted_search_comparator *ssc_ptr = lhs.ssc_ptr; + if (ssc_ptr->m_sort_by_idx > lhs.value.size() || + ssc_ptr->m_sort_by_idx > rhs.value.size() || + lhs.value.size() != rhs.value.size()) + { + return false; + } + int cmp = 0; + if (ssc_ptr->m_sort_by_idx == 0) + { + cmp = ssc_ptr->m_sort_by_di->compare(lhs.key, rhs.key); + } + else + { cmp = ssc_ptr->m_sort_by_di->compare(lhs.value[ssc_ptr->m_sort_by_idx - 1], rhs.value[ssc_ptr->m_sort_by_idx - 1]); - } - - if (ssc_ptr->m_maximize) - { - return cmp > 0; - } - else - { - return cmp < 0; - } + } + if (ssc_ptr->m_maximize) + { + return cmp > 0; + } + else + { + return cmp < 0; + } } } bool -pending_sorted_search :: handle_message(client* cl, - const server_id& si, - const virtual_server_id& vsi, +pending_sorted_search :: handle_message(client *cl, + const server_id &si, + const virtual_server_id &vsi, network_msgtype mt, std::auto_ptr msg, e::unpacker up, - hyperdex_client_returncode* status, - e::error* err) + hyperdex_client_returncode *status, + e::error *err) { - bool handled = pending_aggregation::handle_message(cl, si, vsi, mt, std::auto_ptr(), up, status, err); - assert(handled); - - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - - if (mt != RESP_SORTED_SEARCH) - { - PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to SORTED_SEARCH with " << mt; - m_yield = true; - return true; - } - - uint64_t num_results = 0; - up = up >> num_results; - - if (up.error()) - { - PENDING_ERROR(SERVERERROR) << "communication error: server " - << vsi << " sent corrupt message=" - << msg->as_slice().hex() - << " in response to a SORTED_SEARCH"; - m_yield = true; - return true; - } - - sorted_search_comparator ssc(m_maximize, m_sort_by_idx, m_sort_by_di); - e::compat::shared_ptr backing(msg.release()); - - for (uint64_t i = 0; i < num_results; ++i) - { - e::slice key; - std::vector value; - up = up >> key >> value; - - if (up.error()) - { - PENDING_ERROR(SERVERERROR) << "communication error: server " - << vsi << " sent corrupt message=" - << msg->as_slice().hex() - << " in response to a SORTED_SEARCH"; - m_yield = true; - return true; - } - - m_results.push_back(item(&ssc, key, value, backing)); - std::push_heap(m_results.begin(), m_results.end()); - - if (m_results.size() > m_limit) - { - std::pop_heap(m_results.begin(), m_results.end()); - m_results.pop_back(); - } - } - - m_yield = this->aggregation_done(); - set_status(HYPERDEX_CLIENT_SUCCESS); - set_error(e::error()); - - if (m_yield) - { - std::sort(m_results.begin(), m_results.end(), std::greater()); - } - - return true; + bool handled = pending_aggregation::handle_message(cl, si, vsi, mt, std::auto_ptr(), up, status, err); + assert(handled); + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + if (mt != RESP_SORTED_SEARCH) + { + PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to SORTED_SEARCH with " << mt; + m_yield = true; + return true; + } + uint64_t num_results = 0; + up = up >> num_results; + if (up.error()) + { + PENDING_ERROR(SERVERERROR) << "communication error: server " + << vsi << " sent corrupt message=" + << msg->as_slice().hex() + << " in response to a SORTED_SEARCH"; + m_yield = true; + return true; + } + sorted_search_comparator ssc(m_maximize, m_sort_by_idx, m_sort_by_di); + e::compat::shared_ptr backing(msg.release()); + for (uint64_t i = 0; i < num_results; ++i) + { + e::slice key; + std::vector value; + up = up >> key >> value; + if (up.error()) + { + PENDING_ERROR(SERVERERROR) << "communication error: server " + << vsi << " sent corrupt message=" + << msg->as_slice().hex() + << " in response to a SORTED_SEARCH"; + m_yield = true; + return true; + } + m_results.push_back(item(&ssc, key, value, backing)); + std::push_heap(m_results.begin(), m_results.end()); + if (m_results.size() > m_limit) + { + std::pop_heap(m_results.begin(), m_results.end()); + m_results.pop_back(); + } + } + m_yield = this->aggregation_done(); + set_status(HYPERDEX_CLIENT_SUCCESS); + set_error(e::error()); + if (m_yield) + { + std::sort(m_results.begin(), m_results.end(), std::greater()); + } + return true; } -pending_sorted_search :: item :: item(const sorted_search_comparator *sscobj, - const e::slice& _key, - const std::vector& _value, +pending_sorted_search :: item :: item(const sorted_search_comparator *sscobj, + const e::slice &_key, + const std::vector &_value, e::compat::shared_ptr _backing) - : ssc_ptr(sscobj) + : ssc_ptr(sscobj) , key(_key) - , value(_value) - , backing(_backing) + , value(_value) + , backing(_backing) { } -pending_sorted_search :: item :: item(const item& other) - : ssc_ptr(other.ssc_ptr) - , key(other.key) - , value(other.value) - , backing(other.backing) +pending_sorted_search :: item :: item(const item &other) + : ssc_ptr(other.ssc_ptr) + , key(other.key) + , value(other.value) + , backing(other.backing) { } @@ -301,16 +275,15 @@ pending_sorted_search :: item :: ~item() throw () { } -pending_sorted_search::item& -pending_sorted_search :: item :: operator = (const item& other) +pending_sorted_search::item & +pending_sorted_search :: item :: operator = (const item &other) { - if (this != &other) - { + if (this != &other) + { ssc_ptr = other.ssc_ptr; - key = other.key; - value = other.value; - backing = other.backing; - } - - return *this; + key = other.key; + value = other.value; + backing = other.backing; + } + return *this; } diff --git a/client/pending_sorted_search.h b/client/pending_sorted_search.h index 0ad0416ff..5431cda94 100644 --- a/client/pending_sorted_search.h +++ b/client/pending_sorted_search.h @@ -40,96 +40,97 @@ BEGIN_HYPERDEX_NAMESPACE class pending_sorted_search : public pending_aggregation { - public: - pending_sorted_search(client* cl, - uint64_t id, - bool maximize, - uint64_t limit, - uint16_t sort_by_idx, - datatype_info* sort_by_di, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, - size_t* attrs_sz); - virtual ~pending_sorted_search() throw (); - - // return to client - public: - virtual bool can_yield(); - virtual bool yield(hyperdex_client_returncode* status, e::error* error); - - // events - public: - virtual void handle_sent_to(const server_id& si, - const virtual_server_id& vsi); - virtual void handle_failure(const server_id& si, - const virtual_server_id& vsi); - virtual bool handle_message(client*, - const server_id& si, - const virtual_server_id& vsi, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_client_returncode* status, - e::error* error); - - public: - class item; - - // noncopyable - private: - pending_sorted_search(const pending_sorted_search& other); - pending_sorted_search& operator = (const pending_sorted_search& rhs); - - private: - client* m_cl; - bool m_yield; - region_id m_ri; - bool m_maximize; - const uint64_t m_limit; - const uint16_t m_sort_by_idx; - datatype_info* m_sort_by_di; - const hyperdex_client_attribute** m_attrs; - size_t* m_attrs_sz; - std::vector m_results; - size_t m_results_idx; +public: + pending_sorted_search(client *cl, + uint64_t id, + bool maximize, + uint64_t limit, + uint16_t sort_by_idx, + datatype_info *sort_by_di, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, + size_t *attrs_sz); + virtual ~pending_sorted_search() throw (); + + // return to client +public: + virtual bool can_yield(); + virtual bool yield(hyperdex_client_returncode *status, e::error *error); + + // events +public: + virtual void handle_sent_to(const server_id &si, + const virtual_server_id &vsi); + virtual void handle_failure(const server_id &si, + const virtual_server_id &vsi); + virtual bool handle_message(client *, + const server_id &si, + const virtual_server_id &vsi, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_client_returncode *status, + e::error *error); + +public: + class item; + + // noncopyable +private: + pending_sorted_search(const pending_sorted_search &other); + pending_sorted_search &operator = (const pending_sorted_search &rhs); + +private: + client *m_cl; + bool m_yield; + region_id m_ri; + bool m_maximize; + const uint64_t m_limit; + const uint16_t m_sort_by_idx; + datatype_info *m_sort_by_di; + const hyperdex_client_attribute **m_attrs; + size_t *m_attrs_sz; + std::vector m_results; + size_t m_results_idx; }; class sorted_search_comparator { - public: - sorted_search_comparator(bool maximize, - uint16_t sort_by_idx, - datatype_info* sort_by_di) - : m_maximize(maximize) - , m_sort_by_idx(sort_by_idx) - , m_sort_by_di(sort_by_di) +public: + sorted_search_comparator(bool maximize, + uint16_t sort_by_idx, + datatype_info *sort_by_di) + : m_maximize(maximize) + , m_sort_by_idx(sort_by_idx) + , m_sort_by_di(sort_by_di) { } - public: - bool m_maximize; - uint16_t m_sort_by_idx; - datatype_info* m_sort_by_di; +public: + bool m_maximize; + uint16_t m_sort_by_idx; + datatype_info *m_sort_by_di; }; + class pending_sorted_search :: item { - public: - item(); - item(const sorted_search_comparator *sscobj, - const e::slice& key, - const std::vector& value, - e::compat::shared_ptr backing); - item(const item&); - ~item() throw (); - - public: - item& operator = (const item&); - - public: - const sorted_search_comparator *ssc_ptr; - e::slice key; - std::vector value; - e::compat::shared_ptr backing; +public: + item(); + item(const sorted_search_comparator *sscobj, + const e::slice &key, + const std::vector &value, + e::compat::shared_ptr backing); + item(const item &); + ~item() throw (); + +public: + item &operator = (const item &); + +public: + const sorted_search_comparator *ssc_ptr; + e::slice key; + std::vector value; + e::compat::shared_ptr backing; }; END_HYPERDEX_NAMESPACE diff --git a/client/pending_sum.cc b/client/pending_sum.cc index f3549eefb..67f4fa40f 100644 --- a/client/pending_sum.cc +++ b/client/pending_sum.cc @@ -32,18 +32,18 @@ using hyperdex::pending_sum; pending_sum :: pending_sum(uint64_t id, - uint16_t sum_idx, - datatype_info* sum_di, - hyperdex_client_returncode* status, - uint64_t* count) - : pending_aggregation(id, status) - , m_sum_idx(sum_idx) - , m_sum_di(sum_di) - , m_sum(count) - , m_done(false) + uint16_t sum_idx, + datatype_info *sum_di, + hyperdex_client_returncode *status, + uint64_t *count) + : pending_aggregation(id, status) + , m_sum_idx(sum_idx) + , m_sum_di(sum_di) + , m_sum(count) + , m_done(false) { - set_status(HYPERDEX_CLIENT_SUCCESS); - set_error(e::error()); + set_status(HYPERDEX_CLIENT_SUCCESS); + set_error(e::error()); } pending_sum :: ~pending_sum() throw () @@ -53,65 +53,59 @@ pending_sum :: ~pending_sum() throw () bool pending_sum :: can_yield() { - return this->aggregation_done() && !m_done; + return this->aggregation_done() && !m_done; } bool -pending_sum :: yield(hyperdex_client_returncode* status, e::error* err) +pending_sum :: yield(hyperdex_client_returncode *status, e::error *err) { - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - assert(this->can_yield()); - m_done = true; - return true; + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + assert(this->can_yield()); + m_done = true; + return true; } void -pending_sum :: handle_failure(const server_id& si, - const virtual_server_id& vsi) +pending_sum :: handle_failure(const server_id &si, + const virtual_server_id &vsi) { - PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " - << vsi << "/" << si; - return pending_aggregation::handle_failure(si, vsi); + PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting " + << vsi << "/" << si; + return pending_aggregation::handle_failure(si, vsi); } bool -pending_sum :: handle_message(client* cl, - const server_id& si, - const virtual_server_id& vsi, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_client_returncode* status, - e::error* err) +pending_sum :: handle_message(client *cl, + const server_id &si, + const virtual_server_id &vsi, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_client_returncode *status, + e::error *err) { - bool handled = pending_aggregation::handle_message(cl, si, vsi, mt, std::auto_ptr(), up, status, err); - assert(handled); - - *status = HYPERDEX_CLIENT_SUCCESS; - *err = e::error(); - - if (mt != RESP_SUM) - { - PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to SUM with " << mt; - return true; - } - - - uint64_t local_sum; - up = up >> local_sum; - - if (up.error()) - { - PENDING_ERROR(SERVERERROR) << "communication error: server " - << vsi << " sent corrupt message=" - << msg->as_slice().hex() - << " in response to a SUM"; - return true; - } - - *m_sum += local_sum; - // Don't set the status or error so that errors will carry through. It was - // set to the success state in the constructor - return true; + bool handled = pending_aggregation::handle_message(cl, si, vsi, mt, std::auto_ptr(), up, status, err); + assert(handled); + *status = HYPERDEX_CLIENT_SUCCESS; + *err = e::error(); + if (mt != RESP_SUM) + { + PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to SUM with " << mt; + return true; + } + uint64_t local_sum; + up = up >> local_sum; + if (up.error()) + { + PENDING_ERROR(SERVERERROR) << "communication error: server " + << vsi << " sent corrupt message=" + << msg->as_slice().hex() + << " in response to a SUM"; + return true; + } + *m_sum += local_sum; + // Don't set the status or error so that errors will carry through. It was + // set to the success state in the constructor + return true; } diff --git a/client/pending_sum.h b/client/pending_sum.h index 6b0df3d75..cedd05c5b 100644 --- a/client/pending_sum.h +++ b/client/pending_sum.h @@ -37,42 +37,42 @@ BEGIN_HYPERDEX_NAMESPACE class datatype_info; class pending_sum : public pending_aggregation { - public: - pending_sum(uint64_t client_visible_id, - uint16_t sum_idx, - datatype_info* sum_di, - hyperdex_client_returncode* status, - uint64_t* count); - virtual ~pending_sum() throw (); +public: + pending_sum(uint64_t client_visible_id, + uint16_t sum_idx, + datatype_info *sum_di, + hyperdex_client_returncode *status, + uint64_t *count); + virtual ~pending_sum() throw (); - // return to client - public: - virtual bool can_yield(); - virtual bool yield(hyperdex_client_returncode* status, e::error* error); + // return to client +public: + virtual bool can_yield(); + virtual bool yield(hyperdex_client_returncode *status, e::error *error); - // events - public: - virtual void handle_failure(const server_id& si, - const virtual_server_id& vsi); - virtual bool handle_message(client*, - const server_id& si, - const virtual_server_id& vsi, - network_msgtype mt, - std::auto_ptr msg, - e::unpacker up, - hyperdex_client_returncode* status, - e::error* error); + // events +public: + virtual void handle_failure(const server_id &si, + const virtual_server_id &vsi); + virtual bool handle_message(client *, + const server_id &si, + const virtual_server_id &vsi, + network_msgtype mt, + std::auto_ptr msg, + e::unpacker up, + hyperdex_client_returncode *status, + e::error *error); - // noncopyable - private: - pending_sum(const pending_sum& other); - pending_sum& operator = (const pending_sum& rhs); + // noncopyable +private: + pending_sum(const pending_sum &other); + pending_sum &operator = (const pending_sum &rhs); - private: - const uint16_t m_sum_idx; - datatype_info *m_sum_di; - uint64_t* m_sum; - bool m_done; +private: + const uint16_t m_sum_idx; + datatype_info *m_sum_di; + uint64_t *m_sum; + bool m_done; }; END_HYPERDEX_NAMESPACE diff --git a/client/test/datastructures.cc b/client/test/datastructures.cc index 77a617768..94e4ae531 100644 --- a/client/test/datastructures.cc +++ b/client/test/datastructures.cc @@ -34,796 +34,738 @@ TEST(ClientDataStructures, ArenaCtorDtor) { - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_ds_arena_destroy(a); + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, AllocateAttribute) { - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_client_attribute* attrs; - attrs = hyperdex_ds_allocate_attribute(a, 10); - - for (size_t i = 0; i < 10; ++i) - { - // we don't care what it gets filled with, this just tests that we don't - // overrun the allocated space. - attrs[i].attr = "FOOBAR"; - attrs[i].value = NULL; - attrs[i].value_sz = 0; - attrs[i].datatype = HYPERDATATYPE_GENERIC; - } - - hyperdex_ds_arena_destroy(a); + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_client_attribute *attrs; + attrs = hyperdex_ds_allocate_attribute(a, 10); + for (size_t i = 0; i < 10; ++i) + { + // we don't care what it gets filled with, this just tests that we don't + // overrun the allocated space. + attrs[i].attr = "FOOBAR"; + attrs[i].value = NULL; + attrs[i].value_sz = 0; + attrs[i].datatype = HYPERDATATYPE_GENERIC; + } + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, AllocateAttributeCheck) { - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_client_attribute_check* checks; - checks = hyperdex_ds_allocate_attribute_check(a, 10); - - for (size_t i = 0; i < 10; ++i) - { - // we don't care what it gets filled with, this just tests that we don't - // overrun the allocated space. - checks[i].attr = "FOOBAR"; - checks[i].value = NULL; - checks[i].value_sz = 0; - checks[i].datatype = HYPERDATATYPE_GENERIC; - checks[i].predicate = HYPERPREDICATE_FAIL; - } - - hyperdex_ds_arena_destroy(a); + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_client_attribute_check *checks; + checks = hyperdex_ds_allocate_attribute_check(a, 10); + for (size_t i = 0; i < 10; ++i) + { + // we don't care what it gets filled with, this just tests that we don't + // overrun the allocated space. + checks[i].attr = "FOOBAR"; + checks[i].value = NULL; + checks[i].value_sz = 0; + checks[i].datatype = HYPERDATATYPE_GENERIC; + checks[i].predicate = HYPERPREDICATE_FAIL; + } + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, AllocateMapAttribute) { - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_client_map_attribute* mapattrs; - mapattrs = hyperdex_ds_allocate_map_attribute(a, 10); - - for (size_t i = 0; i < 10; ++i) - { - // we don't care what it gets filled with, this just tests that we don't - // overrun the allocated space. - mapattrs[i].attr = "FOOBAR"; - mapattrs[i].map_key = NULL; - mapattrs[i].map_key_sz = 0; - mapattrs[i].map_key_datatype = HYPERDATATYPE_GENERIC; - mapattrs[i].value = NULL; - mapattrs[i].value_sz = 0; - mapattrs[i].value_datatype = HYPERDATATYPE_GENERIC; - } - - hyperdex_ds_arena_destroy(a); + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_client_map_attribute *mapattrs; + mapattrs = hyperdex_ds_allocate_map_attribute(a, 10); + for (size_t i = 0; i < 10; ++i) + { + // we don't care what it gets filled with, this just tests that we don't + // overrun the allocated space. + mapattrs[i].attr = "FOOBAR"; + mapattrs[i].map_key = NULL; + mapattrs[i].map_key_sz = 0; + mapattrs[i].map_key_datatype = HYPERDATATYPE_GENERIC; + mapattrs[i].value = NULL; + mapattrs[i].value_sz = 0; + mapattrs[i].value_datatype = HYPERDATATYPE_GENERIC; + } + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, PackInt) { - char buf[sizeof(int64_t)]; - hyperdex_ds_pack_int(0, buf); - ASSERT_TRUE(memcmp(buf, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) == 0); - hyperdex_ds_pack_int(0xdeadbeef, buf); - ASSERT_TRUE(memcmp(buf, "\xef\xbe\xad\xde\x00\x00\x00\x00", 8) == 0); + char buf[sizeof(int64_t)]; + hyperdex_ds_pack_int(0, buf); + ASSERT_TRUE(memcmp(buf, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) == 0); + hyperdex_ds_pack_int(0xdeadbeef, buf); + ASSERT_TRUE(memcmp(buf, "\xef\xbe\xad\xde\x00\x00\x00\x00", 8) == 0); } TEST(ClientDataStructures, UnpackInt) { - int64_t num; - ASSERT_TRUE(hyperdex_ds_unpack_int("\x00\x00\x00\x00\x00\x00\x00\x00", 8, &num) == 0); - ASSERT_EQ(num, 0); - ASSERT_TRUE(hyperdex_ds_unpack_int("\xef\xbe\xad\xde\x00\x00\x00\x00", 8, &num) == 0); - ASSERT_EQ(num, 0xdeadbeef); - num = 0x8badf00d; - ASSERT_TRUE(hyperdex_ds_unpack_int("\xef\xbe\xad\xde\x00\x00\x00\x00", 7, &num) < 0); - ASSERT_EQ(num, 0x8badf00d); + int64_t num; + ASSERT_TRUE(hyperdex_ds_unpack_int("\x00\x00\x00\x00\x00\x00\x00\x00", 8, &num) == 0); + ASSERT_EQ(num, 0); + ASSERT_TRUE(hyperdex_ds_unpack_int("\xef\xbe\xad\xde\x00\x00\x00\x00", 8, &num) == 0); + ASSERT_EQ(num, 0xdeadbeef); + num = 0x8badf00d; + ASSERT_TRUE(hyperdex_ds_unpack_int("\xef\xbe\xad\xde\x00\x00\x00\x00", 7, &num) < 0); + ASSERT_EQ(num, 0x8badf00d); } TEST(ClientDataStructures, PackFloat) { - double num = 9006104071832581.0; - char buf[sizeof(double)]; - hyperdex_ds_pack_float(num, buf); - ASSERT_TRUE(memcmp(buf, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0); + double num = 9006104071832581.0; + char buf[sizeof(double)]; + hyperdex_ds_pack_float(num, buf); + ASSERT_TRUE(memcmp(buf, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0); } TEST(ClientDataStructures, UnpackFloat) { - double num; - ASSERT_TRUE(hyperdex_ds_unpack_float("\x05\x04\x03\x02\x01\xff\x3f\x43", 8, &num) == 0); - ASSERT_GE(num, 9006104071832580.9); - ASSERT_LE(num, 9006104071832581.1); + double num; + ASSERT_TRUE(hyperdex_ds_unpack_float("\x05\x04\x03\x02\x01\xff\x3f\x43", 8, &num) == 0); + ASSERT_GE(num, 9006104071832580.9); + ASSERT_LE(num, 9006104071832581.1); } TEST(ClientDataStructures, CopyString) { - char buf[6] = {'h', 'e', 'l', 'l', 'o', '\x00'}; - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_ds_returncode status; - const char* tmp = NULL; - size_t tmp_sz = 0; - - ASSERT_TRUE(hyperdex_ds_copy_string(a, buf, 6, - &status, - &tmp, &tmp_sz) == 0); - ASSERT_EQ(status, HYPERDEX_DS_SUCCESS); - ASSERT_TRUE(tmp_sz == 6); - ASSERT_TRUE(strncmp(tmp, "hello", 6) == 0); - memmove(buf, "world\x00", 6); - ASSERT_TRUE(strncmp(tmp, "hello", 6) == 0); - - hyperdex_ds_arena_destroy(a); + char buf[6] = {'h', 'e', 'l', 'l', 'o', '\x00'}; + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_ds_returncode status; + const char *tmp = NULL; + size_t tmp_sz = 0; + ASSERT_TRUE(hyperdex_ds_copy_string(a, buf, 6, + &status, + &tmp, &tmp_sz) == 0); + ASSERT_EQ(status, HYPERDEX_DS_SUCCESS); + ASSERT_TRUE(tmp_sz == 6); + ASSERT_TRUE(strncmp(tmp, "hello", 6) == 0); + memmove(buf, "world\x00", 6); + ASSERT_TRUE(strncmp(tmp, "hello", 6) == 0); + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, CopyInt) { - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_ds_returncode status; - const char* tmp = NULL; - size_t tmp_sz = 0; - - ASSERT_TRUE(hyperdex_ds_copy_int(a, 0xdeadbeef, - &status, - &tmp, &tmp_sz) == 0); - ASSERT_EQ(status, HYPERDEX_DS_SUCCESS); - ASSERT_TRUE(tmp_sz == 8); - ASSERT_TRUE(memcmp(tmp, "\xef\xbe\xad\xde\x00\x00\x00\x00", 8) == 0); - - hyperdex_ds_arena_destroy(a); + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_ds_returncode status; + const char *tmp = NULL; + size_t tmp_sz = 0; + ASSERT_TRUE(hyperdex_ds_copy_int(a, 0xdeadbeef, + &status, + &tmp, &tmp_sz) == 0); + ASSERT_EQ(status, HYPERDEX_DS_SUCCESS); + ASSERT_TRUE(tmp_sz == 8); + ASSERT_TRUE(memcmp(tmp, "\xef\xbe\xad\xde\x00\x00\x00\x00", 8) == 0); + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, AllocateList) { - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_ds_list* list = hyperdex_ds_allocate_list(a); - list = list; // no more warnings - hyperdex_ds_arena_destroy(a); + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_ds_list *list = hyperdex_ds_allocate_list(a); + list = list; // no more warnings + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, ListString) { - hyperdex_ds_returncode status; - const char* tmp = NULL; - size_t tmp_sz = 0; - hyperdatatype datatype; - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_ds_list* list; - - // example 1 - list = hyperdex_ds_allocate_list(a); - ASSERT_TRUE(hyperdex_ds_list_finalize(list, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 0UL); - ASSERT_EQ(datatype, HYPERDATATYPE_LIST_GENERIC); - // example 2 - list = hyperdex_ds_allocate_list(a); - ASSERT_TRUE(hyperdex_ds_list_append_string(list, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_list_append_string(list, "world", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_list_finalize(list, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 18UL); - ASSERT_TRUE(memcmp(tmp, "\x05\x00\x00\x00hello\x05\x00\x00\x00world", 18) == 0); - ASSERT_EQ(datatype, HYPERDATATYPE_LIST_STRING); - // error on cross-ds insert - list = hyperdex_ds_allocate_list(a); - ASSERT_TRUE(hyperdex_ds_list_append_string(list, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_list_append_int(list, 0, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - list = hyperdex_ds_allocate_list(a); - ASSERT_TRUE(hyperdex_ds_list_append_string(list, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_list_append_float(list, 0., &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - - hyperdex_ds_arena_destroy(a); + hyperdex_ds_returncode status; + const char *tmp = NULL; + size_t tmp_sz = 0; + hyperdatatype datatype; + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_ds_list *list; + // example 1 + list = hyperdex_ds_allocate_list(a); + ASSERT_TRUE(hyperdex_ds_list_finalize(list, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 0UL); + ASSERT_EQ(datatype, HYPERDATATYPE_LIST_GENERIC); + // example 2 + list = hyperdex_ds_allocate_list(a); + ASSERT_TRUE(hyperdex_ds_list_append_string(list, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_list_append_string(list, "world", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_list_finalize(list, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 18UL); + ASSERT_TRUE(memcmp(tmp, "\x05\x00\x00\x00hello\x05\x00\x00\x00world", 18) == 0); + ASSERT_EQ(datatype, HYPERDATATYPE_LIST_STRING); + // error on cross-ds insert + list = hyperdex_ds_allocate_list(a); + ASSERT_TRUE(hyperdex_ds_list_append_string(list, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_list_append_int(list, 0, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + list = hyperdex_ds_allocate_list(a); + ASSERT_TRUE(hyperdex_ds_list_append_string(list, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_list_append_float(list, 0., &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, ListInt) { - hyperdex_ds_returncode status; - const char* tmp = NULL; - size_t tmp_sz = 0; - hyperdatatype datatype; - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_ds_list* list; - - // example 1 - list = hyperdex_ds_allocate_list(a); - ASSERT_TRUE(hyperdex_ds_list_finalize(list, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 0UL); - ASSERT_EQ(datatype, HYPERDATATYPE_LIST_GENERIC); - // example 2 - list = hyperdex_ds_allocate_list(a); - ASSERT_TRUE(hyperdex_ds_list_append_int(list, 1, &status) == 0); - ASSERT_TRUE(hyperdex_ds_list_append_int(list, -1, &status) == 0); - ASSERT_TRUE(hyperdex_ds_list_append_int(list, 0xdeadbeef, &status) == 0); - ASSERT_TRUE(hyperdex_ds_list_finalize(list, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 24UL); - ASSERT_TRUE(memcmp(tmp, "\x01\x00\x00\x00\x00\x00\x00\x00" - "\xff\xff\xff\xff\xff\xff\xff\xff" - "\xef\xbe\xad\xde\x00\x00\x00\x00", 24) == 0); - ASSERT_EQ(datatype, HYPERDATATYPE_LIST_INT64); - // error on cross-ds insert - list = hyperdex_ds_allocate_list(a); - ASSERT_TRUE(hyperdex_ds_list_append_int(list, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_list_append_string(list, "hello", 5, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - list = hyperdex_ds_allocate_list(a); - ASSERT_TRUE(hyperdex_ds_list_append_int(list, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_list_append_float(list, 0., &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - - hyperdex_ds_arena_destroy(a); + hyperdex_ds_returncode status; + const char *tmp = NULL; + size_t tmp_sz = 0; + hyperdatatype datatype; + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_ds_list *list; + // example 1 + list = hyperdex_ds_allocate_list(a); + ASSERT_TRUE(hyperdex_ds_list_finalize(list, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 0UL); + ASSERT_EQ(datatype, HYPERDATATYPE_LIST_GENERIC); + // example 2 + list = hyperdex_ds_allocate_list(a); + ASSERT_TRUE(hyperdex_ds_list_append_int(list, 1, &status) == 0); + ASSERT_TRUE(hyperdex_ds_list_append_int(list, -1, &status) == 0); + ASSERT_TRUE(hyperdex_ds_list_append_int(list, 0xdeadbeef, &status) == 0); + ASSERT_TRUE(hyperdex_ds_list_finalize(list, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 24UL); + ASSERT_TRUE(memcmp(tmp, "\x01\x00\x00\x00\x00\x00\x00\x00" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xef\xbe\xad\xde\x00\x00\x00\x00", 24) == 0); + ASSERT_EQ(datatype, HYPERDATATYPE_LIST_INT64); + // error on cross-ds insert + list = hyperdex_ds_allocate_list(a); + ASSERT_TRUE(hyperdex_ds_list_append_int(list, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_list_append_string(list, "hello", 5, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + list = hyperdex_ds_allocate_list(a); + ASSERT_TRUE(hyperdex_ds_list_append_int(list, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_list_append_float(list, 0., &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, ListFloat) { - hyperdex_ds_returncode status; - const char* tmp = NULL; - size_t tmp_sz = 0; - hyperdatatype datatype; - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_ds_list* list; - - // example 1 - list = hyperdex_ds_allocate_list(a); - ASSERT_TRUE(hyperdex_ds_list_finalize(list, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 0UL); - ASSERT_EQ(datatype, HYPERDATATYPE_LIST_GENERIC); - // example 2 - list = hyperdex_ds_allocate_list(a); - ASSERT_TRUE(hyperdex_ds_list_append_float(list, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_list_append_float(list, 3.1415, &status) == 0); - ASSERT_TRUE(hyperdex_ds_list_finalize(list, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 16UL); - ASSERT_TRUE(memcmp(tmp, "\x00\x00\x00\x00\x00\x00\x00\x00" - "o\x12\x83\xc0\xca!\t@", 16) == 0); - ASSERT_EQ(datatype, HYPERDATATYPE_LIST_FLOAT); - // error on cross-ds insert - list = hyperdex_ds_allocate_list(a); - ASSERT_TRUE(hyperdex_ds_list_append_float(list, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_list_append_string(list, "hello", 5, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - list = hyperdex_ds_allocate_list(a); - ASSERT_TRUE(hyperdex_ds_list_append_float(list, 0., &status) == 0); - ASSERT_TRUE(hyperdex_ds_list_append_int(list, 0, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - - hyperdex_ds_arena_destroy(a); + hyperdex_ds_returncode status; + const char *tmp = NULL; + size_t tmp_sz = 0; + hyperdatatype datatype; + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_ds_list *list; + // example 1 + list = hyperdex_ds_allocate_list(a); + ASSERT_TRUE(hyperdex_ds_list_finalize(list, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 0UL); + ASSERT_EQ(datatype, HYPERDATATYPE_LIST_GENERIC); + // example 2 + list = hyperdex_ds_allocate_list(a); + ASSERT_TRUE(hyperdex_ds_list_append_float(list, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_list_append_float(list, 3.1415, &status) == 0); + ASSERT_TRUE(hyperdex_ds_list_finalize(list, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 16UL); + ASSERT_TRUE(memcmp(tmp, "\x00\x00\x00\x00\x00\x00\x00\x00" + "o\x12\x83\xc0\xca!\t@", 16) == 0); + ASSERT_EQ(datatype, HYPERDATATYPE_LIST_FLOAT); + // error on cross-ds insert + list = hyperdex_ds_allocate_list(a); + ASSERT_TRUE(hyperdex_ds_list_append_float(list, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_list_append_string(list, "hello", 5, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + list = hyperdex_ds_allocate_list(a); + ASSERT_TRUE(hyperdex_ds_list_append_float(list, 0., &status) == 0); + ASSERT_TRUE(hyperdex_ds_list_append_int(list, 0, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, SetString) { - hyperdex_ds_returncode status; - const char* tmp = NULL; - size_t tmp_sz = 0; - hyperdatatype datatype; - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_ds_set* set; - - // example 1 - set = hyperdex_ds_allocate_set(a); - ASSERT_TRUE(hyperdex_ds_set_finalize(set, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 0UL); - ASSERT_EQ(datatype, HYPERDATATYPE_SET_GENERIC); - // example 2 - set = hyperdex_ds_allocate_set(a); - ASSERT_TRUE(hyperdex_ds_set_insert_string(set, "world", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_set_insert_string(set, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_set_finalize(set, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 18UL); - ASSERT_TRUE(memcmp(tmp, "\x05\x00\x00\x00hello\x05\x00\x00\x00world", 16) == 0); - ASSERT_EQ(datatype, HYPERDATATYPE_SET_STRING); - // error on cross-ds insert - set = hyperdex_ds_allocate_set(a); - ASSERT_TRUE(hyperdex_ds_set_insert_string(set, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_set_insert_int(set, 0, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - set = hyperdex_ds_allocate_set(a); - ASSERT_TRUE(hyperdex_ds_set_insert_string(set, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_set_insert_float(set, 0., &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - - hyperdex_ds_arena_destroy(a); + hyperdex_ds_returncode status; + const char *tmp = NULL; + size_t tmp_sz = 0; + hyperdatatype datatype; + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_ds_set *set; + // example 1 + set = hyperdex_ds_allocate_set(a); + ASSERT_TRUE(hyperdex_ds_set_finalize(set, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 0UL); + ASSERT_EQ(datatype, HYPERDATATYPE_SET_GENERIC); + // example 2 + set = hyperdex_ds_allocate_set(a); + ASSERT_TRUE(hyperdex_ds_set_insert_string(set, "world", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_set_insert_string(set, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_set_finalize(set, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 18UL); + ASSERT_TRUE(memcmp(tmp, "\x05\x00\x00\x00hello\x05\x00\x00\x00world", 16) == 0); + ASSERT_EQ(datatype, HYPERDATATYPE_SET_STRING); + // error on cross-ds insert + set = hyperdex_ds_allocate_set(a); + ASSERT_TRUE(hyperdex_ds_set_insert_string(set, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_set_insert_int(set, 0, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + set = hyperdex_ds_allocate_set(a); + ASSERT_TRUE(hyperdex_ds_set_insert_string(set, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_set_insert_float(set, 0., &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, SetInt) { - hyperdex_ds_returncode status; - const char* tmp = NULL; - size_t tmp_sz = 0; - hyperdatatype datatype; - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_ds_set* set; - - // example 1 - set = hyperdex_ds_allocate_set(a); - ASSERT_TRUE(hyperdex_ds_set_finalize(set, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 0UL); - ASSERT_EQ(datatype, HYPERDATATYPE_SET_GENERIC); - // example 2 - set = hyperdex_ds_allocate_set(a); - ASSERT_TRUE(hyperdex_ds_set_insert_int(set, 1, &status) == 0); - ASSERT_TRUE(hyperdex_ds_set_insert_int(set, -1, &status) == 0); - ASSERT_TRUE(hyperdex_ds_set_insert_int(set, 0xdeadbeef, &status) == 0); - ASSERT_TRUE(hyperdex_ds_set_finalize(set, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 24UL); - ASSERT_TRUE(memcmp(tmp, "\xff\xff\xff\xff\xff\xff\xff\xff" - "\x01\x00\x00\x00\x00\x00\x00\x00" - "\xef\xbe\xad\xde\x00\x00\x00\x00", 24) == 0); - ASSERT_EQ(datatype, HYPERDATATYPE_SET_INT64); - // error on cross-ds insert - set = hyperdex_ds_allocate_set(a); - ASSERT_TRUE(hyperdex_ds_set_insert_int(set, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_set_insert_string(set, "hello", 5, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - set = hyperdex_ds_allocate_set(a); - ASSERT_TRUE(hyperdex_ds_set_insert_int(set, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_set_insert_float(set, 0., &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - - hyperdex_ds_arena_destroy(a); + hyperdex_ds_returncode status; + const char *tmp = NULL; + size_t tmp_sz = 0; + hyperdatatype datatype; + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_ds_set *set; + // example 1 + set = hyperdex_ds_allocate_set(a); + ASSERT_TRUE(hyperdex_ds_set_finalize(set, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 0UL); + ASSERT_EQ(datatype, HYPERDATATYPE_SET_GENERIC); + // example 2 + set = hyperdex_ds_allocate_set(a); + ASSERT_TRUE(hyperdex_ds_set_insert_int(set, 1, &status) == 0); + ASSERT_TRUE(hyperdex_ds_set_insert_int(set, -1, &status) == 0); + ASSERT_TRUE(hyperdex_ds_set_insert_int(set, 0xdeadbeef, &status) == 0); + ASSERT_TRUE(hyperdex_ds_set_finalize(set, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 24UL); + ASSERT_TRUE(memcmp(tmp, "\xff\xff\xff\xff\xff\xff\xff\xff" + "\x01\x00\x00\x00\x00\x00\x00\x00" + "\xef\xbe\xad\xde\x00\x00\x00\x00", 24) == 0); + ASSERT_EQ(datatype, HYPERDATATYPE_SET_INT64); + // error on cross-ds insert + set = hyperdex_ds_allocate_set(a); + ASSERT_TRUE(hyperdex_ds_set_insert_int(set, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_set_insert_string(set, "hello", 5, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + set = hyperdex_ds_allocate_set(a); + ASSERT_TRUE(hyperdex_ds_set_insert_int(set, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_set_insert_float(set, 0., &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, SetFloat) { - hyperdex_ds_returncode status; - const char* tmp = NULL; - size_t tmp_sz = 0; - hyperdatatype datatype; - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_ds_set* set; - - // example 1 - set = hyperdex_ds_allocate_set(a); - ASSERT_TRUE(hyperdex_ds_set_finalize(set, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 0UL); - ASSERT_EQ(datatype, HYPERDATATYPE_SET_GENERIC); - // example 2 - set = hyperdex_ds_allocate_set(a); - ASSERT_TRUE(hyperdex_ds_set_insert_float(set, 3.1415, &status) == 0); - ASSERT_TRUE(hyperdex_ds_set_insert_float(set, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_set_finalize(set, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 16UL); - ASSERT_TRUE(memcmp(tmp, "\x00\x00\x00\x00\x00\x00\x00\x00" - "o\x12\x83\xc0\xca!\t@", 16) == 0); - ASSERT_EQ(datatype, HYPERDATATYPE_SET_FLOAT); - // error on cross-ds insert - set = hyperdex_ds_allocate_set(a); - ASSERT_TRUE(hyperdex_ds_set_insert_float(set, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_set_insert_string(set, "hello", 5, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - set = hyperdex_ds_allocate_set(a); - ASSERT_TRUE(hyperdex_ds_set_insert_float(set, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_set_insert_int(set, 0, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - - hyperdex_ds_arena_destroy(a); + hyperdex_ds_returncode status; + const char *tmp = NULL; + size_t tmp_sz = 0; + hyperdatatype datatype; + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_ds_set *set; + // example 1 + set = hyperdex_ds_allocate_set(a); + ASSERT_TRUE(hyperdex_ds_set_finalize(set, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 0UL); + ASSERT_EQ(datatype, HYPERDATATYPE_SET_GENERIC); + // example 2 + set = hyperdex_ds_allocate_set(a); + ASSERT_TRUE(hyperdex_ds_set_insert_float(set, 3.1415, &status) == 0); + ASSERT_TRUE(hyperdex_ds_set_insert_float(set, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_set_finalize(set, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 16UL); + ASSERT_TRUE(memcmp(tmp, "\x00\x00\x00\x00\x00\x00\x00\x00" + "o\x12\x83\xc0\xca!\t@", 16) == 0); + ASSERT_EQ(datatype, HYPERDATATYPE_SET_FLOAT); + // error on cross-ds insert + set = hyperdex_ds_allocate_set(a); + ASSERT_TRUE(hyperdex_ds_set_insert_float(set, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_set_insert_string(set, "hello", 5, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + set = hyperdex_ds_allocate_set(a); + ASSERT_TRUE(hyperdex_ds_set_insert_float(set, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_set_insert_int(set, 0, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, MapStringString) { - hyperdex_ds_returncode status; - const char* tmp = NULL; - size_t tmp_sz = 0; - hyperdatatype datatype; - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_ds_map* map; - - // example 1 - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_finalize(map, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 0UL); - ASSERT_EQ(datatype, HYPERDATATYPE_MAP_GENERIC); - // example 2 - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "world", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map key", 7, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "map val", 7, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map", 3, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "encoding", 8, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_finalize(map, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 59UL); - ASSERT_TRUE(memcmp(tmp, "\x05\x00\x00\x00hello\x05\x00\x00\x00world" - "\x03\x00\x00\x00map\x08\x00\x00\x00""encoding" - "\x07\x00\x00\x00map key\x07\x00\x00\x00map val", 59) == 0); - ASSERT_EQ(datatype, HYPERDATATYPE_MAP_STRING_STRING); - // double key insert - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_WRONG_STATE); - // double value insert - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "hello", 5, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_WRONG_STATE); - // error on cross-ds insert - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "world", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_int(map, 0, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "world", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map key", 7, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "world", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_float(map, 0., &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "world", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map key", 7, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 0., &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - - hyperdex_ds_arena_destroy(a); + hyperdex_ds_returncode status; + const char *tmp = NULL; + size_t tmp_sz = 0; + hyperdatatype datatype; + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_ds_map *map; + // example 1 + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_finalize(map, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 0UL); + ASSERT_EQ(datatype, HYPERDATATYPE_MAP_GENERIC); + // example 2 + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "world", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map key", 7, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "map val", 7, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map", 3, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "encoding", 8, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_finalize(map, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 59UL); + ASSERT_TRUE(memcmp(tmp, "\x05\x00\x00\x00hello\x05\x00\x00\x00world" + "\x03\x00\x00\x00map\x08\x00\x00\x00""encoding" + "\x07\x00\x00\x00map key\x07\x00\x00\x00map val", 59) == 0); + ASSERT_EQ(datatype, HYPERDATATYPE_MAP_STRING_STRING); + // double key insert + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_WRONG_STATE); + // double value insert + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "hello", 5, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_WRONG_STATE); + // error on cross-ds insert + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "world", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_int(map, 0, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "world", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map key", 7, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "world", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_float(map, 0., &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "world", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map key", 7, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 0., &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, MapStringInt) { - hyperdex_ds_returncode status; - const char* tmp = NULL; - size_t tmp_sz = 0; - hyperdatatype datatype; - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_ds_map* map; - - // example 1 - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_finalize(map, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 0UL); - ASSERT_EQ(datatype, HYPERDATATYPE_MAP_GENERIC); - // example 2 - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "world", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, -1, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 1, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_finalize(map, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 34UL); - ASSERT_TRUE(memcmp(tmp, "\x05\x00\x00\x00hello\x01\x00\x00\x00\x00\x00\x00\x00" - "\x05\x00\x00\x00world\xff\xff\xff\xff\xff\xff\xff\xff", 34) == 0); - ASSERT_EQ(datatype, HYPERDATATYPE_MAP_STRING_INT64); - // double key insert - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_WRONG_STATE); - // double value insert - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_WRONG_STATE); - // error on cross-ds insert - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_int(map, 0, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map key", 7, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "hello", 5, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_float(map, 0., &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map key", 7, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 0., &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - - hyperdex_ds_arena_destroy(a); + hyperdex_ds_returncode status; + const char *tmp = NULL; + size_t tmp_sz = 0; + hyperdatatype datatype; + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_ds_map *map; + // example 1 + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_finalize(map, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 0UL); + ASSERT_EQ(datatype, HYPERDATATYPE_MAP_GENERIC); + // example 2 + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "world", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, -1, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 1, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_finalize(map, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 34UL); + ASSERT_TRUE(memcmp(tmp, "\x05\x00\x00\x00hello\x01\x00\x00\x00\x00\x00\x00\x00" + "\x05\x00\x00\x00world\xff\xff\xff\xff\xff\xff\xff\xff", 34) == 0); + ASSERT_EQ(datatype, HYPERDATATYPE_MAP_STRING_INT64); + // double key insert + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_WRONG_STATE); + // double value insert + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_WRONG_STATE); + // error on cross-ds insert + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_int(map, 0, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map key", 7, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "hello", 5, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_float(map, 0., &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map key", 7, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 0., &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + hyperdex_ds_arena_destroy(a); } TEST(ClientDataStructures, MapStringFloat) { - hyperdex_ds_returncode status; - const char* tmp = NULL; - size_t tmp_sz = 0; - hyperdatatype datatype; - hyperdex_ds_arena* a = hyperdex_ds_arena_create(); - hyperdex_ds_map* map; - - // example 1 - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_finalize(map, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 0UL); - ASSERT_EQ(datatype, HYPERDATATYPE_MAP_GENERIC); - // example 2 - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "zero", 4, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 0, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "pi", 2, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 3.1415, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_finalize(map, &status, - &tmp, &tmp_sz, - &datatype) == 0); - ASSERT_EQ(tmp_sz, 30UL); - ASSERT_TRUE(memcmp(tmp, "\x02\x00\x00\x00pio\x12\x83\xc0\xca!\t@" - "\x04\x00\x00\x00zero\x00\x00\x00\x00\x00\x00\x00\x00", 30) == 0); - ASSERT_EQ(datatype, HYPERDATATYPE_MAP_STRING_FLOAT); - // double key insert - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_WRONG_STATE); - // double value insert - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 3.1415, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 3.1415, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_WRONG_STATE); - // error on cross-ds insert - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 3.1415, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_float(map, 3.1415, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 3.1415, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map key", 7, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "hello", 5, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 3.1415, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_float(map, 3.1415, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - map = hyperdex_ds_allocate_map(a); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 3.1415, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map key", 7, &status) == 0); - ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == -1); - ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); - - hyperdex_ds_arena_destroy(a); + hyperdex_ds_returncode status; + const char *tmp = NULL; + size_t tmp_sz = 0; + hyperdatatype datatype; + hyperdex_ds_arena *a = hyperdex_ds_arena_create(); + hyperdex_ds_map *map; + // example 1 + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_finalize(map, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 0UL); + ASSERT_EQ(datatype, HYPERDATATYPE_MAP_GENERIC); + // example 2 + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "zero", 4, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 0, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "pi", 2, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 3.1415, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_finalize(map, &status, + &tmp, &tmp_sz, + &datatype) == 0); + ASSERT_EQ(tmp_sz, 30UL); + ASSERT_TRUE(memcmp(tmp, "\x02\x00\x00\x00pio\x12\x83\xc0\xca!\t@" + "\x04\x00\x00\x00zero\x00\x00\x00\x00\x00\x00\x00\x00", 30) == 0); + ASSERT_EQ(datatype, HYPERDATATYPE_MAP_STRING_FLOAT); + // double key insert + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_WRONG_STATE); + // double value insert + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 3.1415, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 3.1415, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_WRONG_STATE); + // error on cross-ds insert + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 3.1415, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_float(map, 3.1415, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 3.1415, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map key", 7, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_string(map, "hello", 5, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 3.1415, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_float(map, 3.1415, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + map = hyperdex_ds_allocate_map(a); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "hello", 5, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_float(map, 3.1415, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_key_string(map, "map key", 7, &status) == 0); + ASSERT_TRUE(hyperdex_ds_map_insert_val_int(map, 0, &status) == -1); + ASSERT_EQ(status, HYPERDEX_DS_MIXED_TYPES); + hyperdex_ds_arena_destroy(a); } // XXX test cases for the rest of the map types TEST(ClientDataStructures, IterateListString) { - hyperdex_ds_iterator iter; - const char* ptr = "\x05\x00\x00\x00hello\x05\x00\x00\x00world"; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_STRING, ptr, 18); - const char* str = NULL; - size_t str_sz = 0; - - ASSERT_TRUE(hyperdex_ds_iterate_list_string_next(&iter, &str, &str_sz) == 1); - ASSERT_EQ(str_sz, 5UL); - ASSERT_TRUE(memcmp(str, "hello", 5) == 0); - - ASSERT_TRUE(hyperdex_ds_iterate_list_string_next(&iter, &str, &str_sz) == 1); - ASSERT_EQ(str_sz, 5UL); - ASSERT_TRUE(memcmp(str, "world", 5) == 0); - - ASSERT_TRUE(hyperdex_ds_iterate_list_string_next(&iter, &str, &str_sz) == 0); + hyperdex_ds_iterator iter; + const char *ptr = "\x05\x00\x00\x00hello\x05\x00\x00\x00world"; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_STRING, ptr, 18); + const char *str = NULL; + size_t str_sz = 0; + ASSERT_TRUE(hyperdex_ds_iterate_list_string_next(&iter, &str, &str_sz) == 1); + ASSERT_EQ(str_sz, 5UL); + ASSERT_TRUE(memcmp(str, "hello", 5) == 0); + ASSERT_TRUE(hyperdex_ds_iterate_list_string_next(&iter, &str, &str_sz) == 1); + ASSERT_EQ(str_sz, 5UL); + ASSERT_TRUE(memcmp(str, "world", 5) == 0); + ASSERT_TRUE(hyperdex_ds_iterate_list_string_next(&iter, &str, &str_sz) == 0); } TEST(ClientDataStructures, IterateListInt) { - hyperdex_ds_iterator iter; - const char* ptr = "\x01\x00\x00\x00\x00\x00\x00\x00" - "\xff\xff\xff\xff\xff\xff\xff\xff" - "\xef\xbe\xad\xde\x00\x00\x00\x00"; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_INT64, ptr, 24); - int64_t num = 0; - - ASSERT_TRUE(hyperdex_ds_iterate_list_int_next(&iter, &num) == 1); - ASSERT_EQ(num, 1L); - - ASSERT_TRUE(hyperdex_ds_iterate_list_int_next(&iter, &num) == 1); - ASSERT_EQ(num, -1L); - - ASSERT_TRUE(hyperdex_ds_iterate_list_int_next(&iter, &num) == 1); - ASSERT_EQ(num, 0xdeadbeef); - - ASSERT_TRUE(hyperdex_ds_iterate_list_int_next(&iter, &num) == 0); + hyperdex_ds_iterator iter; + const char *ptr = "\x01\x00\x00\x00\x00\x00\x00\x00" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xef\xbe\xad\xde\x00\x00\x00\x00"; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_INT64, ptr, 24); + int64_t num = 0; + ASSERT_TRUE(hyperdex_ds_iterate_list_int_next(&iter, &num) == 1); + ASSERT_EQ(num, 1L); + ASSERT_TRUE(hyperdex_ds_iterate_list_int_next(&iter, &num) == 1); + ASSERT_EQ(num, -1L); + ASSERT_TRUE(hyperdex_ds_iterate_list_int_next(&iter, &num) == 1); + ASSERT_EQ(num, 0xdeadbeef); + ASSERT_TRUE(hyperdex_ds_iterate_list_int_next(&iter, &num) == 0); } TEST(ClientDataStructures, IterateListFloat) { - hyperdex_ds_iterator iter; - const char* ptr = "\x00\x00\x00\x00\x00\x00\x00\x00" - "o\x12\x83\xc0\xca!\t@"; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_FLOAT, ptr, 16); - double num = 1; - - ASSERT_TRUE(hyperdex_ds_iterate_list_float_next(&iter, &num) == 1); - ASSERT_GE(num, -0.001); - ASSERT_LE(num, 0.001); - - ASSERT_TRUE(hyperdex_ds_iterate_list_float_next(&iter, &num) == 1); - ASSERT_GE(num, 3.14149999); - ASSERT_LE(num, 3.14150001); - - ASSERT_TRUE(hyperdex_ds_iterate_list_float_next(&iter, &num) == 0); + hyperdex_ds_iterator iter; + const char *ptr = "\x00\x00\x00\x00\x00\x00\x00\x00" + "o\x12\x83\xc0\xca!\t@"; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_FLOAT, ptr, 16); + double num = 1; + ASSERT_TRUE(hyperdex_ds_iterate_list_float_next(&iter, &num) == 1); + ASSERT_GE(num, -0.001); + ASSERT_LE(num, 0.001); + ASSERT_TRUE(hyperdex_ds_iterate_list_float_next(&iter, &num) == 1); + ASSERT_GE(num, 3.14149999); + ASSERT_LE(num, 3.14150001); + ASSERT_TRUE(hyperdex_ds_iterate_list_float_next(&iter, &num) == 0); } TEST(ClientDataStructures, IterateSetString) { - hyperdex_ds_iterator iter; - const char* ptr = "\x05\x00\x00\x00hello\x05\x00\x00\x00world"; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_STRING, ptr, 18); - const char* str = NULL; - size_t str_sz = 0; - - ASSERT_TRUE(hyperdex_ds_iterate_set_string_next(&iter, &str, &str_sz) == 1); - ASSERT_EQ(str_sz, 5UL); - ASSERT_TRUE(memcmp(str, "hello", 5) == 0); - - ASSERT_TRUE(hyperdex_ds_iterate_set_string_next(&iter, &str, &str_sz) == 1); - ASSERT_EQ(str_sz, 5UL); - ASSERT_TRUE(memcmp(str, "world", 5) == 0); - - ASSERT_TRUE(hyperdex_ds_iterate_set_string_next(&iter, &str, &str_sz) == 0); + hyperdex_ds_iterator iter; + const char *ptr = "\x05\x00\x00\x00hello\x05\x00\x00\x00world"; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_STRING, ptr, 18); + const char *str = NULL; + size_t str_sz = 0; + ASSERT_TRUE(hyperdex_ds_iterate_set_string_next(&iter, &str, &str_sz) == 1); + ASSERT_EQ(str_sz, 5UL); + ASSERT_TRUE(memcmp(str, "hello", 5) == 0); + ASSERT_TRUE(hyperdex_ds_iterate_set_string_next(&iter, &str, &str_sz) == 1); + ASSERT_EQ(str_sz, 5UL); + ASSERT_TRUE(memcmp(str, "world", 5) == 0); + ASSERT_TRUE(hyperdex_ds_iterate_set_string_next(&iter, &str, &str_sz) == 0); } TEST(ClientDataStructures, IterateSetInt) { - hyperdex_ds_iterator iter; - const char* ptr = "\xff\xff\xff\xff\xff\xff\xff\xff" - "\x01\x00\x00\x00\x00\x00\x00\x00" - "\xef\xbe\xad\xde\x00\x00\x00\x00"; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_INT64, ptr, 24); - int64_t num = 0; - - ASSERT_TRUE(hyperdex_ds_iterate_set_int_next(&iter, &num) == 1); - ASSERT_EQ(num, -1L); - - ASSERT_TRUE(hyperdex_ds_iterate_set_int_next(&iter, &num) == 1); - ASSERT_EQ(num, 1L); - - ASSERT_TRUE(hyperdex_ds_iterate_set_int_next(&iter, &num) == 1); - ASSERT_EQ(num, 0xdeadbeef); - - ASSERT_TRUE(hyperdex_ds_iterate_set_int_next(&iter, &num) == 0); + hyperdex_ds_iterator iter; + const char *ptr = "\xff\xff\xff\xff\xff\xff\xff\xff" + "\x01\x00\x00\x00\x00\x00\x00\x00" + "\xef\xbe\xad\xde\x00\x00\x00\x00"; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_INT64, ptr, 24); + int64_t num = 0; + ASSERT_TRUE(hyperdex_ds_iterate_set_int_next(&iter, &num) == 1); + ASSERT_EQ(num, -1L); + ASSERT_TRUE(hyperdex_ds_iterate_set_int_next(&iter, &num) == 1); + ASSERT_EQ(num, 1L); + ASSERT_TRUE(hyperdex_ds_iterate_set_int_next(&iter, &num) == 1); + ASSERT_EQ(num, 0xdeadbeef); + ASSERT_TRUE(hyperdex_ds_iterate_set_int_next(&iter, &num) == 0); } TEST(ClientDataStructures, IterateSetFloat) { - hyperdex_ds_iterator iter; - const char* ptr = "\x00\x00\x00\x00\x00\x00\x00\x00" - "o\x12\x83\xc0\xca!\t@"; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_FLOAT, ptr, 16); - double num = 1; - - ASSERT_TRUE(hyperdex_ds_iterate_set_float_next(&iter, &num) == 1); - ASSERT_GE(num, -0.001); - ASSERT_LE(num, 0.001); - - ASSERT_TRUE(hyperdex_ds_iterate_set_float_next(&iter, &num) == 1); - ASSERT_GE(num, 3.14149999); - ASSERT_LE(num, 3.14150001); - - ASSERT_TRUE(hyperdex_ds_iterate_set_float_next(&iter, &num) == 0); + hyperdex_ds_iterator iter; + const char *ptr = "\x00\x00\x00\x00\x00\x00\x00\x00" + "o\x12\x83\xc0\xca!\t@"; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_SET_FLOAT, ptr, 16); + double num = 1; + ASSERT_TRUE(hyperdex_ds_iterate_set_float_next(&iter, &num) == 1); + ASSERT_GE(num, -0.001); + ASSERT_LE(num, 0.001); + ASSERT_TRUE(hyperdex_ds_iterate_set_float_next(&iter, &num) == 1); + ASSERT_GE(num, 3.14149999); + ASSERT_LE(num, 3.14150001); + ASSERT_TRUE(hyperdex_ds_iterate_set_float_next(&iter, &num) == 0); } TEST(ClientDataStructures, IterateMapStringString) { - hyperdex_ds_iterator iter; - const char* ptr = "\x05\x00\x00\x00hello\x05\x00\x00\x00world" - "\x03\x00\x00\x00map\x08\x00\x00\x00""encoding" - "\x07\x00\x00\x00map key\x07\x00\x00\x00map val"; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_STRING, ptr, 59); - const char* key = NULL; - size_t key_sz = 0; - const char* val = NULL; - size_t val_sz = 0; - - ASSERT_TRUE(hyperdex_ds_iterate_map_string_string_next(&iter, &key, &key_sz, &val, &val_sz) == 1); - ASSERT_EQ(key_sz, 5UL); - ASSERT_TRUE(memcmp(key, "hello", 5) == 0); - ASSERT_EQ(val_sz, 5UL); - ASSERT_TRUE(memcmp(val, "world", 5) == 0); - - ASSERT_TRUE(hyperdex_ds_iterate_map_string_string_next(&iter, &key, &key_sz, &val, &val_sz) == 1); - ASSERT_EQ(key_sz, 3UL); - ASSERT_TRUE(memcmp(key, "map", 3) == 0); - ASSERT_EQ(val_sz, 8UL); - ASSERT_TRUE(memcmp(val, "encoding", 8) == 0); - - ASSERT_TRUE(hyperdex_ds_iterate_map_string_string_next(&iter, &key, &key_sz, &val, &val_sz) == 1); - ASSERT_EQ(key_sz, 7UL); - ASSERT_TRUE(memcmp(key, "map key", 7) == 0); - ASSERT_EQ(val_sz, 7UL); - ASSERT_TRUE(memcmp(val, "map val", 7) == 0); - - ASSERT_TRUE(hyperdex_ds_iterate_map_string_string_next(&iter, &key, &key_sz, &val, &val_sz) == 0); + hyperdex_ds_iterator iter; + const char *ptr = "\x05\x00\x00\x00hello\x05\x00\x00\x00world" + "\x03\x00\x00\x00map\x08\x00\x00\x00""encoding" + "\x07\x00\x00\x00map key\x07\x00\x00\x00map val"; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_STRING, ptr, 59); + const char *key = NULL; + size_t key_sz = 0; + const char *val = NULL; + size_t val_sz = 0; + ASSERT_TRUE(hyperdex_ds_iterate_map_string_string_next(&iter, &key, &key_sz, &val, &val_sz) == 1); + ASSERT_EQ(key_sz, 5UL); + ASSERT_TRUE(memcmp(key, "hello", 5) == 0); + ASSERT_EQ(val_sz, 5UL); + ASSERT_TRUE(memcmp(val, "world", 5) == 0); + ASSERT_TRUE(hyperdex_ds_iterate_map_string_string_next(&iter, &key, &key_sz, &val, &val_sz) == 1); + ASSERT_EQ(key_sz, 3UL); + ASSERT_TRUE(memcmp(key, "map", 3) == 0); + ASSERT_EQ(val_sz, 8UL); + ASSERT_TRUE(memcmp(val, "encoding", 8) == 0); + ASSERT_TRUE(hyperdex_ds_iterate_map_string_string_next(&iter, &key, &key_sz, &val, &val_sz) == 1); + ASSERT_EQ(key_sz, 7UL); + ASSERT_TRUE(memcmp(key, "map key", 7) == 0); + ASSERT_EQ(val_sz, 7UL); + ASSERT_TRUE(memcmp(val, "map val", 7) == 0); + ASSERT_TRUE(hyperdex_ds_iterate_map_string_string_next(&iter, &key, &key_sz, &val, &val_sz) == 0); } TEST(ClientDataStructures, IterateMapStringInt) { - hyperdex_ds_iterator iter; - const char* ptr = "\x05\x00\x00\x00hello\x01\x00\x00\x00\x00\x00\x00\x00" - "\x05\x00\x00\x00world\xff\xff\xff\xff\xff\xff\xff\xff"; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_INT64, ptr, 34); - const char* key = NULL; - size_t key_sz = 0; - int64_t val = 0; - - ASSERT_TRUE(hyperdex_ds_iterate_map_string_int_next(&iter, &key, &key_sz, &val) == 1); - ASSERT_EQ(key_sz, 5UL); - ASSERT_TRUE(memcmp(key, "hello", 5) == 0); - ASSERT_EQ(val, 1L); - - ASSERT_TRUE(hyperdex_ds_iterate_map_string_int_next(&iter, &key, &key_sz, &val) == 1); - ASSERT_EQ(key_sz, 5UL); - ASSERT_TRUE(memcmp(key, "world", 5) == 0); - ASSERT_EQ(val, -1L); - - ASSERT_TRUE(hyperdex_ds_iterate_map_string_int_next(&iter, &key, &key_sz, &val) == 0); + hyperdex_ds_iterator iter; + const char *ptr = "\x05\x00\x00\x00hello\x01\x00\x00\x00\x00\x00\x00\x00" + "\x05\x00\x00\x00world\xff\xff\xff\xff\xff\xff\xff\xff"; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_INT64, ptr, 34); + const char *key = NULL; + size_t key_sz = 0; + int64_t val = 0; + ASSERT_TRUE(hyperdex_ds_iterate_map_string_int_next(&iter, &key, &key_sz, &val) == 1); + ASSERT_EQ(key_sz, 5UL); + ASSERT_TRUE(memcmp(key, "hello", 5) == 0); + ASSERT_EQ(val, 1L); + ASSERT_TRUE(hyperdex_ds_iterate_map_string_int_next(&iter, &key, &key_sz, &val) == 1); + ASSERT_EQ(key_sz, 5UL); + ASSERT_TRUE(memcmp(key, "world", 5) == 0); + ASSERT_EQ(val, -1L); + ASSERT_TRUE(hyperdex_ds_iterate_map_string_int_next(&iter, &key, &key_sz, &val) == 0); } TEST(ClientDataStructures, IterateMapStringFloat) { - hyperdex_ds_iterator iter; - const char* ptr = "\x02\x00\x00\x00pio\x12\x83\xc0\xca!\t@" - "\x04\x00\x00\x00zero\x00\x00\x00\x00\x00\x00\x00\x00"; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_FLOAT, ptr, 30); - const char* key = NULL; - size_t key_sz = 0; - double val = 0; - - ASSERT_TRUE(hyperdex_ds_iterate_map_string_float_next(&iter, &key, &key_sz, &val) == 1); - ASSERT_EQ(key_sz, 2UL); - ASSERT_TRUE(memcmp(key, "pi", 2) == 0); - ASSERT_GE(val, 3.14149999); - ASSERT_LE(val, 3.14150001); - - ASSERT_TRUE(hyperdex_ds_iterate_map_string_float_next(&iter, &key, &key_sz, &val) == 1); - ASSERT_EQ(key_sz, 4UL); - ASSERT_TRUE(memcmp(key, "zero", 4) == 0); - ASSERT_GE(val, -0.0001); - ASSERT_LE(val, 0.0001); - - ASSERT_EQ(hyperdex_ds_iterate_map_string_float_next(&iter, &key, &key_sz, &val), 0); + hyperdex_ds_iterator iter; + const char *ptr = "\x02\x00\x00\x00pio\x12\x83\xc0\xca!\t@" + "\x04\x00\x00\x00zero\x00\x00\x00\x00\x00\x00\x00\x00"; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_MAP_STRING_FLOAT, ptr, 30); + const char *key = NULL; + size_t key_sz = 0; + double val = 0; + ASSERT_TRUE(hyperdex_ds_iterate_map_string_float_next(&iter, &key, &key_sz, &val) == 1); + ASSERT_EQ(key_sz, 2UL); + ASSERT_TRUE(memcmp(key, "pi", 2) == 0); + ASSERT_GE(val, 3.14149999); + ASSERT_LE(val, 3.14150001); + ASSERT_TRUE(hyperdex_ds_iterate_map_string_float_next(&iter, &key, &key_sz, &val) == 1); + ASSERT_EQ(key_sz, 4UL); + ASSERT_TRUE(memcmp(key, "zero", 4) == 0); + ASSERT_GE(val, -0.0001); + ASSERT_LE(val, 0.0001); + ASSERT_EQ(hyperdex_ds_iterate_map_string_float_next(&iter, &key, &key_sz, &val), 0); } diff --git a/client/util.cc b/client/util.cc index 5cfb5634f..439d52932 100644 --- a/client/util.cc +++ b/client/util.cc @@ -36,202 +36,180 @@ #include "client/util.h" #define UTIL_ERROR(CODE) \ - *op_status = HYPERDEX_CLIENT_ ## CODE; \ - op_error->set_loc(__FILE__, __LINE__); \ - op_error->set_msg() + *op_status = HYPERDEX_CLIENT_ ## CODE; \ + op_error->set_loc(__FILE__, __LINE__); \ + op_error->set_msg() bool -hyperdex :: value_to_attributes(const configuration& config, - const region_id& rid, - const uint8_t* key, +hyperdex :: value_to_attributes(const configuration &config, + const region_id &rid, + const uint8_t *key, size_t key_sz, - const std::vector& _value, - hyperdex_client_returncode* op_status, - e::error* op_error, - const hyperdex_client_attribute** attrs, - size_t* attrs_sz, + const std::vector &_value, + hyperdex_client_returncode *op_status, + e::error *op_error, + const hyperdex_client_attribute **attrs, + size_t *attrs_sz, bool convert_types) { - std::vector value(_value); - const schema* sc = config.get_schema(rid); - e::arena memory; - - if (value.size() + 1 != sc->attrs_sz) - { - UTIL_ERROR(SERVERERROR) << "received object with " << value.size() - << " attributes instead of " - << sc->attrs_sz - 1 << " attributes"; - return false; - } - - if (convert_types) - { - for (size_t i = 0; i < value.size(); ++i) - { - datatype_info* di = datatype_info::lookup(sc->attrs[i + 1].type); - - if (!di->server_to_client(value[i], &memory, &value[i])) - { - UTIL_ERROR(SERVERERROR) << "cannot convert from server-side form"; - return false; - } - } - } - - size_t sz = sizeof(hyperdex_client_attribute) * sc->attrs_sz + key_sz - + strlen(sc->attrs[0].name) + 1; - - for (size_t i = 0; i < value.size(); ++i) - { - sz += strlen(sc->attrs[i + 1].name) + 1 + value[i].size(); - } - - std::vector ha; - ha.reserve(sc->attrs_sz); + std::vector value(_value); + const schema *sc = config.get_schema(rid); + e::arena memory; + if (value.size() + 1 != sc->attrs_sz) + { + UTIL_ERROR(SERVERERROR) << "received object with " << value.size() + << " attributes instead of " + << sc->attrs_sz - 1 << " attributes"; + return false; + } + if (convert_types) + { + for (size_t i = 0; i < value.size(); ++i) + { + datatype_info *di = datatype_info::lookup(sc->attrs[i + 1].type); + if (!di->server_to_client(value[i], &memory, &value[i])) + { + UTIL_ERROR(SERVERERROR) << "cannot convert from server-side form"; + return false; + } + } + } + size_t sz = sizeof(hyperdex_client_attribute) * sc->attrs_sz + key_sz + + strlen(sc->attrs[0].name) + 1; + for (size_t i = 0; i < value.size(); ++i) + { + sz += strlen(sc->attrs[i + 1].name) + 1 + value[i].size(); + } + std::vector ha; + ha.reserve(sc->attrs_sz); char *ret = NULL; if (attrs) { - if (*attrs == NULL) - { - ret = static_cast(malloc(sz)); - } + if (*attrs == NULL) + { + ret = static_cast(malloc(sz)); + } else { - ret = static_cast(realloc((void *)*attrs, sz)); + ret = static_cast(realloc((void *)*attrs, sz)); } } - - if (ret == NULL) - { - UTIL_ERROR(NOMEM) << "out of memory"; - return false; - } - - e::guard g = e::makeguard(free, ret); - char* data = ret + sizeof(hyperdex_client_attribute) * value.size(); - - if (key) - { - data += sizeof(hyperdex_client_attribute); - ha.push_back(hyperdex_client_attribute()); - size_t attr_sz = strlen(sc->attrs[0].name) + 1; - ha.back().attr = data; - memmove(data, sc->attrs[0].name, attr_sz); - data += attr_sz; - ha.back().value = data; - memmove(data, key, key_sz); - data += key_sz; - ha.back().value_sz = key_sz; - ha.back().datatype = sc->attrs[0].type; - } - - for (size_t i = 0; i < value.size(); ++i) - { - if (sc->attrs[i + 1].type == HYPERDATATYPE_MACAROON_SECRET) - { - continue; - } - - ha.push_back(hyperdex_client_attribute()); - size_t attr_sz = strlen(sc->attrs[i + 1].name) + 1; - ha.back().attr = data; - memmove(data, sc->attrs[i + 1].name, attr_sz); - data += attr_sz; - ha.back().value = data; - memmove(data, value[i].data(), value[i].size()); - data += value[i].size(); - ha.back().value_sz = value[i].size(); - ha.back().datatype = sc->attrs[i + 1].type; - } - - memmove(ret, &ha.front(), sizeof(hyperdex_client_attribute) * ha.size()); - *op_status = HYPERDEX_CLIENT_SUCCESS; - *op_error = e::error(); - *attrs = reinterpret_cast(ret); - *attrs_sz = ha.size(); - g.dismiss(); - return true; + if (ret == NULL) + { + UTIL_ERROR(NOMEM) << "out of memory"; + return false; + } + e::guard g = e::makeguard(free, ret); + char *data = ret + sizeof(hyperdex_client_attribute) * value.size(); + if (key) + { + data += sizeof(hyperdex_client_attribute); + ha.push_back(hyperdex_client_attribute()); + size_t attr_sz = strlen(sc->attrs[0].name) + 1; + ha.back().attr = data; + memmove(data, sc->attrs[0].name, attr_sz); + data += attr_sz; + ha.back().value = data; + memmove(data, key, key_sz); + data += key_sz; + ha.back().value_sz = key_sz; + ha.back().datatype = sc->attrs[0].type; + } + for (size_t i = 0; i < value.size(); ++i) + { + if (sc->attrs[i + 1].type == HYPERDATATYPE_MACAROON_SECRET) + { + continue; + } + ha.push_back(hyperdex_client_attribute()); + size_t attr_sz = strlen(sc->attrs[i + 1].name) + 1; + ha.back().attr = data; + memmove(data, sc->attrs[i + 1].name, attr_sz); + data += attr_sz; + ha.back().value = data; + memmove(data, value[i].data(), value[i].size()); + data += value[i].size(); + ha.back().value_sz = value[i].size(); + ha.back().datatype = sc->attrs[i + 1].type; + } + memmove(ret, &ha.front(), sizeof(hyperdex_client_attribute) * ha.size()); + *op_status = HYPERDEX_CLIENT_SUCCESS; + *op_error = e::error(); + *attrs = reinterpret_cast(ret); + *attrs_sz = ha.size(); + g.dismiss(); + return true; } bool -hyperdex :: value_to_attributes(const configuration& config, - const region_id& rid, - const std::vector >& _value, - hyperdex_client_returncode* op_status, - e::error* op_error, - const hyperdex_client_attribute** attrs, - size_t* attrs_sz, +hyperdex :: value_to_attributes(const configuration &config, + const region_id &rid, + const std::vector > &_value, + hyperdex_client_returncode *op_status, + e::error *op_error, + const hyperdex_client_attribute **attrs, + size_t *attrs_sz, bool convert_types) { - std::vector > value(_value); - const schema* sc = config.get_schema(rid); - e::arena memory; - size_t sz = sizeof(hyperdex_client_attribute) * value.size() - + strlen(sc->attrs[0].name) + 1; - - for (size_t i = 0; i < value.size(); ++i) - { - uint16_t attr = value[i].first; - - if (attr >= sc->attrs_sz) - { - UTIL_ERROR(SERVERERROR) << "received object with attribute " << value[i].first - << " which exceeds the number of attributes in the schema (" - << sc->attrs_sz << ")"; - return false; - } - - sz += strlen(sc->attrs[attr].name) + 1 + value[i].second.size(); - datatype_info* di = datatype_info::lookup(sc->attrs[attr].type); - - if (convert_types) - { - if (!di->server_to_client(value[i].second, &memory, &value[i].second)) - { - UTIL_ERROR(SERVERERROR) << "cannot convert from server-side form"; - return false; - } - } - } - - std::vector ha; - ha.reserve(sc->attrs_sz); - char* ret = static_cast(malloc(sz)); - - if (!ret) - { - UTIL_ERROR(NOMEM) << "out of memory"; - return false; - } - - e::guard g = e::makeguard(free, ret); - char* data = ret + sizeof(hyperdex_client_attribute) * value.size(); - - for (size_t i = 0; i < value.size(); ++i) - { - if (sc->attrs[i + 1].type == HYPERDATATYPE_MACAROON_SECRET) - { - continue; - } - - uint16_t attr = value[i].first; - ha.push_back(hyperdex_client_attribute()); - size_t attr_sz = strlen(sc->attrs[attr].name) + 1; - ha.back().attr = data; - memmove(data, sc->attrs[attr].name, attr_sz); - data += attr_sz; - ha.back().value = data; - memmove(data, value[i].second.data(), value[i].second.size()); - data += value[i].second.size(); - ha.back().value_sz = value[i].second.size(); - ha.back().datatype = sc->attrs[attr].type; - } - - memmove(ret, &ha.front(), sizeof(hyperdex_client_attribute) * ha.size()); - *op_status = HYPERDEX_CLIENT_SUCCESS; - *op_error = e::error(); - *attrs = reinterpret_cast(ret); - *attrs_sz = ha.size(); - g.dismiss(); - return true; + std::vector > value(_value); + const schema *sc = config.get_schema(rid); + e::arena memory; + size_t sz = sizeof(hyperdex_client_attribute) * value.size() + + strlen(sc->attrs[0].name) + 1; + for (size_t i = 0; i < value.size(); ++i) + { + uint16_t attr = value[i].first; + if (attr >= sc->attrs_sz) + { + UTIL_ERROR(SERVERERROR) << "received object with attribute " << value[i].first + << " which exceeds the number of attributes in the schema (" + << sc->attrs_sz << ")"; + return false; + } + sz += strlen(sc->attrs[attr].name) + 1 + value[i].second.size(); + datatype_info *di = datatype_info::lookup(sc->attrs[attr].type); + if (convert_types) + { + if (!di->server_to_client(value[i].second, &memory, &value[i].second)) + { + UTIL_ERROR(SERVERERROR) << "cannot convert from server-side form"; + return false; + } + } + } + std::vector ha; + ha.reserve(sc->attrs_sz); + char *ret = static_cast(malloc(sz)); + if (!ret) + { + UTIL_ERROR(NOMEM) << "out of memory"; + return false; + } + e::guard g = e::makeguard(free, ret); + char *data = ret + sizeof(hyperdex_client_attribute) * value.size(); + for (size_t i = 0; i < value.size(); ++i) + { + if (sc->attrs[i + 1].type == HYPERDATATYPE_MACAROON_SECRET) + { + continue; + } + uint16_t attr = value[i].first; + ha.push_back(hyperdex_client_attribute()); + size_t attr_sz = strlen(sc->attrs[attr].name) + 1; + ha.back().attr = data; + memmove(data, sc->attrs[attr].name, attr_sz); + data += attr_sz; + ha.back().value = data; + memmove(data, value[i].second.data(), value[i].second.size()); + data += value[i].second.size(); + ha.back().value_sz = value[i].second.size(); + ha.back().datatype = sc->attrs[attr].type; + } + memmove(ret, &ha.front(), sizeof(hyperdex_client_attribute) * ha.size()); + *op_status = HYPERDEX_CLIENT_SUCCESS; + *op_error = e::error(); + *attrs = reinterpret_cast(ret); + *attrs_sz = ha.size(); + g.dismiss(); + return true; } diff --git a/client/util.h b/client/util.h index 0c8eecd74..c426d9c2f 100644 --- a/client/util.h +++ b/client/util.h @@ -42,25 +42,25 @@ BEGIN_HYPERDEX_NAMESPACE // Convert the key and value vector returned by entity to an array of // hyperdex_attribute using the given configuration. bool -value_to_attributes(const configuration& config, - const region_id& rid, - const uint8_t* key, +value_to_attributes(const configuration &config, + const region_id &rid, + const uint8_t *key, size_t key_sz, - const std::vector& value, - hyperdex_client_returncode* op_status, - e::error* op_error, - const hyperdex_client_attribute** attrs, - size_t* attrs_sz, + const std::vector &value, + hyperdex_client_returncode *op_status, + e::error *op_error, + const hyperdex_client_attribute **attrs, + size_t *attrs_sz, bool convert_types); bool -value_to_attributes(const configuration& config, - const region_id& rid, - const std::vector >& value, - hyperdex_client_returncode* op_status, - e::error* op_error, - const hyperdex_client_attribute** attrs, - size_t* attrs_sz, +value_to_attributes(const configuration &config, + const region_id &rid, + const std::vector > &value, + hyperdex_client_returncode *op_status, + e::error *op_error, + const hyperdex_client_attribute **attrs, + size_t *attrs_sz, bool convert_types); END_HYPERDEX_NAMESPACE diff --git a/common/attribute.cc b/common/attribute.cc index 5d8bd1a76..ef26682de 100644 --- a/common/attribute.cc +++ b/common/attribute.cc @@ -31,27 +31,27 @@ using hyperdex::attribute; attribute :: attribute() - : name("") - , type(HYPERDATATYPE_GARBAGE) + : name("") + , type(HYPERDATATYPE_GARBAGE) { } -attribute :: attribute(const char* _name, hyperdatatype _type) - : name(_name) - , type(_type) +attribute :: attribute(const char *_name, hyperdatatype _type) + : name(_name) + , type(_type) { } -attribute :: attribute(const attribute& other) - : name(other.name) - , type(other.type) +attribute :: attribute(const attribute &other) + : name(other.name) + , type(other.type) { } -attribute& -attribute :: operator = (const attribute& rhs) +attribute & +attribute :: operator = (const attribute &rhs) { - name = rhs.name; - type = rhs.type; - return *this; + name = rhs.name; + type = rhs.type; + return *this; } diff --git a/common/attribute.h b/common/attribute.h index 46cbd9cb8..e209eafb8 100644 --- a/common/attribute.h +++ b/common/attribute.h @@ -36,17 +36,17 @@ BEGIN_HYPERDEX_NAMESPACE class attribute { - public: - attribute(); - attribute(const char* name, hyperdatatype type); - attribute(const attribute& other); +public: + attribute(); + attribute(const char *name, hyperdatatype type); + attribute(const attribute &other); - public: - attribute& operator = (const attribute& rhs); +public: + attribute &operator = (const attribute &rhs); - public: - const char* name; - hyperdatatype type; +public: + const char *name; + hyperdatatype type; }; END_HYPERDEX_NAMESPACE diff --git a/common/attribute_check.cc b/common/attribute_check.cc index d5b60db7d..cb3fe2c4a 100644 --- a/common/attribute_check.cc +++ b/common/attribute_check.cc @@ -36,10 +36,10 @@ using hyperdex::attribute_check; attribute_check :: attribute_check() - : attr() - , value() - , datatype(HYPERDATATYPE_GARBAGE) - , predicate(HYPERPREDICATE_FAIL) + : attr() + , value() + , datatype(HYPERDATATYPE_GARBAGE) + , predicate(HYPERPREDICATE_FAIL) { } @@ -49,223 +49,208 @@ attribute_check :: ~attribute_check() throw () bool hyperdex :: validate_attribute_check(hyperdatatype type, - const attribute_check& check) + const attribute_check &check) { - datatype_info* di_attr = datatype_info::lookup(type); - datatype_info* di_check = datatype_info::lookup(check.datatype); - - if (!di_attr || !di_check) - { - return false; - } - - if (di_attr->document()) - { - return true; - } - - if (!di_check->validate(check.value)) - { - return false; - } - - switch (check.predicate) - { - case HYPERPREDICATE_FAIL: - return true; - case HYPERPREDICATE_EQUALS: - return di_attr->datatype() == di_check->datatype(); - case HYPERPREDICATE_LESS_THAN: - case HYPERPREDICATE_LESS_EQUAL: - case HYPERPREDICATE_GREATER_EQUAL: - case HYPERPREDICATE_GREATER_THAN: - return di_attr->datatype() == di_check->datatype() && - di_attr->comparable(); - case HYPERPREDICATE_REGEX: - return di_check->datatype() == HYPERDATATYPE_STRING && - di_attr->has_regex(); - case HYPERPREDICATE_CONTAINS_LESS_THAN: - case HYPERPREDICATE_LENGTH_EQUALS: - case HYPERPREDICATE_LENGTH_LESS_EQUAL: - case HYPERPREDICATE_LENGTH_GREATER_EQUAL: - return di_check->datatype() == HYPERDATATYPE_INT64 && - di_attr->has_length(); - case HYPERPREDICATE_CONTAINS: - return di_attr->has_contains() && - di_attr->contains_datatype() == di_check->datatype(); - default: - return false; - } + datatype_info *di_attr = datatype_info::lookup(type); + datatype_info *di_check = datatype_info::lookup(check.datatype); + if (!di_attr || !di_check) + { + return false; + } + if (di_attr->document()) + { + return true; + } + if (!di_check->validate(check.value)) + { + return false; + } + switch (check.predicate) + { + case HYPERPREDICATE_FAIL: + return true; + case HYPERPREDICATE_EQUALS: + return di_attr->datatype() == di_check->datatype(); + case HYPERPREDICATE_LESS_THAN: + case HYPERPREDICATE_LESS_EQUAL: + case HYPERPREDICATE_GREATER_EQUAL: + case HYPERPREDICATE_GREATER_THAN: + return di_attr->datatype() == di_check->datatype() && + di_attr->comparable(); + case HYPERPREDICATE_REGEX: + return di_check->datatype() == HYPERDATATYPE_STRING && + di_attr->has_regex(); + case HYPERPREDICATE_CONTAINS_LESS_THAN: + case HYPERPREDICATE_LENGTH_EQUALS: + case HYPERPREDICATE_LENGTH_LESS_EQUAL: + case HYPERPREDICATE_LENGTH_GREATER_EQUAL: + return di_check->datatype() == HYPERDATATYPE_INT64 && + di_attr->has_length(); + case HYPERPREDICATE_CONTAINS: + return di_attr->has_contains() && + di_attr->contains_datatype() == di_check->datatype(); + default: + return false; + } } size_t -hyperdex :: validate_attribute_checks(const schema& sc, - const std::vector& checks) +hyperdex :: validate_attribute_checks(const schema &sc, + const std::vector &checks) { - for (size_t i = 0; i < checks.size(); ++i) - { - if (checks[i].attr >= sc.attrs_sz) - { - return i; - } - - hyperdatatype type = sc.attrs[checks[i].attr].type; - - if (!validate_attribute_check(type, checks[i])) - { - return i; - } - } - - return checks.size(); + for (size_t i = 0; i < checks.size(); ++i) + { + if (checks[i].attr >= sc.attrs_sz) + { + return i; + } + hyperdatatype type = sc.attrs[checks[i].attr].type; + if (!validate_attribute_check(type, checks[i])) + { + return i; + } + } + return checks.size(); } bool hyperdex :: passes_attribute_check(hyperdatatype type, - const attribute_check& check, - const e::slice& value) + const attribute_check &check, + const e::slice &value) { - datatype_info* di_attr = datatype_info::lookup(type); - datatype_info* di_check = datatype_info::lookup(check.datatype); - - if (!di_attr || !di_check) - { - return false; - } - - if (di_attr->document()) - { - return di_attr->document_check(check, value); - } - - if (!di_attr->validate(value) || - !di_check->validate(check.value)) - { - return false; - } - - char buf_i[sizeof(int64_t)]; - int64_t tmp_i; - - switch (check.predicate) - { - case HYPERPREDICATE_FAIL: - return false; - case HYPERPREDICATE_EQUALS: - return di_attr->datatype() == di_check->datatype() && - (check.value == value || - (di_attr->comparable() && di_attr->compare(check.value, value) == 0)); - case HYPERPREDICATE_LESS_THAN: - return di_attr->datatype() == di_check->datatype() && - di_attr->comparable() && - di_attr->compare(check.value, value) > 0; - case HYPERPREDICATE_LESS_EQUAL: - return di_attr->datatype() == di_check->datatype() && - di_attr->comparable() && - di_attr->compare(check.value, value) >= 0; - case HYPERPREDICATE_GREATER_EQUAL: - return di_attr->datatype() == di_check->datatype() && - di_attr->comparable() && - di_attr->compare(check.value, value) <= 0; - case HYPERPREDICATE_GREATER_THAN: - return di_attr->datatype() == di_check->datatype() && - di_attr->comparable() && - di_attr->compare(check.value, value) < 0; - case HYPERPREDICATE_REGEX: - return di_check->datatype() == HYPERDATATYPE_STRING && - di_attr->has_regex() && - di_attr->regex(check.value, value); - case HYPERPREDICATE_LENGTH_EQUALS: - memset(buf_i, 0, sizeof(int64_t)); - memmove(buf_i, check.value.data(), std::min(check.value.size(), sizeof(int64_t))); - e::unpack64le(buf_i, &tmp_i); - return di_check->datatype() == HYPERDATATYPE_INT64 && - di_attr->has_length() && - static_cast(di_attr->length(value)) == tmp_i; - case HYPERPREDICATE_CONTAINS_LESS_THAN: - case HYPERPREDICATE_LENGTH_LESS_EQUAL: - memset(buf_i, 0, sizeof(int64_t)); - memmove(buf_i, check.value.data(), std::min(check.value.size(), sizeof(int64_t))); - e::unpack64le(buf_i, &tmp_i); - return di_check->datatype() == HYPERDATATYPE_INT64 && - di_attr->has_length() && - static_cast(di_attr->length(value)) <= tmp_i; - case HYPERPREDICATE_LENGTH_GREATER_EQUAL: - memset(buf_i, 0, sizeof(int64_t)); - memmove(buf_i, check.value.data(), std::min(check.value.size(), sizeof(int64_t))); - e::unpack64le(buf_i, &tmp_i); - return di_check->datatype() == HYPERDATATYPE_INT64 && - di_attr->has_length() && - static_cast(di_attr->length(value)) >= tmp_i; - case HYPERPREDICATE_CONTAINS: - return di_attr->has_contains() && - di_attr->contains_datatype() == di_check->datatype() && - di_attr->contains(value, check.value); - default: - return false; - } + datatype_info *di_attr = datatype_info::lookup(type); + datatype_info *di_check = datatype_info::lookup(check.datatype); + if (!di_attr || !di_check) + { + return false; + } + if (di_attr->document()) + { + return di_attr->document_check(check, value); + } + if (!di_attr->validate(value) || + !di_check->validate(check.value)) + { + return false; + } + char buf_i[sizeof(int64_t)]; + int64_t tmp_i; + switch (check.predicate) + { + case HYPERPREDICATE_FAIL: + return false; + case HYPERPREDICATE_EQUALS: + return di_attr->datatype() == di_check->datatype() && + (check.value == value || + (di_attr->comparable() && di_attr->compare(check.value, value) == 0)); + case HYPERPREDICATE_LESS_THAN: + return di_attr->datatype() == di_check->datatype() && + di_attr->comparable() && + di_attr->compare(check.value, value) > 0; + case HYPERPREDICATE_LESS_EQUAL: + return di_attr->datatype() == di_check->datatype() && + di_attr->comparable() && + di_attr->compare(check.value, value) >= 0; + case HYPERPREDICATE_GREATER_EQUAL: + return di_attr->datatype() == di_check->datatype() && + di_attr->comparable() && + di_attr->compare(check.value, value) <= 0; + case HYPERPREDICATE_GREATER_THAN: + return di_attr->datatype() == di_check->datatype() && + di_attr->comparable() && + di_attr->compare(check.value, value) < 0; + case HYPERPREDICATE_REGEX: + return di_check->datatype() == HYPERDATATYPE_STRING && + di_attr->has_regex() && + di_attr->regex(check.value, value); + case HYPERPREDICATE_LENGTH_EQUALS: + memset(buf_i, 0, sizeof(int64_t)); + memmove(buf_i, check.value.data(), std::min(check.value.size(), sizeof(int64_t))); + e::unpack64le(buf_i, &tmp_i); + return di_check->datatype() == HYPERDATATYPE_INT64 && + di_attr->has_length() && + static_cast(di_attr->length(value)) == tmp_i; + case HYPERPREDICATE_CONTAINS_LESS_THAN: + case HYPERPREDICATE_LENGTH_LESS_EQUAL: + memset(buf_i, 0, sizeof(int64_t)); + memmove(buf_i, check.value.data(), std::min(check.value.size(), sizeof(int64_t))); + e::unpack64le(buf_i, &tmp_i); + return di_check->datatype() == HYPERDATATYPE_INT64 && + di_attr->has_length() && + static_cast(di_attr->length(value)) <= tmp_i; + case HYPERPREDICATE_LENGTH_GREATER_EQUAL: + memset(buf_i, 0, sizeof(int64_t)); + memmove(buf_i, check.value.data(), std::min(check.value.size(), sizeof(int64_t))); + e::unpack64le(buf_i, &tmp_i); + return di_check->datatype() == HYPERDATATYPE_INT64 && + di_attr->has_length() && + static_cast(di_attr->length(value)) >= tmp_i; + case HYPERPREDICATE_CONTAINS: + return di_attr->has_contains() && + di_attr->contains_datatype() == di_check->datatype() && + di_attr->contains(value, check.value); + default: + return false; + } } size_t -hyperdex :: passes_attribute_checks(const schema& sc, - const std::vector& checks, - const e::slice& key, - const std::vector& value) +hyperdex :: passes_attribute_checks(const schema &sc, + const std::vector &checks, + const e::slice &key, + const std::vector &value) { - for (size_t i = 0; i < checks.size(); ++i) - { - if (checks[i].attr >= sc.attrs_sz) - { - return i; - } - - hyperdatatype type = sc.attrs[checks[i].attr].type; - - if (checks[i].attr > 0 && - !passes_attribute_check(type, checks[i], value[checks[i].attr - 1])) - { - return i; - } - else if (checks[i].attr == 0 && - !passes_attribute_check(type, checks[i], key)) - { - return i; - } - } - - return checks.size(); + for (size_t i = 0; i < checks.size(); ++i) + { + if (checks[i].attr >= sc.attrs_sz) + { + return i; + } + hyperdatatype type = sc.attrs[checks[i].attr].type; + if (checks[i].attr > 0 && + !passes_attribute_check(type, checks[i], value[checks[i].attr - 1])) + { + return i; + } + else if (checks[i].attr == 0 && + !passes_attribute_check(type, checks[i], key)) + { + return i; + } + } + return checks.size(); } bool -hyperdex :: operator < (const attribute_check& lhs, const attribute_check& rhs) +hyperdex :: operator < (const attribute_check &lhs, const attribute_check &rhs) { - return lhs.attr < rhs.attr; + return lhs.attr < rhs.attr; } e::packer -hyperdex :: operator << (e::packer lhs, const attribute_check& rhs) +hyperdex :: operator << (e::packer lhs, const attribute_check &rhs) { - return lhs << rhs.attr - << rhs.value - << rhs.datatype - << rhs.predicate; + return lhs << rhs.attr + << rhs.value + << rhs.datatype + << rhs.predicate; } e::unpacker -hyperdex :: operator >> (e::unpacker lhs, attribute_check& rhs) +hyperdex :: operator >> (e::unpacker lhs, attribute_check &rhs) { - return lhs >> rhs.attr - >> rhs.value - >> rhs.datatype - >> rhs.predicate; + return lhs >> rhs.attr + >> rhs.value + >> rhs.datatype + >> rhs.predicate; } size_t -hyperdex :: pack_size(const attribute_check& rhs) +hyperdex :: pack_size(const attribute_check &rhs) { - return sizeof(uint16_t) - + sizeof(uint32_t) - + rhs.value.size() - + pack_size(rhs.datatype) - + pack_size(rhs.predicate); + return sizeof(uint16_t) + + sizeof(uint32_t) + + rhs.value.size() + + pack_size(rhs.datatype) + + pack_size(rhs.predicate); } diff --git a/common/attribute_check.h b/common/attribute_check.h index 7c231d312..0005928c4 100644 --- a/common/attribute_check.h +++ b/common/attribute_check.h @@ -41,47 +41,47 @@ BEGIN_HYPERDEX_NAMESPACE class attribute_check { - public: - attribute_check(); - ~attribute_check() throw (); +public: + attribute_check(); + ~attribute_check() throw (); - public: - uint16_t attr; - e::slice value; - hyperdatatype datatype; - hyperpredicate predicate; +public: + uint16_t attr; + e::slice value; + hyperdatatype datatype; + hyperpredicate predicate; }; bool validate_attribute_check(hyperdatatype type, - const attribute_check& check); + const attribute_check &check); size_t -validate_attribute_checks(const schema& sc, - const std::vector& checks); +validate_attribute_checks(const schema &sc, + const std::vector &checks); bool passes_attribute_check(hyperdatatype type, - const attribute_check& chk, - const e::slice& value); + const attribute_check &chk, + const e::slice &value); // Does several calls of passes_attribute_check at once // Returns point of failure in the vector or checks.size() on success size_t -passes_attribute_checks(const schema& sc, - const std::vector& checks, - const e::slice& key, - const std::vector& values); +passes_attribute_checks(const schema &sc, + const std::vector &checks, + const e::slice &key, + const std::vector &values); bool -operator < (const attribute_check& lhs, - const attribute_check& rhs); +operator < (const attribute_check &lhs, + const attribute_check &rhs); e::packer -operator << (e::packer lhs, const attribute_check& rhs); +operator << (e::packer lhs, const attribute_check &rhs); e::unpacker -operator >> (e::unpacker lhs, attribute_check& rhs); +operator >> (e::unpacker lhs, attribute_check &rhs); size_t -pack_size(const attribute_check& rhs); +pack_size(const attribute_check &rhs); END_HYPERDEX_NAMESPACE diff --git a/common/auth_wallet.cc b/common/auth_wallet.cc index 3b20a18c1..8de5a235d 100644 --- a/common/auth_wallet.cc +++ b/common/auth_wallet.cc @@ -35,85 +35,78 @@ using hyperdex::auth_wallet; auth_wallet :: auth_wallet() - : m_macaroons() + : m_macaroons() { } -auth_wallet :: auth_wallet(const char** macaroons, size_t macaroons_sz) - : m_macaroons() +auth_wallet :: auth_wallet(const char **macaroons, size_t macaroons_sz) + : m_macaroons() { - m_macaroons.reserve(macaroons_sz); - - for (size_t i = 0; i < macaroons_sz; ++i) - { - m_macaroons.push_back(std::string(macaroons[i], strlen(macaroons[i]))); - } + m_macaroons.reserve(macaroons_sz); + for (size_t i = 0; i < macaroons_sz; ++i) + { + m_macaroons.push_back(std::string(macaroons[i], strlen(macaroons[i]))); + } } -auth_wallet :: auth_wallet(const auth_wallet& other) - : m_macaroons(other.m_macaroons) +auth_wallet :: auth_wallet(const auth_wallet &other) + : m_macaroons(other.m_macaroons) { } bool -auth_wallet :: get_macaroons(std::vector* macaroons) +auth_wallet :: get_macaroons(std::vector *macaroons) { - for (size_t i = 0; i < m_macaroons.size(); ++i) - { - macaroon_returncode err; - macaroon* M = macaroon_deserialize(m_macaroons[i].c_str(), &err); - - if (!M) - { - return false; - } - - macaroons->push_back(M); - } - - return true; + for (size_t i = 0; i < m_macaroons.size(); ++i) + { + macaroon_returncode err; + macaroon *M = macaroon_deserialize(m_macaroons[i].c_str(), &err); + if (!M) + { + return false; + } + macaroons->push_back(M); + } + return true; } static void -build_macaroons(const std::vector& in, - std::vector* out) +build_macaroons(const std::vector &in, + std::vector *out) { - out->clear(); - out->reserve(in.size()); - - for (size_t i = 0; i < in.size(); ++i) - { - out->push_back(e::slice(in[i])); - } + out->clear(); + out->reserve(in.size()); + for (size_t i = 0; i < in.size(); ++i) + { + out->push_back(e::slice(in[i])); + } } e::packer -hyperdex :: operator << (e::packer lhs, const auth_wallet& rhs) +hyperdex :: operator << (e::packer lhs, const auth_wallet &rhs) { - std::vector macaroons; - build_macaroons(rhs.m_macaroons, &macaroons); - return lhs << macaroons; + std::vector macaroons; + build_macaroons(rhs.m_macaroons, &macaroons); + return lhs << macaroons; } e::unpacker -hyperdex :: operator >> (e::unpacker lhs, auth_wallet& rhs) +hyperdex :: operator >> (e::unpacker lhs, auth_wallet &rhs) { - std::vector macaroons; - lhs = lhs >> macaroons; - rhs.m_macaroons.resize(macaroons.size()); - - for (size_t i = 0; i < macaroons.size(); ++i) - { - rhs.m_macaroons[i].assign(macaroons[i].cdata(), macaroons[i].size()); - } - - return lhs; + std::vector macaroons; + lhs = lhs >> macaroons; + rhs.m_macaroons.resize(macaroons.size()); + for (size_t i = 0; i < macaroons.size(); ++i) + { + rhs.m_macaroons[i].assign(macaroons[i].cdata(), macaroons[i].size()); + } + return lhs; } size_t -hyperdex :: pack_size(const auth_wallet& aw) +hyperdex :: pack_size(const auth_wallet &aw) { - std::vector macaroons; - build_macaroons(aw.m_macaroons, &macaroons); - return pack_size(macaroons); + std::vector macaroons; + build_macaroons(aw.m_macaroons, &macaroons); + return pack_size(macaroons); } diff --git a/common/auth_wallet.h b/common/auth_wallet.h index 3621c695e..316dd1058 100644 --- a/common/auth_wallet.h +++ b/common/auth_wallet.h @@ -42,34 +42,34 @@ BEGIN_HYPERDEX_NAMESPACE class auth_wallet { - public: - auth_wallet(); - auth_wallet(const char** macaroons, size_t macaroons_sz); - auth_wallet(const auth_wallet&); +public: + auth_wallet(); + auth_wallet(const char **macaroons, size_t macaroons_sz); + auth_wallet(const auth_wallet &); - public: - bool get_macaroons(std::vector* macaroons); +public: + bool get_macaroons(std::vector *macaroons); - private: - friend e::packer operator << (e::packer lhs, const auth_wallet& rhs); - friend e::unpacker operator >> (e::unpacker lhs, auth_wallet& rhs); - friend size_t pack_size(const auth_wallet& aw); +private: + friend e::packer operator << (e::packer lhs, const auth_wallet &rhs); + friend e::unpacker operator >> (e::unpacker lhs, auth_wallet &rhs); + friend size_t pack_size(const auth_wallet &aw); - friend std::ostream& operator << (std::ostream& lhs, const auth_wallet& rhs); // XXX + friend std::ostream &operator << (std::ostream &lhs, const auth_wallet &rhs); // XXX - private: - auth_wallet& operator = (const auth_wallet&); +private: + auth_wallet &operator = (const auth_wallet &); - private: - std::vector m_macaroons; +private: + std::vector m_macaroons; }; e::packer -operator << (e::packer lhs, const auth_wallet& rhs); +operator << (e::packer lhs, const auth_wallet &rhs); e::unpacker -operator >> (e::unpacker lhs, auth_wallet& rhs); +operator >> (e::unpacker lhs, auth_wallet &rhs); size_t -pack_size(const auth_wallet& aw); +pack_size(const auth_wallet &aw); END_HYPERDEX_NAMESPACE diff --git a/common/configuration.cc b/common/configuration.cc index 0120ff8f5..09f166704 100644 --- a/common/configuration.cc +++ b/common/configuration.cc @@ -50,47 +50,47 @@ using hyperdex::subspace_id; using hyperdex::virtual_server_id; configuration :: configuration() - : m_cluster(0) - , m_version(0) - , m_flags(0) - , m_servers() - , m_region_ids_by_virtual() - , m_server_ids_by_virtual() - , m_schemas_by_region() - , m_subspaces_by_region() - , m_subspace_ids_by_region() - , m_subspace_ids_for_prev() - , m_subspace_ids_for_next() - , m_heads_by_region() - , m_tails_by_region() - , m_next_by_virtual() - , m_point_leaders_by_virtual() - , m_spaces() - , m_transfers() + : m_cluster(0) + , m_version(0) + , m_flags(0) + , m_servers() + , m_region_ids_by_virtual() + , m_server_ids_by_virtual() + , m_schemas_by_region() + , m_subspaces_by_region() + , m_subspace_ids_by_region() + , m_subspace_ids_for_prev() + , m_subspace_ids_for_next() + , m_heads_by_region() + , m_tails_by_region() + , m_next_by_virtual() + , m_point_leaders_by_virtual() + , m_spaces() + , m_transfers() { - refill_cache(); + refill_cache(); } -configuration :: configuration(const configuration& other) - : m_cluster(other.m_cluster) - , m_version(other.m_version) - , m_flags(other.m_flags) - , m_servers(other.m_servers) - , m_region_ids_by_virtual(other.m_region_ids_by_virtual) - , m_server_ids_by_virtual(other.m_server_ids_by_virtual) - , m_schemas_by_region(other.m_schemas_by_region) - , m_subspaces_by_region(other.m_subspaces_by_region) - , m_subspace_ids_by_region(other.m_subspace_ids_by_region) - , m_subspace_ids_for_prev(other.m_subspace_ids_for_prev) - , m_subspace_ids_for_next(other.m_subspace_ids_for_next) - , m_heads_by_region(other.m_heads_by_region) - , m_tails_by_region(other.m_tails_by_region) - , m_next_by_virtual(other.m_next_by_virtual) - , m_point_leaders_by_virtual(other.m_point_leaders_by_virtual) - , m_spaces(other.m_spaces) - , m_transfers(other.m_transfers) +configuration :: configuration(const configuration &other) + : m_cluster(other.m_cluster) + , m_version(other.m_version) + , m_flags(other.m_flags) + , m_servers(other.m_servers) + , m_region_ids_by_virtual(other.m_region_ids_by_virtual) + , m_server_ids_by_virtual(other.m_server_ids_by_virtual) + , m_schemas_by_region(other.m_schemas_by_region) + , m_subspaces_by_region(other.m_subspaces_by_region) + , m_subspace_ids_by_region(other.m_subspace_ids_by_region) + , m_subspace_ids_for_prev(other.m_subspace_ids_for_prev) + , m_subspace_ids_for_next(other.m_subspace_ids_for_next) + , m_heads_by_region(other.m_heads_by_region) + , m_tails_by_region(other.m_tails_by_region) + , m_next_by_virtual(other.m_next_by_virtual) + , m_point_leaders_by_virtual(other.m_point_leaders_by_virtual) + , m_spaces(other.m_spaces) + , m_transfers(other.m_transfers) { - refill_cache(); + refill_cache(); } configuration :: ~configuration() throw () @@ -100,1122 +100,987 @@ configuration :: ~configuration() throw () uint64_t configuration :: cluster() const { - return m_cluster; + return m_cluster; } uint64_t configuration :: version() const { - return m_version; + return m_version; } bool configuration :: read_only() const { - return m_flags & HYPERDEX_CONFIG_READ_ONLY; + return m_flags & HYPERDEX_CONFIG_READ_ONLY; } void -configuration :: get_all_addresses(std::vector >* addrs) const +configuration :: get_all_addresses(std::vector > *addrs) const { - addrs->resize(m_servers.size()); - - for (size_t i = 0; i < m_servers.size(); ++i) - { - (*addrs)[i].first = m_servers[i].id; - (*addrs)[i].second = m_servers[i].bind_to; - } + addrs->resize(m_servers.size()); + for (size_t i = 0; i < m_servers.size(); ++i) + { + (*addrs)[i].first = m_servers[i].id; + (*addrs)[i].second = m_servers[i].bind_to; + } } bool -configuration :: exists(const server_id& id) const +configuration :: exists(const server_id &id) const { - for (size_t i = 0; i < m_servers.size(); ++i) - { - if (m_servers[i].id == id) - { - return true; - } - } - - return false; + for (size_t i = 0; i < m_servers.size(); ++i) + { + if (m_servers[i].id == id) + { + return true; + } + } + return false; } po6::net::location -configuration :: get_address(const server_id& id) const +configuration :: get_address(const server_id &id) const { - for (size_t i = 0; i < m_servers.size(); ++i) - { - if (m_servers[i].id == id) - { - return m_servers[i].bind_to; - } - } - - return po6::net::location(); + for (size_t i = 0; i < m_servers.size(); ++i) + { + if (m_servers[i].id == id) + { + return m_servers[i].bind_to; + } + } + return po6::net::location(); } server::state_t -configuration :: get_state(const server_id& id) const +configuration :: get_state(const server_id &id) const { - for (size_t i = 0; i < m_servers.size(); ++i) - { - if (m_servers[i].id == id) - { - return m_servers[i].state; - } - } - - return server::KILLED; + for (size_t i = 0; i < m_servers.size(); ++i) + { + if (m_servers[i].id == id) + { + return m_servers[i].state; + } + } + return server::KILLED; } region_id -configuration :: get_region_id(const virtual_server_id& id) const +configuration :: get_region_id(const virtual_server_id &id) const { - std::vector::const_iterator it; - it = std::lower_bound(m_region_ids_by_virtual.begin(), - m_region_ids_by_virtual.end(), - pair_uint64_t(id.get(), 0)); - - if (it != m_region_ids_by_virtual.end() && it->first == id.get()) - { - return region_id(it->second); - } - - return region_id(); + std::vector::const_iterator it; + it = std::lower_bound(m_region_ids_by_virtual.begin(), + m_region_ids_by_virtual.end(), + pair_uint64_t(id.get(), 0)); + if (it != m_region_ids_by_virtual.end() && it->first == id.get()) + { + return region_id(it->second); + } + return region_id(); } server_id -configuration :: get_server_id(const virtual_server_id& id) const +configuration :: get_server_id(const virtual_server_id &id) const { - std::vector::const_iterator it; - it = std::lower_bound(m_server_ids_by_virtual.begin(), - m_server_ids_by_virtual.end(), - pair_uint64_t(id.get(), 0)); - - if (it != m_server_ids_by_virtual.end() && it->first == id.get()) - { - return server_id(it->second); - } - - return server_id(); + std::vector::const_iterator it; + it = std::lower_bound(m_server_ids_by_virtual.begin(), + m_server_ids_by_virtual.end(), + pair_uint64_t(id.get(), 0)); + if (it != m_server_ids_by_virtual.end() && it->first == id.get()) + { + return server_id(it->second); + } + return server_id(); } -const schema* -configuration :: get_schema(const char* sname) const +const schema * +configuration :: get_schema(const char *sname) const { - for (size_t s = 0; s < m_spaces.size(); ++s) - { - if (strcmp(sname, m_spaces[s].name) == 0) - { - return &m_spaces[s].sc; - } - } - - return NULL; + for (size_t s = 0; s < m_spaces.size(); ++s) + { + if (strcmp(sname, m_spaces[s].name) == 0) + { + return &m_spaces[s].sc; + } + } + return NULL; } -const schema* -configuration :: get_schema(const region_id& ri) const +const schema * +configuration :: get_schema(const region_id &ri) const { - std::vector::const_iterator it; - it = std::lower_bound(m_schemas_by_region.begin(), - m_schemas_by_region.end(), - uint64_schema_t(ri.get(), NULL)); - - if (it != m_schemas_by_region.end() && it->first == ri.get()) - { - return it->second; - } - - return NULL; + std::vector::const_iterator it; + it = std::lower_bound(m_schemas_by_region.begin(), + m_schemas_by_region.end(), + uint64_schema_t(ri.get(), NULL)); + if (it != m_schemas_by_region.end() && it->first == ri.get()) + { + return it->second; + } + return NULL; } -const subspace* -configuration :: get_subspace(const region_id& ri) const +const subspace * +configuration :: get_subspace(const region_id &ri) const { - std::vector::const_iterator it; - it = std::lower_bound(m_subspaces_by_region.begin(), - m_subspaces_by_region.end(), - uint64_subspace_t(ri.get(), NULL)); - - if (it != m_subspaces_by_region.end() && it->first == ri.get()) - { - return it->second; - } - - return NULL; + std::vector::const_iterator it; + it = std::lower_bound(m_subspaces_by_region.begin(), + m_subspaces_by_region.end(), + uint64_subspace_t(ri.get(), NULL)); + if (it != m_subspaces_by_region.end() && it->first == ri.get()) + { + return it->second; + } + return NULL; } virtual_server_id -configuration :: get_virtual(const region_id& ri, const server_id& si) const +configuration :: get_virtual(const region_id &ri, const server_id &si) const { - for (size_t w = 0; w < m_spaces.size(); ++w) - { - const space& s(m_spaces[w]); - - for (size_t x = 0; x < s.subspaces.size(); ++x) - { - const subspace& ss(s.subspaces[x]); - - for (size_t y = 0; y < ss.regions.size(); ++y) - { - const region& r(ss.regions[y]); - - if (r.id != ri) - { - continue; - } - - for (size_t z = 0; z < r.replicas.size(); ++z) - { - if (r.replicas[z].si == si) - { - return r.replicas[z].vsi; - } - } - - return virtual_server_id(); - } - } - } - - return virtual_server_id(); + for (size_t w = 0; w < m_spaces.size(); ++w) + { + const space &s(m_spaces[w]); + for (size_t x = 0; x < s.subspaces.size(); ++x) + { + const subspace &ss(s.subspaces[x]); + for (size_t y = 0; y < ss.regions.size(); ++y) + { + const region &r(ss.regions[y]); + if (r.id != ri) + { + continue; + } + for (size_t z = 0; z < r.replicas.size(); ++z) + { + if (r.replicas[z].si == si) + { + return r.replicas[z].vsi; + } + } + return virtual_server_id(); + } + } + } + return virtual_server_id(); } subspace_id -configuration :: subspace_of(const region_id& ri) const +configuration :: subspace_of(const region_id &ri) const { - std::vector::const_iterator it; - it = std::lower_bound(m_subspace_ids_by_region.begin(), - m_subspace_ids_by_region.end(), - pair_uint64_t(ri.get(), 0)); - - if (it != m_subspace_ids_by_region.end() && it->first == ri.get()) - { - return subspace_id(it->second); - } - - return subspace_id(); + std::vector::const_iterator it; + it = std::lower_bound(m_subspace_ids_by_region.begin(), + m_subspace_ids_by_region.end(), + pair_uint64_t(ri.get(), 0)); + if (it != m_subspace_ids_by_region.end() && it->first == ri.get()) + { + return subspace_id(it->second); + } + return subspace_id(); } subspace_id -configuration :: subspace_prev(const subspace_id& ss) const +configuration :: subspace_prev(const subspace_id &ss) const { - std::vector::const_iterator it; - it = std::lower_bound(m_subspace_ids_for_prev.begin(), - m_subspace_ids_for_prev.end(), - pair_uint64_t(ss.get(), 0)); - - if (it != m_subspace_ids_for_prev.end() && it->first == ss.get()) - { - return subspace_id(it->second); - } - - return subspace_id(); + std::vector::const_iterator it; + it = std::lower_bound(m_subspace_ids_for_prev.begin(), + m_subspace_ids_for_prev.end(), + pair_uint64_t(ss.get(), 0)); + if (it != m_subspace_ids_for_prev.end() && it->first == ss.get()) + { + return subspace_id(it->second); + } + return subspace_id(); } subspace_id -configuration :: subspace_next(const subspace_id& ss) const +configuration :: subspace_next(const subspace_id &ss) const { - std::vector::const_iterator it; - it = std::lower_bound(m_subspace_ids_for_next.begin(), - m_subspace_ids_for_next.end(), - pair_uint64_t(ss.get(), 0)); - - if (it != m_subspace_ids_for_next.end() && it->first == ss.get()) - { - return subspace_id(it->second); - } - - return subspace_id(); + std::vector::const_iterator it; + it = std::lower_bound(m_subspace_ids_for_next.begin(), + m_subspace_ids_for_next.end(), + pair_uint64_t(ss.get(), 0)); + if (it != m_subspace_ids_for_next.end() && it->first == ss.get()) + { + return subspace_id(it->second); + } + return subspace_id(); } virtual_server_id -configuration :: head_of_region(const region_id& ri) const +configuration :: head_of_region(const region_id &ri) const { - std::vector::const_iterator it; - it = std::lower_bound(m_heads_by_region.begin(), - m_heads_by_region.end(), - pair_uint64_t(ri.get(), 0)); - - if (it != m_heads_by_region.end() && it->first == ri.get()) - { - return virtual_server_id(it->second); - } - - return virtual_server_id(); + std::vector::const_iterator it; + it = std::lower_bound(m_heads_by_region.begin(), + m_heads_by_region.end(), + pair_uint64_t(ri.get(), 0)); + if (it != m_heads_by_region.end() && it->first == ri.get()) + { + return virtual_server_id(it->second); + } + return virtual_server_id(); } virtual_server_id -configuration :: tail_of_region(const region_id& ri) const +configuration :: tail_of_region(const region_id &ri) const { - std::vector::const_iterator it; - it = std::lower_bound(m_tails_by_region.begin(), - m_tails_by_region.end(), - pair_uint64_t(ri.get(), 0)); - - if (it != m_tails_by_region.end() && it->first == ri.get()) - { - return virtual_server_id(it->second); - } - - return virtual_server_id(); + std::vector::const_iterator it; + it = std::lower_bound(m_tails_by_region.begin(), + m_tails_by_region.end(), + pair_uint64_t(ri.get(), 0)); + if (it != m_tails_by_region.end() && it->first == ri.get()) + { + return virtual_server_id(it->second); + } + return virtual_server_id(); } virtual_server_id -configuration :: next_in_region(const virtual_server_id& vsi) const +configuration :: next_in_region(const virtual_server_id &vsi) const { - std::vector::const_iterator it; - it = std::lower_bound(m_next_by_virtual.begin(), - m_next_by_virtual.end(), - pair_uint64_t(vsi.get(), 0)); - - if (it != m_next_by_virtual.end() && it->first == vsi.get()) - { - return virtual_server_id(it->second); - } - - return virtual_server_id(); + std::vector::const_iterator it; + it = std::lower_bound(m_next_by_virtual.begin(), + m_next_by_virtual.end(), + pair_uint64_t(vsi.get(), 0)); + if (it != m_next_by_virtual.end() && it->first == vsi.get()) + { + return virtual_server_id(it->second); + } + return virtual_server_id(); } void -configuration :: point_leaders(const server_id& si, std::vector* servers) const +configuration :: point_leaders(const server_id &si, std::vector *servers) const { - for (size_t s = 0; s < m_spaces.size(); ++s) - { - for (size_t r = 0; r < m_spaces[s].subspaces[0].regions.size(); ++r) - { - if (!m_spaces[s].subspaces[0].regions[r].replicas.empty() && - m_spaces[s].subspaces[0].regions[r].replicas[0].si == si) - { - servers->push_back(m_spaces[s].subspaces[0].regions[r].id); - } - } - } + for (size_t s = 0; s < m_spaces.size(); ++s) + { + for (size_t r = 0; r < m_spaces[s].subspaces[0].regions.size(); ++r) + { + if (!m_spaces[s].subspaces[0].regions[r].replicas.empty() && + m_spaces[s].subspaces[0].regions[r].replicas[0].si == si) + { + servers->push_back(m_spaces[s].subspaces[0].regions[r].id); + } + } + } } void -configuration :: key_regions(const server_id& si, std::vector* regions) const +configuration :: key_regions(const server_id &si, std::vector *regions) const { - for (size_t s = 0; s < m_spaces.size(); ++s) - { - for (size_t r = 0; r < m_spaces[s].subspaces[0].regions.size(); ++r) - { - for (size_t R = 0; R < m_spaces[s].subspaces[0].regions[r].replicas.size(); ++R) - { - if (m_spaces[s].subspaces[0].regions[r].replicas[R].si == si) - { - regions->push_back(m_spaces[s].subspaces[0].regions[r].id); - break; - } - } - } - } - - std::sort(regions->begin(), regions->end()); + for (size_t s = 0; s < m_spaces.size(); ++s) + { + for (size_t r = 0; r < m_spaces[s].subspaces[0].regions.size(); ++r) + { + for (size_t R = 0; R < m_spaces[s].subspaces[0].regions[r].replicas.size(); ++R) + { + if (m_spaces[s].subspaces[0].regions[r].replicas[R].si == si) + { + regions->push_back(m_spaces[s].subspaces[0].regions[r].id); + break; + } + } + } + } + std::sort(regions->begin(), regions->end()); } bool -configuration :: is_point_leader(const virtual_server_id& e) const +configuration :: is_point_leader(const virtual_server_id &e) const { - return std::binary_search(m_point_leaders_by_virtual.begin(), - m_point_leaders_by_virtual.end(), - e.get()); + return std::binary_search(m_point_leaders_by_virtual.begin(), + m_point_leaders_by_virtual.end(), + e.get()); } virtual_server_id -configuration :: point_leader(const char* sname, const e::slice& key) const +configuration :: point_leader(const char *sname, const e::slice &key) const { - for (size_t s = 0; s < m_spaces.size(); ++s) - { - if (strcmp(sname, m_spaces[s].name) != 0) - { - continue; - } - - uint64_t h; - hash(m_spaces[s].sc, key, &h); - - for (size_t pl = 0; pl < m_spaces[s].subspaces[0].regions.size(); ++pl) - { - if (m_spaces[s].subspaces[0].regions[pl].lower_coord[0] <= h && - h <= m_spaces[s].subspaces[0].regions[pl].upper_coord[0]) - { - if (m_spaces[s].subspaces[0].regions[pl].replicas.empty()) - { - return virtual_server_id(); - } - - return m_spaces[s].subspaces[0].regions[pl].replicas[0].vsi; - } - } - - abort(); - } - - return virtual_server_id(); + for (size_t s = 0; s < m_spaces.size(); ++s) + { + if (strcmp(sname, m_spaces[s].name) != 0) + { + continue; + } + uint64_t h; + hash(m_spaces[s].sc, key, &h); + for (size_t pl = 0; pl < m_spaces[s].subspaces[0].regions.size(); ++pl) + { + if (m_spaces[s].subspaces[0].regions[pl].lower_coord[0] <= h && + h <= m_spaces[s].subspaces[0].regions[pl].upper_coord[0]) + { + if (m_spaces[s].subspaces[0].regions[pl].replicas.empty()) + { + return virtual_server_id(); + } + return m_spaces[s].subspaces[0].regions[pl].replicas[0].vsi; + } + } + abort(); + } + return virtual_server_id(); } virtual_server_id -configuration :: point_leader(const region_id& rid, const e::slice& key) const +configuration :: point_leader(const region_id &rid, const e::slice &key) const { - for (size_t s = 0; s < m_spaces.size(); ++s) - { - for (size_t ss = 0; ss < m_spaces[s].subspaces.size(); ++ss) - { - for (size_t r = 0; r < m_spaces[s].subspaces[ss].regions.size(); ++r) - { - if (m_spaces[s].subspaces[ss].regions[r].id != rid) - { - continue; - } - - uint64_t h; - hash(m_spaces[s].sc, key, &h); - - for (size_t pl = 0; pl < m_spaces[s].subspaces[0].regions.size(); ++pl) - { - if (m_spaces[s].subspaces[0].regions[pl].lower_coord[0] <= h && - h <= m_spaces[s].subspaces[0].regions[pl].upper_coord[0]) - { - if (m_spaces[s].subspaces[0].regions[pl].replicas.empty()) - { - return virtual_server_id(); - } - - return m_spaces[s].subspaces[0].regions[pl].replicas[0].vsi; - } - } - - abort(); - } - } - } - - return virtual_server_id(); + for (size_t s = 0; s < m_spaces.size(); ++s) + { + for (size_t ss = 0; ss < m_spaces[s].subspaces.size(); ++ss) + { + for (size_t r = 0; r < m_spaces[s].subspaces[ss].regions.size(); ++r) + { + if (m_spaces[s].subspaces[ss].regions[r].id != rid) + { + continue; + } + uint64_t h; + hash(m_spaces[s].sc, key, &h); + for (size_t pl = 0; pl < m_spaces[s].subspaces[0].regions.size(); ++pl) + { + if (m_spaces[s].subspaces[0].regions[pl].lower_coord[0] <= h && + h <= m_spaces[s].subspaces[0].regions[pl].upper_coord[0]) + { + if (m_spaces[s].subspaces[0].regions[pl].replicas.empty()) + { + return virtual_server_id(); + } + return m_spaces[s].subspaces[0].regions[pl].replicas[0].vsi; + } + } + abort(); + } + } + } + return virtual_server_id(); } bool -configuration :: subspace_adjacent(const virtual_server_id& lhs, const virtual_server_id& rhs) const +configuration :: subspace_adjacent(const virtual_server_id &lhs, const virtual_server_id &rhs) const { - region_id rlhs = get_region_id(lhs); - region_id rrhs = get_region_id(rhs); - subspace_id slhs = subspace_of(rlhs); - subspace_id srhs = subspace_of(rrhs); - return subspace_next(slhs) == srhs && - lhs == tail_of_region(rlhs) && - rhs == head_of_region(rrhs); + region_id rlhs = get_region_id(lhs); + region_id rrhs = get_region_id(rhs); + subspace_id slhs = subspace_of(rlhs); + subspace_id srhs = subspace_of(rrhs); + return subspace_next(slhs) == srhs && + lhs == tail_of_region(rlhs) && + rhs == head_of_region(rrhs); } void -configuration :: mapped_regions(const server_id& si, std::vector* servers) const +configuration :: mapped_regions(const server_id &si, std::vector *servers) const { - for (size_t s = 0; s < m_spaces.size(); ++s) - { - for (size_t ss = 0; ss < m_spaces[s].subspaces.size(); ++ss) - { - for (size_t r = 0; r < m_spaces[s].subspaces[ss].regions.size(); ++r) - { - for (size_t R = 0; R < m_spaces[s].subspaces[ss].regions[r].replicas.size(); ++R) - { - if (m_spaces[s].subspaces[ss].regions[r].replicas[R].si == si) - { - servers->push_back(m_spaces[s].subspaces[ss].regions[r].id); - break; - } - } - } - } - } - - std::sort(servers->begin(), servers->end()); + for (size_t s = 0; s < m_spaces.size(); ++s) + { + for (size_t ss = 0; ss < m_spaces[s].subspaces.size(); ++ss) + { + for (size_t r = 0; r < m_spaces[s].subspaces[ss].regions.size(); ++r) + { + for (size_t R = 0; R < m_spaces[s].subspaces[ss].regions[r].replicas.size(); ++R) + { + if (m_spaces[s].subspaces[ss].regions[r].replicas[R].si == si) + { + servers->push_back(m_spaces[s].subspaces[ss].regions[r].id); + break; + } + } + } + } + } + std::sort(servers->begin(), servers->end()); } -const hyperdex::index* -configuration :: get_index(const index_id& ii) const +const hyperdex::index * +configuration :: get_index(const index_id &ii) const { - for (size_t s = 0; s < m_spaces.size(); ++s) - { - for (size_t i = 0; i < m_spaces[s].indices.size(); ++i) - { - if (m_spaces[s].indices[i].id == ii) - { - return &m_spaces[s].indices[i]; - } - } - } - - return NULL; + for (size_t s = 0; s < m_spaces.size(); ++s) + { + for (size_t i = 0; i < m_spaces[s].indices.size(); ++i) + { + if (m_spaces[s].indices[i].id == ii) + { + return &m_spaces[s].indices[i]; + } + } + } + return NULL; } void -configuration :: all_indices(const server_id& si, std::vector >* indices) const +configuration :: all_indices(const server_id &si, std::vector > *indices) const { - for (size_t s = 0; s < m_spaces.size(); ++s) - { - for (size_t ss = 0; ss < m_spaces[s].subspaces.size(); ++ss) - { - for (size_t r = 0; r < m_spaces[s].subspaces[ss].regions.size(); ++r) - { - bool found = false; - - for (size_t R = 0; !found && R < m_spaces[s].subspaces[ss].regions[r].replicas.size(); ++R) - { - if (m_spaces[s].subspaces[ss].regions[r].replicas[R].si == si) - { - found = true; - break; - } - } - - for (size_t i = 0; !found && i < m_transfers.size(); ++i) - { - if (m_transfers[i].dst == si && - m_transfers[i].rid == m_spaces[s].subspaces[ss].regions[r].id) - { - found = true; - } - } - - if (found) - { - for (size_t i = 0; i < m_spaces[s].indices.size(); ++i) - { - indices->push_back(std::make_pair(m_spaces[s].subspaces[ss].regions[r].id, - m_spaces[s].indices[i].id)); - } - } - } - } - } + for (size_t s = 0; s < m_spaces.size(); ++s) + { + for (size_t ss = 0; ss < m_spaces[s].subspaces.size(); ++ss) + { + for (size_t r = 0; r < m_spaces[s].subspaces[ss].regions.size(); ++r) + { + bool found = false; + for (size_t R = 0; !found && R < m_spaces[s].subspaces[ss].regions[r].replicas.size(); ++R) + { + if (m_spaces[s].subspaces[ss].regions[r].replicas[R].si == si) + { + found = true; + break; + } + } + for (size_t i = 0; !found && i < m_transfers.size(); ++i) + { + if (m_transfers[i].dst == si && + m_transfers[i].rid == m_spaces[s].subspaces[ss].regions[r].id) + { + found = true; + } + } + if (found) + { + for (size_t i = 0; i < m_spaces[s].indices.size(); ++i) + { + indices->push_back(std::make_pair(m_spaces[s].subspaces[ss].regions[r].id, + m_spaces[s].indices[i].id)); + } + } + } + } + } } bool -configuration :: is_server_involved_in_transfer(const server_id& si, const region_id& ri) const +configuration :: is_server_involved_in_transfer(const server_id &si, const region_id &ri) const { - for (size_t i = 0; i < m_transfers.size(); ++i) - { - if (m_transfers[i].rid == ri && - (m_transfers[i].src == si || m_transfers[i].dst == si)) - { - return true; - } - } - - return false; + for (size_t i = 0; i < m_transfers.size(); ++i) + { + if (m_transfers[i].rid == ri && + (m_transfers[i].src == si || m_transfers[i].dst == si)) + { + return true; + } + } + return false; } bool -configuration :: is_server_blocked_by_live_transfer(const server_id& si, const region_id& id) const +configuration :: is_server_blocked_by_live_transfer(const server_id &si, const region_id &id) const { - for (size_t i = 0; i < m_transfers.size(); ++i) - { - if (m_transfers[i].src != si || m_transfers[i].rid != id) - { - continue; - } - - virtual_server_id tail = tail_of_region(m_transfers[i].rid); - - if (tail == m_transfers[i].vdst) - { - return true; - } - - assert(tail == m_transfers[i].vsrc); - } - - return false; + for (size_t i = 0; i < m_transfers.size(); ++i) + { + if (m_transfers[i].src != si || m_transfers[i].rid != id) + { + continue; + } + virtual_server_id tail = tail_of_region(m_transfers[i].rid); + if (tail == m_transfers[i].vdst) + { + return true; + } + assert(tail == m_transfers[i].vsrc); + } + return false; } bool -configuration :: is_transfer_live(const transfer_id& id) const +configuration :: is_transfer_live(const transfer_id &id) const { - for (size_t i = 0; i < m_transfers.size(); ++i) - { - if (m_transfers[i].id != id) - { - continue; - } - - return m_transfers[i].vdst == tail_of_region(m_transfers[i].rid); - } - - return false; + for (size_t i = 0; i < m_transfers.size(); ++i) + { + if (m_transfers[i].id != id) + { + continue; + } + return m_transfers[i].vdst == tail_of_region(m_transfers[i].rid); + } + return false; } void -configuration :: transfers_in(const server_id& si, std::vector* transfers) const +configuration :: transfers_in(const server_id &si, std::vector *transfers) const { - for (size_t i = 0; i < m_transfers.size(); ++i) - { - if (m_transfers[i].dst == si) - { - transfers->push_back(m_transfers[i]); - } - } + for (size_t i = 0; i < m_transfers.size(); ++i) + { + if (m_transfers[i].dst == si) + { + transfers->push_back(m_transfers[i]); + } + } } void -configuration :: transfers_out(const server_id& si, std::vector* transfers) const +configuration :: transfers_out(const server_id &si, std::vector *transfers) const { - for (size_t i = 0; i < m_transfers.size(); ++i) - { - if (m_transfers[i].src == si) - { - transfers->push_back(m_transfers[i]); - } - } + for (size_t i = 0; i < m_transfers.size(); ++i) + { + if (m_transfers[i].src == si) + { + transfers->push_back(m_transfers[i]); + } + } } void -configuration :: transfers_in_regions(const server_id& si, std::vector* transfers) const +configuration :: transfers_in_regions(const server_id &si, std::vector *transfers) const { - for (size_t i = 0; i < m_transfers.size(); ++i) - { - if (m_transfers[i].dst == si) - { - transfers->push_back(m_transfers[i].rid); - } - } - - std::sort(transfers->begin(), transfers->end()); + for (size_t i = 0; i < m_transfers.size(); ++i) + { + if (m_transfers[i].dst == si) + { + transfers->push_back(m_transfers[i].rid); + } + } + std::sort(transfers->begin(), transfers->end()); } void -configuration :: transfers_out_regions(const server_id& si, std::vector* transfers) const +configuration :: transfers_out_regions(const server_id &si, std::vector *transfers) const { - for (size_t i = 0; i < m_transfers.size(); ++i) - { - if (m_transfers[i].src == si) - { - transfers->push_back(m_transfers[i].rid); - } - } + for (size_t i = 0; i < m_transfers.size(); ++i) + { + if (m_transfers[i].src == si) + { + transfers->push_back(m_transfers[i].rid); + } + } } void -configuration :: lookup_region(const subspace_id& ssid, - const std::vector& hashes, - region_id* rid) const +configuration :: lookup_region(const subspace_id &ssid, + const std::vector &hashes, + region_id *rid) const { - for (size_t s = 0; s < m_spaces.size(); ++s) - { - for (size_t ss = 0; ss < m_spaces[s].subspaces.size(); ++ss) - { - if (m_spaces[s].subspaces[ss].id != ssid) - { - continue; - } - - assert(m_spaces[s].sc.attrs_sz == hashes.size()); - - for (size_t r = 0; r < m_spaces[s].subspaces[ss].regions.size(); ++r) - { - bool matches = true; - - for (size_t a = 0; matches && a < m_spaces[s].subspaces[ss].attrs.size(); ++a) - { - assert(a < m_spaces[s].sc.attrs_sz); - matches &= m_spaces[s].subspaces[ss].regions[r].lower_coord[a] <= hashes[m_spaces[s].subspaces[ss].attrs[a]] && - hashes[m_spaces[s].subspaces[ss].attrs[a]] <= m_spaces[s].subspaces[ss].regions[r].upper_coord[a]; - } - - if (matches) - { - *rid = m_spaces[s].subspaces[ss].regions[r].id; - return; - } - } - } - } - - *rid = region_id(); + for (size_t s = 0; s < m_spaces.size(); ++s) + { + for (size_t ss = 0; ss < m_spaces[s].subspaces.size(); ++ss) + { + if (m_spaces[s].subspaces[ss].id != ssid) + { + continue; + } + assert(m_spaces[s].sc.attrs_sz == hashes.size()); + for (size_t r = 0; r < m_spaces[s].subspaces[ss].regions.size(); ++r) + { + bool matches = true; + for (size_t a = 0; matches && a < m_spaces[s].subspaces[ss].attrs.size(); ++a) + { + assert(a < m_spaces[s].sc.attrs_sz); + matches &= m_spaces[s].subspaces[ss].regions[r].lower_coord[a] <= hashes[m_spaces[s].subspaces[ss].attrs[a]] && + hashes[m_spaces[s].subspaces[ss].attrs[a]] <= m_spaces[s].subspaces[ss].regions[r].upper_coord[a]; + } + if (matches) + { + *rid = m_spaces[s].subspaces[ss].regions[r].id; + return; + } + } + } + } + *rid = region_id(); } void -configuration :: lookup_search(const char* space_name, - const std::vector& chks, - std::vector* servers) const +configuration :: lookup_search(const char *space_name, + const std::vector &chks, + std::vector *servers) const { - const space* s = NULL; - - for (size_t i = 0; i < m_spaces.size(); ++i) - { - if (strcmp(space_name, m_spaces[i].name) == 0) - { - s = &m_spaces[i]; - break; - } - } - - if (!s) - { - servers->clear(); - return; - } - - std::vector ranges; - range_searches(s->sc, chks, &ranges); - - for (size_t i = 0; i < ranges.size(); ++i) - { - if (ranges[i].invalid) - { - servers->clear(); - return; - } - } - - bool initialized = false; - std::vector smallest_server_set; - - for (size_t i = 0; i < s->subspaces.size(); ++i) - { - std::vector this_server_set; - - for (size_t j = 0; j < s->subspaces[i].regions.size(); ++j) - { - const region& reg(s->subspaces[i].regions[j]); - - if (reg.replicas.empty()) - { - continue; - } - - bool exclude = false; - - for (size_t k = 0; !exclude && k < ranges.size(); ++k) - { - assert(reg.lower_coord.size() == reg.upper_coord.size()); - uint16_t attr = UINT16_MAX; - - for (size_t l = 0; l < s->subspaces[i].attrs.size(); ++l) - { - if (s->subspaces[i].attrs[l] == ranges[k].attr) - { - attr = l; - break; - } - } - - if (attr == UINT16_MAX) - { - continue; - } - - if (attr >= reg.lower_coord.size() || - reg.lower_coord[attr] > reg.upper_coord[attr]) - { - servers->clear(); - return; - } - - if (ranges[k].type == HYPERDATATYPE_STRING && - ranges[k].has_start && ranges[k].has_end && - ranges[k].start == ranges[k].end) - { - uint64_t h = hash(ranges[k].type, ranges[k].start); - - if (reg.lower_coord[attr] > h || - reg.upper_coord[attr] < h) - { - exclude = true; - } - } - - if (ranges[k].type == HYPERDATATYPE_INT64 || - ranges[k].type == HYPERDATATYPE_FLOAT) - { - if (ranges[k].has_start) - { - uint64_t h = hash(ranges[k].type, ranges[k].start); - - if (reg.upper_coord[attr] < h) - { - exclude = true; - } - } - - if (ranges[k].has_end) - { - uint64_t h = hash(ranges[k].type, ranges[k].end); - - if (reg.lower_coord[attr] > h) - { - exclude = true; - } - } - } - } - - if (!exclude) - { - this_server_set.push_back(reg.replicas.back().vsi); - } - } - - if (!initialized || - (!this_server_set.empty() && - this_server_set.size() <= smallest_server_set.size())) - { - smallest_server_set.swap(this_server_set); - initialized = true; - } - } - - servers->swap(smallest_server_set); + const space *s = NULL; + for (size_t i = 0; i < m_spaces.size(); ++i) + { + if (strcmp(space_name, m_spaces[i].name) == 0) + { + s = &m_spaces[i]; + break; + } + } + if (!s) + { + servers->clear(); + return; + } + std::vector ranges; + range_searches(s->sc, chks, &ranges); + for (size_t i = 0; i < ranges.size(); ++i) + { + if (ranges[i].invalid) + { + servers->clear(); + return; + } + } + bool initialized = false; + std::vector smallest_server_set; + for (size_t i = 0; i < s->subspaces.size(); ++i) + { + std::vector this_server_set; + for (size_t j = 0; j < s->subspaces[i].regions.size(); ++j) + { + const region ®(s->subspaces[i].regions[j]); + if (reg.replicas.empty()) + { + continue; + } + bool exclude = false; + for (size_t k = 0; !exclude && k < ranges.size(); ++k) + { + assert(reg.lower_coord.size() == reg.upper_coord.size()); + uint16_t attr = UINT16_MAX; + for (size_t l = 0; l < s->subspaces[i].attrs.size(); ++l) + { + if (s->subspaces[i].attrs[l] == ranges[k].attr) + { + attr = l; + break; + } + } + if (attr == UINT16_MAX) + { + continue; + } + if (attr >= reg.lower_coord.size() || + reg.lower_coord[attr] > reg.upper_coord[attr]) + { + servers->clear(); + return; + } + if (ranges[k].type == HYPERDATATYPE_STRING && + ranges[k].has_start && ranges[k].has_end && + ranges[k].start == ranges[k].end) + { + uint64_t h = hash(ranges[k].type, ranges[k].start); + if (reg.lower_coord[attr] > h || + reg.upper_coord[attr] < h) + { + exclude = true; + } + } + if (ranges[k].type == HYPERDATATYPE_INT64 || + ranges[k].type == HYPERDATATYPE_FLOAT) + { + if (ranges[k].has_start) + { + uint64_t h = hash(ranges[k].type, ranges[k].start); + if (reg.upper_coord[attr] < h) + { + exclude = true; + } + } + if (ranges[k].has_end) + { + uint64_t h = hash(ranges[k].type, ranges[k].end); + if (reg.lower_coord[attr] > h) + { + exclude = true; + } + } + } + } + if (!exclude) + { + this_server_set.push_back(reg.replicas.back().vsi); + } + } + if (!initialized || + (!this_server_set.empty() && + this_server_set.size() <= smallest_server_set.size())) + { + smallest_server_set.swap(this_server_set); + initialized = true; + } + } + servers->swap(smallest_server_set); } std::string -configuration :: list_indices(const char* space_name) const +configuration :: list_indices(const char *space_name) const { - std::ostringstream out; - ssize_t pos = -1; - - for (size_t w = 0; w < m_spaces.size() && pos == -1; ++w) - { - if(strcmp(m_spaces[w].name, space_name) == 0) - { - pos = w; - } - } - - if(pos < 0) - { - return ""; - } - - const space& s(m_spaces[pos]); - - for(std::vector::const_iterator it = s.indices.begin(); it != s.indices.end(); ++it) - { - out << it->id.get() << ":"; - out << s.get_attribute(it->attr).name; - out << "\n"; - } - - return out.str(); + std::ostringstream out; + ssize_t pos = -1; + for (size_t w = 0; w < m_spaces.size() && pos == -1; ++w) + { + if (strcmp(m_spaces[w].name, space_name) == 0) + { + pos = w; + } + } + if (pos < 0) + { + return ""; + } + const space &s(m_spaces[pos]); + for (std::vector::const_iterator it = s.indices.begin(); it != s.indices.end(); ++it) + { + out << it->id.get() << ":"; + out << s.get_attribute(it->attr).name; + out << "\n"; + } + return out.str(); } std::string -configuration :: list_subspaces(const char* space_name) const +configuration :: list_subspaces(const char *space_name) const { - std::ostringstream out; - ssize_t pos = -1; - - for (size_t w = 0; w < m_spaces.size() && pos == -1; ++w) - { - if(strcmp(m_spaces[w].name, space_name) == 0) - { - pos = w; - } - } - - if(pos < 0) - { - return ""; - } - - const space& s(m_spaces[pos]); - - for(std::vector::const_iterator it = s.subspaces.begin(); it != s.subspaces.end(); ++it) - { - out << it->id.get() << ":"; - - for(std::vector::const_iterator it2 = it->attrs.begin(); it2 != it->attrs.end(); ++it2) - { - if(it2 != it->attrs.begin()) - out << ","; - - out << s.get_attribute(*it2).name; - } - - out << "\n"; - } - - return out.str(); + std::ostringstream out; + ssize_t pos = -1; + for (size_t w = 0; w < m_spaces.size() && pos == -1; ++w) + { + if (strcmp(m_spaces[w].name, space_name) == 0) + { + pos = w; + } + } + if (pos < 0) + { + return ""; + } + const space &s(m_spaces[pos]); + for (std::vector::const_iterator it = s.subspaces.begin(); it != s.subspaces.end(); ++it) + { + out << it->id.get() << ":"; + for (std::vector::const_iterator it2 = it->attrs.begin(); it2 != it->attrs.end(); ++it2) + { + if (it2 != it->attrs.begin()) + out << ","; + out << s.get_attribute(*it2).name; + } + out << "\n"; + } + return out.str(); } std::string configuration :: dump() const { - std::ostringstream out; - out << "cluster " << m_cluster << "\n"; - out << "version " << m_version << "\n"; - out << "flags " << std::hex << m_flags << std::dec << "\n"; - - for (size_t i = 0; i < m_servers.size(); ++i) - { - out << "server " - << m_servers[i].id.get() << " " - << m_servers[i].bind_to << " " - << server::to_string(m_servers[i].state) << "\n"; - } - - for (size_t w = 0; w < m_spaces.size(); ++w) - { - const space& s(m_spaces[w]); - out << "space " << s.id.get() << " " << s.name << "\n"; - out << " fault_tolerance " << s.fault_tolerance << "\n"; - out << " predecessor_width " << s.predecessor_width << "\n"; - out << " schema" << "\n"; - - for (size_t i = 0; i < s.sc.attrs_sz; ++i) - { - out << " attribute " - << s.sc.attrs[i].name << " " - << s.sc.attrs[i].type << "\n"; - } - - if (s.sc.authorization) - { - out << " with authorization\n"; - } - - for (size_t x = 0; x < s.subspaces.size(); ++x) - { - const subspace& ss(s.subspaces[x]); - out << " subspace " << ss.id.get() << "\n"; - out << " attributes"; - - for (size_t i = 0; i < ss.attrs.size(); ++i) - { - out << " " << s.sc.attrs[ss.attrs[i]].name; - } - - out << "\n"; - - for (size_t y = 0; y < ss.regions.size(); ++y) - { - const region& r(ss.regions[y]); - out << " region " << r.id.get() << " lower=("; - - for (size_t i = 0; i < r.lower_coord.size(); ++i) - { - out << r.lower_coord[i] << ","; - } - - out << ") upper=("; - - for (size_t i = 0; i < r.upper_coord.size(); ++i) - { - out << r.upper_coord[i] << ","; - } - - out << ") replicas=["; - bool first = true; - - for (size_t z = 0; z < r.replicas.size(); ++z) - { - const replica& rr(r.replicas[z]); - out << (first ? "" : ", ") << rr.si << "/" << rr.vsi; - first = false; - } - - out << "]" << std::endl; - } - } - - for (size_t x = 0; x < s.indices.size(); ++x) - { - const index& idx(s.indices[x]); - out << " index " << idx.id.get() << " attribute " << idx.attr; - - if (idx.type == index::DOCUMENT) - { - out << " " << idx.extra.str(); - } - - out << "\n"; - } - } - - for (size_t i = 0; i < m_transfers.size(); ++i) - { - out << m_transfers[i] << std::endl; - } - - return out.str(); + std::ostringstream out; + out << "cluster " << m_cluster << "\n"; + out << "version " << m_version << "\n"; + out << "flags " << std::hex << m_flags << std::dec << "\n"; + for (size_t i = 0; i < m_servers.size(); ++i) + { + out << "server " + << m_servers[i].id.get() << " " + << m_servers[i].bind_to << " " + << server::to_string(m_servers[i].state) << "\n"; + } + for (size_t w = 0; w < m_spaces.size(); ++w) + { + const space &s(m_spaces[w]); + out << "space " << s.id.get() << " " << s.name << "\n"; + out << " fault_tolerance " << s.fault_tolerance << "\n"; + out << " predecessor_width " << s.predecessor_width << "\n"; + out << " schema" << "\n"; + for (size_t i = 0; i < s.sc.attrs_sz; ++i) + { + out << " attribute " + << s.sc.attrs[i].name << " " + << s.sc.attrs[i].type << "\n"; + } + if (s.sc.authorization) + { + out << " with authorization\n"; + } + for (size_t x = 0; x < s.subspaces.size(); ++x) + { + const subspace &ss(s.subspaces[x]); + out << " subspace " << ss.id.get() << "\n"; + out << " attributes"; + for (size_t i = 0; i < ss.attrs.size(); ++i) + { + out << " " << s.sc.attrs[ss.attrs[i]].name; + } + out << "\n"; + for (size_t y = 0; y < ss.regions.size(); ++y) + { + const region &r(ss.regions[y]); + out << " region " << r.id.get() << " lower=("; + for (size_t i = 0; i < r.lower_coord.size(); ++i) + { + out << r.lower_coord[i] << ","; + } + out << ") upper=("; + for (size_t i = 0; i < r.upper_coord.size(); ++i) + { + out << r.upper_coord[i] << ","; + } + out << ") replicas=["; + bool first = true; + for (size_t z = 0; z < r.replicas.size(); ++z) + { + const replica &rr(r.replicas[z]); + out << (first ? "" : ", ") << rr.si << "/" << rr.vsi; + first = false; + } + out << "]" << std::endl; + } + } + for (size_t x = 0; x < s.indices.size(); ++x) + { + const index &idx(s.indices[x]); + out << " index " << idx.id.get() << " attribute " << idx.attr; + if (idx.type == index::DOCUMENT) + { + out << " " << idx.extra.str(); + } + out << "\n"; + } + } + for (size_t i = 0; i < m_transfers.size(); ++i) + { + out << m_transfers[i] << std::endl; + } + return out.str(); } std::string configuration :: list_spaces() const { - std::ostringstream out; - - for (size_t i = 0; i < m_spaces.size(); ++i) - { - out << m_spaces[i].name << std::endl; - } - - return out.str(); + std::ostringstream out; + for (size_t i = 0; i < m_spaces.size(); ++i) + { + out << m_spaces[i].name << std::endl; + } + return out.str(); } -configuration& -configuration :: operator = (const configuration& rhs) +configuration & +configuration :: operator = (const configuration &rhs) { - if (this == &rhs) - { - return *this; - } - - m_cluster = rhs.m_cluster; - m_version = rhs.m_version; - m_flags = rhs.m_flags; - m_servers = rhs.m_servers; - m_region_ids_by_virtual = rhs.m_region_ids_by_virtual; - m_server_ids_by_virtual = rhs.m_server_ids_by_virtual; - m_schemas_by_region = rhs.m_schemas_by_region; - m_subspaces_by_region = rhs.m_subspaces_by_region; - m_subspace_ids_by_region = rhs.m_subspace_ids_by_region; - m_subspace_ids_for_prev = rhs.m_subspace_ids_for_prev; - m_subspace_ids_for_next = rhs.m_subspace_ids_for_next; - m_heads_by_region = rhs.m_heads_by_region; - m_tails_by_region = rhs.m_tails_by_region; - m_next_by_virtual = rhs.m_next_by_virtual; - m_point_leaders_by_virtual = rhs.m_point_leaders_by_virtual; - m_spaces = rhs.m_spaces; - m_transfers = rhs.m_transfers; - refill_cache(); - return *this; + if (this == &rhs) + { + return *this; + } + m_cluster = rhs.m_cluster; + m_version = rhs.m_version; + m_flags = rhs.m_flags; + m_servers = rhs.m_servers; + m_region_ids_by_virtual = rhs.m_region_ids_by_virtual; + m_server_ids_by_virtual = rhs.m_server_ids_by_virtual; + m_schemas_by_region = rhs.m_schemas_by_region; + m_subspaces_by_region = rhs.m_subspaces_by_region; + m_subspace_ids_by_region = rhs.m_subspace_ids_by_region; + m_subspace_ids_for_prev = rhs.m_subspace_ids_for_prev; + m_subspace_ids_for_next = rhs.m_subspace_ids_for_next; + m_heads_by_region = rhs.m_heads_by_region; + m_tails_by_region = rhs.m_tails_by_region; + m_next_by_virtual = rhs.m_next_by_virtual; + m_point_leaders_by_virtual = rhs.m_point_leaders_by_virtual; + m_spaces = rhs.m_spaces; + m_transfers = rhs.m_transfers; + refill_cache(); + return *this; } void configuration :: refill_cache() { - m_region_ids_by_virtual.clear(); - m_server_ids_by_virtual.clear(); - m_schemas_by_region.clear(); - m_subspaces_by_region.clear(); - m_subspace_ids_by_region.clear(); - m_subspace_ids_for_prev.clear(); - m_subspace_ids_for_next.clear(); - m_heads_by_region.clear(); - m_tails_by_region.clear(); - m_next_by_virtual.clear(); - m_point_leaders_by_virtual.clear(); - - for (size_t w = 0; w < m_spaces.size(); ++w) - { - space& s(m_spaces[w]); - - for (size_t x = 0; x < s.subspaces.size(); ++x) - { - subspace& ss(s.subspaces[x]); - - if (x > 0) - { - m_subspace_ids_for_prev.push_back(std::make_pair(ss.id.get(), - s.subspaces[x - 1].id.get())); - } - - if (x + 1 < s.subspaces.size()) - { - m_subspace_ids_for_next.push_back(std::make_pair(ss.id.get(), - s.subspaces[x + 1].id.get())); - } - - for (size_t y = 0; y < ss.regions.size(); ++y) - { - region& r(ss.regions[y]); - m_schemas_by_region.push_back(std::make_pair(r.id.get(), &s.sc)); - m_subspaces_by_region.push_back(std::make_pair(r.id.get(), &ss)); - m_subspace_ids_by_region.push_back(std::make_pair(r.id.get(), ss.id.get())); - - if (r.replicas.empty()) - { - continue; - } - - if (x == 0) - { - m_point_leaders_by_virtual.push_back(r.replicas[0].vsi.get()); - } - - m_heads_by_region.push_back(std::make_pair(r.id.get(), - r.replicas[0].vsi.get())); - m_tails_by_region.push_back(std::make_pair(r.id.get(), - r.replicas[r.replicas.size() - 1].vsi.get())); - - for (size_t z = 0; z < r.replicas.size(); ++z) - { - m_region_ids_by_virtual.push_back(std::make_pair(r.replicas[z].vsi.get(), - r.id.get())); - m_server_ids_by_virtual.push_back(std::make_pair(r.replicas[z].vsi.get(), - r.replicas[z].si.get())); - - if (z + 1 < r.replicas.size()) - { - m_next_by_virtual.push_back(std::make_pair(r.replicas[z].vsi.get(), - r.replicas[z + 1].vsi.get())); - } - } - } - } - } - - for (size_t i = 0; i < m_transfers.size(); ++i) - { - transfer& xfer(m_transfers[i]); - m_region_ids_by_virtual.push_back(std::make_pair(xfer.vsrc.get(), xfer.rid.get())); - m_server_ids_by_virtual.push_back(std::make_pair(xfer.vdst.get(), xfer.dst.get())); - } - - std::sort(m_servers.begin(), m_servers.end()); - std::sort(m_region_ids_by_virtual.begin(), m_region_ids_by_virtual.end()); - std::sort(m_server_ids_by_virtual.begin(), m_server_ids_by_virtual.end()); - std::sort(m_schemas_by_region.begin(), m_schemas_by_region.end()); - std::sort(m_subspaces_by_region.begin(), m_subspaces_by_region.end()); - std::sort(m_subspace_ids_by_region.begin(), m_subspace_ids_by_region.end()); - std::sort(m_subspace_ids_for_prev.begin(), m_subspace_ids_for_prev.end()); - std::sort(m_subspace_ids_for_next.begin(), m_subspace_ids_for_next.end()); - std::sort(m_heads_by_region.begin(), m_heads_by_region.end()); - std::sort(m_tails_by_region.begin(), m_tails_by_region.end()); - std::sort(m_next_by_virtual.begin(), m_next_by_virtual.end()); - std::sort(m_point_leaders_by_virtual.begin(), m_point_leaders_by_virtual.end()); + m_region_ids_by_virtual.clear(); + m_server_ids_by_virtual.clear(); + m_schemas_by_region.clear(); + m_subspaces_by_region.clear(); + m_subspace_ids_by_region.clear(); + m_subspace_ids_for_prev.clear(); + m_subspace_ids_for_next.clear(); + m_heads_by_region.clear(); + m_tails_by_region.clear(); + m_next_by_virtual.clear(); + m_point_leaders_by_virtual.clear(); + for (size_t w = 0; w < m_spaces.size(); ++w) + { + space &s(m_spaces[w]); + for (size_t x = 0; x < s.subspaces.size(); ++x) + { + subspace &ss(s.subspaces[x]); + if (x > 0) + { + m_subspace_ids_for_prev.push_back(std::make_pair(ss.id.get(), + s.subspaces[x - 1].id.get())); + } + if (x + 1 < s.subspaces.size()) + { + m_subspace_ids_for_next.push_back(std::make_pair(ss.id.get(), + s.subspaces[x + 1].id.get())); + } + for (size_t y = 0; y < ss.regions.size(); ++y) + { + region &r(ss.regions[y]); + m_schemas_by_region.push_back(std::make_pair(r.id.get(), &s.sc)); + m_subspaces_by_region.push_back(std::make_pair(r.id.get(), &ss)); + m_subspace_ids_by_region.push_back(std::make_pair(r.id.get(), ss.id.get())); + if (r.replicas.empty()) + { + continue; + } + if (x == 0) + { + m_point_leaders_by_virtual.push_back(r.replicas[0].vsi.get()); + } + m_heads_by_region.push_back(std::make_pair(r.id.get(), + r.replicas[0].vsi.get())); + m_tails_by_region.push_back(std::make_pair(r.id.get(), + r.replicas[r.replicas.size() - 1].vsi.get())); + for (size_t z = 0; z < r.replicas.size(); ++z) + { + m_region_ids_by_virtual.push_back(std::make_pair(r.replicas[z].vsi.get(), + r.id.get())); + m_server_ids_by_virtual.push_back(std::make_pair(r.replicas[z].vsi.get(), + r.replicas[z].si.get())); + if (z + 1 < r.replicas.size()) + { + m_next_by_virtual.push_back(std::make_pair(r.replicas[z].vsi.get(), + r.replicas[z + 1].vsi.get())); + } + } + } + } + } + for (size_t i = 0; i < m_transfers.size(); ++i) + { + transfer &xfer(m_transfers[i]); + m_region_ids_by_virtual.push_back(std::make_pair(xfer.vsrc.get(), xfer.rid.get())); + m_server_ids_by_virtual.push_back(std::make_pair(xfer.vdst.get(), xfer.dst.get())); + } + std::sort(m_servers.begin(), m_servers.end()); + std::sort(m_region_ids_by_virtual.begin(), m_region_ids_by_virtual.end()); + std::sort(m_server_ids_by_virtual.begin(), m_server_ids_by_virtual.end()); + std::sort(m_schemas_by_region.begin(), m_schemas_by_region.end()); + std::sort(m_subspaces_by_region.begin(), m_subspaces_by_region.end()); + std::sort(m_subspace_ids_by_region.begin(), m_subspace_ids_by_region.end()); + std::sort(m_subspace_ids_for_prev.begin(), m_subspace_ids_for_prev.end()); + std::sort(m_subspace_ids_for_next.begin(), m_subspace_ids_for_next.end()); + std::sort(m_heads_by_region.begin(), m_heads_by_region.end()); + std::sort(m_tails_by_region.begin(), m_tails_by_region.end()); + std::sort(m_next_by_virtual.begin(), m_next_by_virtual.end()); + std::sort(m_point_leaders_by_virtual.begin(), m_point_leaders_by_virtual.end()); } e::unpacker -hyperdex :: operator >> (e::unpacker up, configuration& c) +hyperdex :: operator >> (e::unpacker up, configuration &c) { - uint64_t num_servers = 0; - uint64_t num_spaces = 0; - uint64_t num_transfers = 0; - up = up >> c.m_cluster >> c.m_version >> c.m_flags - >> num_servers >> num_spaces - >> num_transfers; - c.m_servers.clear(); - c.m_servers.reserve(num_servers); - - for (size_t i = 0; !up.error() && i < num_servers; ++i) - { - server s; - up = up >> s; - c.m_servers.push_back(s); - } - - c.m_spaces.clear(); - c.m_spaces.reserve(num_spaces); - - for (size_t i = 0; !up.error() && i < num_spaces; ++i) - { - space s; - up = up >> s; - c.m_spaces.push_back(s); - } - - c.m_transfers.clear(); - c.m_transfers.reserve(num_transfers); - - for (size_t i = 0; !up.error() && i < num_transfers; ++i) - { - transfer xfer; - up = up >> xfer; - c.m_transfers.push_back(xfer); - } - - c.refill_cache(); - return up; + uint64_t num_servers = 0; + uint64_t num_spaces = 0; + uint64_t num_transfers = 0; + up = up >> c.m_cluster >> c.m_version >> c.m_flags + >> num_servers >> num_spaces + >> num_transfers; + c.m_servers.clear(); + c.m_servers.reserve(num_servers); + for (size_t i = 0; !up.error() && i < num_servers; ++i) + { + server s; + up = up >> s; + c.m_servers.push_back(s); + } + c.m_spaces.clear(); + c.m_spaces.reserve(num_spaces); + for (size_t i = 0; !up.error() && i < num_spaces; ++i) + { + space s; + up = up >> s; + c.m_spaces.push_back(s); + } + c.m_transfers.clear(); + c.m_transfers.reserve(num_transfers); + for (size_t i = 0; !up.error() && i < num_transfers; ++i) + { + transfer xfer; + up = up >> xfer; + c.m_transfers.push_back(xfer); + } + c.refill_cache(); + return up; } diff --git a/common/configuration.h b/common/configuration.h index 13c3d467e..9da962712 100644 --- a/common/configuration.h +++ b/common/configuration.h @@ -52,132 +52,132 @@ BEGIN_HYPERDEX_NAMESPACE class configuration { - public: - configuration(); - configuration(const configuration& other); - ~configuration() throw (); - - // configuration metadata - public: - uint64_t cluster() const; - uint64_t version() const; - bool read_only() const; - - // membership metadata - public: - void get_all_addresses(std::vector >* addrs) const; - bool exists(const server_id& id) const; - po6::net::location get_address(const server_id& id) const; - server::state_t get_state(const server_id& id) const; - region_id get_region_id(const virtual_server_id& id) const; - server_id get_server_id(const virtual_server_id& id) const; - - // hyperspace metadata - public: - const schema* get_schema(const char* space) const; - const schema* get_schema(const region_id& ri) const; - const subspace* get_subspace(const region_id& ri) const; - virtual_server_id get_virtual(const region_id& ri, const server_id& si) const; - subspace_id subspace_of(const region_id& ri) const; - subspace_id subspace_prev(const subspace_id& ss) const; - subspace_id subspace_next(const subspace_id& ss) const; - virtual_server_id head_of_region(const region_id& ri) const; - virtual_server_id tail_of_region(const region_id& ri) const; - virtual_server_id next_in_region(const virtual_server_id& vsi) const; - void point_leaders(const server_id& s, std::vector* servers) const; - void key_regions(const server_id& s, std::vector* servers) const; - bool is_point_leader(const virtual_server_id& e) const; - virtual_server_id point_leader(const char* space, const e::slice& key) const; - // point leader for this key in the same space as ri - virtual_server_id point_leader(const region_id& ri, const e::slice& key) const; - // lhs and rhs are in adjacent subspaces such that lhs sends CHAIN_PUT - // to rhs and rhs sends CHAIN_ACK to lhs - bool subspace_adjacent(const virtual_server_id& lhs, const virtual_server_id& rhs) const; - // mapped regions -- regions mapped for server "us" - void mapped_regions(const server_id& s, std::vector* servers) const; - - // index metadata - public: - const index* get_index(const index_id& ii) const; - void all_indices(const server_id& s, std::vector >* indices) const; - - // transfers - public: - bool is_server_involved_in_transfer(const server_id& si, const region_id& ri) const; - bool is_server_blocked_by_live_transfer(const server_id& si, const region_id& ri) const; - bool is_transfer_live(const transfer_id& tid) const; - void transfers_in(const server_id& s, std::vector* transfers) const; - void transfers_out(const server_id& s, std::vector* transfers) const; - void transfers_in_regions(const server_id& s, std::vector* transfers) const; - void transfers_out_regions(const server_id& s, std::vector* transfers) const; - - // hashing functions - public: - void lookup_region(const subspace_id& subspace, - const std::vector& hashes, - region_id* region) const; - void lookup_search(const char* space, - const std::vector& chks, - std::vector* servers) const; - - public: - std::string dump() const; - - // List all spaces separated by \n - std::string list_spaces() const; - - // List all suspaces of a space - // Attributes will be separated by a comma - // Spaces will be separated by a new line - std::string list_subspaces(const char* space) const; - - // List all indexes of a space - // Indices will be seperate by a new line - // The output for each index is: - // : - std::string list_indices(const char* space) const; - - public: - configuration& operator = (const configuration& rhs); - - private: - void refill_cache(); - friend size_t pack_size(const configuration&); - friend e::packer operator << (e::packer, const configuration& s); - friend e::unpacker operator >> (e::unpacker, configuration& s); - - private: - typedef std::pair pair_uint64_t; - typedef std::pair uint64_schema_t; - typedef std::pair uint64_subspace_t; - typedef std::pair uint64_location_t; - - private: - uint64_t m_cluster; - uint64_t m_version; - uint64_t m_flags; - std::vector m_servers; - std::vector m_region_ids_by_virtual; - std::vector m_server_ids_by_virtual; - std::vector m_schemas_by_region; - std::vector m_subspaces_by_region; - std::vector m_subspace_ids_by_region; - std::vector m_subspace_ids_for_prev; - std::vector m_subspace_ids_for_next; - std::vector m_heads_by_region; - std::vector m_tails_by_region; - std::vector m_next_by_virtual; - std::vector m_point_leaders_by_virtual; - std::vector m_spaces; - std::vector m_transfers; +public: + configuration(); + configuration(const configuration &other); + ~configuration() throw (); + + // configuration metadata +public: + uint64_t cluster() const; + uint64_t version() const; + bool read_only() const; + + // membership metadata +public: + void get_all_addresses(std::vector > *addrs) const; + bool exists(const server_id &id) const; + po6::net::location get_address(const server_id &id) const; + server::state_t get_state(const server_id &id) const; + region_id get_region_id(const virtual_server_id &id) const; + server_id get_server_id(const virtual_server_id &id) const; + + // hyperspace metadata +public: + const schema *get_schema(const char *space) const; + const schema *get_schema(const region_id &ri) const; + const subspace *get_subspace(const region_id &ri) const; + virtual_server_id get_virtual(const region_id &ri, const server_id &si) const; + subspace_id subspace_of(const region_id &ri) const; + subspace_id subspace_prev(const subspace_id &ss) const; + subspace_id subspace_next(const subspace_id &ss) const; + virtual_server_id head_of_region(const region_id &ri) const; + virtual_server_id tail_of_region(const region_id &ri) const; + virtual_server_id next_in_region(const virtual_server_id &vsi) const; + void point_leaders(const server_id &s, std::vector *servers) const; + void key_regions(const server_id &s, std::vector *servers) const; + bool is_point_leader(const virtual_server_id &e) const; + virtual_server_id point_leader(const char *space, const e::slice &key) const; + // point leader for this key in the same space as ri + virtual_server_id point_leader(const region_id &ri, const e::slice &key) const; + // lhs and rhs are in adjacent subspaces such that lhs sends CHAIN_PUT + // to rhs and rhs sends CHAIN_ACK to lhs + bool subspace_adjacent(const virtual_server_id &lhs, const virtual_server_id &rhs) const; + // mapped regions -- regions mapped for server "us" + void mapped_regions(const server_id &s, std::vector *servers) const; + + // index metadata +public: + const index *get_index(const index_id &ii) const; + void all_indices(const server_id &s, std::vector > *indices) const; + + // transfers +public: + bool is_server_involved_in_transfer(const server_id &si, const region_id &ri) const; + bool is_server_blocked_by_live_transfer(const server_id &si, const region_id &ri) const; + bool is_transfer_live(const transfer_id &tid) const; + void transfers_in(const server_id &s, std::vector *transfers) const; + void transfers_out(const server_id &s, std::vector *transfers) const; + void transfers_in_regions(const server_id &s, std::vector *transfers) const; + void transfers_out_regions(const server_id &s, std::vector *transfers) const; + + // hashing functions +public: + void lookup_region(const subspace_id &subspace, + const std::vector &hashes, + region_id *region) const; + void lookup_search(const char *space, + const std::vector &chks, + std::vector *servers) const; + +public: + std::string dump() const; + + // List all spaces separated by \n + std::string list_spaces() const; + + // List all suspaces of a space + // Attributes will be separated by a comma + // Spaces will be separated by a new line + std::string list_subspaces(const char *space) const; + + // List all indexes of a space + // Indices will be seperate by a new line + // The output for each index is: + // : + std::string list_indices(const char *space) const; + +public: + configuration &operator = (const configuration &rhs); + +private: + void refill_cache(); + friend size_t pack_size(const configuration &); + friend e::packer operator << (e::packer, const configuration &s); + friend e::unpacker operator >> (e::unpacker, configuration &s); + +private: + typedef std::pair pair_uint64_t; + typedef std::pair uint64_schema_t; + typedef std::pair uint64_subspace_t; + typedef std::pair uint64_location_t; + +private: + uint64_t m_cluster; + uint64_t m_version; + uint64_t m_flags; + std::vector m_servers; + std::vector m_region_ids_by_virtual; + std::vector m_server_ids_by_virtual; + std::vector m_schemas_by_region; + std::vector m_subspaces_by_region; + std::vector m_subspace_ids_by_region; + std::vector m_subspace_ids_for_prev; + std::vector m_subspace_ids_for_next; + std::vector m_heads_by_region; + std::vector m_tails_by_region; + std::vector m_next_by_virtual; + std::vector m_point_leaders_by_virtual; + std::vector m_spaces; + std::vector m_transfers; }; e::packer -operator << (e::packer, const configuration& c); +operator << (e::packer, const configuration &c); e::unpacker -operator >> (e::unpacker, configuration& c); +operator >> (e::unpacker, configuration &c); size_t -pack_size(const configuration&); +pack_size(const configuration &); END_HYPERDEX_NAMESPACE diff --git a/common/coordinator_returncode.cc b/common/coordinator_returncode.cc index 28a60923d..c2ea1406f 100644 --- a/common/coordinator_returncode.cc +++ b/common/coordinator_returncode.cc @@ -29,21 +29,20 @@ #include "common/coordinator_returncode.h" #include "common/macros.h" -std::ostream& -hyperdex :: operator << (std::ostream& lhs, coordinator_returncode rhs) +std::ostream & +hyperdex :: operator << (std::ostream &lhs, coordinator_returncode rhs) { - switch (rhs) - { - STRINGIFY(COORD_SUCCESS); - STRINGIFY(COORD_MALFORMED); - STRINGIFY(COORD_DUPLICATE); - STRINGIFY(COORD_NOT_FOUND); - STRINGIFY(COORD_UNINITIALIZED); - STRINGIFY(COORD_NO_CAN_DO); - default: - lhs << "unknown coordinator_returncode"; - break; - } - - return lhs; + switch (rhs) + { + STRINGIFY(COORD_SUCCESS); + STRINGIFY(COORD_MALFORMED); + STRINGIFY(COORD_DUPLICATE); + STRINGIFY(COORD_NOT_FOUND); + STRINGIFY(COORD_UNINITIALIZED); + STRINGIFY(COORD_NO_CAN_DO); + default: + lhs << "unknown coordinator_returncode"; + break; + } + return lhs; } diff --git a/common/coordinator_returncode.h b/common/coordinator_returncode.h old mode 100755 new mode 100644 index 08802c202..677d13395 --- a/common/coordinator_returncode.h +++ b/common/coordinator_returncode.h @@ -41,16 +41,16 @@ BEGIN_HYPERDEX_NAMESPACE // keep them in sync enum coordinator_returncode { - COORD_SUCCESS = 8832, - COORD_MALFORMED = 8833, - COORD_DUPLICATE = 8834, - COORD_NOT_FOUND = 8835, - COORD_UNINITIALIZED = 8837, - COORD_NO_CAN_DO = 8839 + COORD_SUCCESS = 8832, + COORD_MALFORMED = 8833, + COORD_DUPLICATE = 8834, + COORD_NOT_FOUND = 8835, + COORD_UNINITIALIZED = 8837, + COORD_NO_CAN_DO = 8839 }; -std::ostream& -operator << (std::ostream& lhs, coordinator_returncode rhs); +std::ostream & +operator << (std::ostream &lhs, coordinator_returncode rhs); END_HYPERDEX_NAMESPACE diff --git a/common/datatype_document.cc b/common/datatype_document.cc index c3068c5d2..be252dd1e 100644 --- a/common/datatype_document.cc +++ b/common/datatype_document.cc @@ -37,14 +37,14 @@ #include "common/datatype_int64.h" #include "common/datatype_float.h" -inline bool is_numeral(const hyperdatatype& t) +inline bool is_numeral(const hyperdatatype &t) { - return t == HYPERDATATYPE_FLOAT || t == HYPERDATATYPE_INT64; + return t == HYPERDATATYPE_FLOAT || t == HYPERDATATYPE_INT64; } -inline bool is_document_primitive(const hyperdatatype& t) +inline bool is_document_primitive(const hyperdatatype &t) { - return is_numeral(t) || t == HYPERDATATYPE_STRING || t == HYPERDATATYPE_DOCUMENT; + return is_numeral(t) || t == HYPERDATATYPE_STRING || t == HYPERDATATYPE_DOCUMENT; } using hyperdex::datatype_document; @@ -60,465 +60,423 @@ datatype_document :: ~datatype_document() throw () hyperdatatype datatype_document :: datatype() const { - return HYPERDATATYPE_DOCUMENT; + return HYPERDATATYPE_DOCUMENT; } bool -datatype_document :: validate(const e::slice& value) const +datatype_document :: validate(const e::slice &value) const { - if (value.size() == 0) - { - // empty == "object" - return true; - } - - return treadstone_binary_validate(value.data(), value.size()) == 0; + if (value.size() == 0) + { + // empty == "object" + return true; + } + return treadstone_binary_validate(value.data(), value.size()) == 0; } bool -datatype_document :: check_args(const funcall& func) const +datatype_document :: check_args(const funcall &func) const { - // A transformation that either sets (all/part of) the document, or - // pushes/pops an array (that is/within) the document. - if (is_document_primitive(func.arg1_datatype) && - (func.name == FUNC_SET || - func.name == FUNC_LIST_LPUSH || - func.name == FUNC_LIST_RPUSH)) - { - datatype_info* di = datatype_info::lookup(func.arg1_datatype); - return (func.arg2.empty() || - (func.arg2_datatype == HYPERDATATYPE_STRING && - is_document_path(func.arg2))) && - di && di->validate(func.arg1); - } - // Remove a particular path (arg2) - else if (func.arg2_datatype == HYPERDATATYPE_STRING && - func.name == FUNC_DOC_UNSET) - { - return is_document_path(func.arg2); - } - // Rename a particular path (arg1)->(arg2) - else if (func.arg1_datatype == HYPERDATATYPE_STRING && - func.arg2_datatype == HYPERDATATYPE_STRING && - func.name == FUNC_DOC_RENAME) - { - return is_document_path(func.arg1) && - is_document_path(func.arg2); - } - // Perform a nested operation on primitives - else if (func.arg2_datatype == HYPERDATATYPE_STRING && - is_document_primitive(func.arg1_datatype) && - func.arg1_datatype != HYPERDATATYPE_DOCUMENT) - { - datatype_info* di = datatype_info::lookup(func.arg1_datatype); - return is_document_path(func.arg2) && di->check_args(func); - } - // No other cases - else - { - return false; - } + // A transformation that either sets (all/part of) the document, or + // pushes/pops an array (that is/within) the document. + if (is_document_primitive(func.arg1_datatype) && + (func.name == FUNC_SET || + func.name == FUNC_LIST_LPUSH || + func.name == FUNC_LIST_RPUSH)) + { + datatype_info *di = datatype_info::lookup(func.arg1_datatype); + return (func.arg2.empty() || + (func.arg2_datatype == HYPERDATATYPE_STRING && + is_document_path(func.arg2))) && + di && di->validate(func.arg1); + } + // Remove a particular path (arg2) + else if (func.arg2_datatype == HYPERDATATYPE_STRING && + func.name == FUNC_DOC_UNSET) + { + return is_document_path(func.arg2); + } + // Rename a particular path (arg1)->(arg2) + else if (func.arg1_datatype == HYPERDATATYPE_STRING && + func.arg2_datatype == HYPERDATATYPE_STRING && + func.name == FUNC_DOC_RENAME) + { + return is_document_path(func.arg1) && + is_document_path(func.arg2); + } + // Perform a nested operation on primitives + else if (func.arg2_datatype == HYPERDATATYPE_STRING && + is_document_primitive(func.arg1_datatype) && + func.arg1_datatype != HYPERDATATYPE_DOCUMENT) + { + datatype_info *di = datatype_info::lookup(func.arg1_datatype); + return is_document_path(func.arg2) && di->check_args(func); + } + // No other cases + else + { + return false; + } } void -free_if_allocated(unsigned char** x) +free_if_allocated(unsigned char **x) { - if (*x) - { - free(*x); - } + if (*x) + { + free(*x); + } } bool -datatype_document :: apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const +datatype_document :: apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const { - struct treadstone_transformer* trans = NULL; - - if (old_value.empty()) - { - trans = treadstone_transformer_create(reinterpret_cast("\x40\x00"), 2); - } - else - { - trans = treadstone_transformer_create(old_value.data(), old_value.size()); - } - - if (!trans) - { - return false; - } - - e::guard transg = e::makeguard(treadstone_transformer_destroy, trans); - - for (size_t idx = 0; idx < funcs_sz; ++idx) - { - const funcall& func = funcs[idx]; - - if (is_document_primitive(func.arg1_datatype) && - (func.name == FUNC_SET || - func.name == FUNC_LIST_LPUSH || - func.name == FUNC_LIST_RPUSH)) - { - std::vector scratch; - e::slice v; - coerce_primitive_to_binary(func.arg1_datatype, func.arg1, &scratch, &v); - std::string path(func.arg2.cdata(), func.arg2.size()); - - if (func.name == FUNC_SET) - { - if (treadstone_transformer_set_value(trans, path.c_str(), v.data(), v.size()) < 0) - { - return false; - } - } - else if (func.name == FUNC_LIST_LPUSH) - { - if (treadstone_transformer_array_prepend_value(trans, path.c_str(), v.data(), v.size()) < 0) - { - return false; - } - } - else if (func.name == FUNC_LIST_RPUSH) - { - if (treadstone_transformer_array_append_value(trans, path.c_str(), v.data(), v.size()) < 0) - { - return false; - } - } - else - { - return false; - } - } - else if (func.arg2_datatype == HYPERDATATYPE_STRING && - func.name == FUNC_DOC_UNSET) - { - std::string path(func.arg2.cdata(), func.arg2.size()); - - if (treadstone_transformer_unset_value(trans, path.c_str()) < 0) - { - return false; - } - } - else if (func.arg1_datatype == HYPERDATATYPE_STRING && - func.arg2_datatype == HYPERDATATYPE_STRING && - func.name == FUNC_DOC_RENAME) - { - std::string src(func.arg2.cdata(), func.arg2.size()); - std::string dst(func.arg1.cdata(), func.arg1.size()); - - unsigned char* value = NULL; - size_t value_sz = 0; - e::guard g = e::makeguard(free_if_allocated, &value); - - if (treadstone_transformer_extract_value(trans, src.c_str(), &value, &value_sz) < 0) - { - return false; - } - - if (treadstone_transformer_unset_value(trans, src.c_str()) < 0) - { - return false; - } - - if (treadstone_transformer_set_value(trans, dst.c_str(), value, value_sz) < 0) - { - return false; - } - } - else if (func.arg2_datatype == HYPERDATATYPE_STRING && - is_document_primitive(func.arg1_datatype) && - func.arg1_datatype != HYPERDATATYPE_DOCUMENT) - { - unsigned char* value = NULL; - size_t value_sz = 0; - e::guard g = e::makeguard(free_if_allocated, &value); - std::string path(func.arg2.cdata(), func.arg2.size()); - hyperdatatype type; - std::vector scratch; - e::slice v; - - if (treadstone_transformer_extract_value(trans, path.c_str(), &value, &value_sz) < 0) - { - // Value doesn't exist yet - type = func.arg1_datatype; - v = e::slice(); - } - else - { - // Extract existing value from the document - if (!coerce_binary_to_primitive(e::slice(value, value_sz), &type, &scratch, &v)) - { - return false; - } - - - if (type == HYPERDATATYPE_INT64 && - func.arg1_datatype == HYPERDATATYPE_FLOAT) - { - int64_t x = datatype_int64::unpack(v); - double d = x; - datatype_float::pack(d, &scratch, &v); - type = HYPERDATATYPE_FLOAT; - } - - // Both types are numerals (integer or float) - const bool numeral = is_numeral(type) && is_numeral(func.arg1_datatype); - - if (func.name != FUNC_SET && - func.name != FUNC_DOC_UNSET && - func.name != FUNC_DOC_RENAME && - !numeral) - { - // More complex modifications (string append etc) - // only work with the same type - if(type != func.arg1_datatype) - { - return false; - } - } - } - - datatype_info* di = datatype_info::lookup(type); - e::slice tmp_value; - - if (!di->check_args(func)) - { - return false; - } - - // Pass funcall down to underlying datatype (string, integer etc...) - if (!di->apply(v, &func, 1, new_memory, &tmp_value)) - { - return false; - } - - std::vector scratch_binary; - e::slice binary; - coerce_primitive_to_binary(type, tmp_value, &scratch_binary, &binary); - - if (treadstone_transformer_set_value(trans, path.c_str(), binary.data(), binary.size()) < 0) - { - return false; - } - } - else - { - abort(); - } - } - - unsigned char* final_doc = NULL; - size_t final_doc_sz = 0; - e::guard g = e::makeguard(free_if_allocated, &final_doc); - - if (treadstone_transformer_output(trans, &final_doc, &final_doc_sz) < 0) - { - return false; - } - - new_memory->takeover(final_doc); - g.dismiss(); - *new_value = e::slice(final_doc, final_doc_sz); - return true; + struct treadstone_transformer *trans = NULL; + if (old_value.empty()) + { + trans = treadstone_transformer_create(reinterpret_cast("\x40\x00"), 2); + } + else + { + trans = treadstone_transformer_create(old_value.data(), old_value.size()); + } + if (!trans) + { + return false; + } + e::guard transg = e::makeguard(treadstone_transformer_destroy, trans); + for (size_t idx = 0; idx < funcs_sz; ++idx) + { + const funcall &func = funcs[idx]; + if (is_document_primitive(func.arg1_datatype) && + (func.name == FUNC_SET || + func.name == FUNC_LIST_LPUSH || + func.name == FUNC_LIST_RPUSH)) + { + std::vector scratch; + e::slice v; + coerce_primitive_to_binary(func.arg1_datatype, func.arg1, &scratch, &v); + std::string path(func.arg2.cdata(), func.arg2.size()); + if (func.name == FUNC_SET) + { + if (treadstone_transformer_set_value(trans, path.c_str(), v.data(), v.size()) < 0) + { + return false; + } + } + else if (func.name == FUNC_LIST_LPUSH) + { + if (treadstone_transformer_array_prepend_value(trans, path.c_str(), v.data(), v.size()) < 0) + { + return false; + } + } + else if (func.name == FUNC_LIST_RPUSH) + { + if (treadstone_transformer_array_append_value(trans, path.c_str(), v.data(), v.size()) < 0) + { + return false; + } + } + else + { + return false; + } + } + else if (func.arg2_datatype == HYPERDATATYPE_STRING && + func.name == FUNC_DOC_UNSET) + { + std::string path(func.arg2.cdata(), func.arg2.size()); + if (treadstone_transformer_unset_value(trans, path.c_str()) < 0) + { + return false; + } + } + else if (func.arg1_datatype == HYPERDATATYPE_STRING && + func.arg2_datatype == HYPERDATATYPE_STRING && + func.name == FUNC_DOC_RENAME) + { + std::string src(func.arg2.cdata(), func.arg2.size()); + std::string dst(func.arg1.cdata(), func.arg1.size()); + unsigned char *value = NULL; + size_t value_sz = 0; + e::guard g = e::makeguard(free_if_allocated, &value); + if (treadstone_transformer_extract_value(trans, src.c_str(), &value, &value_sz) < 0) + { + return false; + } + if (treadstone_transformer_unset_value(trans, src.c_str()) < 0) + { + return false; + } + if (treadstone_transformer_set_value(trans, dst.c_str(), value, value_sz) < 0) + { + return false; + } + } + else if (func.arg2_datatype == HYPERDATATYPE_STRING && + is_document_primitive(func.arg1_datatype) && + func.arg1_datatype != HYPERDATATYPE_DOCUMENT) + { + unsigned char *value = NULL; + size_t value_sz = 0; + e::guard g = e::makeguard(free_if_allocated, &value); + std::string path(func.arg2.cdata(), func.arg2.size()); + hyperdatatype type; + std::vector scratch; + e::slice v; + if (treadstone_transformer_extract_value(trans, path.c_str(), &value, &value_sz) < 0) + { + // Value doesn't exist yet + type = func.arg1_datatype; + v = e::slice(); + } + else + { + // Extract existing value from the document + if (!coerce_binary_to_primitive(e::slice(value, value_sz), &type, &scratch, &v)) + { + return false; + } + if (type == HYPERDATATYPE_INT64 && + func.arg1_datatype == HYPERDATATYPE_FLOAT) + { + int64_t x = datatype_int64::unpack(v); + double d = x; + datatype_float::pack(d, &scratch, &v); + type = HYPERDATATYPE_FLOAT; + } + // Both types are numerals (integer or float) + const bool numeral = is_numeral(type) && is_numeral(func.arg1_datatype); + if (func.name != FUNC_SET && + func.name != FUNC_DOC_UNSET && + func.name != FUNC_DOC_RENAME && + !numeral) + { + // More complex modifications (string append etc) + // only work with the same type + if (type != func.arg1_datatype) + { + return false; + } + } + } + datatype_info *di = datatype_info::lookup(type); + e::slice tmp_value; + if (!di->check_args(func)) + { + return false; + } + // Pass funcall down to underlying datatype (string, integer etc...) + if (!di->apply(v, &func, 1, new_memory, &tmp_value)) + { + return false; + } + std::vector scratch_binary; + e::slice binary; + coerce_primitive_to_binary(type, tmp_value, &scratch_binary, &binary); + if (treadstone_transformer_set_value(trans, path.c_str(), binary.data(), binary.size()) < 0) + { + return false; + } + } + else + { + abort(); + } + } + unsigned char *final_doc = NULL; + size_t final_doc_sz = 0; + e::guard g = e::makeguard(free_if_allocated, &final_doc); + if (treadstone_transformer_output(trans, &final_doc, &final_doc_sz) < 0) + { + return false; + } + new_memory->takeover(final_doc); + g.dismiss(); + *new_value = e::slice(final_doc, final_doc_sz); + return true; } bool -datatype_document :: client_to_server(const e::slice& client, - e::arena* new_memory, - e::slice* server) const +datatype_document :: client_to_server(const e::slice &client, + e::arena *new_memory, + e::slice *server) const { - unsigned char* binary; - size_t binary_sz; - std::string tmp(client.cdata(), client.size()); - - if (treadstone_json_to_binary(tmp.c_str(), &binary, &binary_sz) < 0) - { - return false; - } - - new_memory->takeover(binary); - *server = e::slice(binary, binary_sz); - return true; + unsigned char *binary; + size_t binary_sz; + std::string tmp(client.cdata(), client.size()); + if (treadstone_json_to_binary(tmp.c_str(), &binary, &binary_sz) < 0) + { + return false; + } + new_memory->takeover(binary); + *server = e::slice(binary, binary_sz); + return true; } bool -datatype_document :: server_to_client(const e::slice& server, - e::arena* new_memory, - e::slice* client) const +datatype_document :: server_to_client(const e::slice &server, + e::arena *new_memory, + e::slice *client) const { - char* json; - - if (treadstone_binary_to_json(server.data(), server.size(), &json) < 0) - { - return false; - } - - new_memory->takeover(json); - *client = e::slice(json, strlen(json) + 1); - return true; + char *json; + if (treadstone_binary_to_json(server.data(), server.size(), &json) < 0) + { + return false; + } + new_memory->takeover(json); + *client = e::slice(json, strlen(json) + 1); + return true; } bool datatype_document :: document() const { - return true; + return true; } bool -datatype_document :: document_check(const attribute_check& check, - const e::slice& doc) const +datatype_document :: document_check(const attribute_check &check, + const e::slice &doc) const { - // We expected the follwing format: - // \0\n - - const char* path = reinterpret_cast(check.value.data()); - size_t path_sz = strnlen(path, check.value.size()); - - if (path_sz >= check.value.size()) - { - return false; - } - - hyperdatatype type; - std::vector scratch; - e::slice value; - - if (!extract_value(path, doc, &type, &scratch, &value)) - { - return false; - } - - if(type == HYPERDATATYPE_DOCUMENT) - { - // Compare two subdocuments - e::slice chk_value = check.value; - chk_value.advance(path_sz + 1); - return (value == chk_value); - } - else - { - // Pass down to underlying datatype - attribute_check new_check; - new_check.attr = check.attr; - new_check.value = check.value; - new_check.datatype = check.datatype; - new_check.predicate = check.predicate; - new_check.value.advance(path_sz + 1); - return passes_attribute_check(type, new_check, value); - } + // We expected the follwing format: + // \0\n + const char *path = reinterpret_cast(check.value.data()); + size_t path_sz = strnlen(path, check.value.size()); + if (path_sz >= check.value.size()) + { + return false; + } + hyperdatatype type; + std::vector scratch; + e::slice value; + if (!extract_value(path, doc, &type, &scratch, &value)) + { + return false; + } + if (type == HYPERDATATYPE_DOCUMENT) + { + // Compare two subdocuments + e::slice chk_value = check.value; + chk_value.advance(path_sz + 1); + return (value == chk_value); + } + else + { + // Pass down to underlying datatype + attribute_check new_check; + new_check.attr = check.attr; + new_check.value = check.value; + new_check.datatype = check.datatype; + new_check.predicate = check.predicate; + new_check.value.advance(path_sz + 1); + return passes_attribute_check(type, new_check, value); + } } bool -datatype_document :: extract_value(const char* path, - const e::slice& data, - hyperdatatype* type, - std::vector* scratch, - e::slice* value) const +datatype_document :: extract_value(const char *path, + const e::slice &data, + hyperdatatype *type, + std::vector *scratch, + e::slice *value) const { - struct treadstone_transformer* trans = NULL; - trans = treadstone_transformer_create(data.data(), data.size()); - - if (!trans) - { - return false; - } - - e::guard transg = e::makeguard(treadstone_transformer_destroy, trans); - unsigned char* v = NULL; - size_t v_sz = 0; - e::guard g = e::makeguard(free_if_allocated, &v); - - if (treadstone_transformer_extract_value(trans, path, &v, &v_sz) < 0) - { - return false; - } - - return coerce_binary_to_primitive(e::slice(v, v_sz), type, scratch, value); + struct treadstone_transformer *trans = NULL; + trans = treadstone_transformer_create(data.data(), data.size()); + if (!trans) + { + return false; + } + e::guard transg = e::makeguard(treadstone_transformer_destroy, trans); + unsigned char *v = NULL; + size_t v_sz = 0; + e::guard g = e::makeguard(free_if_allocated, &v); + if (treadstone_transformer_extract_value(trans, path, &v, &v_sz) < 0) + { + return false; + } + return coerce_binary_to_primitive(e::slice(v, v_sz), type, scratch, value); } void datatype_document :: coerce_primitive_to_binary(hyperdatatype type, - const e::slice& in, - std::vector* scratch, - e::slice* value) const + const e::slice &in, + std::vector *scratch, + e::slice *value) const { - assert(is_document_primitive(type)); - unsigned char* v = NULL; - size_t v_sz = 0; - e::guard g = e::makeguard(free_if_allocated, &v); - - if (type == HYPERDATATYPE_STRING) - { - int rc = treadstone_string_to_binary(in.cdata(), in.size(), &v, &v_sz); - assert(rc == 0); - } - else if (type == HYPERDATATYPE_INT64) - { - int rc = treadstone_integer_to_binary(datatype_int64::unpack(in), &v, &v_sz); - assert(rc == 0); - } - else if (type == HYPERDATATYPE_FLOAT) - { - int rc = treadstone_double_to_binary(datatype_float::unpack(in), &v, &v_sz); - assert(rc == 0); - } - else if (type == HYPERDATATYPE_DOCUMENT) - { - *value = in; - return; - } - else - { - abort(); - } - - scratch->resize(v_sz); - memmove(&(*scratch)[0], v, v_sz); - *value = e::slice(&(*scratch)[0], v_sz); + assert(is_document_primitive(type)); + unsigned char *v = NULL; + size_t v_sz = 0; + e::guard g = e::makeguard(free_if_allocated, &v); + if (type == HYPERDATATYPE_STRING) + { + int rc = treadstone_string_to_binary(in.cdata(), in.size(), &v, &v_sz); + assert(rc == 0); + } + else if (type == HYPERDATATYPE_INT64) + { + int rc = treadstone_integer_to_binary(datatype_int64::unpack(in), &v, &v_sz); + assert(rc == 0); + } + else if (type == HYPERDATATYPE_FLOAT) + { + int rc = treadstone_double_to_binary(datatype_float::unpack(in), &v, &v_sz); + assert(rc == 0); + } + else if (type == HYPERDATATYPE_DOCUMENT) + { + *value = in; + return; + } + else + { + abort(); + } + scratch->resize(v_sz); + memmove(&(*scratch)[0], v, v_sz); + *value = e::slice(&(*scratch)[0], v_sz); } bool -datatype_document :: coerce_binary_to_primitive(const e::slice& in, - hyperdatatype* type, - std::vector* scratch, - e::slice* value) const +datatype_document :: coerce_binary_to_primitive(const e::slice &in, + hyperdatatype *type, + std::vector *scratch, + e::slice *value) const { - if (treadstone_binary_validate(in.data(), in.size()) < 0) - { - return false; - } - - if (treadstone_binary_is_string(in.data(), in.size()) == 0) - { - *type = HYPERDATATYPE_STRING; - size_t sz = treadstone_binary_string_bytes(in.data(), in.size()); - scratch->resize(sz); - treadstone_binary_to_string(in.data(), in.size(), &(*scratch)[0]); - *value = e::slice(&(*scratch)[0], sz); - } - else if (treadstone_binary_is_integer(in.data(), in.size()) == 0) - { - *type = HYPERDATATYPE_INT64; - int64_t num = treadstone_binary_to_integer(in.data(), in.size()); - datatype_int64::pack(num, scratch, value); - } - else if (treadstone_binary_is_double(in.data(), in.size()) == 0) - { - *type = HYPERDATATYPE_FLOAT; - double num = treadstone_binary_to_double(in.data(), in.size()); - datatype_float::pack(num, scratch, value); - } - else - { - *type = HYPERDATATYPE_DOCUMENT; - scratch->resize(in.size()); - memmove(scratch->data(), in.data(), in.size()); - *value = e::slice(&(*scratch)[0], in.size()); - } - - return true; + if (treadstone_binary_validate(in.data(), in.size()) < 0) + { + return false; + } + if (treadstone_binary_is_string(in.data(), in.size()) == 0) + { + *type = HYPERDATATYPE_STRING; + size_t sz = treadstone_binary_string_bytes(in.data(), in.size()); + scratch->resize(sz); + treadstone_binary_to_string(in.data(), in.size(), &(*scratch)[0]); + *value = e::slice(&(*scratch)[0], sz); + } + else if (treadstone_binary_is_integer(in.data(), in.size()) == 0) + { + *type = HYPERDATATYPE_INT64; + int64_t num = treadstone_binary_to_integer(in.data(), in.size()); + datatype_int64::pack(num, scratch, value); + } + else if (treadstone_binary_is_double(in.data(), in.size()) == 0) + { + *type = HYPERDATATYPE_FLOAT; + double num = treadstone_binary_to_double(in.data(), in.size()); + datatype_float::pack(num, scratch, value); + } + else + { + *type = HYPERDATATYPE_DOCUMENT; + scratch->resize(in.size()); + memmove(scratch->data(), in.data(), in.size()); + *value = e::slice(&(*scratch)[0], in.size()); + } + return true; } diff --git a/common/datatype_document.h b/common/datatype_document.h index a34cf714e..b7c589941 100644 --- a/common/datatype_document.h +++ b/common/datatype_document.h @@ -36,48 +36,48 @@ BEGIN_HYPERDEX_NAMESPACE class datatype_document : public datatype_info { - public: - datatype_document(); - virtual ~datatype_document() throw (); +public: + datatype_document(); + virtual ~datatype_document() throw (); - public: - virtual hyperdatatype datatype() const; - virtual bool validate(const e::slice& value) const; - virtual bool check_args(const funcall& func) const; - virtual bool apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const; +public: + virtual hyperdatatype datatype() const; + virtual bool validate(const e::slice &value) const; + virtual bool check_args(const funcall &func) const; + virtual bool apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const; - public: - virtual bool client_to_server(const e::slice& client, - e::arena* new_memory, - e::slice* server) const; - virtual bool server_to_client(const e::slice& server, - e::arena* new_memory, - e::slice* client) const; +public: + virtual bool client_to_server(const e::slice &client, + e::arena *new_memory, + e::slice *server) const; + virtual bool server_to_client(const e::slice &server, + e::arena *new_memory, + e::slice *client) const; - public: - virtual bool document() const; - virtual bool document_check(const attribute_check& check, - const e::slice& value) const; +public: + virtual bool document() const; + virtual bool document_check(const attribute_check &check, + const e::slice &value) const; - public: - bool extract_value(const char* path, - const e::slice& data, - hyperdatatype* type, - std::vector* scratch, - e::slice* value) const; +public: + bool extract_value(const char *path, + const e::slice &data, + hyperdatatype *type, + std::vector *scratch, + e::slice *value) const; - private: - void coerce_primitive_to_binary(hyperdatatype type, - const e::slice& in, - std::vector* scratch, - e::slice* value) const; - bool coerce_binary_to_primitive(const e::slice& in, - hyperdatatype* type, - std::vector* scratch, - e::slice* value) const; +private: + void coerce_primitive_to_binary(hyperdatatype type, + const e::slice &in, + std::vector *scratch, + e::slice *value) const; + bool coerce_binary_to_primitive(const e::slice &in, + hyperdatatype *type, + std::vector *scratch, + e::slice *value) const; }; END_HYPERDEX_NAMESPACE diff --git a/common/datatype_float.cc b/common/datatype_float.cc index d451f4134..2b0414b03 100644 --- a/common/datatype_float.cc +++ b/common/datatype_float.cc @@ -42,53 +42,50 @@ using hyperdex::datatype_info; using hyperdex::datatype_float; double -datatype_float :: unpack(const e::slice& value) +datatype_float :: unpack(const e::slice &value) { - assert(value.size() == 0 || value.size() == sizeof(int64_t)); - - if (value.size() == 0) - { - return 0; - } - - double number; - e::unpackdoublele(value.data(), &number); - return number; + assert(value.size() == 0 || value.size() == sizeof(int64_t)); + if (value.size() == 0) + { + return 0; + } + double number; + e::unpackdoublele(value.data(), &number); + return number; } double -datatype_float :: unpack(const funcall& value) +datatype_float :: unpack(const funcall &value) { - if (value.arg1_datatype == HYPERDATATYPE_INT64) - { - return datatype_int64::unpack(value.arg1); - } - else if (value.arg1_datatype == HYPERDATATYPE_FLOAT) - { - return datatype_float::unpack(value.arg1); - } - else - { - return 0; - } + if (value.arg1_datatype == HYPERDATATYPE_INT64) + { + return datatype_int64::unpack(value.arg1); + } + else if (value.arg1_datatype == HYPERDATATYPE_FLOAT) + { + return datatype_float::unpack(value.arg1); + } + else + { + return 0; + } } void -datatype_float :: pack(double num, std::vector* scratch, e::slice* value) +datatype_float :: pack(double num, std::vector *scratch, e::slice *value) { - if (scratch->size() < sizeof(double)) - { - scratch->resize(sizeof(double)); - } - - e::packdoublele(num, &(*scratch)[0]); - *value = e::slice(&(*scratch)[0], sizeof(double)); + if (scratch->size() < sizeof(double)) + { + scratch->resize(sizeof(double)); + } + e::packdoublele(num, &(*scratch)[0]); + *value = e::slice(&(*scratch)[0], sizeof(double)); } bool -datatype_float :: static_validate(const e::slice& value) +datatype_float :: static_validate(const e::slice &value) { - return value.size() == sizeof(double) || value.empty(); + return value.size() == sizeof(double) || value.empty(); } datatype_float :: datatype_float() @@ -102,191 +99,185 @@ datatype_float :: ~datatype_float() throw () hyperdatatype datatype_float :: datatype() const { - return HYPERDATATYPE_FLOAT; + return HYPERDATATYPE_FLOAT; } bool -datatype_float :: validate(const e::slice& value) const +datatype_float :: validate(const e::slice &value) const { - return static_validate(value); + return static_validate(value); } bool -datatype_float :: check_args(const funcall& func) const +datatype_float :: check_args(const funcall &func) const { - return ((func.arg1_datatype == HYPERDATATYPE_FLOAT && validate(func.arg1)) || - (func.arg1_datatype == HYPERDATATYPE_INT64 && datatype_int64::static_validate(func.arg1))) && - (func.name == FUNC_SET || - func.name == FUNC_NUM_ADD || - func.name == FUNC_NUM_SUB || - func.name == FUNC_NUM_MUL || - func.name == FUNC_NUM_DIV || - func.name == FUNC_NUM_MAX || - func.name == FUNC_NUM_MIN); + return ((func.arg1_datatype == HYPERDATATYPE_FLOAT && validate(func.arg1)) || + (func.arg1_datatype == HYPERDATATYPE_INT64 && datatype_int64::static_validate(func.arg1))) && + (func.name == FUNC_SET || + func.name == FUNC_NUM_ADD || + func.name == FUNC_NUM_SUB || + func.name == FUNC_NUM_MUL || + func.name == FUNC_NUM_DIV || + func.name == FUNC_NUM_MAX || + func.name == FUNC_NUM_MIN); } bool -datatype_float :: apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const +datatype_float :: apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const { - double number = unpack(old_value); - - for (size_t i = 0; i < funcs_sz; ++i) - { - const funcall* func = funcs + i; - double arg = unpack(*func); - - switch (func->name) - { - case FUNC_SET: - number = arg; - break; - case FUNC_NUM_ADD: - number += arg; - break; - case FUNC_NUM_SUB: - number -= arg; - break; - case FUNC_NUM_MUL: - number *= arg; - break; - case FUNC_NUM_DIV: - number /= arg; - break; - case FUNC_NUM_MAX: - number = std::max(number, arg); - break; - case FUNC_NUM_MIN: - number = std::min(number, arg); - break; - case FUNC_NUM_MOD: - case FUNC_NUM_AND: - case FUNC_NUM_OR: - case FUNC_NUM_XOR: - case FUNC_STRING_APPEND: - case FUNC_STRING_PREPEND: - case FUNC_STRING_LTRIM: - case FUNC_STRING_RTRIM: - case FUNC_LIST_LPUSH: - case FUNC_LIST_RPUSH: - case FUNC_SET_ADD: - case FUNC_SET_REMOVE: - case FUNC_SET_INTERSECT: - case FUNC_SET_UNION: - case FUNC_DOC_RENAME: - case FUNC_DOC_UNSET: - case FUNC_MAP_ADD: - case FUNC_MAP_REMOVE: - case FUNC_FAIL: - default: - abort(); - } - } - - uint8_t* ptr = NULL; - new_memory->allocate(sizeof(double), &ptr); - e::packdoublele(number, ptr); - *new_value = e::slice(ptr, sizeof(double)); - return true; + double number = unpack(old_value); + for (size_t i = 0; i < funcs_sz; ++i) + { + const funcall *func = funcs + i; + double arg = unpack(*func); + switch (func->name) + { + case FUNC_SET: + number = arg; + break; + case FUNC_NUM_ADD: + number += arg; + break; + case FUNC_NUM_SUB: + number -= arg; + break; + case FUNC_NUM_MUL: + number *= arg; + break; + case FUNC_NUM_DIV: + number /= arg; + break; + case FUNC_NUM_MAX: + number = std::max(number, arg); + break; + case FUNC_NUM_MIN: + number = std::min(number, arg); + break; + case FUNC_NUM_MOD: + case FUNC_NUM_AND: + case FUNC_NUM_OR: + case FUNC_NUM_XOR: + case FUNC_STRING_APPEND: + case FUNC_STRING_PREPEND: + case FUNC_STRING_LTRIM: + case FUNC_STRING_RTRIM: + case FUNC_LIST_LPUSH: + case FUNC_LIST_RPUSH: + case FUNC_SET_ADD: + case FUNC_SET_REMOVE: + case FUNC_SET_INTERSECT: + case FUNC_SET_UNION: + case FUNC_DOC_RENAME: + case FUNC_DOC_UNSET: + case FUNC_MAP_ADD: + case FUNC_MAP_REMOVE: + case FUNC_FAIL: + default: + abort(); + } + } + uint8_t *ptr = NULL; + new_memory->allocate(sizeof(double), &ptr); + e::packdoublele(number, ptr); + *new_value = e::slice(ptr, sizeof(double)); + return true; } bool datatype_float :: hashable() const { - return true; + return true; } uint64_t -datatype_float :: hash(const e::slice& value) const +datatype_float :: hash(const e::slice &value) const { - assert(validate(value)); - double number = unpack(value); - return ordered_encode_double(number); + assert(validate(value)); + double number = unpack(value); + return ordered_encode_double(number); } bool datatype_float :: indexable() const { - return true; + return true; } bool datatype_float :: containable() const { - return true; + return true; } bool -datatype_float :: step(const uint8_t** ptr, - const uint8_t* end, - e::slice* elem) const +datatype_float :: step(const uint8_t **ptr, + const uint8_t *end, + e::slice *elem) const { - if (static_cast(end - *ptr) < sizeof(double)) - { - return false; - } - - *elem = e::slice(*ptr, sizeof(double)); - *ptr += sizeof(double); - return true; + if (static_cast(end - *ptr) < sizeof(double)) + { + return false; + } + *elem = e::slice(*ptr, sizeof(double)); + *ptr += sizeof(double); + return true; } uint64_t -datatype_float :: write_sz(const e::slice& elem) const +datatype_float :: write_sz(const e::slice &elem) const { - return elem.size(); + return elem.size(); } -uint8_t* -datatype_float :: write(const e::slice& elem, - uint8_t* write_to) const +uint8_t * +datatype_float :: write(const e::slice &elem, + uint8_t *write_to) const { - memmove(write_to, elem.data(), elem.size()); - return write_to + elem.size(); + memmove(write_to, elem.data(), elem.size()); + return write_to + elem.size(); } bool datatype_float :: comparable() const { - return true; + return true; } static int -compare(const e::slice& lhs, - const e::slice& rhs) +compare(const e::slice &lhs, + const e::slice &rhs) { - double lhsnum = datatype_float::unpack(lhs); - double rhsnum = datatype_float::unpack(rhs); - - if (lhsnum < rhsnum) - { - return -1; - } - if (lhsnum > rhsnum) - { - return 1; - } - - return 0; + double lhsnum = datatype_float::unpack(lhs); + double rhsnum = datatype_float::unpack(rhs); + if (lhsnum < rhsnum) + { + return -1; + } + if (lhsnum > rhsnum) + { + return 1; + } + return 0; } int -datatype_float :: compare(const e::slice& lhs, const e::slice& rhs) const +datatype_float :: compare(const e::slice &lhs, const e::slice &rhs) const { - return ::compare(lhs, rhs); + return ::compare(lhs, rhs); } static bool -compare_less(const e::slice& lhs, - const e::slice& rhs) +compare_less(const e::slice &lhs, + const e::slice &rhs) { - return compare(lhs, rhs) < 0; + return compare(lhs, rhs) < 0; } datatype_info::compares_less datatype_float :: compare_less() const { - return &::compare_less; + return &::compare_less; } diff --git a/common/datatype_float.h b/common/datatype_float.h index eef741ebb..972021845 100644 --- a/common/datatype_float.h +++ b/common/datatype_float.h @@ -36,43 +36,43 @@ BEGIN_HYPERDEX_NAMESPACE class datatype_float : public datatype_info { - public: - static double unpack(const e::slice& value); - static double unpack(const funcall& value); - static void pack(double num, std::vector* scratch, e::slice* value); - static bool static_validate(const e::slice& value); +public: + static double unpack(const e::slice &value); + static double unpack(const funcall &value); + static void pack(double num, std::vector *scratch, e::slice *value); + static bool static_validate(const e::slice &value); - public: - datatype_float(); - virtual ~datatype_float() throw (); +public: + datatype_float(); + virtual ~datatype_float() throw (); - public: - virtual hyperdatatype datatype() const; - virtual bool validate(const e::slice& value) const; - virtual bool check_args(const funcall& func) const; - virtual bool apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const; +public: + virtual hyperdatatype datatype() const; + virtual bool validate(const e::slice &value) const; + virtual bool check_args(const funcall &func) const; + virtual bool apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const; - public: - virtual bool hashable() const; - virtual uint64_t hash(const e::slice& value) const; - virtual bool indexable() const; +public: + virtual bool hashable() const; + virtual uint64_t hash(const e::slice &value) const; + virtual bool indexable() const; - public: - virtual bool containable() const; - virtual bool step(const uint8_t** ptr, - const uint8_t* end, - e::slice* elem) const; - virtual uint64_t write_sz(const e::slice& elem) const; - virtual uint8_t* write(const e::slice& elem, - uint8_t* write_to) const; +public: + virtual bool containable() const; + virtual bool step(const uint8_t **ptr, + const uint8_t *end, + e::slice *elem) const; + virtual uint64_t write_sz(const e::slice &elem) const; + virtual uint8_t *write(const e::slice &elem, + uint8_t *write_to) const; - public: - virtual bool comparable() const; - virtual int compare(const e::slice& lhs, const e::slice& rhs) const; - virtual compares_less compare_less() const; +public: + virtual bool comparable() const; + virtual int compare(const e::slice &lhs, const e::slice &rhs) const; + virtual compares_less compare_less() const; }; END_HYPERDEX_NAMESPACE diff --git a/common/datatype_info.cc b/common/datatype_info.cc index 106b88130..3a503ae5e 100644 --- a/common/datatype_info.cc +++ b/common/datatype_info.cc @@ -69,75 +69,75 @@ static hyperdex::datatype_timestamp d_timestamp_week(HYPERDATATYPE_TIMESTAMP_WEE static hyperdex::datatype_timestamp d_timestamp_month(HYPERDATATYPE_TIMESTAMP_MONTH); static hyperdex::datatype_macaroon_secret d_macaroon_secret; -datatype_info* +datatype_info * datatype_info :: lookup(hyperdatatype datatype) { - switch (datatype) - { - case HYPERDATATYPE_STRING: - return &d_string; - case HYPERDATATYPE_INT64: - return &d_int64; - case HYPERDATATYPE_FLOAT: - return &d_float; - case HYPERDATATYPE_DOCUMENT: - return &d_document; - case HYPERDATATYPE_LIST_STRING: - return &d_list_string; - case HYPERDATATYPE_LIST_INT64: - return &d_list_int64; - case HYPERDATATYPE_LIST_FLOAT: - return &d_list_float; - case HYPERDATATYPE_SET_STRING: - return &d_set_string; - case HYPERDATATYPE_SET_INT64: - return &d_set_int64; - case HYPERDATATYPE_SET_FLOAT: - return &d_set_float; - case HYPERDATATYPE_MAP_STRING_STRING: - return &d_map_string_string; - case HYPERDATATYPE_MAP_STRING_INT64: - return &d_map_string_int64; - case HYPERDATATYPE_MAP_STRING_FLOAT: - return &d_map_string_float; - case HYPERDATATYPE_MAP_INT64_STRING: - return &d_map_int64_string; - case HYPERDATATYPE_MAP_INT64_INT64: - return &d_map_int64_int64; - case HYPERDATATYPE_MAP_INT64_FLOAT: - return &d_map_int64_float; - case HYPERDATATYPE_MAP_FLOAT_STRING: - return &d_map_float_string; - case HYPERDATATYPE_MAP_FLOAT_INT64: - return &d_map_float_int64; - case HYPERDATATYPE_MAP_FLOAT_FLOAT: - return &d_map_float_float; - case HYPERDATATYPE_TIMESTAMP_SECOND: - return &d_timestamp_second; - case HYPERDATATYPE_TIMESTAMP_MINUTE: - return &d_timestamp_minute; - case HYPERDATATYPE_TIMESTAMP_HOUR: - return &d_timestamp_hour; - case HYPERDATATYPE_TIMESTAMP_DAY: - return &d_timestamp_day; - case HYPERDATATYPE_TIMESTAMP_WEEK: - return &d_timestamp_week; - case HYPERDATATYPE_TIMESTAMP_MONTH: - return &d_timestamp_month; - case HYPERDATATYPE_MACAROON_SECRET: - return &d_macaroon_secret; - case HYPERDATATYPE_GENERIC: - case HYPERDATATYPE_TIMESTAMP_GENERIC: - case HYPERDATATYPE_LIST_GENERIC: - case HYPERDATATYPE_SET_GENERIC: - case HYPERDATATYPE_MAP_GENERIC: - case HYPERDATATYPE_MAP_STRING_KEYONLY: - case HYPERDATATYPE_MAP_INT64_KEYONLY: - case HYPERDATATYPE_MAP_FLOAT_KEYONLY: - case HYPERDATATYPE_GARBAGE: - default: - return NULL; - } + switch (datatype) + { + case HYPERDATATYPE_STRING: + return &d_string; + case HYPERDATATYPE_INT64: + return &d_int64; + case HYPERDATATYPE_FLOAT: + return &d_float; + case HYPERDATATYPE_DOCUMENT: + return &d_document; + case HYPERDATATYPE_LIST_STRING: + return &d_list_string; + case HYPERDATATYPE_LIST_INT64: + return &d_list_int64; + case HYPERDATATYPE_LIST_FLOAT: + return &d_list_float; + case HYPERDATATYPE_SET_STRING: + return &d_set_string; + case HYPERDATATYPE_SET_INT64: + return &d_set_int64; + case HYPERDATATYPE_SET_FLOAT: + return &d_set_float; + case HYPERDATATYPE_MAP_STRING_STRING: + return &d_map_string_string; + case HYPERDATATYPE_MAP_STRING_INT64: + return &d_map_string_int64; + case HYPERDATATYPE_MAP_STRING_FLOAT: + return &d_map_string_float; + case HYPERDATATYPE_MAP_INT64_STRING: + return &d_map_int64_string; + case HYPERDATATYPE_MAP_INT64_INT64: + return &d_map_int64_int64; + case HYPERDATATYPE_MAP_INT64_FLOAT: + return &d_map_int64_float; + case HYPERDATATYPE_MAP_FLOAT_STRING: + return &d_map_float_string; + case HYPERDATATYPE_MAP_FLOAT_INT64: + return &d_map_float_int64; + case HYPERDATATYPE_MAP_FLOAT_FLOAT: + return &d_map_float_float; + case HYPERDATATYPE_TIMESTAMP_SECOND: + return &d_timestamp_second; + case HYPERDATATYPE_TIMESTAMP_MINUTE: + return &d_timestamp_minute; + case HYPERDATATYPE_TIMESTAMP_HOUR: + return &d_timestamp_hour; + case HYPERDATATYPE_TIMESTAMP_DAY: + return &d_timestamp_day; + case HYPERDATATYPE_TIMESTAMP_WEEK: + return &d_timestamp_week; + case HYPERDATATYPE_TIMESTAMP_MONTH: + return &d_timestamp_month; + case HYPERDATATYPE_MACAROON_SECRET: + return &d_macaroon_secret; + case HYPERDATATYPE_GENERIC: + case HYPERDATATYPE_TIMESTAMP_GENERIC: + case HYPERDATATYPE_LIST_GENERIC: + case HYPERDATATYPE_SET_GENERIC: + case HYPERDATATYPE_MAP_GENERIC: + case HYPERDATATYPE_MAP_STRING_KEYONLY: + case HYPERDATATYPE_MAP_INT64_KEYONLY: + case HYPERDATATYPE_MAP_FLOAT_KEYONLY: + case HYPERDATATYPE_GARBAGE: + default: + return NULL; + } } datatype_info :: datatype_info() @@ -149,154 +149,154 @@ datatype_info :: ~datatype_info() throw () } bool -datatype_info :: client_to_server(const e::slice& client, - e::arena*, - e::slice* server) const +datatype_info :: client_to_server(const e::slice &client, + e::arena *, + e::slice *server) const { - *server = client; - return true; + *server = client; + return true; } bool -datatype_info :: server_to_client(const e::slice& server, - e::arena*, - e::slice* client) const +datatype_info :: server_to_client(const e::slice &server, + e::arena *, + e::slice *client) const { - *client = server; - return true; + *client = server; + return true; } bool datatype_info :: hashable() const { - return false; + return false; } uint64_t -datatype_info :: hash(const e::slice&) const +datatype_info :: hash(const e::slice &) const { - // if you see an abort here, you overrode "hashable", but not this method - abort(); + // if you see an abort here, you overrode "hashable", but not this method + abort(); } bool datatype_info :: indexable() const { - return false; + return false; } bool datatype_info :: has_length() const { - return false; + return false; } uint64_t -datatype_info :: length(const e::slice&) const +datatype_info :: length(const e::slice &) const { - // if you see an abort here, you overrode "has_length", but not this method - abort(); + // if you see an abort here, you overrode "has_length", but not this method + abort(); } bool datatype_info :: has_regex() const { - return false; + return false; } bool -datatype_info :: regex(const e::slice&, - const e::slice&) const +datatype_info :: regex(const e::slice &, + const e::slice &) const { - // if you see an abort here, you overrode "has_regex", but not this method - abort(); + // if you see an abort here, you overrode "has_regex", but not this method + abort(); } bool datatype_info :: has_contains() const { - return false; + return false; } hyperdatatype datatype_info :: contains_datatype() const { - // if you see an abort here, you overrode "has_contains", but not this method - abort(); + // if you see an abort here, you overrode "has_contains", but not this method + abort(); } bool -datatype_info :: contains(const e::slice&, const e::slice&) const +datatype_info :: contains(const e::slice &, const e::slice &) const { - // if you see an abort here, you overrode "has_contains", but not this method - abort(); + // if you see an abort here, you overrode "has_contains", but not this method + abort(); } bool datatype_info :: containable() const { - return false; + return false; } bool -datatype_info :: step(const uint8_t**, - const uint8_t*, - e::slice*) const +datatype_info :: step(const uint8_t **, + const uint8_t *, + e::slice *) const { - // if you see an abort here, you overrode "containable", but not this - // method - abort(); + // if you see an abort here, you overrode "containable", but not this + // method + abort(); } uint64_t -datatype_info :: write_sz(const e::slice&) const +datatype_info :: write_sz(const e::slice &) const { - // if you see an abort here, you overrode "containable", but not this - // method - abort(); + // if you see an abort here, you overrode "containable", but not this + // method + abort(); } -uint8_t* -datatype_info :: write(const e::slice&, uint8_t*) const +uint8_t * +datatype_info :: write(const e::slice &, uint8_t *) const { - // if you see an abort here, you overrode "containable", but not this - // method - abort(); + // if you see an abort here, you overrode "containable", but not this + // method + abort(); } bool datatype_info :: comparable() const { - return false; + return false; } int -datatype_info :: compare(const e::slice&, const e::slice&) const +datatype_info :: compare(const e::slice &, const e::slice &) const { - // if you see an abort here, you overrode "comparable", but not this - // method - abort(); + // if you see an abort here, you overrode "comparable", but not this + // method + abort(); } datatype_info::compares_less datatype_info :: compare_less() const { - // if you see an abort here, you overrode "comparable", but not this - // method - abort(); + // if you see an abort here, you overrode "comparable", but not this + // method + abort(); } bool datatype_info :: document() const { - return false; + return false; } bool -datatype_info :: document_check(const attribute_check&, - const e::slice&) const +datatype_info :: document_check(const attribute_check &, + const e::slice &) const { - // if you see an abort here, you overrode "document", but not this - // method - abort(); + // if you see an abort here, you overrode "document", but not this + // method + abort(); } diff --git a/common/datatype_info.h b/common/datatype_info.h index f5be572e4..febaf843b 100644 --- a/common/datatype_info.h +++ b/common/datatype_info.h @@ -43,92 +43,92 @@ BEGIN_HYPERDEX_NAMESPACE class datatype_info { - public: - // Return a pointer to the datatype_info representing the specific datatyp - // Must not be deleted - static datatype_info* lookup(hyperdatatype datatype); - - public: - datatype_info(); - virtual ~datatype_info() throw (); - - // all types must implement these - public: - virtual hyperdatatype datatype() const = 0; - virtual bool validate(const e::slice& value) const = 0; - virtual bool check_args(const funcall& func) const = 0; - virtual bool apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const = 0; - - // override these if the type's client-facing representation is not used as - // the server-side representation - public: - virtual bool client_to_server(const e::slice& client, - e::arena* new_memory, - e::slice* server) const; - virtual bool server_to_client(const e::slice& server, - e::arena* new_memory, - e::slice* client) const; - - // override these if the type is hashable - public: - virtual bool hashable() const; - virtual uint64_t hash(const e::slice& value) const; - - // override these if the type is indexable - public: - virtual bool indexable() const; - - // override these if the type has a "length" - public: - virtual bool has_length() const; - virtual uint64_t length(const e::slice& value) const; - - // override these if the type can be matched with regexes - public: - virtual bool has_regex() const; - virtual bool regex(const e::slice& regex, - const e::slice& value) const; - - // override these if the type can be matched with "contains" - public: - virtual bool has_contains() const; - virtual hyperdatatype contains_datatype() const; - virtual bool contains(const e::slice& value, const e::slice& needle) const; - - // override these if the type will be used within containers - public: - virtual bool containable() const; - virtual bool step(const uint8_t** ptr, - const uint8_t* end, - e::slice* elem) const; - virtual uint64_t write_sz(const e::slice& elem) const; - // must handle the case where elem/writeto overlap - // may only touch [write_to,write_to+write_sz(elem)) - virtual uint8_t* write(const e::slice& elem, - uint8_t* write_to) const; - - // override these if the type can be compared - public: - virtual bool comparable() const; - virtual int compare(const e::slice& lhs, const e::slice& rhs) const; - typedef bool (*compares_less)(const e::slice& lhs, const e::slice& rhs); - virtual compares_less compare_less() const; - - // override these if the type can be variable/document-like - // - // Custom document-like types cannot use the above comparables because they - // don't fit our long-held assumptions about different datatypes. - // Rather than break those assumptions and chase bugs, introduce a - // document_check call that converts the document check into something sane, - // possibly a non-document type. It's easy to create a sample value/check - // and pass that to the attribute checks instead. - public: - virtual bool document() const; - virtual bool document_check(const attribute_check& check, - const e::slice& value) const; +public: + // Return a pointer to the datatype_info representing the specific datatyp + // Must not be deleted + static datatype_info *lookup(hyperdatatype datatype); + +public: + datatype_info(); + virtual ~datatype_info() throw (); + + // all types must implement these +public: + virtual hyperdatatype datatype() const = 0; + virtual bool validate(const e::slice &value) const = 0; + virtual bool check_args(const funcall &func) const = 0; + virtual bool apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const = 0; + + // override these if the type's client-facing representation is not used as + // the server-side representation +public: + virtual bool client_to_server(const e::slice &client, + e::arena *new_memory, + e::slice *server) const; + virtual bool server_to_client(const e::slice &server, + e::arena *new_memory, + e::slice *client) const; + + // override these if the type is hashable +public: + virtual bool hashable() const; + virtual uint64_t hash(const e::slice &value) const; + + // override these if the type is indexable +public: + virtual bool indexable() const; + + // override these if the type has a "length" +public: + virtual bool has_length() const; + virtual uint64_t length(const e::slice &value) const; + + // override these if the type can be matched with regexes +public: + virtual bool has_regex() const; + virtual bool regex(const e::slice ®ex, + const e::slice &value) const; + + // override these if the type can be matched with "contains" +public: + virtual bool has_contains() const; + virtual hyperdatatype contains_datatype() const; + virtual bool contains(const e::slice &value, const e::slice &needle) const; + + // override these if the type will be used within containers +public: + virtual bool containable() const; + virtual bool step(const uint8_t **ptr, + const uint8_t *end, + e::slice *elem) const; + virtual uint64_t write_sz(const e::slice &elem) const; + // must handle the case where elem/writeto overlap + // may only touch [write_to,write_to+write_sz(elem)) + virtual uint8_t *write(const e::slice &elem, + uint8_t *write_to) const; + + // override these if the type can be compared +public: + virtual bool comparable() const; + virtual int compare(const e::slice &lhs, const e::slice &rhs) const; + typedef bool (*compares_less)(const e::slice &lhs, const e::slice &rhs); + virtual compares_less compare_less() const; + + // override these if the type can be variable/document-like + // + // Custom document-like types cannot use the above comparables because they + // don't fit our long-held assumptions about different datatypes. + // Rather than break those assumptions and chase bugs, introduce a + // document_check call that converts the document check into something sane, + // possibly a non-document type. It's easy to create a sample value/check + // and pass that to the attribute checks instead. +public: + virtual bool document() const; + virtual bool document_check(const attribute_check &check, + const e::slice &value) const; }; END_HYPERDEX_NAMESPACE diff --git a/common/datatype_int64.cc b/common/datatype_int64.cc index d705cfe06..e5c018441 100644 --- a/common/datatype_int64.cc +++ b/common/datatype_int64.cc @@ -44,53 +44,50 @@ using hyperdex::datatype_info; using hyperdex::datatype_int64; int64_t -datatype_int64 :: unpack(const e::slice& value) +datatype_int64 :: unpack(const e::slice &value) { - assert(value.size() == 0 || value.size() == sizeof(int64_t)); - - if (value.size() == 0) - { - return 0; - } - - int64_t number; - e::unpack64le(value.data(), &number); - return number; + assert(value.size() == 0 || value.size() == sizeof(int64_t)); + if (value.size() == 0) + { + return 0; + } + int64_t number; + e::unpack64le(value.data(), &number); + return number; } int64_t -datatype_int64 :: unpack(const funcall& value) +datatype_int64 :: unpack(const funcall &value) { - if (value.arg1_datatype == HYPERDATATYPE_INT64) - { - return datatype_int64::unpack(value.arg1); - } - else if (value.arg1_datatype == HYPERDATATYPE_FLOAT) - { - return llrint(datatype_float::unpack(value.arg1)); - } - else - { - return 0; - } + if (value.arg1_datatype == HYPERDATATYPE_INT64) + { + return datatype_int64::unpack(value.arg1); + } + else if (value.arg1_datatype == HYPERDATATYPE_FLOAT) + { + return llrint(datatype_float::unpack(value.arg1)); + } + else + { + return 0; + } } void -datatype_int64 :: pack(int64_t num, std::vector* scratch, e::slice* value) +datatype_int64 :: pack(int64_t num, std::vector *scratch, e::slice *value) { - if (scratch->size() < sizeof(int64_t)) - { - scratch->resize(sizeof(int64_t)); - } - - e::pack64le(num, &(*scratch)[0]); - *value = e::slice(&(*scratch)[0], sizeof(int64_t)); + if (scratch->size() < sizeof(int64_t)) + { + scratch->resize(sizeof(int64_t)); + } + e::pack64le(num, &(*scratch)[0]); + *value = e::slice(&(*scratch)[0], sizeof(int64_t)); } bool -datatype_int64 :: static_validate(const e::slice& value) +datatype_int64 :: static_validate(const e::slice &value) { - return value.size() == sizeof(int64_t) || value.empty(); + return value.size() == sizeof(int64_t) || value.empty(); } datatype_int64 :: datatype_int64() @@ -104,217 +101,211 @@ datatype_int64 :: ~datatype_int64() throw () hyperdatatype datatype_int64 :: datatype() const { - return HYPERDATATYPE_INT64; + return HYPERDATATYPE_INT64; } bool -datatype_int64 :: validate(const e::slice& value) const +datatype_int64 :: validate(const e::slice &value) const { - return static_validate(value); + return static_validate(value); } bool -datatype_int64 :: check_args(const funcall& func) const +datatype_int64 :: check_args(const funcall &func) const { - return ((func.arg1_datatype == HYPERDATATYPE_INT64 && validate(func.arg1)) || - (func.arg1_datatype == HYPERDATATYPE_FLOAT && datatype_float::static_validate(func.arg1))) && - (func.name == FUNC_SET || - func.name == FUNC_NUM_MAX || - func.name == FUNC_NUM_MIN || - func.name == FUNC_NUM_ADD || - func.name == FUNC_NUM_SUB || - func.name == FUNC_NUM_MUL || - func.name == FUNC_NUM_DIV || - func.name == FUNC_NUM_MOD || - func.name == FUNC_NUM_AND || - func.name == FUNC_NUM_OR || - func.name == FUNC_NUM_XOR); + return ((func.arg1_datatype == HYPERDATATYPE_INT64 && validate(func.arg1)) || + (func.arg1_datatype == HYPERDATATYPE_FLOAT && datatype_float::static_validate(func.arg1))) && + (func.name == FUNC_SET || + func.name == FUNC_NUM_MAX || + func.name == FUNC_NUM_MIN || + func.name == FUNC_NUM_ADD || + func.name == FUNC_NUM_SUB || + func.name == FUNC_NUM_MUL || + func.name == FUNC_NUM_DIV || + func.name == FUNC_NUM_MOD || + func.name == FUNC_NUM_AND || + func.name == FUNC_NUM_OR || + func.name == FUNC_NUM_XOR); } bool -datatype_int64 :: apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const +datatype_int64 :: apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const { - int64_t number = unpack(old_value); - - for (size_t i = 0; i < funcs_sz; ++i) - { - const funcall* func = funcs + i; - int64_t arg = unpack(*func); - - switch (func->name) - { - case FUNC_SET: - number = arg; - break; - case FUNC_NUM_MAX: - number = std::max(number, arg); - break; - case FUNC_NUM_MIN: - number = std::min(number, arg); - break; - case FUNC_NUM_ADD: - if (!e::safe_add(number, arg, &number)) - { - return false; // XXX signed overflow - } - break; - case FUNC_NUM_SUB: - if (!e::safe_sub(number, arg, &number)) - { - return false; // XXX signed overflow - } - break; - case FUNC_NUM_MUL: - if (!e::safe_mul(number, arg, &number)) - { - return false; // XXX signed overflow - } - break; - case FUNC_NUM_DIV: - if (!e::safe_div(number, arg, &number)) - { - return false; // XXX signed overflow - } - break; - case FUNC_NUM_MOD: - if (!e::safe_mod(number, arg, &number)) - { - return false; // XXX signed overflow - } - break; - case FUNC_NUM_AND: - number &= arg; - break; - case FUNC_NUM_OR: - number |= arg; - break; - case FUNC_NUM_XOR: - number ^= arg; - break; - case FUNC_STRING_APPEND: - case FUNC_STRING_PREPEND: - case FUNC_STRING_LTRIM: - case FUNC_STRING_RTRIM: - case FUNC_LIST_LPUSH: - case FUNC_LIST_RPUSH: - case FUNC_SET_ADD: - case FUNC_SET_REMOVE: - case FUNC_SET_INTERSECT: - case FUNC_SET_UNION: - case FUNC_MAP_ADD: - case FUNC_MAP_REMOVE: - case FUNC_FAIL: - case FUNC_DOC_RENAME: - case FUNC_DOC_UNSET: - default: - abort(); - } - } - - uint8_t* ptr = NULL; - new_memory->allocate(sizeof(int64_t), &ptr); - e::pack64le(number, ptr); - *new_value = e::slice(ptr, sizeof(int64_t)); - return true; + int64_t number = unpack(old_value); + for (size_t i = 0; i < funcs_sz; ++i) + { + const funcall *func = funcs + i; + int64_t arg = unpack(*func); + switch (func->name) + { + case FUNC_SET: + number = arg; + break; + case FUNC_NUM_MAX: + number = std::max(number, arg); + break; + case FUNC_NUM_MIN: + number = std::min(number, arg); + break; + case FUNC_NUM_ADD: + if (!e::safe_add(number, arg, &number)) + { + return false; // XXX signed overflow + } + break; + case FUNC_NUM_SUB: + if (!e::safe_sub(number, arg, &number)) + { + return false; // XXX signed overflow + } + break; + case FUNC_NUM_MUL: + if (!e::safe_mul(number, arg, &number)) + { + return false; // XXX signed overflow + } + break; + case FUNC_NUM_DIV: + if (!e::safe_div(number, arg, &number)) + { + return false; // XXX signed overflow + } + break; + case FUNC_NUM_MOD: + if (!e::safe_mod(number, arg, &number)) + { + return false; // XXX signed overflow + } + break; + case FUNC_NUM_AND: + number &= arg; + break; + case FUNC_NUM_OR: + number |= arg; + break; + case FUNC_NUM_XOR: + number ^= arg; + break; + case FUNC_STRING_APPEND: + case FUNC_STRING_PREPEND: + case FUNC_STRING_LTRIM: + case FUNC_STRING_RTRIM: + case FUNC_LIST_LPUSH: + case FUNC_LIST_RPUSH: + case FUNC_SET_ADD: + case FUNC_SET_REMOVE: + case FUNC_SET_INTERSECT: + case FUNC_SET_UNION: + case FUNC_MAP_ADD: + case FUNC_MAP_REMOVE: + case FUNC_FAIL: + case FUNC_DOC_RENAME: + case FUNC_DOC_UNSET: + default: + abort(); + } + } + uint8_t *ptr = NULL; + new_memory->allocate(sizeof(int64_t), &ptr); + e::pack64le(number, ptr); + *new_value = e::slice(ptr, sizeof(int64_t)); + return true; } bool datatype_int64 :: hashable() const { - return true; + return true; } uint64_t -datatype_int64 :: hash(const e::slice& value) const +datatype_int64 :: hash(const e::slice &value) const { - assert(validate(value)); - return ordered_encode_int64(unpack(value)); + assert(validate(value)); + return ordered_encode_int64(unpack(value)); } bool datatype_int64 :: indexable() const { - return true; + return true; } bool datatype_int64 :: containable() const { - return true; + return true; } bool -datatype_int64 :: step(const uint8_t** ptr, - const uint8_t* end, - e::slice* elem) const +datatype_int64 :: step(const uint8_t **ptr, + const uint8_t *end, + e::slice *elem) const { - if (static_cast(end - *ptr) < sizeof(int64_t)) - { - return false; - } - - *elem = e::slice(*ptr, sizeof(int64_t)); - *ptr += sizeof(int64_t); - return true; + if (static_cast(end - *ptr) < sizeof(int64_t)) + { + return false; + } + *elem = e::slice(*ptr, sizeof(int64_t)); + *ptr += sizeof(int64_t); + return true; } uint64_t -datatype_int64 :: write_sz(const e::slice& elem) const +datatype_int64 :: write_sz(const e::slice &elem) const { - return elem.size(); + return elem.size(); } -uint8_t* -datatype_int64 :: write(const e::slice& elem, - uint8_t* write_to) const +uint8_t * +datatype_int64 :: write(const e::slice &elem, + uint8_t *write_to) const { - memmove(write_to, elem.data(), elem.size()); - return write_to + elem.size(); + memmove(write_to, elem.data(), elem.size()); + return write_to + elem.size(); } bool datatype_int64 :: comparable() const { - return true; + return true; } static int -compare(const e::slice& lhs, - const e::slice& rhs) +compare(const e::slice &lhs, + const e::slice &rhs) { - int64_t lhsnum = datatype_int64::unpack(lhs); - int64_t rhsnum = datatype_int64::unpack(rhs); - - if (lhsnum < rhsnum) - { - return -1; - } - if (lhsnum > rhsnum) - { - return 1; - } - - return 0; + int64_t lhsnum = datatype_int64::unpack(lhs); + int64_t rhsnum = datatype_int64::unpack(rhs); + if (lhsnum < rhsnum) + { + return -1; + } + if (lhsnum > rhsnum) + { + return 1; + } + return 0; } int -datatype_int64 :: compare(const e::slice& lhs, const e::slice& rhs) const +datatype_int64 :: compare(const e::slice &lhs, const e::slice &rhs) const { - return ::compare(lhs, rhs); + return ::compare(lhs, rhs); } static bool -compare_less(const e::slice& lhs, - const e::slice& rhs) +compare_less(const e::slice &lhs, + const e::slice &rhs) { - return compare(lhs, rhs) < 0; + return compare(lhs, rhs) < 0; } datatype_info::compares_less datatype_int64 :: compare_less() const { - return &::compare_less; + return &::compare_less; } diff --git a/common/datatype_int64.h b/common/datatype_int64.h index 49a4e6b2f..5c030769d 100644 --- a/common/datatype_int64.h +++ b/common/datatype_int64.h @@ -36,43 +36,43 @@ BEGIN_HYPERDEX_NAMESPACE class datatype_int64 : public datatype_info { - public: - static int64_t unpack(const e::slice& value); - static int64_t unpack(const funcall& func); - static void pack(int64_t num, std::vector* scratch, e::slice* value); - static bool static_validate(const e::slice& value); +public: + static int64_t unpack(const e::slice &value); + static int64_t unpack(const funcall &func); + static void pack(int64_t num, std::vector *scratch, e::slice *value); + static bool static_validate(const e::slice &value); - public: - datatype_int64(); - virtual ~datatype_int64() throw (); +public: + datatype_int64(); + virtual ~datatype_int64() throw (); - public: - virtual hyperdatatype datatype() const; - virtual bool validate(const e::slice& value) const; - virtual bool check_args(const funcall& func) const; - virtual bool apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const; +public: + virtual hyperdatatype datatype() const; + virtual bool validate(const e::slice &value) const; + virtual bool check_args(const funcall &func) const; + virtual bool apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const; - public: - virtual bool hashable() const; - virtual uint64_t hash(const e::slice& value) const; - virtual bool indexable() const; +public: + virtual bool hashable() const; + virtual uint64_t hash(const e::slice &value) const; + virtual bool indexable() const; - public: - virtual bool containable() const; - virtual bool step(const uint8_t** ptr, - const uint8_t* end, - e::slice* elem) const; - virtual uint64_t write_sz(const e::slice& elem) const; - virtual uint8_t* write(const e::slice& elem, - uint8_t* write_to) const; +public: + virtual bool containable() const; + virtual bool step(const uint8_t **ptr, + const uint8_t *end, + e::slice *elem) const; + virtual uint64_t write_sz(const e::slice &elem) const; + virtual uint8_t *write(const e::slice &elem, + uint8_t *write_to) const; - public: - virtual bool comparable() const; - virtual int compare(const e::slice& lhs, const e::slice& rhs) const; - virtual compares_less compare_less() const; +public: + virtual bool comparable() const; + virtual int compare(const e::slice &lhs, const e::slice &rhs) const; + virtual compares_less compare_less() const; }; END_HYPERDEX_NAMESPACE diff --git a/common/datatype_list.cc b/common/datatype_list.cc index 519deffb0..5a6d8beda 100644 --- a/common/datatype_list.cc +++ b/common/datatype_list.cc @@ -42,10 +42,10 @@ using hyperdex::datatype_list; -datatype_list :: datatype_list(datatype_info* elem) - : m_elem(elem) +datatype_list :: datatype_list(datatype_info *elem) + : m_elem(elem) { - assert(m_elem->containable()); + assert(m_elem->containable()); } datatype_list :: ~datatype_list() throw () @@ -55,188 +55,172 @@ datatype_list :: ~datatype_list() throw () hyperdatatype datatype_list :: datatype() const { - return CREATE_CONTAINER(HYPERDATATYPE_LIST_GENERIC, m_elem->datatype()); + return CREATE_CONTAINER(HYPERDATATYPE_LIST_GENERIC, m_elem->datatype()); } bool -datatype_list :: validate(const e::slice& list) const +datatype_list :: validate(const e::slice &list) const { - const uint8_t* ptr = list.data(); - const uint8_t* end = list.data() + list.size(); - e::slice elem; - - while (ptr < end) - { - if (!m_elem->step(&ptr, end, &elem)) - { - return false; - } - } - - return ptr == end; + const uint8_t *ptr = list.data(); + const uint8_t *end = list.data() + list.size(); + e::slice elem; + while (ptr < end) + { + if (!m_elem->step(&ptr, end, &elem)) + { + return false; + } + } + return ptr == end; } bool -datatype_list :: check_args(const funcall& func) const +datatype_list :: check_args(const funcall &func) const { - return ((func.arg1_datatype == datatype() || - func.arg1_datatype == HYPERDATATYPE_LIST_GENERIC) && - validate(func.arg1) && func.name == FUNC_SET) || - (func.arg1_datatype == m_elem->datatype() && - m_elem->validate(func.arg1) && - (func.name == FUNC_LIST_LPUSH || - func.name == FUNC_LIST_RPUSH)); + return ((func.arg1_datatype == datatype() || + func.arg1_datatype == HYPERDATATYPE_LIST_GENERIC) && + validate(func.arg1) && func.name == FUNC_SET) || + (func.arg1_datatype == m_elem->datatype() && + m_elem->validate(func.arg1) && + (func.name == FUNC_LIST_LPUSH || + func.name == FUNC_LIST_RPUSH)); } bool -datatype_list :: apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const +datatype_list :: apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const { - std::list list; - const uint8_t* ptr = old_value.data(); - const uint8_t* end = old_value.data() + old_value.size(); - e::slice elem; - - while (ptr < end) - { - bool stepped = m_elem->step(&ptr, end, &elem); - assert(stepped); // safe because of check_args - list.push_back(elem); - } - - for (size_t i = 0; i < funcs_sz; ++i) - { - switch (funcs[i].name) - { - case FUNC_SET: - list.clear(); - ptr = funcs[i].arg1.data(); - end = funcs[i].arg1.data() + funcs[i].arg1.size(); - - while (ptr < end) - { - bool stepped = m_elem->step(&ptr, end, &elem); - assert(stepped); // safe because of check_args - list.push_back(elem); - } - - break; - case FUNC_LIST_LPUSH: - list.push_front(funcs[i].arg1); - break; - case FUNC_LIST_RPUSH: - list.push_back(funcs[i].arg1); - break; - case FUNC_FAIL: - case FUNC_STRING_APPEND: - case FUNC_STRING_PREPEND: - case FUNC_STRING_LTRIM: - case FUNC_STRING_RTRIM: - case FUNC_NUM_ADD: - case FUNC_NUM_SUB: - case FUNC_NUM_MUL: - case FUNC_NUM_DIV: - case FUNC_NUM_MOD: - case FUNC_NUM_AND: - case FUNC_NUM_OR: - case FUNC_NUM_XOR: - case FUNC_NUM_MAX: - case FUNC_NUM_MIN: - case FUNC_SET_ADD: - case FUNC_SET_REMOVE: - case FUNC_SET_INTERSECT: - case FUNC_SET_UNION: - case FUNC_MAP_ADD: - case FUNC_MAP_REMOVE: - case FUNC_DOC_RENAME: - case FUNC_DOC_UNSET: - default: - abort(); - } - } - - size_t sz = 0; - - for (std::list::iterator i = list.begin(); i != list.end(); ++i) - { - sz += m_elem->write_sz(*i); - } - - uint8_t* write_to = NULL; - new_memory->allocate(sz, &write_to); - *new_value = e::slice(write_to, sz); - - for (std::list::iterator i = list.begin(); i != list.end(); ++i) - { - write_to = m_elem->write(*i, write_to); - } - - return true; + std::list list; + const uint8_t *ptr = old_value.data(); + const uint8_t *end = old_value.data() + old_value.size(); + e::slice elem; + while (ptr < end) + { + bool stepped = m_elem->step(&ptr, end, &elem); + assert(stepped); // safe because of check_args + list.push_back(elem); + } + for (size_t i = 0; i < funcs_sz; ++i) + { + switch (funcs[i].name) + { + case FUNC_SET: + list.clear(); + ptr = funcs[i].arg1.data(); + end = funcs[i].arg1.data() + funcs[i].arg1.size(); + while (ptr < end) + { + bool stepped = m_elem->step(&ptr, end, &elem); + assert(stepped); // safe because of check_args + list.push_back(elem); + } + break; + case FUNC_LIST_LPUSH: + list.push_front(funcs[i].arg1); + break; + case FUNC_LIST_RPUSH: + list.push_back(funcs[i].arg1); + break; + case FUNC_FAIL: + case FUNC_STRING_APPEND: + case FUNC_STRING_PREPEND: + case FUNC_STRING_LTRIM: + case FUNC_STRING_RTRIM: + case FUNC_NUM_ADD: + case FUNC_NUM_SUB: + case FUNC_NUM_MUL: + case FUNC_NUM_DIV: + case FUNC_NUM_MOD: + case FUNC_NUM_AND: + case FUNC_NUM_OR: + case FUNC_NUM_XOR: + case FUNC_NUM_MAX: + case FUNC_NUM_MIN: + case FUNC_SET_ADD: + case FUNC_SET_REMOVE: + case FUNC_SET_INTERSECT: + case FUNC_SET_UNION: + case FUNC_MAP_ADD: + case FUNC_MAP_REMOVE: + case FUNC_DOC_RENAME: + case FUNC_DOC_UNSET: + default: + abort(); + } + } + size_t sz = 0; + for (std::list::iterator i = list.begin(); i != list.end(); ++i) + { + sz += m_elem->write_sz(*i); + } + uint8_t *write_to = NULL; + new_memory->allocate(sz, &write_to); + *new_value = e::slice(write_to, sz); + for (std::list::iterator i = list.begin(); i != list.end(); ++i) + { + write_to = m_elem->write(*i, write_to); + } + return true; } bool datatype_list :: indexable() const { - return m_elem->indexable(); + return m_elem->indexable(); } bool datatype_list :: has_length() const { - return true; + return true; } uint64_t -datatype_list :: length(const e::slice& list) const +datatype_list :: length(const e::slice &list) const { - const uint8_t* ptr = list.data(); - const uint8_t* end = list.data() + list.size(); - e::slice elem; - uint64_t count = 0; - - while (ptr < end) - { - bool stepped = m_elem->step(&ptr, end, &elem); - assert(stepped); - ++count; - } - - assert(ptr == end); - return count; + const uint8_t *ptr = list.data(); + const uint8_t *end = list.data() + list.size(); + e::slice elem; + uint64_t count = 0; + while (ptr < end) + { + bool stepped = m_elem->step(&ptr, end, &elem); + assert(stepped); + ++count; + } + assert(ptr == end); + return count; } bool datatype_list :: has_contains() const { - return true; + return true; } hyperdatatype datatype_list :: contains_datatype() const { - return m_elem->datatype(); + return m_elem->datatype(); } bool -datatype_list :: contains(const e::slice& list, const e::slice& needle) const +datatype_list :: contains(const e::slice &list, const e::slice &needle) const { - const uint8_t* ptr = list.data(); - const uint8_t* end = list.data() + list.size(); - e::slice elem; - - while (ptr < end) - { - bool stepped = m_elem->step(&ptr, end, &elem); - assert(stepped); - - if (elem == needle) - { - return true; - } - } - - assert(ptr == end); - return false; + const uint8_t *ptr = list.data(); + const uint8_t *end = list.data() + list.size(); + e::slice elem; + while (ptr < end) + { + bool stepped = m_elem->step(&ptr, end, &elem); + assert(stepped); + if (elem == needle) + { + return true; + } + } + assert(ptr == end); + return false; } diff --git a/common/datatype_list.h b/common/datatype_list.h index 4fdc7ed54..e36c7bbee 100644 --- a/common/datatype_list.h +++ b/common/datatype_list.h @@ -39,37 +39,37 @@ BEGIN_HYPERDEX_NAMESPACE class datatype_list : public datatype_info { - public: - datatype_list(datatype_info* elem); - virtual ~datatype_list() throw (); +public: + datatype_list(datatype_info *elem); + virtual ~datatype_list() throw (); - public: - virtual hyperdatatype datatype() const; - virtual bool validate(const e::slice& value) const; - virtual bool check_args(const funcall& func) const; - virtual bool apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const; +public: + virtual hyperdatatype datatype() const; + virtual bool validate(const e::slice &value) const; + virtual bool check_args(const funcall &func) const; + virtual bool apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const; - public: - virtual bool indexable() const; +public: + virtual bool indexable() const; - public: - virtual bool has_length() const; - virtual uint64_t length(const e::slice& value) const; +public: + virtual bool has_length() const; + virtual uint64_t length(const e::slice &value) const; - public: - virtual bool has_contains() const; - virtual hyperdatatype contains_datatype() const; - virtual bool contains(const e::slice& value, const e::slice& needle) const; +public: + virtual bool has_contains() const; + virtual hyperdatatype contains_datatype() const; + virtual bool contains(const e::slice &value, const e::slice &needle) const; - private: - datatype_list(const datatype_list&); - datatype_list& operator = (const datatype_list&); +private: + datatype_list(const datatype_list &); + datatype_list &operator = (const datatype_list &); - private: - datatype_info* m_elem; +private: + datatype_info *m_elem; }; END_HYPERDEX_NAMESPACE diff --git a/common/datatype_macaroon_secret.cc b/common/datatype_macaroon_secret.cc index 4b505dd22..9e35f4070 100644 --- a/common/datatype_macaroon_secret.cc +++ b/common/datatype_macaroon_secret.cc @@ -43,39 +43,37 @@ datatype_macaroon_secret :: ~datatype_macaroon_secret() throw () hyperdatatype datatype_macaroon_secret :: datatype() const { - return HYPERDATATYPE_STRING; + return HYPERDATATYPE_STRING; } bool -datatype_macaroon_secret :: validate(const e::slice&) const +datatype_macaroon_secret :: validate(const e::slice &) const { - return true; + return true; } bool -datatype_macaroon_secret :: check_args(const funcall& func) const +datatype_macaroon_secret :: check_args(const funcall &func) const { - return func.arg1_datatype == HYPERDATATYPE_MACAROON_SECRET && - validate(func.arg1) && func.name == FUNC_SET; + return func.arg1_datatype == HYPERDATATYPE_MACAROON_SECRET && + validate(func.arg1) && func.name == FUNC_SET; } bool -datatype_macaroon_secret :: apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const +datatype_macaroon_secret :: apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const { - *new_value = old_value; - - if (funcs_sz > 0) - { - assert(funcs[funcs_sz - 1].name == FUNC_SET); - *new_value = funcs[funcs_sz - 1].arg1; - } - - uint8_t* ptr = NULL; - new_memory->allocate(new_value->size(), &ptr); - memmove(ptr, new_value->data(), new_value->size()); - *new_value = e::slice(ptr, new_value->size()); - return true; + *new_value = old_value; + if (funcs_sz > 0) + { + assert(funcs[funcs_sz - 1].name == FUNC_SET); + *new_value = funcs[funcs_sz - 1].arg1; + } + uint8_t *ptr = NULL; + new_memory->allocate(new_value->size(), &ptr); + memmove(ptr, new_value->data(), new_value->size()); + *new_value = e::slice(ptr, new_value->size()); + return true; } diff --git a/common/datatype_macaroon_secret.h b/common/datatype_macaroon_secret.h index 7c01aa979..76263dd16 100644 --- a/common/datatype_macaroon_secret.h +++ b/common/datatype_macaroon_secret.h @@ -36,18 +36,18 @@ BEGIN_HYPERDEX_NAMESPACE class datatype_macaroon_secret : public datatype_info { - public: - datatype_macaroon_secret(); - virtual ~datatype_macaroon_secret() throw (); +public: + datatype_macaroon_secret(); + virtual ~datatype_macaroon_secret() throw (); - public: - virtual hyperdatatype datatype() const; - virtual bool validate(const e::slice& value) const; - virtual bool check_args(const funcall& func) const; - virtual bool apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const; +public: + virtual hyperdatatype datatype() const; + virtual bool validate(const e::slice &value) const; + virtual bool check_args(const funcall &func) const; + virtual bool apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const; }; END_HYPERDEX_NAMESPACE diff --git a/common/datatype_map.cc b/common/datatype_map.cc index 61023116a..3c8c661c0 100644 --- a/common/datatype_map.cc +++ b/common/datatype_map.cc @@ -39,12 +39,12 @@ using hyperdex::datatype_map; -datatype_map :: datatype_map(datatype_info* k, datatype_info* v) - : m_k(k) - , m_v(v) +datatype_map :: datatype_map(datatype_info *k, datatype_info *v) + : m_k(k) + , m_v(v) { - assert(m_k->containable() && m_k->comparable()); - assert(m_v->containable() && m_v->comparable()); + assert(m_k->containable() && m_k->comparable()); + assert(m_v->containable() && m_v->comparable()); } datatype_map :: ~datatype_map() throw () @@ -54,297 +54,271 @@ datatype_map :: ~datatype_map() throw () hyperdatatype datatype_map :: datatype() const { - return CREATE_CONTAINER2(HYPERDATATYPE_MAP_GENERIC, m_k->datatype(), m_v->datatype()); + return CREATE_CONTAINER2(HYPERDATATYPE_MAP_GENERIC, m_k->datatype(), m_v->datatype()); } bool -datatype_map :: validate(const e::slice& map) const +datatype_map :: validate(const e::slice &map) const { - const uint8_t* ptr = map.data(); - const uint8_t* end = map.data() + map.size(); - e::slice key; - e::slice val; - e::slice old; - bool has_old = false; - - while (ptr < end) - { - if (!m_k->step(&ptr, end, &key)) - { - return false; - } - - if (!m_v->step(&ptr, end, &val)) - { - return false; - } - - if (has_old) - { - if (m_k->compare(old, key) >= 0) - { - return false; - } - } - - old = key; - has_old = true; - } - - return ptr == end; + const uint8_t *ptr = map.data(); + const uint8_t *end = map.data() + map.size(); + e::slice key; + e::slice val; + e::slice old; + bool has_old = false; + while (ptr < end) + { + if (!m_k->step(&ptr, end, &key)) + { + return false; + } + if (!m_v->step(&ptr, end, &val)) + { + return false; + } + if (has_old) + { + if (m_k->compare(old, key) >= 0) + { + return false; + } + } + old = key; + has_old = true; + } + return ptr == end; } bool -datatype_map :: check_args(const funcall& func) const +datatype_map :: check_args(const funcall &func) const { - // depending on the operation the arguments may differ - // we must ensure that they match - - // set needs a whole map as an argument - if(func.name == FUNC_SET) - { - return (func.arg1_datatype == datatype() || - func.arg1_datatype == HYPERDATATYPE_MAP_GENERIC) - && validate(func.arg1); - } - // inserting a new element needs a key/value-pair - else if(func.name == FUNC_MAP_ADD) - { - return m_v->validate(func.arg1) && - m_k->validate(func.arg2) && - func.arg1_datatype == m_v->datatype() && - func.arg2_datatype == m_k->datatype(); - } - // Remove only needs a key - else if(func.name == FUNC_MAP_REMOVE) - { - return m_k->validate(func.arg1) && func.arg1_datatype == m_k->datatype(); - } - // Other operations embed their arguments in the second datatype - else if(func.name == FUNC_STRING_APPEND || - func.name == FUNC_STRING_PREPEND || - func.name == FUNC_NUM_ADD || - func.name == FUNC_NUM_SUB || - func.name == FUNC_NUM_MUL || - func.name == FUNC_NUM_DIV || - func.name == FUNC_NUM_MOD || - func.name == FUNC_NUM_AND || - func.name == FUNC_NUM_OR || - func.name == FUNC_NUM_XOR || - func.name == FUNC_NUM_MIN || - func.name == FUNC_NUM_MAX) - { - return m_k->validate(func.arg2) - && func.arg2_datatype == m_k->datatype() - && m_v->check_args(func); - } - else - { - return false; - } + // depending on the operation the arguments may differ + // we must ensure that they match + // set needs a whole map as an argument + if (func.name == FUNC_SET) + { + return (func.arg1_datatype == datatype() || + func.arg1_datatype == HYPERDATATYPE_MAP_GENERIC) + && validate(func.arg1); + } + // inserting a new element needs a key/value-pair + else if (func.name == FUNC_MAP_ADD) + { + return m_v->validate(func.arg1) && + m_k->validate(func.arg2) && + func.arg1_datatype == m_v->datatype() && + func.arg2_datatype == m_k->datatype(); + } + // Remove only needs a key + else if (func.name == FUNC_MAP_REMOVE) + { + return m_k->validate(func.arg1) && func.arg1_datatype == m_k->datatype(); + } + // Other operations embed their arguments in the second datatype + else if (func.name == FUNC_STRING_APPEND || + func.name == FUNC_STRING_PREPEND || + func.name == FUNC_NUM_ADD || + func.name == FUNC_NUM_SUB || + func.name == FUNC_NUM_MUL || + func.name == FUNC_NUM_DIV || + func.name == FUNC_NUM_MOD || + func.name == FUNC_NUM_AND || + func.name == FUNC_NUM_OR || + func.name == FUNC_NUM_XOR || + func.name == FUNC_NUM_MIN || + func.name == FUNC_NUM_MAX) + { + return m_k->validate(func.arg2) + && func.arg2_datatype == m_k->datatype() + && m_v->check_args(func); + } + else + { + return false; + } } bool -datatype_map :: apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const +datatype_map :: apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const { - // Initialize map with the compare operator of the key's datatype - map_t map(m_k->compare_less()); - - const uint8_t* ptr = old_value.data(); - const uint8_t* end = old_value.data() + old_value.size(); - e::slice key; - e::slice val; - - // Read previous data into the map - while (ptr < end) - { - bool stepped; - stepped = m_k->step(&ptr, end, &key); - assert(stepped); - stepped = m_v->step(&ptr, end, &val); - assert(stepped); - map.insert(std::make_pair(key, val)); - } - - for (size_t i = 0; i < funcs_sz; ++i) - { - switch (funcs[i].name) - { - case FUNC_SET: - // Discard current content and insert a new key-value-pair - map.clear(); - ptr = funcs[i].arg1.data(); - end = funcs[i].arg1.data() + funcs[i].arg1.size(); - - while (ptr < end) - { - bool stepped; - stepped = m_k->step(&ptr, end, &key); - assert(stepped); - stepped = m_v->step(&ptr, end, &val); - assert(stepped); - map.insert(std::make_pair(key, val)); - } - - break; - case FUNC_MAP_ADD: - map[funcs[i].arg2] = funcs[i].arg1; - break; - case FUNC_MAP_REMOVE: - map.erase(funcs[i].arg1); - break; - case FUNC_STRING_APPEND: - case FUNC_STRING_PREPEND: - case FUNC_STRING_LTRIM: - case FUNC_STRING_RTRIM: - case FUNC_NUM_ADD: - case FUNC_NUM_MIN: - case FUNC_NUM_MAX: - case FUNC_NUM_SUB: - case FUNC_NUM_MUL: - case FUNC_NUM_DIV: - case FUNC_NUM_MOD: - case FUNC_NUM_AND: - case FUNC_NUM_OR: - case FUNC_NUM_XOR: - // This function is a composite of several subfunctions - if (!apply_inner(&map, funcs + i, new_memory)) - { - return false; - } - - break; - case FUNC_FAIL: - case FUNC_LIST_LPUSH: - case FUNC_LIST_RPUSH: - case FUNC_DOC_RENAME: - case FUNC_DOC_UNSET: - case FUNC_SET_ADD: - case FUNC_SET_REMOVE: - case FUNC_SET_INTERSECT: - case FUNC_SET_UNION: - default: - abort(); - } - } - - size_t sz = 0; - - for (map_t::iterator i = map.begin(); i != map.end(); ++i) - { - sz += m_k->write_sz(i->first); - sz += m_v->write_sz(i->second); - } - - uint8_t* write_to = NULL; - new_memory->allocate(sz, &write_to); - *new_value = e::slice(write_to, sz); - - for (map_t::iterator i = map.begin(); i != map.end(); ++i) - { - write_to = m_k->write(i->first, write_to); - write_to = m_v->write(i->second, write_to); - } - - return true; + // Initialize map with the compare operator of the key's datatype + map_t map(m_k->compare_less()); + const uint8_t *ptr = old_value.data(); + const uint8_t *end = old_value.data() + old_value.size(); + e::slice key; + e::slice val; + // Read previous data into the map + while (ptr < end) + { + bool stepped; + stepped = m_k->step(&ptr, end, &key); + assert(stepped); + stepped = m_v->step(&ptr, end, &val); + assert(stepped); + map.insert(std::make_pair(key, val)); + } + for (size_t i = 0; i < funcs_sz; ++i) + { + switch (funcs[i].name) + { + case FUNC_SET: + // Discard current content and insert a new key-value-pair + map.clear(); + ptr = funcs[i].arg1.data(); + end = funcs[i].arg1.data() + funcs[i].arg1.size(); + while (ptr < end) + { + bool stepped; + stepped = m_k->step(&ptr, end, &key); + assert(stepped); + stepped = m_v->step(&ptr, end, &val); + assert(stepped); + map.insert(std::make_pair(key, val)); + } + break; + case FUNC_MAP_ADD: + map[funcs[i].arg2] = funcs[i].arg1; + break; + case FUNC_MAP_REMOVE: + map.erase(funcs[i].arg1); + break; + case FUNC_STRING_APPEND: + case FUNC_STRING_PREPEND: + case FUNC_STRING_LTRIM: + case FUNC_STRING_RTRIM: + case FUNC_NUM_ADD: + case FUNC_NUM_MIN: + case FUNC_NUM_MAX: + case FUNC_NUM_SUB: + case FUNC_NUM_MUL: + case FUNC_NUM_DIV: + case FUNC_NUM_MOD: + case FUNC_NUM_AND: + case FUNC_NUM_OR: + case FUNC_NUM_XOR: + // This function is a composite of several subfunctions + if (!apply_inner(&map, funcs + i, new_memory)) + { + return false; + } + break; + case FUNC_FAIL: + case FUNC_LIST_LPUSH: + case FUNC_LIST_RPUSH: + case FUNC_DOC_RENAME: + case FUNC_DOC_UNSET: + case FUNC_SET_ADD: + case FUNC_SET_REMOVE: + case FUNC_SET_INTERSECT: + case FUNC_SET_UNION: + default: + abort(); + } + } + size_t sz = 0; + for (map_t::iterator i = map.begin(); i != map.end(); ++i) + { + sz += m_k->write_sz(i->first); + sz += m_v->write_sz(i->second); + } + uint8_t *write_to = NULL; + new_memory->allocate(sz, &write_to); + *new_value = e::slice(write_to, sz); + for (map_t::iterator i = map.begin(); i != map.end(); ++i) + { + write_to = m_k->write(i->first, write_to); + write_to = m_v->write(i->second, write_to); + } + return true; } bool -datatype_map :: apply_inner(map_t* m, - const funcall* func, - e::arena* new_memory) const +datatype_map :: apply_inner(map_t *m, + const funcall *func, + e::arena *new_memory) const { - map_t::iterator it = m->find(func->arg2); - e::slice old_value("", 0); - - if (it != m->end()) - { - old_value = it->second; - } - - e::slice new_value; - - if (!m_v->apply(old_value, func, 1, new_memory, &new_value)) - { - return false; - } - - (*m)[func->arg2] = new_value; - return true; + map_t::iterator it = m->find(func->arg2); + e::slice old_value("", 0); + if (it != m->end()) + { + old_value = it->second; + } + e::slice new_value; + if (!m_v->apply(old_value, func, 1, new_memory, &new_value)) + { + return false; + } + (*m)[func->arg2] = new_value; + return true; } bool datatype_map :: indexable() const { - return m_k->indexable(); + return m_k->indexable(); } bool datatype_map :: has_length() const { - return true; + return true; } uint64_t -datatype_map :: length(const e::slice& map) const +datatype_map :: length(const e::slice &map) const { - const uint8_t* ptr = map.data(); - const uint8_t* end = map.data() + map.size(); - e::slice key; - e::slice val; - uint64_t count = 0; - - while (ptr < end) - { - bool stepped; - stepped = m_k->step(&ptr, end, &key); - assert(stepped); - stepped = m_v->step(&ptr, end, &val); - assert(stepped); - ++count; - } - - assert(ptr == end); - return count; + const uint8_t *ptr = map.data(); + const uint8_t *end = map.data() + map.size(); + e::slice key; + e::slice val; + uint64_t count = 0; + while (ptr < end) + { + bool stepped; + stepped = m_k->step(&ptr, end, &key); + assert(stepped); + stepped = m_v->step(&ptr, end, &val); + assert(stepped); + ++count; + } + assert(ptr == end); + return count; } bool datatype_map :: has_contains() const { - return true; + return true; } hyperdatatype datatype_map :: contains_datatype() const { - return m_k->datatype(); + return m_k->datatype(); } bool -datatype_map :: contains(const e::slice& map, const e::slice& needle) const +datatype_map :: contains(const e::slice &map, const e::slice &needle) const { - const uint8_t* ptr = map.data(); - const uint8_t* end = map.data() + map.size(); - e::slice key; - e::slice val; - - while (ptr < end) - { - bool stepped; - stepped = m_k->step(&ptr, end, &key); - assert(stepped); - stepped = m_v->step(&ptr, end, &val); - assert(stepped); - - if (key == needle) - { - return true; - } - } - - assert(ptr == end); - return false; + const uint8_t *ptr = map.data(); + const uint8_t *end = map.data() + map.size(); + e::slice key; + e::slice val; + while (ptr < end) + { + bool stepped; + stepped = m_k->step(&ptr, end, &key); + assert(stepped); + stepped = m_v->step(&ptr, end, &val); + assert(stepped); + if (key == needle) + { + return true; + } + } + assert(ptr == end); + return false; } diff --git a/common/datatype_map.h b/common/datatype_map.h index b1966476e..79aad8051 100644 --- a/common/datatype_map.h +++ b/common/datatype_map.h @@ -42,48 +42,48 @@ BEGIN_HYPERDEX_NAMESPACE class datatype_map : public datatype_info { - public: - datatype_map(datatype_info* k, datatype_info* v); - virtual ~datatype_map() throw (); - - public: - virtual hyperdatatype datatype() const; - virtual bool validate(const e::slice& value) const; - virtual bool check_args(const funcall& func) const; - virtual bool apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const; - - public: - virtual bool indexable() const; - - public: - virtual bool has_length() const; - virtual uint64_t length(const e::slice& value) const; - - public: - virtual bool has_contains() const; - virtual hyperdatatype contains_datatype() const; - virtual bool contains(const e::slice& value, const e::slice& needle) const; - - private: - typedef std::map map_t; - - private: - datatype_map(const datatype_map&); - datatype_map& operator = (const datatype_map&); - - private: - bool apply_inner(map_t* m, - const funcall* func, - e::arena* new_memory) const; - - private: - // Datatype of the keys - datatype_info* m_k; - // Datatype of the values - datatype_info* m_v; +public: + datatype_map(datatype_info *k, datatype_info *v); + virtual ~datatype_map() throw (); + +public: + virtual hyperdatatype datatype() const; + virtual bool validate(const e::slice &value) const; + virtual bool check_args(const funcall &func) const; + virtual bool apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const; + +public: + virtual bool indexable() const; + +public: + virtual bool has_length() const; + virtual uint64_t length(const e::slice &value) const; + +public: + virtual bool has_contains() const; + virtual hyperdatatype contains_datatype() const; + virtual bool contains(const e::slice &value, const e::slice &needle) const; + +private: + typedef std::map map_t; + +private: + datatype_map(const datatype_map &); + datatype_map &operator = (const datatype_map &); + +private: + bool apply_inner(map_t *m, + const funcall *func, + e::arena *new_memory) const; + +private: + // Datatype of the keys + datatype_info *m_k; + // Datatype of the values + datatype_info *m_v; }; END_HYPERDEX_NAMESPACE diff --git a/common/datatype_set.cc b/common/datatype_set.cc index 811b1e91c..6f97282e9 100644 --- a/common/datatype_set.cc +++ b/common/datatype_set.cc @@ -43,10 +43,10 @@ using hyperdex::datatype_set; -datatype_set :: datatype_set(datatype_info* elem) - : m_elem(elem) +datatype_set :: datatype_set(datatype_info *elem) + : m_elem(elem) { - assert(m_elem->containable() && m_elem->comparable()); + assert(m_elem->containable() && m_elem->comparable()); } datatype_set :: ~datatype_set() throw () @@ -56,224 +56,203 @@ datatype_set :: ~datatype_set() throw () hyperdatatype datatype_set :: datatype() const { - return CREATE_CONTAINER(HYPERDATATYPE_SET_GENERIC, m_elem->datatype()); + return CREATE_CONTAINER(HYPERDATATYPE_SET_GENERIC, m_elem->datatype()); } bool -datatype_set :: validate(const e::slice& set) const +datatype_set :: validate(const e::slice &set) const { - const uint8_t* ptr = set.data(); - const uint8_t* end = set.data() + set.size(); - e::slice elem; - e::slice old; - bool has_old = false; - - while (ptr < end) - { - if (!m_elem->step(&ptr, end, &elem)) - { - return false; - } - - if (has_old) - { - if (m_elem->compare(old, elem) >= 0) - { - return false; - } - } - - old = elem; - has_old = true; - } - - return ptr == end; + const uint8_t *ptr = set.data(); + const uint8_t *end = set.data() + set.size(); + e::slice elem; + e::slice old; + bool has_old = false; + while (ptr < end) + { + if (!m_elem->step(&ptr, end, &elem)) + { + return false; + } + if (has_old) + { + if (m_elem->compare(old, elem) >= 0) + { + return false; + } + } + old = elem; + has_old = true; + } + return ptr == end; } bool -datatype_set :: check_args(const funcall& func) const +datatype_set :: check_args(const funcall &func) const { - return ((func.arg1_datatype == datatype() || - func.arg1_datatype == HYPERDATATYPE_SET_GENERIC) && - validate(func.arg1) && - (func.name == FUNC_SET || - func.name == FUNC_SET_UNION || - func.name == FUNC_SET_INTERSECT)) || - (func.arg1_datatype == m_elem->datatype() && - m_elem->validate(func.arg1) && - (func.name == FUNC_SET_ADD || - func.name == FUNC_SET_REMOVE)); + return ((func.arg1_datatype == datatype() || + func.arg1_datatype == HYPERDATATYPE_SET_GENERIC) && + validate(func.arg1) && + (func.name == FUNC_SET || + func.name == FUNC_SET_UNION || + func.name == FUNC_SET_INTERSECT)) || + (func.arg1_datatype == m_elem->datatype() && + m_elem->validate(func.arg1) && + (func.name == FUNC_SET_ADD || + func.name == FUNC_SET_REMOVE)); } bool -datatype_set :: apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const +datatype_set :: apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const { - typedef std::set set_t; - set_t set(m_elem->compare_less()); - set_t tmp(m_elem->compare_less()); - const uint8_t* ptr = old_value.data(); - const uint8_t* end = old_value.data() + old_value.size(); - e::slice elem; - - while (ptr < end) - { - bool stepped = m_elem->step(&ptr, end, &elem); - assert(stepped); // safe because of check_args - set.insert(elem); - } - - for (size_t i = 0; i < funcs_sz; ++i) - { - switch (funcs[i].name) - { - case FUNC_SET: - set.clear(); - // intentional fall-through - case FUNC_SET_UNION: - ptr = funcs[i].arg1.data(); - end = funcs[i].arg1.data() + funcs[i].arg1.size(); - - while (ptr < end) - { - bool stepped = m_elem->step(&ptr, end, &elem); - assert(stepped); // safe because of check_args - set.insert(elem); - } - - break; - case FUNC_SET_ADD: - set.insert(funcs[i].arg1); - break; - case FUNC_SET_REMOVE: - set.erase(funcs[i].arg1); - break; - case FUNC_SET_INTERSECT: - tmp.clear(); - ptr = funcs[i].arg1.data(); - end = funcs[i].arg1.data() + funcs[i].arg1.size(); - - while (ptr < end) - { - bool stepped = m_elem->step(&ptr, end, &elem); - assert(stepped); // safe because of check_args - - if (set.find(elem) != set.end()) - { - tmp.insert(elem); - } - } - - set.swap(tmp); - break; - case FUNC_FAIL: - case FUNC_STRING_APPEND: - case FUNC_STRING_PREPEND: - case FUNC_STRING_LTRIM: - case FUNC_STRING_RTRIM: - case FUNC_NUM_ADD: - case FUNC_NUM_SUB: - case FUNC_NUM_MUL: - case FUNC_NUM_DIV: - case FUNC_NUM_MOD: - case FUNC_NUM_AND: - case FUNC_NUM_OR: - case FUNC_NUM_XOR: - case FUNC_NUM_MIN: - case FUNC_NUM_MAX: - case FUNC_DOC_RENAME: - case FUNC_DOC_UNSET: - case FUNC_LIST_LPUSH: - case FUNC_LIST_RPUSH: - case FUNC_MAP_ADD: - case FUNC_MAP_REMOVE: - default: - abort(); - } - } - - size_t sz = 0; - - for (set_t::iterator i = set.begin(); i != set.end(); ++i) - { - sz += m_elem->write_sz(*i); - } - - uint8_t* write_to = NULL; - new_memory->allocate(sz, &write_to); - *new_value = e::slice(write_to, sz); - - for (set_t::iterator i = set.begin(); i != set.end(); ++i) - { - write_to = m_elem->write(*i, write_to); - } - - return true; + typedef std::set set_t; + set_t set(m_elem->compare_less()); + set_t tmp(m_elem->compare_less()); + const uint8_t *ptr = old_value.data(); + const uint8_t *end = old_value.data() + old_value.size(); + e::slice elem; + while (ptr < end) + { + bool stepped = m_elem->step(&ptr, end, &elem); + assert(stepped); // safe because of check_args + set.insert(elem); + } + for (size_t i = 0; i < funcs_sz; ++i) + { + switch (funcs[i].name) + { + case FUNC_SET: + set.clear(); + // intentional fall-through + case FUNC_SET_UNION: + ptr = funcs[i].arg1.data(); + end = funcs[i].arg1.data() + funcs[i].arg1.size(); + while (ptr < end) + { + bool stepped = m_elem->step(&ptr, end, &elem); + assert(stepped); // safe because of check_args + set.insert(elem); + } + break; + case FUNC_SET_ADD: + set.insert(funcs[i].arg1); + break; + case FUNC_SET_REMOVE: + set.erase(funcs[i].arg1); + break; + case FUNC_SET_INTERSECT: + tmp.clear(); + ptr = funcs[i].arg1.data(); + end = funcs[i].arg1.data() + funcs[i].arg1.size(); + while (ptr < end) + { + bool stepped = m_elem->step(&ptr, end, &elem); + assert(stepped); // safe because of check_args + if (set.find(elem) != set.end()) + { + tmp.insert(elem); + } + } + set.swap(tmp); + break; + case FUNC_FAIL: + case FUNC_STRING_APPEND: + case FUNC_STRING_PREPEND: + case FUNC_STRING_LTRIM: + case FUNC_STRING_RTRIM: + case FUNC_NUM_ADD: + case FUNC_NUM_SUB: + case FUNC_NUM_MUL: + case FUNC_NUM_DIV: + case FUNC_NUM_MOD: + case FUNC_NUM_AND: + case FUNC_NUM_OR: + case FUNC_NUM_XOR: + case FUNC_NUM_MIN: + case FUNC_NUM_MAX: + case FUNC_DOC_RENAME: + case FUNC_DOC_UNSET: + case FUNC_LIST_LPUSH: + case FUNC_LIST_RPUSH: + case FUNC_MAP_ADD: + case FUNC_MAP_REMOVE: + default: + abort(); + } + } + size_t sz = 0; + for (set_t::iterator i = set.begin(); i != set.end(); ++i) + { + sz += m_elem->write_sz(*i); + } + uint8_t *write_to = NULL; + new_memory->allocate(sz, &write_to); + *new_value = e::slice(write_to, sz); + for (set_t::iterator i = set.begin(); i != set.end(); ++i) + { + write_to = m_elem->write(*i, write_to); + } + return true; } bool datatype_set :: indexable() const { - return m_elem->indexable(); + return m_elem->indexable(); } bool datatype_set :: has_length() const { - return true; + return true; } uint64_t -datatype_set :: length(const e::slice& set) const +datatype_set :: length(const e::slice &set) const { - const uint8_t* ptr = set.data(); - const uint8_t* end = set.data() + set.size(); - e::slice elem; - uint64_t count = 0; - - while (ptr < end) - { - bool stepped = m_elem->step(&ptr, end, &elem); - assert(stepped); - ++count; - } - - assert(ptr == end); - return count; + const uint8_t *ptr = set.data(); + const uint8_t *end = set.data() + set.size(); + e::slice elem; + uint64_t count = 0; + while (ptr < end) + { + bool stepped = m_elem->step(&ptr, end, &elem); + assert(stepped); + ++count; + } + assert(ptr == end); + return count; } bool datatype_set :: has_contains() const { - return true; + return true; } hyperdatatype datatype_set :: contains_datatype() const { - return m_elem->datatype(); + return m_elem->datatype(); } bool -datatype_set :: contains(const e::slice& set, const e::slice& needle) const +datatype_set :: contains(const e::slice &set, const e::slice &needle) const { - const uint8_t* ptr = set.data(); - const uint8_t* end = set.data() + set.size(); - e::slice elem; - - while (ptr < end) - { - bool stepped = m_elem->step(&ptr, end, &elem); - assert(stepped); - - if (elem == needle) - { - return true; - } - } - - assert(ptr == end); - return false; + const uint8_t *ptr = set.data(); + const uint8_t *end = set.data() + set.size(); + e::slice elem; + while (ptr < end) + { + bool stepped = m_elem->step(&ptr, end, &elem); + assert(stepped); + if (elem == needle) + { + return true; + } + } + assert(ptr == end); + return false; } diff --git a/common/datatype_set.h b/common/datatype_set.h index 01b3a2ebf..608cca864 100644 --- a/common/datatype_set.h +++ b/common/datatype_set.h @@ -36,37 +36,37 @@ BEGIN_HYPERDEX_NAMESPACE class datatype_set : public datatype_info { - public: - datatype_set(datatype_info* elem); - virtual ~datatype_set() throw (); +public: + datatype_set(datatype_info *elem); + virtual ~datatype_set() throw (); - public: - virtual hyperdatatype datatype() const; - virtual bool validate(const e::slice& value) const; - virtual bool check_args(const funcall& func) const; - virtual bool apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const; +public: + virtual hyperdatatype datatype() const; + virtual bool validate(const e::slice &value) const; + virtual bool check_args(const funcall &func) const; + virtual bool apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const; - public: - virtual bool indexable() const; +public: + virtual bool indexable() const; - public: - virtual bool has_length() const; - virtual uint64_t length(const e::slice& value) const; +public: + virtual bool has_length() const; + virtual uint64_t length(const e::slice &value) const; - public: - virtual bool has_contains() const; - virtual hyperdatatype contains_datatype() const; - virtual bool contains(const e::slice& value, const e::slice& needle) const; +public: + virtual bool has_contains() const; + virtual hyperdatatype contains_datatype() const; + virtual bool contains(const e::slice &value, const e::slice &needle) const; - private: - datatype_set(const datatype_set&); - datatype_set& operator = (const datatype_set&); +private: + datatype_set(const datatype_set &); + datatype_set &operator = (const datatype_set &); - private: - datatype_info* m_elem; +private: + datatype_info *m_elem; }; END_HYPERDEX_NAMESPACE diff --git a/common/datatype_string.cc b/common/datatype_string.cc index 4440c2ed2..f8ecf8c94 100644 --- a/common/datatype_string.cc +++ b/common/datatype_string.cc @@ -51,253 +51,242 @@ datatype_string :: ~datatype_string() throw () hyperdatatype datatype_string :: datatype() const { - return HYPERDATATYPE_STRING; + return HYPERDATATYPE_STRING; } bool -datatype_string :: validate(const e::slice&) const +datatype_string :: validate(const e::slice &) const { - return true; + return true; } bool -datatype_string :: check_args(const funcall& func) const +datatype_string :: check_args(const funcall &func) const { - if (func.name == FUNC_SET || - func.name == FUNC_STRING_PREPEND || - func.name == FUNC_STRING_APPEND) - { - return func.arg1_datatype == HYPERDATATYPE_STRING && - validate(func.arg1); - } - else if (func.name == FUNC_STRING_LTRIM || - func.name == FUNC_STRING_RTRIM) - { - datatype_info* di = datatype_info::lookup(HYPERDATATYPE_INT64); - - if (func.arg1_datatype != HYPERDATATYPE_INT64 || - !di->validate(func.arg1)) - { - return false; - } - - return datatype_int64::unpack(func.arg1) >= 0; - } - else - { - return false; - } + if (func.name == FUNC_SET || + func.name == FUNC_STRING_PREPEND || + func.name == FUNC_STRING_APPEND) + { + return func.arg1_datatype == HYPERDATATYPE_STRING && + validate(func.arg1); + } + else if (func.name == FUNC_STRING_LTRIM || + func.name == FUNC_STRING_RTRIM) + { + datatype_info *di = datatype_info::lookup(HYPERDATATYPE_INT64); + if (func.arg1_datatype != HYPERDATATYPE_INT64 || + !di->validate(func.arg1)) + { + return false; + } + return datatype_int64::unpack(func.arg1) >= 0; + } + else + { + return false; + } } bool -datatype_string :: apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const +datatype_string :: apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const { - size_t alloc_sz = old_value.size(); - - for (size_t i = 0; i < funcs_sz; ++i) - { - alloc_sz += funcs[i].arg1.size(); - } - - uint8_t* ptr = NULL; - new_memory->allocate(alloc_sz, &ptr); - size_t sz = old_value.size(); - memmove(ptr, old_value.data(), sz); - int64_t x = 0; - - for (size_t i = 0; i < funcs_sz; ++i) - { - switch (funcs[i].name) - { - case FUNC_SET: - // Overwrite - memmove(ptr, funcs[i].arg1.data(), funcs[i].arg1.size()); - sz = funcs[i].arg1.size(); - break; - case FUNC_STRING_PREPEND: - // Shift - memmove(ptr + funcs[i].arg1.size(), ptr, sz); - // Fill - memmove(ptr, funcs[i].arg1.data(), funcs[i].arg1.size()); - // Resize - sz += funcs[i].arg1.size(); - break; - case FUNC_STRING_APPEND: - // Fill - memmove(ptr + sz, funcs[i].arg1.data(), funcs[i].arg1.size()); - // Resize - sz += funcs[i].arg1.size(); - break; - case FUNC_STRING_LTRIM: - x = datatype_int64::unpack(funcs[i].arg1); - x = uint64_t(x) > sz ? sz : x; - sz -= x; - memmove(ptr, ptr + x, sz); - break; - case FUNC_STRING_RTRIM: - x = datatype_int64::unpack(funcs[i].arg1); - x = uint64_t(x) > sz ? sz : x; - sz -= x; - break; - case FUNC_FAIL: - case FUNC_NUM_ADD: - case FUNC_NUM_SUB: - case FUNC_NUM_MUL: - case FUNC_NUM_DIV: - case FUNC_NUM_MOD: - case FUNC_NUM_AND: - case FUNC_NUM_OR: - case FUNC_NUM_XOR: - case FUNC_NUM_MAX: - case FUNC_NUM_MIN: - case FUNC_LIST_LPUSH: - case FUNC_LIST_RPUSH: - case FUNC_SET_ADD: - case FUNC_SET_REMOVE: - case FUNC_SET_INTERSECT: - case FUNC_SET_UNION: - case FUNC_MAP_ADD: - case FUNC_MAP_REMOVE: - case FUNC_DOC_RENAME: - case FUNC_DOC_UNSET: - default: - abort(); - } - } - - *new_value = e::slice(ptr, sz); - return true; + size_t alloc_sz = old_value.size(); + for (size_t i = 0; i < funcs_sz; ++i) + { + alloc_sz += funcs[i].arg1.size(); + } + uint8_t *ptr = NULL; + new_memory->allocate(alloc_sz, &ptr); + size_t sz = old_value.size(); + memmove(ptr, old_value.data(), sz); + int64_t x = 0; + for (size_t i = 0; i < funcs_sz; ++i) + { + switch (funcs[i].name) + { + case FUNC_SET: + // Overwrite + memmove(ptr, funcs[i].arg1.data(), funcs[i].arg1.size()); + sz = funcs[i].arg1.size(); + break; + case FUNC_STRING_PREPEND: + // Shift + memmove(ptr + funcs[i].arg1.size(), ptr, sz); + // Fill + memmove(ptr, funcs[i].arg1.data(), funcs[i].arg1.size()); + // Resize + sz += funcs[i].arg1.size(); + break; + case FUNC_STRING_APPEND: + // Fill + memmove(ptr + sz, funcs[i].arg1.data(), funcs[i].arg1.size()); + // Resize + sz += funcs[i].arg1.size(); + break; + case FUNC_STRING_LTRIM: + x = datatype_int64::unpack(funcs[i].arg1); + x = uint64_t(x) > sz ? sz : x; + sz -= x; + memmove(ptr, ptr + x, sz); + break; + case FUNC_STRING_RTRIM: + x = datatype_int64::unpack(funcs[i].arg1); + x = uint64_t(x) > sz ? sz : x; + sz -= x; + break; + case FUNC_FAIL: + case FUNC_NUM_ADD: + case FUNC_NUM_SUB: + case FUNC_NUM_MUL: + case FUNC_NUM_DIV: + case FUNC_NUM_MOD: + case FUNC_NUM_AND: + case FUNC_NUM_OR: + case FUNC_NUM_XOR: + case FUNC_NUM_MAX: + case FUNC_NUM_MIN: + case FUNC_LIST_LPUSH: + case FUNC_LIST_RPUSH: + case FUNC_SET_ADD: + case FUNC_SET_REMOVE: + case FUNC_SET_INTERSECT: + case FUNC_SET_UNION: + case FUNC_MAP_ADD: + case FUNC_MAP_REMOVE: + case FUNC_DOC_RENAME: + case FUNC_DOC_UNSET: + default: + abort(); + } + } + *new_value = e::slice(ptr, sz); + return true; } bool datatype_string :: hashable() const { - return true; + return true; } uint64_t -datatype_string :: hash(const e::slice& value) const +datatype_string :: hash(const e::slice &value) const { - return CityHash64(reinterpret_cast(value.data()), value.size()); + return CityHash64(reinterpret_cast(value.data()), value.size()); } bool datatype_string :: indexable() const { - return true; + return true; } bool datatype_string :: has_length() const { - return true; + return true; } uint64_t -datatype_string :: length(const e::slice& value) const +datatype_string :: length(const e::slice &value) const { - return value.size(); + return value.size(); } bool datatype_string :: has_regex() const { - return true; + return true; } bool -datatype_string :: regex(const e::slice& r, - const e::slice& v) const +datatype_string :: regex(const e::slice &r, + const e::slice &v) const { - return regex_match(r.data(), r.size(), v.data(), v.size()); + return regex_match(r.data(), r.size(), v.data(), v.size()); } bool datatype_string :: containable() const { - return true; + return true; } bool -datatype_string :: step(const uint8_t** ptr, - const uint8_t* end, - e::slice* elem) const +datatype_string :: step(const uint8_t **ptr, + const uint8_t *end, + e::slice *elem) const { - if (static_cast(end - *ptr) < sizeof(uint32_t)) - { - return false; - } - - uint32_t sz = 0; - *ptr = e::unpack32le(*ptr, &sz); - *elem = e::slice(*ptr, sz); - *ptr += sz; - return *ptr <= end; + if (static_cast(end - *ptr) < sizeof(uint32_t)) + { + return false; + } + uint32_t sz = 0; + *ptr = e::unpack32le(*ptr, &sz); + *elem = e::slice(*ptr, sz); + *ptr += sz; + return *ptr <= end; } uint64_t -datatype_string :: write_sz(const e::slice& elem) const +datatype_string :: write_sz(const e::slice &elem) const { - return sizeof(uint32_t) + elem.size(); + return sizeof(uint32_t) + elem.size(); } -uint8_t* -datatype_string :: write(const e::slice& elem, - uint8_t* write_to) const +uint8_t * +datatype_string :: write(const e::slice &elem, + uint8_t *write_to) const { - memmove(write_to + sizeof(uint32_t), elem.data(), elem.size()); - e::pack32le(elem.size(), write_to); - return write_to + sizeof(uint32_t) + elem.size(); + memmove(write_to + sizeof(uint32_t), elem.data(), elem.size()); + e::pack32le(elem.size(), write_to); + return write_to + sizeof(uint32_t) + elem.size(); } bool datatype_string :: comparable() const { - return true; + return true; } static int -compare(const e::slice& lhs, - const e::slice& rhs) +compare(const e::slice &lhs, + const e::slice &rhs) { - int cmp = memcmp(lhs.data(), rhs.data(), std::min(lhs.size(), rhs.size())); - - if (cmp == 0) - { - if (lhs.size() < rhs.size()) - { - return -1; - } - - if (lhs.size() > rhs.size()) - { - return 1; - } - - return 0; - } - - return cmp; + int cmp = memcmp(lhs.data(), rhs.data(), std::min(lhs.size(), rhs.size())); + if (cmp == 0) + { + if (lhs.size() < rhs.size()) + { + return -1; + } + if (lhs.size() > rhs.size()) + { + return 1; + } + return 0; + } + return cmp; } int -datatype_string :: compare(const e::slice& lhs, const e::slice& rhs) const +datatype_string :: compare(const e::slice &lhs, const e::slice &rhs) const { - return ::compare(lhs, rhs); + return ::compare(lhs, rhs); } static bool -compare_less(const e::slice& lhs, - const e::slice& rhs) +compare_less(const e::slice &lhs, + const e::slice &rhs) { - return compare(lhs, rhs) < 0; + return compare(lhs, rhs) < 0; } datatype_info::compares_less datatype_string :: compare_less() const { - return &::compare_less; + return &::compare_less; } diff --git a/common/datatype_string.h b/common/datatype_string.h index f7e84c50a..65127d81c 100644 --- a/common/datatype_string.h +++ b/common/datatype_string.h @@ -36,46 +36,46 @@ BEGIN_HYPERDEX_NAMESPACE class datatype_string : public datatype_info { - public: - datatype_string(); - virtual ~datatype_string() throw (); +public: + datatype_string(); + virtual ~datatype_string() throw (); - public: - virtual hyperdatatype datatype() const; - virtual bool validate(const e::slice& value) const; - virtual bool check_args(const funcall& func) const; - virtual bool apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const; +public: + virtual hyperdatatype datatype() const; + virtual bool validate(const e::slice &value) const; + virtual bool check_args(const funcall &func) const; + virtual bool apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const; - public: - virtual bool hashable() const; - virtual uint64_t hash(const e::slice& value) const; - virtual bool indexable() const; +public: + virtual bool hashable() const; + virtual uint64_t hash(const e::slice &value) const; + virtual bool indexable() const; - public: - virtual bool has_length() const; - virtual uint64_t length(const e::slice& value) const; +public: + virtual bool has_length() const; + virtual uint64_t length(const e::slice &value) const; - public: - virtual bool has_regex() const; - virtual bool regex(const e::slice& regex, - const e::slice& value) const; +public: + virtual bool has_regex() const; + virtual bool regex(const e::slice ®ex, + const e::slice &value) const; - public: - virtual bool containable() const; - virtual bool step(const uint8_t** ptr, - const uint8_t* end, - e::slice* elem) const; - virtual uint64_t write_sz(const e::slice& elem) const; - virtual uint8_t* write(const e::slice& elem, - uint8_t* write_to) const; +public: + virtual bool containable() const; + virtual bool step(const uint8_t **ptr, + const uint8_t *end, + e::slice *elem) const; + virtual uint64_t write_sz(const e::slice &elem) const; + virtual uint8_t *write(const e::slice &elem, + uint8_t *write_to) const; - public: - virtual bool comparable() const; - virtual int compare(const e::slice& lhs, const e::slice& rhs) const; - virtual compares_less compare_less() const; +public: + virtual bool comparable() const; + virtual int compare(const e::slice &lhs, const e::slice &rhs) const; + virtual compares_less compare_less() const; }; END_HYPERDEX_NAMESPACE diff --git a/common/datatype_timestamp.cc b/common/datatype_timestamp.cc index 9e3b9b6fe..97568de33 100644 --- a/common/datatype_timestamp.cc +++ b/common/datatype_timestamp.cc @@ -41,26 +41,24 @@ namespace { int64_t -unpack(const e::slice& value) +unpack(const e::slice &value) { - assert(value.size() == sizeof(int64_t) || value.empty()); - - if (value.empty()) - { - return 0; - } - - int64_t timestamp; - e::unpack64le(value.data(), ×tamp); - return timestamp; + assert(value.size() == sizeof(int64_t) || value.empty()); + if (value.empty()) + { + return 0; + } + int64_t timestamp; + e::unpack64le(value.data(), ×tamp); + return timestamp; } } datatype_timestamp :: datatype_timestamp(hyperdatatype t) - : m_type(t) + : m_type(t) { - assert(CONTAINER_TYPE(m_type) == HYPERDATATYPE_TIMESTAMP_GENERIC); + assert(CONTAINER_TYPE(m_type) == HYPERDATATYPE_TIMESTAMP_GENERIC); } datatype_timestamp :: ~datatype_timestamp() throw () @@ -70,48 +68,45 @@ datatype_timestamp :: ~datatype_timestamp() throw () hyperdatatype datatype_timestamp :: datatype() const { - return m_type; - + return m_type; } bool -datatype_timestamp :: validate(const e::slice& value) const +datatype_timestamp :: validate(const e::slice &value) const { - return value.size() == sizeof(int64_t) || value.empty(); + return value.size() == sizeof(int64_t) || value.empty(); } bool -datatype_timestamp :: check_args(const funcall& func) const +datatype_timestamp :: check_args(const funcall &func) const { - return func.name == FUNC_SET && func.arg1_datatype == this->datatype() && validate(func.arg1); + return func.name == FUNC_SET && func.arg1_datatype == this->datatype() && validate(func.arg1); } bool -datatype_timestamp :: apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const +datatype_timestamp :: apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const { - int64_t timestamp = unpack(old_value); - - for(size_t i = 0; i < funcs_sz; i++ ) - { - const funcall* func = funcs + i; - assert(func->name == FUNC_SET); - timestamp = unpack(func->arg1); - } - - uint8_t* ptr = NULL; - new_memory->allocate(sizeof(int64_t), &ptr); - e::pack64le(timestamp, ptr); - *new_value = e::slice(ptr, sizeof(int64_t)); - return true; + int64_t timestamp = unpack(old_value); + for (size_t i = 0; i < funcs_sz; i++ ) + { + const funcall *func = funcs + i; + assert(func->name == FUNC_SET); + timestamp = unpack(func->arg1); + } + uint8_t *ptr = NULL; + new_memory->allocate(sizeof(int64_t), &ptr); + e::pack64le(timestamp, ptr); + *new_value = e::slice(ptr, sizeof(int64_t)); + return true; } bool datatype_timestamp::hashable() const { - return true; + return true; } #define INT_SECONDS 60 @@ -126,7 +121,8 @@ const uint64_t INTERVALS[] = {INT_SECONDS, INT_HOURS, INT_DAYS, INT_WEEKS, - INT_MONTHS}; + INT_MONTHS + }; const unsigned TABLE_SECOND[] = {0, 1, 2, 3, 4, 5, 6}; const unsigned TABLE_MINUTE[] = {1, 0, 2, 3, 4, 5, 6}; @@ -136,169 +132,160 @@ const unsigned TABLE_WEEK[] = {4, 3, 2, 1, 0, 5, 6}; const unsigned TABLE_MONTH[] = {5, 4, 3, 2, 1, 0, 6}; uint64_t -datatype_timestamp :: hash(const e::slice& v) const +datatype_timestamp :: hash(const e::slice &v) const { - uint64_t timestamp = unpack(v); - const unsigned* table = NULL; - uint64_t value[7]; - - switch (m_type) - { - case HYPERDATATYPE_TIMESTAMP_SECOND: - table = TABLE_SECOND; - break; - case HYPERDATATYPE_TIMESTAMP_MINUTE: - table = TABLE_MINUTE; - break; - case HYPERDATATYPE_TIMESTAMP_HOUR: - table = TABLE_HOUR; - break; - case HYPERDATATYPE_TIMESTAMP_DAY: - table = TABLE_DAY; - break; - case HYPERDATATYPE_TIMESTAMP_WEEK: - table = TABLE_WEEK; - break; - case HYPERDATATYPE_TIMESTAMP_MONTH: - table = TABLE_MONTH; - break; - case HYPERDATATYPE_GENERIC: - case HYPERDATATYPE_STRING: - case HYPERDATATYPE_INT64: - case HYPERDATATYPE_FLOAT: - case HYPERDATATYPE_DOCUMENT: - case HYPERDATATYPE_LIST_GENERIC: - case HYPERDATATYPE_LIST_STRING: - case HYPERDATATYPE_LIST_INT64: - case HYPERDATATYPE_LIST_FLOAT: - case HYPERDATATYPE_SET_GENERIC: - case HYPERDATATYPE_SET_STRING: - case HYPERDATATYPE_SET_INT64: - case HYPERDATATYPE_SET_FLOAT: - case HYPERDATATYPE_MAP_GENERIC: - case HYPERDATATYPE_MAP_STRING_KEYONLY: - case HYPERDATATYPE_MAP_STRING_STRING: - case HYPERDATATYPE_MAP_STRING_INT64: - case HYPERDATATYPE_MAP_STRING_FLOAT: - case HYPERDATATYPE_MAP_INT64_KEYONLY: - case HYPERDATATYPE_MAP_INT64_STRING: - case HYPERDATATYPE_MAP_INT64_INT64: - case HYPERDATATYPE_MAP_INT64_FLOAT: - case HYPERDATATYPE_MAP_FLOAT_KEYONLY: - case HYPERDATATYPE_MAP_FLOAT_STRING: - case HYPERDATATYPE_MAP_FLOAT_INT64: - case HYPERDATATYPE_MAP_FLOAT_FLOAT: - case HYPERDATATYPE_TIMESTAMP_GENERIC: - case HYPERDATATYPE_MACAROON_SECRET: - case HYPERDATATYPE_GARBAGE: - default: - return timestamp; - } - - uint64_t x = timestamp / 1000000.; - - for (unsigned i = 0; i < 6; ++i) - { - value[i] = x % INTERVALS[i]; - x /= INTERVALS[i]; - } - - value[6] = x; - assert(table); - uint64_t y = UINT64_MAX; - uint64_t h = 0; - - for (unsigned i = 0; i < 6; ++i) - { - y = y / INTERVALS[table[i]]; - h += value[table[i]] * y; - } - - h += value[table[6]]; - return h; + uint64_t timestamp = unpack(v); + const unsigned *table = NULL; + uint64_t value[7]; + switch (m_type) + { + case HYPERDATATYPE_TIMESTAMP_SECOND: + table = TABLE_SECOND; + break; + case HYPERDATATYPE_TIMESTAMP_MINUTE: + table = TABLE_MINUTE; + break; + case HYPERDATATYPE_TIMESTAMP_HOUR: + table = TABLE_HOUR; + break; + case HYPERDATATYPE_TIMESTAMP_DAY: + table = TABLE_DAY; + break; + case HYPERDATATYPE_TIMESTAMP_WEEK: + table = TABLE_WEEK; + break; + case HYPERDATATYPE_TIMESTAMP_MONTH: + table = TABLE_MONTH; + break; + case HYPERDATATYPE_GENERIC: + case HYPERDATATYPE_STRING: + case HYPERDATATYPE_INT64: + case HYPERDATATYPE_FLOAT: + case HYPERDATATYPE_DOCUMENT: + case HYPERDATATYPE_LIST_GENERIC: + case HYPERDATATYPE_LIST_STRING: + case HYPERDATATYPE_LIST_INT64: + case HYPERDATATYPE_LIST_FLOAT: + case HYPERDATATYPE_SET_GENERIC: + case HYPERDATATYPE_SET_STRING: + case HYPERDATATYPE_SET_INT64: + case HYPERDATATYPE_SET_FLOAT: + case HYPERDATATYPE_MAP_GENERIC: + case HYPERDATATYPE_MAP_STRING_KEYONLY: + case HYPERDATATYPE_MAP_STRING_STRING: + case HYPERDATATYPE_MAP_STRING_INT64: + case HYPERDATATYPE_MAP_STRING_FLOAT: + case HYPERDATATYPE_MAP_INT64_KEYONLY: + case HYPERDATATYPE_MAP_INT64_STRING: + case HYPERDATATYPE_MAP_INT64_INT64: + case HYPERDATATYPE_MAP_INT64_FLOAT: + case HYPERDATATYPE_MAP_FLOAT_KEYONLY: + case HYPERDATATYPE_MAP_FLOAT_STRING: + case HYPERDATATYPE_MAP_FLOAT_INT64: + case HYPERDATATYPE_MAP_FLOAT_FLOAT: + case HYPERDATATYPE_TIMESTAMP_GENERIC: + case HYPERDATATYPE_MACAROON_SECRET: + case HYPERDATATYPE_GARBAGE: + default: + return timestamp; + } + uint64_t x = timestamp / 1000000.; + for (unsigned i = 0; i < 6; ++i) + { + value[i] = x % INTERVALS[i]; + x /= INTERVALS[i]; + } + value[6] = x; + assert(table); + uint64_t y = UINT64_MAX; + uint64_t h = 0; + for (unsigned i = 0; i < 6; ++i) + { + y = y / INTERVALS[table[i]]; + h += value[table[i]] * y; + } + h += value[table[6]]; + return h; } bool datatype_timestamp :: indexable() const { - return true; + return true; } bool datatype_timestamp :: containable() const { - return true; + return true; } bool -datatype_timestamp :: step(const uint8_t** ptr, - const uint8_t* end, - e::slice* elem) const +datatype_timestamp :: step(const uint8_t **ptr, + const uint8_t *end, + e::slice *elem) const { - if (static_cast(end - *ptr) < sizeof(int64_t)) - { - return false; - } - - *elem = e::slice(*ptr, sizeof(int64_t)); - *ptr += sizeof(int64_t); - return true; + if (static_cast(end - *ptr) < sizeof(int64_t)) + { + return false; + } + *elem = e::slice(*ptr, sizeof(int64_t)); + *ptr += sizeof(int64_t); + return true; } uint64_t -datatype_timestamp :: write_sz(const e::slice& elem) const +datatype_timestamp :: write_sz(const e::slice &elem) const { - return elem.size(); + return elem.size(); } -uint8_t* -datatype_timestamp :: write(const e::slice& elem, - uint8_t* write_to) const +uint8_t * +datatype_timestamp :: write(const e::slice &elem, + uint8_t *write_to) const { - memmove(write_to, elem.data(), elem.size()); - return write_to + elem.size(); + memmove(write_to, elem.data(), elem.size()); + return write_to + elem.size(); } bool datatype_timestamp :: comparable() const { - return true; + return true; } static int -compare(const e::slice& lhs, - const e::slice& rhs) +compare(const e::slice &lhs, + const e::slice &rhs) { - int64_t lhsnum = unpack(lhs); - int64_t rhsnum = unpack(rhs); - - if (lhsnum < rhsnum) - { - return -1; - } - if (lhsnum > rhsnum) - { - return 1; - } - - return 0; + int64_t lhsnum = unpack(lhs); + int64_t rhsnum = unpack(rhs); + if (lhsnum < rhsnum) + { + return -1; + } + if (lhsnum > rhsnum) + { + return 1; + } + return 0; } int -datatype_timestamp :: compare(const e::slice& lhs, const e::slice& rhs) const +datatype_timestamp :: compare(const e::slice &lhs, const e::slice &rhs) const { - return ::compare(lhs, rhs); + return ::compare(lhs, rhs); } static bool -compare_less(const e::slice& lhs, - const e::slice& rhs) +compare_less(const e::slice &lhs, + const e::slice &rhs) { - return compare(lhs, rhs) < 0; + return compare(lhs, rhs) < 0; } datatype_info::compares_less datatype_timestamp :: compare_less() const { - return &::compare_less; + return &::compare_less; } diff --git a/common/datatype_timestamp.h b/common/datatype_timestamp.h index 87cb8d9f7..caf84f28c 100644 --- a/common/datatype_timestamp.h +++ b/common/datatype_timestamp.h @@ -36,40 +36,40 @@ BEGIN_HYPERDEX_NAMESPACE class datatype_timestamp : public datatype_info { - public: - datatype_timestamp(hyperdatatype t); - virtual ~datatype_timestamp() throw (); +public: + datatype_timestamp(hyperdatatype t); + virtual ~datatype_timestamp() throw (); - public: - virtual hyperdatatype datatype() const; - virtual bool validate(const e::slice& value) const; - virtual bool check_args(const funcall& func) const; - virtual bool apply(const e::slice& old_value, - const funcall* funcs, size_t funcs_sz, - e::arena* new_memory, - e::slice* new_value) const; +public: + virtual hyperdatatype datatype() const; + virtual bool validate(const e::slice &value) const; + virtual bool check_args(const funcall &func) const; + virtual bool apply(const e::slice &old_value, + const funcall *funcs, size_t funcs_sz, + e::arena *new_memory, + e::slice *new_value) const; - public: - virtual bool hashable() const; - virtual uint64_t hash(const e::slice& value) const; - virtual bool indexable() const; +public: + virtual bool hashable() const; + virtual uint64_t hash(const e::slice &value) const; + virtual bool indexable() const; - public: - virtual bool containable() const; - virtual bool step(const uint8_t** ptr, - const uint8_t* end, - e::slice* elem) const; - virtual uint64_t write_sz(const e::slice& elem) const; - virtual uint8_t* write(const e::slice& elem, - uint8_t* write_to) const; +public: + virtual bool containable() const; + virtual bool step(const uint8_t **ptr, + const uint8_t *end, + e::slice *elem) const; + virtual uint64_t write_sz(const e::slice &elem) const; + virtual uint8_t *write(const e::slice &elem, + uint8_t *write_to) const; - public: - virtual bool comparable() const; - virtual int compare(const e::slice& lhs, const e::slice& rhs) const; - virtual compares_less compare_less() const; +public: + virtual bool comparable() const; + virtual int compare(const e::slice &lhs, const e::slice &rhs) const; + virtual compares_less compare_less() const; - private: - hyperdatatype m_type; +private: + hyperdatatype m_type; }; END_HYPERDEX_NAMESPACE diff --git a/common/documents.cc b/common/documents.cc index 9fbc2f66a..0fd230727 100644 --- a/common/documents.cc +++ b/common/documents.cc @@ -32,30 +32,29 @@ #include "common/documents.h" bool -hyperdex :: is_document_path(const e::slice& p) +hyperdex :: is_document_path(const e::slice &p) { - std::string path(p.cdata(), p.size()); - return treadstone_validate_path(path.c_str()) == 0; + std::string path(p.cdata(), p.size()); + return treadstone_validate_path(path.c_str()) == 0; } void -hyperdex :: parse_document_path(const char* attr_path, - const char** attr, - const char** path, - std::string* scratch) +hyperdex :: parse_document_path(const char *attr_path, + const char **attr, + const char **path, + std::string *scratch) { - *attr = attr_path; - *path = NULL; - - for (size_t i = 0; attr_path[i] != '\0'; ++i) - { - if (attr_path[i] == '[' || - attr_path[i] == '.') - { - scratch->assign(attr_path, attr_path + i); - *attr = scratch->c_str(); - *path = attr_path + i + 1; - break; - } - } + *attr = attr_path; + *path = NULL; + for (size_t i = 0; attr_path[i] != '\0'; ++i) + { + if (attr_path[i] == '[' || + attr_path[i] == '.') + { + scratch->assign(attr_path, attr_path + i); + *attr = scratch->c_str(); + *path = attr_path + i + 1; + break; + } + } } diff --git a/common/documents.h b/common/documents.h index 3eaf218d7..66c432a18 100644 --- a/common/documents.h +++ b/common/documents.h @@ -37,13 +37,13 @@ BEGIN_HYPERDEX_NAMESPACE bool -is_document_path(const e::slice& p); +is_document_path(const e::slice &p); void -parse_document_path(const char* attr_path, - const char** attr, - const char** path, - std::string* scratch); +parse_document_path(const char *attr_path, + const char **attr, + const char **path, + std::string *scratch); END_HYPERDEX_NAMESPACE diff --git a/common/funcall.cc b/common/funcall.cc index d9378fd0b..1cbef0831 100644 --- a/common/funcall.cc +++ b/common/funcall.cc @@ -35,12 +35,12 @@ using hyperdex::funcall; funcall :: funcall() - : attr(UINT16_MAX) - , name(FUNC_FAIL) - , arg1() - , arg1_datatype() - , arg2() - , arg2_datatype() + : attr(UINT16_MAX) + , name(FUNC_FAIL) + , arg1() + , arg1_datatype() + , arg2() + , arg2_datatype() { } @@ -49,189 +49,170 @@ funcall :: ~funcall() throw () } bool -hyperdex :: validate_func(const schema& sc, const funcall& func) +hyperdex :: validate_func(const schema &sc, const funcall &func) { - if (func.attr >= sc.attrs_sz) - { - return false; - } - - datatype_info* di = datatype_info::lookup(sc.attrs[func.attr].type); - - if (!di || !di->check_args(func)) - { - return false; - } - - return true; + if (func.attr >= sc.attrs_sz) + { + return false; + } + datatype_info *di = datatype_info::lookup(sc.attrs[func.attr].type); + if (!di || !di->check_args(func)) + { + return false; + } + return true; } size_t -hyperdex :: validate_funcs(const schema& sc, - const std::vector& funcs) +hyperdex :: validate_funcs(const schema &sc, + const std::vector &funcs) { - for (size_t i = 0; i < funcs.size(); ++i) - { - if ((i > 0 && funcs[i - 1].attr > funcs[i].attr) || - !validate_func(sc, funcs[i])) - { - return i; - } - } - - return funcs.size(); + for (size_t i = 0; i < funcs.size(); ++i) + { + if ((i > 0 && funcs[i - 1].attr > funcs[i].attr) || + !validate_func(sc, funcs[i])) + { + return i; + } + } + return funcs.size(); } size_t -hyperdex :: apply_funcs(const schema& sc, - const std::vector& funcs, - const e::slice& key, - const std::vector& old_value, - e::arena* new_memory, - std::vector* new_value) +hyperdex :: apply_funcs(const schema &sc, + const std::vector &funcs, + const e::slice &key, + const std::vector &old_value, + e::arena *new_memory, + std::vector *new_value) { - // Figure out the size of the new buffer - size_t sz = key.size(); - - // size of the old value. - for (size_t i = 0; i < old_value.size(); ++i) - { - sz += old_value[i].size() + sizeof(uint64_t); - } - - // size of the funcalls. - for (size_t i = 0; i < funcs.size(); ++i) - { - sz += 2 * sizeof(uint32_t) - + funcs[i].arg1.size() - + funcs[i].arg2.size() + sizeof(uint64_t); - } - - new_memory->reserve(sz); - - // Apply the funcalls to each value - const funcall* op = funcs.empty() ? NULL : &funcs.front(); - const funcall* const stop = op + funcs.size(); - // The next attribute to copy, indexed based on the total number of - // dimensions. It starts at 1, because the key is 0, and 1 is the first - // secondary attribute. - uint16_t next_to_copy = 1; - - while (op < stop) - { - const funcall* end = op; - - // Advance until [op, end) is all a continuous range of funcs that all - // apply to the same attribute value. - while (end < stop && op->attr == end->attr) - { - if (end->attr == 0 || - end->attr >= sc.attrs_sz || - end->attr < next_to_copy) - { - return (op - &funcs.front()); - } - - ++end; - } - - // Copy the attributes that are unaffected by funcs. - while (next_to_copy < op->attr) - { - assert(next_to_copy > 0); - size_t idx = next_to_copy - 1; - unsigned char* tmp = NULL; - new_memory->allocate(old_value[idx].size(), &tmp); - memmove(tmp, old_value[idx].data(), old_value[idx].size()); - (*new_value)[idx] = e::slice(tmp, old_value[idx].size()); - ++next_to_copy; - } - - // - "op" now points to the first unapplied funcall - // - "end" points to one funcall past the last op we want to apply - // - we've copied all attributes so far, even those not mentioned by - // funcs. - - // This call may modify [op, end) funcs. - datatype_info* di = datatype_info::lookup(sc.attrs[op->attr].type); - - if (!di->apply(old_value[op->attr - 1], op, end - op, new_memory, &(*new_value)[next_to_copy - 1])) - { - return (op - &funcs.front()); - } - - // Why ++ and assert rather than straight assign? This will help us to - // catch any problems in the interaction between funcs and - // attributes which we just copy. - assert(next_to_copy == op->attr); - ++next_to_copy; - - op = end; - } - - // Copy the attributes that are unaffected by funcs. - while (next_to_copy < sc.attrs_sz) - { - assert(next_to_copy > 0); - size_t idx = next_to_copy - 1; - unsigned char* tmp = NULL; - new_memory->allocate(old_value[idx].size(), &tmp); - memmove(tmp, old_value[idx].data(), old_value[idx].size()); - (*new_value)[idx] = e::slice(tmp, old_value[idx].size()); - ++next_to_copy; - } - - return funcs.size(); + // Figure out the size of the new buffer + size_t sz = key.size(); + // size of the old value. + for (size_t i = 0; i < old_value.size(); ++i) + { + sz += old_value[i].size() + sizeof(uint64_t); + } + // size of the funcalls. + for (size_t i = 0; i < funcs.size(); ++i) + { + sz += 2 * sizeof(uint32_t) + + funcs[i].arg1.size() + + funcs[i].arg2.size() + sizeof(uint64_t); + } + new_memory->reserve(sz); + // Apply the funcalls to each value + const funcall *op = funcs.empty() ? NULL : &funcs.front(); + const funcall *const stop = op + funcs.size(); + // The next attribute to copy, indexed based on the total number of + // dimensions. It starts at 1, because the key is 0, and 1 is the first + // secondary attribute. + uint16_t next_to_copy = 1; + while (op < stop) + { + const funcall *end = op; + // Advance until [op, end) is all a continuous range of funcs that all + // apply to the same attribute value. + while (end < stop && op->attr == end->attr) + { + if (end->attr == 0 || + end->attr >= sc.attrs_sz || + end->attr < next_to_copy) + { + return (op - &funcs.front()); + } + ++end; + } + // Copy the attributes that are unaffected by funcs. + while (next_to_copy < op->attr) + { + assert(next_to_copy > 0); + size_t idx = next_to_copy - 1; + unsigned char *tmp = NULL; + new_memory->allocate(old_value[idx].size(), &tmp); + memmove(tmp, old_value[idx].data(), old_value[idx].size()); + (*new_value)[idx] = e::slice(tmp, old_value[idx].size()); + ++next_to_copy; + } + // - "op" now points to the first unapplied funcall + // - "end" points to one funcall past the last op we want to apply + // - we've copied all attributes so far, even those not mentioned by + // funcs. + // This call may modify [op, end) funcs. + datatype_info *di = datatype_info::lookup(sc.attrs[op->attr].type); + if (!di->apply(old_value[op->attr - 1], op, end - op, new_memory, &(*new_value)[next_to_copy - 1])) + { + return (op - &funcs.front()); + } + // Why ++ and assert rather than straight assign? This will help us to + // catch any problems in the interaction between funcs and + // attributes which we just copy. + assert(next_to_copy == op->attr); + ++next_to_copy; + op = end; + } + // Copy the attributes that are unaffected by funcs. + while (next_to_copy < sc.attrs_sz) + { + assert(next_to_copy > 0); + size_t idx = next_to_copy - 1; + unsigned char *tmp = NULL; + new_memory->allocate(old_value[idx].size(), &tmp); + memmove(tmp, old_value[idx].data(), old_value[idx].size()); + (*new_value)[idx] = e::slice(tmp, old_value[idx].size()); + ++next_to_copy; + } + return funcs.size(); } bool -hyperdex :: operator < (const funcall& lhs, const funcall& rhs) +hyperdex :: operator < (const funcall &lhs, const funcall &rhs) { - return lhs.attr < rhs.attr; + return lhs.attr < rhs.attr; } e::packer -hyperdex :: operator << (e::packer lhs, const funcall_t& rhs) +hyperdex :: operator << (e::packer lhs, const funcall_t &rhs) { - uint8_t name = static_cast(rhs); - return lhs << name; + uint8_t name = static_cast(rhs); + return lhs << name; } e::unpacker -hyperdex :: operator >> (e::unpacker lhs, funcall_t& rhs) +hyperdex :: operator >> (e::unpacker lhs, funcall_t &rhs) { - uint8_t name; - lhs = lhs >> name; - rhs = static_cast(name); - return lhs; + uint8_t name; + lhs = lhs >> name; + rhs = static_cast(name); + return lhs; } size_t -hyperdex :: pack_size(const funcall_t&) +hyperdex :: pack_size(const funcall_t &) { - return sizeof(uint8_t); + return sizeof(uint8_t); } e::packer -hyperdex :: operator << (e::packer lhs, const funcall& rhs) +hyperdex :: operator << (e::packer lhs, const funcall &rhs) { - return lhs << rhs.attr << rhs.name - << rhs.arg1 << rhs.arg1_datatype - << rhs.arg2 << rhs.arg2_datatype; + return lhs << rhs.attr << rhs.name + << rhs.arg1 << rhs.arg1_datatype + << rhs.arg2 << rhs.arg2_datatype; } e::unpacker -hyperdex :: operator >> (e::unpacker lhs, funcall& rhs) +hyperdex :: operator >> (e::unpacker lhs, funcall &rhs) { - return lhs >> rhs.attr >> rhs.name - >> rhs.arg1 >> rhs.arg1_datatype - >> rhs.arg2 >> rhs.arg2_datatype; + return lhs >> rhs.attr >> rhs.name + >> rhs.arg1 >> rhs.arg1_datatype + >> rhs.arg2 >> rhs.arg2_datatype; } size_t -hyperdex :: pack_size(const funcall& m) +hyperdex :: pack_size(const funcall &m) { - return sizeof(uint16_t) + pack_size(m.name) - + pack_size(m.arg1) + pack_size(m.arg1_datatype) - + pack_size(m.arg2) + pack_size(m.arg2_datatype); + return sizeof(uint16_t) + pack_size(m.name) + + pack_size(m.arg1) + pack_size(m.arg1_datatype) + + pack_size(m.arg2) + pack_size(m.arg2_datatype); } diff --git a/common/funcall.h b/common/funcall.h index a12355542..d46c6530c 100644 --- a/common/funcall.h +++ b/common/funcall.h @@ -48,87 +48,87 @@ BEGIN_HYPERDEX_NAMESPACE enum funcall_t { - FUNC_FAIL = 0, - - FUNC_SET = 1, - - FUNC_STRING_APPEND = 2, - FUNC_STRING_PREPEND = 3, - FUNC_STRING_LTRIM = 24, - FUNC_STRING_RTRIM = 25, - - FUNC_NUM_ADD = 4, - FUNC_NUM_SUB = 5, - FUNC_NUM_MUL = 6, - FUNC_NUM_DIV = 7, - FUNC_NUM_MOD = 8, - FUNC_NUM_AND = 9, - FUNC_NUM_OR = 10, - FUNC_NUM_XOR = 11, - FUNC_NUM_MAX = 12, - FUNC_NUM_MIN = 13, - - FUNC_LIST_LPUSH = 14, - FUNC_LIST_RPUSH = 15, - - FUNC_SET_ADD = 16, - FUNC_SET_REMOVE = 17, - FUNC_SET_INTERSECT = 18, - FUNC_SET_UNION = 19, - - FUNC_MAP_ADD = 20, - FUNC_MAP_REMOVE = 21, - - FUNC_DOC_RENAME = 22, - FUNC_DOC_UNSET = 23 + FUNC_FAIL = 0, + + FUNC_SET = 1, + + FUNC_STRING_APPEND = 2, + FUNC_STRING_PREPEND = 3, + FUNC_STRING_LTRIM = 24, + FUNC_STRING_RTRIM = 25, + + FUNC_NUM_ADD = 4, + FUNC_NUM_SUB = 5, + FUNC_NUM_MUL = 6, + FUNC_NUM_DIV = 7, + FUNC_NUM_MOD = 8, + FUNC_NUM_AND = 9, + FUNC_NUM_OR = 10, + FUNC_NUM_XOR = 11, + FUNC_NUM_MAX = 12, + FUNC_NUM_MIN = 13, + + FUNC_LIST_LPUSH = 14, + FUNC_LIST_RPUSH = 15, + + FUNC_SET_ADD = 16, + FUNC_SET_REMOVE = 17, + FUNC_SET_INTERSECT = 18, + FUNC_SET_UNION = 19, + + FUNC_MAP_ADD = 20, + FUNC_MAP_REMOVE = 21, + + FUNC_DOC_RENAME = 22, + FUNC_DOC_UNSET = 23 }; class funcall { - public: - funcall(); - ~funcall() throw (); - - public: - uint16_t attr; - funcall_t name; - e::slice arg1; - hyperdatatype arg1_datatype; - e::slice arg2; - hyperdatatype arg2_datatype; +public: + funcall(); + ~funcall() throw (); + +public: + uint16_t attr; + funcall_t name; + e::slice arg1; + hyperdatatype arg1_datatype; + e::slice arg2; + hyperdatatype arg2_datatype; }; bool -validate_func(const schema& sc, const funcall& func); +validate_func(const schema &sc, const funcall &func); size_t -validate_funcs(const schema& sc, - const std::vector& funcs); +validate_funcs(const schema &sc, + const std::vector &funcs); size_t -apply_funcs(const schema& sc, - const std::vector& funcs, - const e::slice& key, - const std::vector& old_value, - e::arena* new_memory, - std::vector* new_value); +apply_funcs(const schema &sc, + const std::vector &funcs, + const e::slice &key, + const std::vector &old_value, + e::arena *new_memory, + std::vector *new_value); bool -operator < (const funcall& lhs, const funcall& rhs); +operator < (const funcall &lhs, const funcall &rhs); e::packer -operator << (e::packer lhs, const funcall_t& rhs); +operator << (e::packer lhs, const funcall_t &rhs); e::unpacker -operator >> (e::unpacker lhs, funcall_t& rhs); +operator >> (e::unpacker lhs, funcall_t &rhs); size_t -pack_size(const funcall_t& f); +pack_size(const funcall_t &f); e::packer -operator << (e::packer lhs, const funcall& rhs); +operator << (e::packer lhs, const funcall &rhs); e::unpacker -operator >> (e::unpacker lhs, funcall& rhs); +operator >> (e::unpacker lhs, funcall &rhs); size_t -pack_size(const funcall& f); +pack_size(const funcall &f); END_HYPERDEX_NAMESPACE diff --git a/common/hash.cc b/common/hash.cc index 36785c0f8..92edbe142 100644 --- a/common/hash.cc +++ b/common/hash.cc @@ -32,37 +32,34 @@ #include "common/hash.h" uint64_t -hyperdex :: hash(hyperdatatype t, const e::slice& v) +hyperdex :: hash(hyperdatatype t, const e::slice &v) { - datatype_info* di = datatype_info::lookup(t); - assert(di); - - if (!di->hashable()) - { - return 0; - } - - return di->hash(v); + datatype_info *di = datatype_info::lookup(t); + assert(di); + if (!di->hashable()) + { + return 0; + } + return di->hash(v); } void -hyperdex :: hash(const schema& sc, - const e::slice& key, - uint64_t* h) +hyperdex :: hash(const schema &sc, + const e::slice &key, + uint64_t *h) { - *h = hash(sc.attrs[0].type, key); + *h = hash(sc.attrs[0].type, key); } void -hyperdex :: hash(const hyperdex::schema& sc, - const e::slice& key, - const std::vector& value, - uint64_t* hs) +hyperdex :: hash(const hyperdex::schema &sc, + const e::slice &key, + const std::vector &value, + uint64_t *hs) { - hs[0] = hash(sc.attrs[0].type, key); - - for (size_t i = 1; i < sc.attrs_sz; ++i) - { - hs[i] = hash(sc.attrs[i].type, value[i - 1]); - } + hs[0] = hash(sc.attrs[0].type, key); + for (size_t i = 1; i < sc.attrs_sz; ++i) + { + hs[i] = hash(sc.attrs[i].type, value[i - 1]); + } } diff --git a/common/hash.h b/common/hash.h index 15f7411f1..b7924dff9 100644 --- a/common/hash.h +++ b/common/hash.h @@ -41,18 +41,18 @@ BEGIN_HYPERDEX_NAMESPACE uint64_t -hash(hyperdatatype t, const e::slice& v); +hash(hyperdatatype t, const e::slice &v); void -hash(const schema& sc, - const e::slice& key, - uint64_t* h); +hash(const schema &sc, + const e::slice &key, + uint64_t *h); void -hash(const schema& sc, - const e::slice& key, - const std::vector& value, - uint64_t* hs); +hash(const schema &sc, + const e::slice &key, + const std::vector &value, + uint64_t *hs); END_HYPERDEX_NAMESPACE diff --git a/common/hyperdex.cc b/common/hyperdex.cc index 3f177c811..b539b98e4 100644 --- a/common/hyperdex.cc +++ b/common/hyperdex.cc @@ -30,75 +30,73 @@ #include "visibility.h" #include "common/macros.h" -HYPERDEX_API std::ostream& -operator << (std::ostream& lhs, hyperdatatype rhs) +HYPERDEX_API std::ostream & +operator << (std::ostream &lhs, hyperdatatype rhs) { - switch (rhs) - { - STRINGIFY(HYPERDATATYPE_GENERIC); - STRINGIFY(HYPERDATATYPE_STRING); - STRINGIFY(HYPERDATATYPE_INT64); - STRINGIFY(HYPERDATATYPE_FLOAT); - STRINGIFY(HYPERDATATYPE_DOCUMENT); - STRINGIFY(HYPERDATATYPE_LIST_GENERIC); - STRINGIFY(HYPERDATATYPE_LIST_STRING); - STRINGIFY(HYPERDATATYPE_LIST_INT64); - STRINGIFY(HYPERDATATYPE_LIST_FLOAT); - STRINGIFY(HYPERDATATYPE_SET_GENERIC); - STRINGIFY(HYPERDATATYPE_SET_STRING); - STRINGIFY(HYPERDATATYPE_SET_INT64); - STRINGIFY(HYPERDATATYPE_SET_FLOAT); - STRINGIFY(HYPERDATATYPE_MAP_GENERIC); - STRINGIFY(HYPERDATATYPE_MAP_STRING_KEYONLY); - STRINGIFY(HYPERDATATYPE_MAP_STRING_STRING); - STRINGIFY(HYPERDATATYPE_MAP_STRING_INT64); - STRINGIFY(HYPERDATATYPE_MAP_STRING_FLOAT); - STRINGIFY(HYPERDATATYPE_MAP_INT64_KEYONLY); - STRINGIFY(HYPERDATATYPE_MAP_INT64_STRING); - STRINGIFY(HYPERDATATYPE_MAP_INT64_INT64); - STRINGIFY(HYPERDATATYPE_MAP_INT64_FLOAT); - STRINGIFY(HYPERDATATYPE_MAP_FLOAT_KEYONLY); - STRINGIFY(HYPERDATATYPE_MAP_FLOAT_STRING); - STRINGIFY(HYPERDATATYPE_MAP_FLOAT_INT64); - STRINGIFY(HYPERDATATYPE_MAP_FLOAT_FLOAT); - STRINGIFY(HYPERDATATYPE_TIMESTAMP_GENERIC); - STRINGIFY(HYPERDATATYPE_TIMESTAMP_SECOND); - STRINGIFY(HYPERDATATYPE_TIMESTAMP_MINUTE); - STRINGIFY(HYPERDATATYPE_TIMESTAMP_HOUR); - STRINGIFY(HYPERDATATYPE_TIMESTAMP_DAY); - STRINGIFY(HYPERDATATYPE_TIMESTAMP_WEEK); - STRINGIFY(HYPERDATATYPE_TIMESTAMP_MONTH); - STRINGIFY(HYPERDATATYPE_MACAROON_SECRET); - STRINGIFY(HYPERDATATYPE_GARBAGE); - default: - lhs << "unknown hyperdatatype"; - break; - } - - return lhs; + switch (rhs) + { + STRINGIFY(HYPERDATATYPE_GENERIC); + STRINGIFY(HYPERDATATYPE_STRING); + STRINGIFY(HYPERDATATYPE_INT64); + STRINGIFY(HYPERDATATYPE_FLOAT); + STRINGIFY(HYPERDATATYPE_DOCUMENT); + STRINGIFY(HYPERDATATYPE_LIST_GENERIC); + STRINGIFY(HYPERDATATYPE_LIST_STRING); + STRINGIFY(HYPERDATATYPE_LIST_INT64); + STRINGIFY(HYPERDATATYPE_LIST_FLOAT); + STRINGIFY(HYPERDATATYPE_SET_GENERIC); + STRINGIFY(HYPERDATATYPE_SET_STRING); + STRINGIFY(HYPERDATATYPE_SET_INT64); + STRINGIFY(HYPERDATATYPE_SET_FLOAT); + STRINGIFY(HYPERDATATYPE_MAP_GENERIC); + STRINGIFY(HYPERDATATYPE_MAP_STRING_KEYONLY); + STRINGIFY(HYPERDATATYPE_MAP_STRING_STRING); + STRINGIFY(HYPERDATATYPE_MAP_STRING_INT64); + STRINGIFY(HYPERDATATYPE_MAP_STRING_FLOAT); + STRINGIFY(HYPERDATATYPE_MAP_INT64_KEYONLY); + STRINGIFY(HYPERDATATYPE_MAP_INT64_STRING); + STRINGIFY(HYPERDATATYPE_MAP_INT64_INT64); + STRINGIFY(HYPERDATATYPE_MAP_INT64_FLOAT); + STRINGIFY(HYPERDATATYPE_MAP_FLOAT_KEYONLY); + STRINGIFY(HYPERDATATYPE_MAP_FLOAT_STRING); + STRINGIFY(HYPERDATATYPE_MAP_FLOAT_INT64); + STRINGIFY(HYPERDATATYPE_MAP_FLOAT_FLOAT); + STRINGIFY(HYPERDATATYPE_TIMESTAMP_GENERIC); + STRINGIFY(HYPERDATATYPE_TIMESTAMP_SECOND); + STRINGIFY(HYPERDATATYPE_TIMESTAMP_MINUTE); + STRINGIFY(HYPERDATATYPE_TIMESTAMP_HOUR); + STRINGIFY(HYPERDATATYPE_TIMESTAMP_DAY); + STRINGIFY(HYPERDATATYPE_TIMESTAMP_WEEK); + STRINGIFY(HYPERDATATYPE_TIMESTAMP_MONTH); + STRINGIFY(HYPERDATATYPE_MACAROON_SECRET); + STRINGIFY(HYPERDATATYPE_GARBAGE); + default: + lhs << "unknown hyperdatatype"; + break; + } + return lhs; } -HYPERDEX_API std::ostream& -operator << (std::ostream& lhs, hyperpredicate rhs) +HYPERDEX_API std::ostream & +operator << (std::ostream &lhs, hyperpredicate rhs) { - switch (rhs) - { - STRINGIFY(HYPERPREDICATE_FAIL); - STRINGIFY(HYPERPREDICATE_EQUALS); - STRINGIFY(HYPERPREDICATE_LESS_THAN); - STRINGIFY(HYPERPREDICATE_LESS_EQUAL); - STRINGIFY(HYPERPREDICATE_GREATER_EQUAL); - STRINGIFY(HYPERPREDICATE_GREATER_THAN); - STRINGIFY(HYPERPREDICATE_CONTAINS_LESS_THAN); - STRINGIFY(HYPERPREDICATE_REGEX); - STRINGIFY(HYPERPREDICATE_LENGTH_EQUALS); - STRINGIFY(HYPERPREDICATE_LENGTH_LESS_EQUAL); - STRINGIFY(HYPERPREDICATE_LENGTH_GREATER_EQUAL); - STRINGIFY(HYPERPREDICATE_CONTAINS); - default: - lhs << "unknown hyperpredicate"; - break; - } - - return lhs; + switch (rhs) + { + STRINGIFY(HYPERPREDICATE_FAIL); + STRINGIFY(HYPERPREDICATE_EQUALS); + STRINGIFY(HYPERPREDICATE_LESS_THAN); + STRINGIFY(HYPERPREDICATE_LESS_EQUAL); + STRINGIFY(HYPERPREDICATE_GREATER_EQUAL); + STRINGIFY(HYPERPREDICATE_GREATER_THAN); + STRINGIFY(HYPERPREDICATE_CONTAINS_LESS_THAN); + STRINGIFY(HYPERPREDICATE_REGEX); + STRINGIFY(HYPERPREDICATE_LENGTH_EQUALS); + STRINGIFY(HYPERPREDICATE_LENGTH_LESS_EQUAL); + STRINGIFY(HYPERPREDICATE_LENGTH_GREATER_EQUAL); + STRINGIFY(HYPERPREDICATE_CONTAINS); + default: + lhs << "unknown hyperpredicate"; + break; + } + return lhs; } diff --git a/common/hyperspace.cc b/common/hyperspace.cc index 757af47aa..18c72e44e 100644 --- a/common/hyperspace.cc +++ b/common/hyperspace.cc @@ -35,44 +35,44 @@ using hyperdex::region; using hyperdex::replica; space :: space() - : id() - , name("") - , fault_tolerance() - , predecessor_width(1) - , sc() - , subspaces() - , indices() - , m_c_strs() - , m_attrs() -{ -} - -space :: space(const char* new_name, const hyperdex::schema& _sc) - : id() - , name(new_name) - , fault_tolerance() - , predecessor_width(1) - , sc(_sc) - , subspaces() - , indices() - , m_c_strs() - , m_attrs() -{ - reestablish_backing(); -} - -space :: space(const space& other) - : id(other.id) - , name(other.name) - , fault_tolerance(other.fault_tolerance) - , predecessor_width(other.predecessor_width) - , sc(other.sc) - , subspaces(other.subspaces) - , indices(other.indices) - , m_c_strs() - , m_attrs() -{ - reestablish_backing(); + : id() + , name("") + , fault_tolerance() + , predecessor_width(1) + , sc() + , subspaces() + , indices() + , m_c_strs() + , m_attrs() +{ +} + +space :: space(const char *new_name, const hyperdex::schema &_sc) + : id() + , name(new_name) + , fault_tolerance() + , predecessor_width(1) + , sc(_sc) + , subspaces() + , indices() + , m_c_strs() + , m_attrs() +{ + reestablish_backing(); +} + +space :: space(const space &other) + : id(other.id) + , name(other.name) + , fault_tolerance(other.fault_tolerance) + , predecessor_width(other.predecessor_width) + , sc(other.sc) + , subspaces(other.subspaces) + , indices(other.indices) + , m_c_strs() + , m_attrs() +{ + reestablish_backing(); } space :: ~space() throw () @@ -82,239 +82,211 @@ space :: ~space() throw () bool space :: validate() const { - for (size_t i = 0; i < sc.attrs_sz; ++i) - { - for (size_t j = i + 1; j < sc.attrs_sz; ++j) - { - if (strcmp(sc.attrs[i].name, sc.attrs[j].name) == 0) - { - return false; - } - } - } - - for (size_t i = 0; i < subspaces.size(); ++i) - { - // XXX if subspaces[i].regions does not fill volume, then fail - - for (size_t j = 0; j < subspaces[i].regions.size(); ++j) - { - if (subspaces[i].attrs.size() != subspaces[i].regions[j].lower_coord.size() || - subspaces[i].attrs.size() != subspaces[i].regions[j].upper_coord.size()) - { - return false; - } - } - - for (size_t j = 0; j < subspaces[i].attrs.size(); ++j) - { - if (subspaces[i].attrs[j] >= sc.attrs_sz) - { - return false; - } - - for (size_t k = j + 1; k < subspaces[i].attrs.size(); ++k) - { - if (subspaces[i].attrs[j] == subspaces[i].attrs[k]) - { - return false; - } - } - } - } - - for (size_t i = 0; i < indices.size(); ++i) - { - if (indices[i].attr >= sc.attrs_sz) - { - return false; - } - } - - return true; -} - -space& -space :: operator = (const space& rhs) -{ - id = rhs.id; - name = rhs.name; - fault_tolerance = rhs.fault_tolerance; - sc = rhs.sc; - subspaces = rhs.subspaces; - indices = rhs.indices; - reestablish_backing(); - return *this; + for (size_t i = 0; i < sc.attrs_sz; ++i) + { + for (size_t j = i + 1; j < sc.attrs_sz; ++j) + { + if (strcmp(sc.attrs[i].name, sc.attrs[j].name) == 0) + { + return false; + } + } + } + for (size_t i = 0; i < subspaces.size(); ++i) + { + // XXX if subspaces[i].regions does not fill volume, then fail + for (size_t j = 0; j < subspaces[i].regions.size(); ++j) + { + if (subspaces[i].attrs.size() != subspaces[i].regions[j].lower_coord.size() || + subspaces[i].attrs.size() != subspaces[i].regions[j].upper_coord.size()) + { + return false; + } + } + for (size_t j = 0; j < subspaces[i].attrs.size(); ++j) + { + if (subspaces[i].attrs[j] >= sc.attrs_sz) + { + return false; + } + for (size_t k = j + 1; k < subspaces[i].attrs.size(); ++k) + { + if (subspaces[i].attrs[j] == subspaces[i].attrs[k]) + { + return false; + } + } + } + } + for (size_t i = 0; i < indices.size(); ++i) + { + if (indices[i].attr >= sc.attrs_sz) + { + return false; + } + } + return true; +} + +space & +space :: operator = (const space &rhs) +{ + id = rhs.id; + name = rhs.name; + fault_tolerance = rhs.fault_tolerance; + sc = rhs.sc; + subspaces = rhs.subspaces; + indices = rhs.indices; + reestablish_backing(); + return *this; } void space :: reestablish_backing() { - // Compute the size of the c_strs backing - size_t sz = strlen(name) + 1; - - for (size_t i = 0; i < sc.attrs_sz; ++i) - { - sz += strlen(sc.attrs[i].name) + 1; - } - - for (size_t i = 0; i < indices.size(); ++i) - { - sz += indices[i].extra.size(); - } - - // Create the two new backings - e::array_ptr old_c_strs = m_c_strs; - e::array_ptr old_attrs = m_attrs; - m_c_strs = new char[sz]; - m_attrs = new attribute[sc.attrs_sz]; - char* ptr = m_c_strs.get(); - sz = strlen(name) + 1; - memmove(ptr, name, sz); - name = ptr; - ptr += sz; - - for (size_t i = 0; i < sc.attrs_sz; ++i) - { - m_attrs[i].type = sc.attrs[i].type; - sz = strlen(sc.attrs[i].name) + 1; - memmove(ptr, sc.attrs[i].name, sz); - m_attrs[i].name = ptr; - ptr += sz; - } - - sc.attrs = m_attrs.get(); - - for (size_t i = 0; i < indices.size(); ++i) - { - memmove(ptr, indices[i].extra.data(), indices[i].extra.size()); - indices[i].extra = e::slice(ptr, indices[i].extra.size()); - ptr += indices[i].extra.size(); - } + // Compute the size of the c_strs backing + size_t sz = strlen(name) + 1; + for (size_t i = 0; i < sc.attrs_sz; ++i) + { + sz += strlen(sc.attrs[i].name) + 1; + } + for (size_t i = 0; i < indices.size(); ++i) + { + sz += indices[i].extra.size(); + } + // Create the two new backings + e::array_ptr old_c_strs = m_c_strs; + e::array_ptr old_attrs = m_attrs; + m_c_strs = new char[sz]; + m_attrs = new attribute[sc.attrs_sz]; + char *ptr = m_c_strs.get(); + sz = strlen(name) + 1; + memmove(ptr, name, sz); + name = ptr; + ptr += sz; + for (size_t i = 0; i < sc.attrs_sz; ++i) + { + m_attrs[i].type = sc.attrs[i].type; + sz = strlen(sc.attrs[i].name) + 1; + memmove(ptr, sc.attrs[i].name, sz); + m_attrs[i].name = ptr; + ptr += sz; + } + sc.attrs = m_attrs.get(); + for (size_t i = 0; i < indices.size(); ++i) + { + memmove(ptr, indices[i].extra.data(), indices[i].extra.size()); + indices[i].extra = e::slice(ptr, indices[i].extra.size()); + ptr += indices[i].extra.size(); + } } e::packer -hyperdex :: operator << (e::packer pa, const space& s) -{ - e::slice name; - uint16_t num_subspaces = s.subspaces.size(); - uint16_t num_indices = s.indices.size(); - name = e::slice(s.name, strlen(s.name)); - pa = pa << s.id.get() << name << s.fault_tolerance << s.sc.attrs_sz - << num_subspaces << num_indices; - - for (size_t i = 0; i < s.sc.attrs_sz; ++i) - { - name = e::slice(s.sc.attrs[i].name, strlen(s.sc.attrs[i].name)); - pa = pa << name << static_cast(s.sc.attrs[i].type); - } - - for (size_t i = 0; i < num_subspaces; ++i) - { - pa = pa << s.subspaces[i]; - } - - for (size_t i = 0; i < num_indices; ++i) - { - pa = pa << s.indices[i]; - } - - return pa; +hyperdex :: operator << (e::packer pa, const space &s) +{ + e::slice name; + uint16_t num_subspaces = s.subspaces.size(); + uint16_t num_indices = s.indices.size(); + name = e::slice(s.name, strlen(s.name)); + pa = pa << s.id.get() << name << s.fault_tolerance << s.sc.attrs_sz + << num_subspaces << num_indices; + for (size_t i = 0; i < s.sc.attrs_sz; ++i) + { + name = e::slice(s.sc.attrs[i].name, strlen(s.sc.attrs[i].name)); + pa = pa << name << static_cast(s.sc.attrs[i].type); + } + for (size_t i = 0; i < num_subspaces; ++i) + { + pa = pa << s.subspaces[i]; + } + for (size_t i = 0; i < num_indices; ++i) + { + pa = pa << s.indices[i]; + } + return pa; } e::unpacker -hyperdex :: operator >> (e::unpacker up, space& s) -{ - e::slice name; - std::vector strs; - std::vector attrs; - uint16_t num_subspaces; - uint16_t num_indices; - up = up >> s.id >> name >> s.fault_tolerance >> s.sc.attrs_sz - >> num_subspaces >> num_indices; - strs.reserve(s.sc.attrs_sz + 1); - attrs.reserve(s.sc.attrs_sz); - strs.push_back(std::string(name.cdata(), name.size())); - s.name = strs.back().c_str(); - - // Unpack all attributes - for (size_t i = 0; !up.error() && i < s.sc.attrs_sz; ++i) - { - e::slice attr; - hyperdatatype type; - up = up >> attr >> type; - strs.push_back(std::string(attr.cdata(), attr.size())); - attrs.push_back(attribute(strs.back().c_str(), type)); - - if (type == HYPERDATATYPE_MACAROON_SECRET) - { - s.sc.authorization = true; - } - } - - s.sc.attrs = &attrs.front(); - s.sc.attrs_sz = attrs.size(); - - // Unpack subspaces - s.subspaces.resize(num_subspaces); - - for (size_t i = 0; !up.error() && i < num_subspaces; ++i) - { - up = up >> s.subspaces[i]; - } - - // Unpack indices - s.indices.resize(num_indices); - - for (size_t i = 0; !up.error() && i < num_indices; ++i) - { - up = up >> s.indices[i]; - } - - s.reestablish_backing(); - return up; +hyperdex :: operator >> (e::unpacker up, space &s) +{ + e::slice name; + std::vector strs; + std::vector attrs; + uint16_t num_subspaces; + uint16_t num_indices; + up = up >> s.id >> name >> s.fault_tolerance >> s.sc.attrs_sz + >> num_subspaces >> num_indices; + strs.reserve(s.sc.attrs_sz + 1); + attrs.reserve(s.sc.attrs_sz); + strs.push_back(std::string(name.cdata(), name.size())); + s.name = strs.back().c_str(); + // Unpack all attributes + for (size_t i = 0; !up.error() && i < s.sc.attrs_sz; ++i) + { + e::slice attr; + hyperdatatype type; + up = up >> attr >> type; + strs.push_back(std::string(attr.cdata(), attr.size())); + attrs.push_back(attribute(strs.back().c_str(), type)); + if (type == HYPERDATATYPE_MACAROON_SECRET) + { + s.sc.authorization = true; + } + } + s.sc.attrs = &attrs.front(); + s.sc.attrs_sz = attrs.size(); + // Unpack subspaces + s.subspaces.resize(num_subspaces); + for (size_t i = 0; !up.error() && i < num_subspaces; ++i) + { + up = up >> s.subspaces[i]; + } + // Unpack indices + s.indices.resize(num_indices); + for (size_t i = 0; !up.error() && i < num_indices; ++i) + { + up = up >> s.indices[i]; + } + s.reestablish_backing(); + return up; } size_t -hyperdex :: pack_size(const space& s) -{ - size_t sz = sizeof(uint64_t) /* id */ - + sizeof(uint32_t) + strlen(s.name) /* name */ - + sizeof(uint64_t) /* fault_tolerance */ - + sizeof(uint16_t) /* sc.attrs_sz */ - + sizeof(uint16_t) /* num subspaces */ - + sizeof(uint16_t); /* num indices */ - - for (size_t i = 0; i < s.sc.attrs_sz; ++i) - { - sz += sizeof(uint32_t) + strlen(s.sc.attrs[i].name) - + sizeof(uint16_t); - } - - for (size_t i = 0; i < s.subspaces.size(); ++i) - { - sz += pack_size(s.subspaces[i]); - } - - for (size_t i = 0; i < s.indices.size(); ++i) - { - sz += pack_size(s.indices[i]); - } - - return sz; +hyperdex :: pack_size(const space &s) +{ + size_t sz = sizeof(uint64_t) /* id */ + + sizeof(uint32_t) + strlen(s.name) /* name */ + + sizeof(uint64_t) /* fault_tolerance */ + + sizeof(uint16_t) /* sc.attrs_sz */ + + sizeof(uint16_t) /* num subspaces */ + + sizeof(uint16_t); /* num indices */ + for (size_t i = 0; i < s.sc.attrs_sz; ++i) + { + sz += sizeof(uint32_t) + strlen(s.sc.attrs[i].name) + + sizeof(uint16_t); + } + for (size_t i = 0; i < s.subspaces.size(); ++i) + { + sz += pack_size(s.subspaces[i]); + } + for (size_t i = 0; i < s.indices.size(); ++i) + { + sz += pack_size(s.indices[i]); + } + return sz; } subspace :: subspace() - : id() - , attrs() - , regions() + : id() + , attrs() + , regions() { } -subspace :: subspace(const subspace& other) - : id(other.id) - , attrs(other.attrs) - , regions(other.regions) +subspace :: subspace(const subspace &other) + : id(other.id) + , attrs(other.attrs) + , regions(other.regions) { } @@ -322,90 +294,82 @@ subspace :: ~subspace() throw () { } -subspace& -subspace :: operator = (const subspace& rhs) +subspace & +subspace :: operator = (const subspace &rhs) { - id = rhs.id; - attrs = rhs.attrs; - regions = rhs.regions; - return *this; + id = rhs.id; + attrs = rhs.attrs; + regions = rhs.regions; + return *this; } e::packer -hyperdex :: operator << (e::packer pa, const subspace& s) -{ - uint16_t num_attrs = s.attrs.size(); - uint32_t num_regions = s.regions.size(); - pa = pa << s.id.get() << num_attrs << num_regions; - - for (size_t i = 0; i < num_attrs; ++i) - { - pa = pa << s.attrs[i]; - } - - for (size_t i = 0; i < num_regions; ++i) - { - pa = pa << s.regions[i]; - } - - return pa; +hyperdex :: operator << (e::packer pa, const subspace &s) +{ + uint16_t num_attrs = s.attrs.size(); + uint32_t num_regions = s.regions.size(); + pa = pa << s.id.get() << num_attrs << num_regions; + for (size_t i = 0; i < num_attrs; ++i) + { + pa = pa << s.attrs[i]; + } + for (size_t i = 0; i < num_regions; ++i) + { + pa = pa << s.regions[i]; + } + return pa; } e::unpacker -hyperdex :: operator >> (e::unpacker up, subspace& s) -{ - uint64_t id; - uint16_t num_attrs; - uint32_t num_regions; - up = up >> id >> num_attrs >> num_regions; - s.id = subspace_id(id); - s.attrs.clear(); - s.regions.resize(num_regions); - - for (size_t i = 0; !up.error() && i < num_attrs; ++i) - { - uint16_t attr; - up = up >> attr; - s.attrs.push_back(attr); - } - - for (size_t i = 0; !up.error() && i < num_regions; ++i) - { - up = up >> s.regions[i]; - } - - return up; +hyperdex :: operator >> (e::unpacker up, subspace &s) +{ + uint64_t id; + uint16_t num_attrs; + uint32_t num_regions; + up = up >> id >> num_attrs >> num_regions; + s.id = subspace_id(id); + s.attrs.clear(); + s.regions.resize(num_regions); + for (size_t i = 0; !up.error() && i < num_attrs; ++i) + { + uint16_t attr; + up = up >> attr; + s.attrs.push_back(attr); + } + for (size_t i = 0; !up.error() && i < num_regions; ++i) + { + up = up >> s.regions[i]; + } + return up; } size_t -hyperdex :: pack_size(const subspace& s) +hyperdex :: pack_size(const subspace &s) { - size_t sz = sizeof(uint64_t) /* id */ - + sizeof(uint16_t) /* num_attrs */ - + sizeof(uint32_t) /* num_regions */ - + sizeof(uint16_t) * s.attrs.size(); - - for (size_t i = 0; i < s.regions.size(); ++i) - { - sz += pack_size(s.regions[i]); - } - - return sz; + size_t sz = sizeof(uint64_t) /* id */ + + sizeof(uint16_t) /* num_attrs */ + + sizeof(uint32_t) /* num_regions */ + + sizeof(uint16_t) * s.attrs.size(); + for (size_t i = 0; i < s.regions.size(); ++i) + { + sz += pack_size(s.regions[i]); + } + return sz; } region :: region() - : id() - , lower_coord() - , upper_coord() - , replicas() + : id() + , lower_coord() + , upper_coord() + , replicas() { } -region :: region(const region& other) - : id(other.id) - , lower_coord(other.lower_coord) - , upper_coord(other.upper_coord) - , replicas(other.replicas) +region :: region(const region &other) + : id(other.id) + , lower_coord(other.lower_coord) + , upper_coord(other.upper_coord) + , replicas(other.replicas) { } @@ -413,93 +377,85 @@ region :: ~region() throw () { } -region& -region :: operator = (const region& rhs) +region & +region :: operator = (const region &rhs) { - id = rhs.id; - lower_coord = rhs.lower_coord; - upper_coord = rhs.upper_coord; - replicas = rhs.replicas; - return *this; + id = rhs.id; + lower_coord = rhs.lower_coord; + upper_coord = rhs.upper_coord; + replicas = rhs.replicas; + return *this; } e::packer -hyperdex :: operator << (e::packer pa, const region& r) -{ - uint16_t num_hashes = r.lower_coord.size(); - uint8_t num_replicas = r.replicas.size(); - pa = pa << r.id.get() << num_hashes << num_replicas; - - for (size_t i = 0; i < num_hashes; ++i) - { - pa = pa << r.lower_coord[i] << r.upper_coord[i]; - } - - for (size_t i = 0; i < num_replicas; ++i) - { - pa = pa << r.replicas[i]; - } - - return pa; +hyperdex :: operator << (e::packer pa, const region &r) +{ + uint16_t num_hashes = r.lower_coord.size(); + uint8_t num_replicas = r.replicas.size(); + pa = pa << r.id.get() << num_hashes << num_replicas; + for (size_t i = 0; i < num_hashes; ++i) + { + pa = pa << r.lower_coord[i] << r.upper_coord[i]; + } + for (size_t i = 0; i < num_replicas; ++i) + { + pa = pa << r.replicas[i]; + } + return pa; } e::unpacker -hyperdex :: operator >> (e::unpacker up, region& r) -{ - uint64_t id; - uint16_t num_hashes; - uint8_t num_replicas; - up = up >> id >> num_hashes >> num_replicas; - r.id = region_id(id); - r.lower_coord.resize(num_hashes); - r.upper_coord.resize(num_hashes); - r.replicas.resize(num_replicas); - - for (size_t i = 0; !up.error() && i < num_hashes; ++i) - { - up = up >> r.lower_coord[i] >> r.upper_coord[i]; - } - - for (size_t i = 0; !up.error() && i < num_replicas; ++i) - { - up = up >> r.replicas[i]; - } - - return up; +hyperdex :: operator >> (e::unpacker up, region &r) +{ + uint64_t id; + uint16_t num_hashes; + uint8_t num_replicas; + up = up >> id >> num_hashes >> num_replicas; + r.id = region_id(id); + r.lower_coord.resize(num_hashes); + r.upper_coord.resize(num_hashes); + r.replicas.resize(num_replicas); + for (size_t i = 0; !up.error() && i < num_hashes; ++i) + { + up = up >> r.lower_coord[i] >> r.upper_coord[i]; + } + for (size_t i = 0; !up.error() && i < num_replicas; ++i) + { + up = up >> r.replicas[i]; + } + return up; } size_t -hyperdex :: pack_size(const region& r) +hyperdex :: pack_size(const region &r) { - size_t sz = sizeof(uint64_t) /* id */ - + sizeof(uint16_t) /* num_hashes */ - + sizeof(uint8_t) /* num_replicas */ - + 2 * sizeof(uint64_t) * r.lower_coord.size(); - - for (size_t i = 0; i < r.replicas.size(); ++i) - { - sz += pack_size(r.replicas[i]); - } - - return sz; + size_t sz = sizeof(uint64_t) /* id */ + + sizeof(uint16_t) /* num_hashes */ + + sizeof(uint8_t) /* num_replicas */ + + 2 * sizeof(uint64_t) * r.lower_coord.size(); + for (size_t i = 0; i < r.replicas.size(); ++i) + { + sz += pack_size(r.replicas[i]); + } + return sz; } replica :: replica() - : si() - , vsi() + : si() + , vsi() { } -replica :: replica(const hyperdex::server_id& s, - const hyperdex::virtual_server_id& v) - : si(s) - , vsi(v) +replica :: replica(const hyperdex::server_id &s, + const hyperdex::virtual_server_id &v) + : si(s) + , vsi(v) { } -replica :: replica(const replica& other) - : si(other.si) - , vsi(other.vsi) +replica :: replica(const replica &other) + : si(other.si) + , vsi(other.vsi) { } @@ -507,33 +463,33 @@ replica :: ~replica() throw () { } -replica& -replica :: operator = (const replica& rhs) +replica & +replica :: operator = (const replica &rhs) { - si = rhs.si; - vsi = rhs.vsi; - return *this; + si = rhs.si; + vsi = rhs.vsi; + return *this; } e::packer -hyperdex :: operator << (e::packer pa, const replica& r) +hyperdex :: operator << (e::packer pa, const replica &r) { - return pa << r.si.get() << r.vsi.get(); + return pa << r.si.get() << r.vsi.get(); } e::unpacker -hyperdex :: operator >> (e::unpacker up, replica& r) +hyperdex :: operator >> (e::unpacker up, replica &r) { - uint64_t si; - uint64_t vsi; - up = up >> si >> vsi; - r.si = server_id(si); - r.vsi = virtual_server_id(vsi); - return up; + uint64_t si; + uint64_t vsi; + up = up >> si >> vsi; + r.si = server_id(si); + r.vsi = virtual_server_id(vsi); + return up; } size_t -hyperdex :: pack_size(const replica&) +hyperdex :: pack_size(const replica &) { - return sizeof(uint64_t) + sizeof(uint64_t); + return sizeof(uint64_t) + sizeof(uint64_t); } diff --git a/common/hyperspace.h b/common/hyperspace.h index a785bc48b..35c8cad5b 100644 --- a/common/hyperspace.h +++ b/common/hyperspace.h @@ -49,123 +49,123 @@ class replica; class space { - public: - space(); - space(const char* name, const schema& sc); - space(const space&); - ~space() throw (); - - public: - bool validate() const; - void reestablish_backing(); - - public: - space& operator = (const space&); - - public: - space_id id; - const char* name; - uint64_t fault_tolerance; - uint64_t predecessor_width; - hyperdex::schema sc; - std::vector subspaces; - std::vector indices; - - const attribute& get_attribute(uint16_t index) const; - - private: - friend e::packer operator << (e::packer, const space& s); - friend e::unpacker operator >> (e::unpacker, space& s); - friend size_t pack_size(const space&); - - private: - e::array_ptr m_c_strs; - e::array_ptr m_attrs; +public: + space(); + space(const char *name, const schema &sc); + space(const space &); + ~space() throw (); + +public: + bool validate() const; + void reestablish_backing(); + +public: + space &operator = (const space &); + +public: + space_id id; + const char *name; + uint64_t fault_tolerance; + uint64_t predecessor_width; + hyperdex::schema sc; + std::vector subspaces; + std::vector indices; + + const attribute &get_attribute(uint16_t index) const; + +private: + friend e::packer operator << (e::packer, const space &s); + friend e::unpacker operator >> (e::unpacker, space &s); + friend size_t pack_size(const space &); + +private: + e::array_ptr m_c_strs; + e::array_ptr m_attrs; }; -inline const attribute& space::get_attribute(uint16_t index) const +inline const attribute &space::get_attribute(uint16_t index) const { - return m_attrs[index]; + return m_attrs[index]; } e::packer -operator << (e::packer, const space& s); +operator << (e::packer, const space &s); e::unpacker -operator >> (e::unpacker, space& s); +operator >> (e::unpacker, space &s); size_t -pack_size(const space& s); +pack_size(const space &s); class subspace { - public: - subspace(); - subspace(const subspace&); - ~subspace() throw (); - - public: - subspace& operator = (const subspace&); - - public: - subspace_id id; - std::vector attrs; - std::vector regions; +public: + subspace(); + subspace(const subspace &); + ~subspace() throw (); + +public: + subspace &operator = (const subspace &); + +public: + subspace_id id; + std::vector attrs; + std::vector regions; }; e::packer -operator << (e::packer, const subspace& s); +operator << (e::packer, const subspace &s); e::unpacker -operator >> (e::unpacker, subspace& s); +operator >> (e::unpacker, subspace &s); size_t -pack_size(const subspace& s); +pack_size(const subspace &s); class region { - public: - region(); - region(const region&); - ~region() throw (); - - public: - region& operator = (const region&); - - public: - region_id id; - std::vector lower_coord; - std::vector upper_coord; - std::vector replicas; +public: + region(); + region(const region &); + ~region() throw (); + +public: + region &operator = (const region &); + +public: + region_id id; + std::vector lower_coord; + std::vector upper_coord; + std::vector replicas; }; e::packer -operator << (e::packer, const region& r); +operator << (e::packer, const region &r); e::unpacker -operator >> (e::unpacker, region& r); +operator >> (e::unpacker, region &r); size_t -pack_size(const region& r); +pack_size(const region &r); class replica { - public: - replica(); - replica(const server_id& si, - const virtual_server_id& vsi); - replica(const replica&); - ~replica() throw (); - - public: - replica& operator = (const replica&); - - public: - server_id si; - virtual_server_id vsi; +public: + replica(); + replica(const server_id &si, + const virtual_server_id &vsi); + replica(const replica &); + ~replica() throw (); + +public: + replica &operator = (const replica &); + +public: + server_id si; + virtual_server_id vsi; }; e::packer -operator << (e::packer, const replica& r); +operator << (e::packer, const replica &r); e::unpacker -operator >> (e::unpacker, replica& r); +operator >> (e::unpacker, replica &r); size_t -pack_size(const replica& r); +pack_size(const replica &r); END_HYPERDEX_NAMESPACE diff --git a/common/ids.cc b/common/ids.cc index 39a1dab1c..350b3c02c 100644 --- a/common/ids.cc +++ b/common/ids.cc @@ -29,24 +29,24 @@ #include "common/ids.h" #define CREATE_ID(TYPE) \ - std::ostream& \ - operator << (std::ostream& lhs, const TYPE ## _id& rhs) \ - { \ - return lhs << #TYPE "(" << rhs.get() << ")"; \ - } \ - e::packer \ - operator << (e::packer pa, const TYPE ## _id& rhs) \ - { \ - return pa << rhs.get(); \ - } \ - e::unpacker \ - operator >> (e::unpacker up, TYPE ## _id& rhs) \ - { \ - uint64_t id; \ - up = up >> id; \ - rhs = TYPE ## _id(id); \ - return up; \ - } + std::ostream& \ + operator << (std::ostream& lhs, const TYPE ## _id& rhs) \ + { \ + return lhs << #TYPE "(" << rhs.get() << ")"; \ + } \ + e::packer \ + operator << (e::packer pa, const TYPE ## _id& rhs) \ + { \ + return pa << rhs.get(); \ + } \ + e::unpacker \ + operator >> (e::unpacker up, TYPE ## _id& rhs) \ + { \ + uint64_t id; \ + up = up >> id; \ + rhs = TYPE ## _id(id); \ + return up; \ + } BEGIN_HYPERDEX_NAMESPACE diff --git a/common/ids.h b/common/ids.h index 13720c121..01ce8021c 100644 --- a/common/ids.h +++ b/common/ids.h @@ -45,40 +45,40 @@ // accidently using one type of ID as another. #define OPERATOR(TYPE, OP) \ - inline bool \ - operator OP (const TYPE ## _id& lhs, const TYPE ## _id& rhs) \ - { \ - return lhs.get() OP rhs.get(); \ - } + inline bool \ + operator OP (const TYPE ## _id& lhs, const TYPE ## _id& rhs) \ + { \ + return lhs.get() OP rhs.get(); \ + } #define CREATE_ID(TYPE) \ - class TYPE ## _id \ - { \ - public: \ - static uint64_t hash(const TYPE ## _id& x) { return x.get(); } \ - TYPE ## _id() : m_id(0) {} \ - explicit TYPE ## _id(uint64_t id) : m_id(id) {} \ - public: \ - uint64_t get() const { return m_id; } \ - private: \ - uint64_t m_id; \ - }; \ - std::ostream& \ - operator << (std::ostream& lhs, const TYPE ## _id& rhs); \ - inline size_t \ - pack_size(const TYPE ## _id&) \ - { \ - return sizeof(uint64_t); \ - } \ - e::packer \ - operator << (e::packer pa, const TYPE ## _id& rhs); \ - e::unpacker \ - operator >> (e::unpacker up, TYPE ## _id& rhs); \ - OPERATOR(TYPE, <) \ - OPERATOR(TYPE, <=) \ - OPERATOR(TYPE, ==) \ - OPERATOR(TYPE, !=) \ - OPERATOR(TYPE, >=) \ - OPERATOR(TYPE, >) + class TYPE ## _id \ + { \ + public: \ + static uint64_t hash(const TYPE ## _id& x) { return x.get(); } \ + TYPE ## _id() : m_id(0) {} \ + explicit TYPE ## _id(uint64_t id) : m_id(id) {} \ + public: \ + uint64_t get() const { return m_id; } \ + private: \ + uint64_t m_id; \ + }; \ + std::ostream& \ + operator << (std::ostream& lhs, const TYPE ## _id& rhs); \ + inline size_t \ + pack_size(const TYPE ## _id&) \ + { \ + return sizeof(uint64_t); \ + } \ + e::packer \ + operator << (e::packer pa, const TYPE ## _id& rhs); \ + e::unpacker \ + operator >> (e::unpacker up, TYPE ## _id& rhs); \ + OPERATOR(TYPE, <) \ + OPERATOR(TYPE, <=) \ + OPERATOR(TYPE, ==) \ + OPERATOR(TYPE, !=) \ + OPERATOR(TYPE, >=) \ + OPERATOR(TYPE, >) BEGIN_HYPERDEX_NAMESPACE diff --git a/common/ieee.h b/common/ieee.h index 2b34ab08f..4a8620619 100644 --- a/common/ieee.h +++ b/common/ieee.h @@ -94,29 +94,32 @@ #define EXT_FRACBITS 64 #define EXT_TO_ARRAY32(p, a) do { \ - (a)[0] = (uint32_t)(p)->ext_fracl; \ - (a)[1] = (uint32_t)(p)->ext_frach; \ -} while(0) + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_frach; \ + } while(0) -struct ieee_single { - unsigned int sng_frac:23; - unsigned int sng_exp:8; - unsigned int sng_sign:1; +struct ieee_single +{ + unsigned int sng_frac: 23; + unsigned int sng_exp: 8; + unsigned int sng_sign: 1; }; -struct ieee_double { +struct ieee_double +{ unsigned int dbl_fracl; - unsigned int dbl_frach:20; - unsigned int dbl_exp:11; - unsigned int dbl_sign:1; + unsigned int dbl_frach: 20; + unsigned int dbl_exp: 11; + unsigned int dbl_sign: 1; }; -struct ieee_ext { +struct ieee_ext +{ unsigned int ext_fracl; unsigned int ext_frach; - unsigned int ext_exp:15; - unsigned int ext_sign:1; - unsigned int ext_padl:16; + unsigned int ext_exp: 15; + unsigned int ext_sign: 1; + unsigned int ext_padl: 16; unsigned int ext_padh; }; diff --git a/common/index.cc b/common/index.cc index c51b7c559..987861a60 100644 --- a/common/index.cc +++ b/common/index.cc @@ -33,18 +33,18 @@ using hyperdex::index; index :: index() - : type(NORMAL) - , id() - , attr(UINT16_MAX) - , extra() + : type(NORMAL) + , id() + , attr(UINT16_MAX) + , extra() { } -index :: index(index_t t, index_id i, uint16_t a, const e::slice& e) - : type(t) - , id(i) - , attr(a) - , extra(e) +index :: index(index_t t, index_id i, uint16_t a, const e::slice &e) + : type(t) + , id(i) + , attr(a) + , extra(e) { } @@ -52,76 +52,74 @@ index :: ~index() throw () { } -hyperdex::index& -index :: operator = (const index& rhs) +hyperdex::index & +index :: operator = (const index &rhs) { - if (this != &rhs) - { - id = rhs.id; - attr = rhs.attr; - } - - return *this; + if (this != &rhs) + { + id = rhs.id; + attr = rhs.attr; + } + return *this; } -std::ostream& -hyperdex :: operator << (std::ostream& lhs, const index& rhs) +std::ostream & +hyperdex :: operator << (std::ostream &lhs, const index &rhs) { - switch (rhs.type) - { - case index::NORMAL: - lhs << "index(" << rhs.id.get() << ", " << rhs.attr << ")"; - break; - case index::DOCUMENT: - lhs << "index(" << rhs.id.get() - << ", " << rhs.extra.str() - << ", " << rhs.attr << ")"; - break; - default: - abort(); - } - - return lhs; + switch (rhs.type) + { + case index::NORMAL: + lhs << "index(" << rhs.id.get() << ", " << rhs.attr << ")"; + break; + case index::DOCUMENT: + lhs << "index(" << rhs.id.get() + << ", " << rhs.extra.str() + << ", " << rhs.attr << ")"; + break; + default: + abort(); + } + return lhs; } e::packer -hyperdex :: operator << (e::packer pa, const index& t) +hyperdex :: operator << (e::packer pa, const index &t) { - return pa << t.type << t.id << t.attr << t.extra; + return pa << t.type << t.id << t.attr << t.extra; } e::unpacker -hyperdex :: operator >> (e::unpacker up, index& t) +hyperdex :: operator >> (e::unpacker up, index &t) { - up = up >> t.type >> t.id >> t.attr >> t.extra; - return up; + up = up >> t.type >> t.id >> t.attr >> t.extra; + return up; } size_t -hyperdex :: pack_size(const index& t) +hyperdex :: pack_size(const index &t) { - return pack_size(t.type) + pack_size(t.id) + sizeof(t.attr) - + sizeof(uint32_t) + t.extra.size(); + return pack_size(t.type) + pack_size(t.id) + sizeof(t.attr) + + sizeof(uint32_t) + t.extra.size(); } e::packer -hyperdex :: operator << (e::packer pa, const index::index_t& t) +hyperdex :: operator << (e::packer pa, const index::index_t &t) { - uint8_t x = t; - return pa << x; + uint8_t x = t; + return pa << x; } e::unpacker -hyperdex :: operator >> (e::unpacker up, index::index_t& t) +hyperdex :: operator >> (e::unpacker up, index::index_t &t) { - uint8_t x; - up = up >> x; - t = static_cast(x); - return up; + uint8_t x; + up = up >> x; + t = static_cast(x); + return up; } size_t -hyperdex :: pack_size(const index::index_t&) +hyperdex :: pack_size(const index::index_t &) { - return sizeof(uint8_t); + return sizeof(uint8_t); } diff --git a/common/index.h b/common/index.h index f4458b3f9..e965c3152 100644 --- a/common/index.h +++ b/common/index.h @@ -40,40 +40,40 @@ BEGIN_HYPERDEX_NAMESPACE class index { - public: - enum index_t { NORMAL, DOCUMENT }; +public: + enum index_t { NORMAL, DOCUMENT }; - public: - index(); - index(index_t t, index_id i, uint16_t a, const e::slice& e); - ~index() throw (); +public: + index(); + index(index_t t, index_id i, uint16_t a, const e::slice &e); + ~index() throw (); - public: - index& operator = (const index&); +public: + index &operator = (const index &); - public: - index_t type; - index_id id; - uint16_t attr; - e::slice extra; +public: + index_t type; + index_id id; + uint16_t attr; + e::slice extra; }; -std::ostream& -operator << (std::ostream& lhs, const index& rhs); +std::ostream & +operator << (std::ostream &lhs, const index &rhs); e::packer -operator << (e::packer, const index& t); +operator << (e::packer, const index &t); e::unpacker -operator >> (e::unpacker, index& t); +operator >> (e::unpacker, index &t); size_t -pack_size(const index& t); +pack_size(const index &t); e::packer -operator << (e::packer, const index::index_t& t); +operator << (e::packer, const index::index_t &t); e::unpacker -operator >> (e::unpacker, index::index_t& t); +operator >> (e::unpacker, index::index_t &t); size_t -pack_size(const index::index_t& t); +pack_size(const index::index_t &t); END_HYPERDEX_NAMESPACE diff --git a/common/json_path.h b/common/json_path.h index fe59b59ad..73aeed839 100644 --- a/common/json_path.h +++ b/common/json_path.h @@ -38,87 +38,82 @@ BEGIN_HYPERDEX_NAMESPACE class json_path { public: - json_path(const char* cstr) - : path(cstr) - {} - - json_path(const std::string& path_ = "") - : path(path_) - {} - - json_path(const e::slice& slice) - : path(slice.cdata(), slice.size()) - {} - - bool empty() const - { - return str().size() == 0; - } - - size_t size() const - { - return str().size(); - } - - void append(const std::string elem) - { - if(empty()) - { - path = elem; - } - else - { - path += "." + elem; - } - } - - // Does this path have a subtree? - // If not is is just the name of a single element - bool has_subtree() const - { - return path.find(".") != std::string::npos; - } - - // Split path at the first . - bool split(std::string& root_name, json_path& subtree) const - { - size_t pos = path.find('.'); - - if(pos == std::string::npos) - { - return false; - } - - root_name = path.substr(0, pos); - subtree.path = path.substr(pos+1); - - return true; - } - - // Split path at the last '.' - // i.e. Retrieve last element in the path - bool split_reverse(json_path& parent_path, std::string& child_name) const - { - size_t pos = path.find_last_of('.'); - - if(pos == std::string::npos) - { - return false; - } - - child_name = path.substr(pos+1); - parent_path.path = path.substr(0, pos); - return true; - } - - // Get a string representation of the path - const std::string& str() const - { - return path; - } + json_path(const char *cstr) + : path(cstr) + {} + + json_path(const std::string &path_ = "") + : path(path_) + {} + + json_path(const e::slice &slice) + : path(slice.cdata(), slice.size()) + {} + + bool empty() const + { + return str().size() == 0; + } + + size_t size() const + { + return str().size(); + } + + void append(const std::string elem) + { + if (empty()) + { + path = elem; + } + else + { + path += "." + elem; + } + } + + // Does this path have a subtree? + // If not is is just the name of a single element + bool has_subtree() const + { + return path.find(".") != std::string::npos; + } + + // Split path at the first . + bool split(std::string &root_name, json_path &subtree) const + { + size_t pos = path.find('.'); + if (pos == std::string::npos) + { + return false; + } + root_name = path.substr(0, pos); + subtree.path = path.substr(pos + 1); + return true; + } + + // Split path at the last '.' + // i.e. Retrieve last element in the path + bool split_reverse(json_path &parent_path, std::string &child_name) const + { + size_t pos = path.find_last_of('.'); + if (pos == std::string::npos) + { + return false; + } + child_name = path.substr(pos + 1); + parent_path.path = path.substr(0, pos); + return true; + } + + // Get a string representation of the path + const std::string &str() const + { + return path; + } private: - std::string path; + std::string path; }; END_HYPERDEX_NAMESPACE diff --git a/common/key_change.cc b/common/key_change.cc index 1ec19b60e..07afff9a9 100644 --- a/common/key_change.cc +++ b/common/key_change.cc @@ -37,29 +37,29 @@ using hyperdex::key_change; key_change :: key_change() - : key() - , erase(false) - , fail_if_not_found(false) - , fail_if_found(false) - , checks() - , funcs() - , auth() + : key() + , erase(false) + , fail_if_not_found(false) + , fail_if_found(false) + , checks() + , funcs() + , auth() { } -key_change :: key_change(const key_change& other) - : key(other.key) - , erase(other.erase) - , fail_if_not_found(other.fail_if_not_found) - , fail_if_found(other.fail_if_found) - , checks(other.checks) - , funcs(other.funcs) - , auth() +key_change :: key_change(const key_change &other) + : key(other.key) + , erase(other.erase) + , fail_if_not_found(other.fail_if_not_found) + , fail_if_found(other.fail_if_found) + , checks(other.checks) + , funcs(other.funcs) + , auth() { - if (other.auth.get()) - { - auth.reset(new auth_wallet(*other.auth)); - } + if (other.auth.get()) + { + auth.reset(new auth_wallet(*other.auth)); + } } key_change :: ~key_change() throw () @@ -67,60 +67,56 @@ key_change :: ~key_change() throw () } bool -key_change :: validate(const schema& sc) const +key_change :: validate(const schema &sc) const { - return datatype_info::lookup(sc.attrs[0].type)->validate(key) && - validate_attribute_checks(sc, checks) == checks.size() && - validate_funcs(sc, funcs) == funcs.size() && - (!erase || funcs.empty()); + return datatype_info::lookup(sc.attrs[0].type)->validate(key) && + validate_attribute_checks(sc, checks) == checks.size() && + validate_funcs(sc, funcs) == funcs.size() && + (!erase || funcs.empty()); } hyperdex::network_returncode -key_change :: check(const schema& sc, +key_change :: check(const schema &sc, bool has_old_value, - const std::vector* old_value) const + const std::vector *old_value) const { - const key_change* kc = this; - - if (!has_old_value && kc->erase) - { - return NET_NOTFOUND; - } - else if (!has_old_value && kc->fail_if_not_found) - { - return NET_NOTFOUND; - } - else if (has_old_value && kc->fail_if_found) - { - return NET_CMPFAIL; - } - else if (has_old_value && passes_attribute_checks(sc, kc->checks, key, *old_value) < kc->checks.size()) - { - return NET_CMPFAIL; - } - - return NET_SUCCESS; + const key_change *kc = this; + if (!has_old_value && kc->erase) + { + return NET_NOTFOUND; + } + else if (!has_old_value && kc->fail_if_not_found) + { + return NET_NOTFOUND; + } + else if (has_old_value && kc->fail_if_found) + { + return NET_CMPFAIL; + } + else if (has_old_value && passes_attribute_checks(sc, kc->checks, key, *old_value) < kc->checks.size()) + { + return NET_CMPFAIL; + } + return NET_SUCCESS; } -key_change& -key_change :: operator = (const key_change& rhs) +key_change & +key_change :: operator = (const key_change &rhs) { - if (this != &rhs) - { - key = rhs.key; - erase = rhs.erase; - fail_if_not_found = rhs.fail_if_not_found; - fail_if_found = rhs.fail_if_found; - checks = rhs.checks; - funcs = rhs.funcs; - - if (rhs.auth.get()) - { - auth.reset(new auth_wallet(*rhs.auth)); - } - } - - return *this; + if (this != &rhs) + { + key = rhs.key; + erase = rhs.erase; + fail_if_not_found = rhs.fail_if_not_found; + fail_if_found = rhs.fail_if_found; + checks = rhs.checks; + funcs = rhs.funcs; + if (rhs.auth.get()) + { + auth.reset(new auth_wallet(*rhs.auth)); + } + } + return *this; } #define FLAG_WRITE 128 @@ -129,46 +125,42 @@ key_change :: operator = (const key_change& rhs) #define FLAG_FIF 2 e::packer -hyperdex :: operator << (e::packer pa, const key_change& td) +hyperdex :: operator << (e::packer pa, const key_change &td) { - uint8_t flags = (td.erase ? 0 : FLAG_WRITE) - | (td.fail_if_not_found ? FLAG_FINF : 0) - | (td.fail_if_found ? FLAG_FIF : 0) - | (td.auth.get() ? FLAG_AUTH : 0); - pa = pa << td.key << flags << td.checks << td.funcs; - - if (td.auth.get()) - { - pa = pa << *td.auth; - } - - return pa; + uint8_t flags = (td.erase ? 0 : FLAG_WRITE) + | (td.fail_if_not_found ? FLAG_FINF : 0) + | (td.fail_if_found ? FLAG_FIF : 0) + | (td.auth.get() ? FLAG_AUTH : 0); + pa = pa << td.key << flags << td.checks << td.funcs; + if (td.auth.get()) + { + pa = pa << *td.auth; + } + return pa; } e::unpacker -hyperdex :: operator >> (e::unpacker up, key_change& td) +hyperdex :: operator >> (e::unpacker up, key_change &td) { - uint8_t flags; - up = up >> td.key >> flags >> td.checks >> td.funcs; - td.erase = !(flags & FLAG_WRITE); - td.fail_if_not_found = flags & FLAG_FINF; - td.fail_if_found = flags & FLAG_FIF; - - if ((flags & FLAG_AUTH)) - { - td.auth.reset(new auth_wallet()); - up = up >> *td.auth; - } - - return up; + uint8_t flags; + up = up >> td.key >> flags >> td.checks >> td.funcs; + td.erase = !(flags & FLAG_WRITE); + td.fail_if_not_found = flags & FLAG_FINF; + td.fail_if_found = flags & FLAG_FIF; + if ((flags & FLAG_AUTH)) + { + td.auth.reset(new auth_wallet()); + up = up >> *td.auth; + } + return up; } size_t -hyperdex :: pack_size(const key_change& td) +hyperdex :: pack_size(const key_change &td) { - return pack_size(td.key) - + sizeof(uint8_t) - + pack_size(td.checks) - + pack_size(td.funcs) - + (td.auth.get() ? pack_size(*td.auth) : 0); + return pack_size(td.key) + + sizeof(uint8_t) + + pack_size(td.checks) + + pack_size(td.funcs) + + (td.auth.get() ? pack_size(*td.auth) : 0); } diff --git a/common/key_change.h b/common/key_change.h index e81633ee7..dafb71187 100644 --- a/common/key_change.h +++ b/common/key_change.h @@ -40,50 +40,50 @@ BEGIN_HYPERDEX_NAMESPACE // A (pending) change to an entry in the database class key_change { - public: - key_change(); - key_change(const key_change& other); - ~key_change() throw (); +public: + key_change(); + key_change(const key_change &other); + ~key_change() throw (); - public: - bool validate(const schema& sc) const; +public: + bool validate(const schema &sc) const; - // Check if a key change can be peformed - network_returncode check(const schema& sc, - bool has_old_value, - const std::vector* old_value) const; + // Check if a key change can be peformed + network_returncode check(const schema &sc, + bool has_old_value, + const std::vector *old_value) const; - public: - key_change& operator = (const key_change&); +public: + key_change &operator = (const key_change &); - public: - e::slice key; +public: + e::slice key; - // Will this entry be removed? - bool erase; + // Will this entry be removed? + bool erase; - // Keychange should fail if there is no previous value - bool fail_if_not_found; + // Keychange should fail if there is no previous value + bool fail_if_not_found; - // Keychange should fail if there is a previous value - bool fail_if_found; + // Keychange should fail if there is a previous value + bool fail_if_found; - // Checks to be performed before key change - std::vector checks; + // Checks to be performed before key change + std::vector checks; - // The actual keychange is stored here - std::vector funcs; + // The actual keychange is stored here + std::vector funcs; - // Authorization info is stored here - std::auto_ptr auth; + // Authorization info is stored here + std::auto_ptr auth; }; e::packer -operator << (e::packer, const key_change& td); +operator << (e::packer, const key_change &td); e::unpacker -operator >> (e::unpacker, key_change& td); +operator >> (e::unpacker, key_change &td); size_t -pack_size(const key_change& td); +pack_size(const key_change &td); END_HYPERDEX_NAMESPACE diff --git a/common/mapper.cc b/common/mapper.cc index 315e16120..17b59b86f 100644 --- a/common/mapper.cc +++ b/common/mapper.cc @@ -30,8 +30,8 @@ using hyperdex::mapper; -mapper :: mapper(const hyperdex::configuration* config) - : m_config(config) +mapper :: mapper(const hyperdex::configuration *config) + : m_config(config) { } @@ -40,8 +40,8 @@ mapper :: ~mapper() throw () } bool -mapper :: lookup(uint64_t id, po6::net::location* addr) +mapper :: lookup(uint64_t id, po6::net::location *addr) { - *addr = m_config->get_address(server_id(id)); - return *addr != po6::net::location(); + *addr = m_config->get_address(server_id(id)); + return *addr != po6::net::location(); } diff --git a/common/mapper.h b/common/mapper.h index b84577d92..ff92ac6a3 100644 --- a/common/mapper.h +++ b/common/mapper.h @@ -39,19 +39,19 @@ BEGIN_HYPERDEX_NAMESPACE class mapper : public ::busybee_mapper { - public: - mapper(const configuration* config); - ~mapper() throw (); +public: + mapper(const configuration *config); + ~mapper() throw (); - public: - virtual bool lookup(uint64_t id, po6::net::location* addr); +public: + virtual bool lookup(uint64_t id, po6::net::location *addr); - private: - mapper(const mapper&); - mapper& operator = (const mapper&); +private: + mapper(const mapper &); + mapper &operator = (const mapper &); - private: - const configuration* m_config; +private: + const configuration *m_config; }; END_HYPERDEX_NAMESPACE diff --git a/common/network_msgtype.cc b/common/network_msgtype.cc index 7a869f9ca..d94d03fcb 100644 --- a/common/network_msgtype.cc +++ b/common/network_msgtype.cc @@ -29,49 +29,48 @@ #include "common/macros.h" #include "common/network_msgtype.h" -std::ostream& -hyperdex :: operator << (std::ostream& lhs, const network_msgtype& rhs) +std::ostream & +hyperdex :: operator << (std::ostream &lhs, const network_msgtype &rhs) { - switch(rhs) - { - STRINGIFY(REQ_GET); - STRINGIFY(RESP_GET); - STRINGIFY(REQ_GET_PARTIAL); - STRINGIFY(RESP_GET_PARTIAL); - STRINGIFY(REQ_ATOMIC); - STRINGIFY(RESP_ATOMIC); - STRINGIFY(REQ_SEARCH_START); - STRINGIFY(REQ_SEARCH_NEXT); - STRINGIFY(REQ_SEARCH_STOP); - STRINGIFY(RESP_SEARCH_ITEM); - STRINGIFY(RESP_SEARCH_DONE); - STRINGIFY(REQ_SORTED_SEARCH); - STRINGIFY(RESP_SORTED_SEARCH); - STRINGIFY(REQ_COUNT); - STRINGIFY(RESP_COUNT); - STRINGIFY(REQ_SUM); - STRINGIFY(RESP_SUM); - STRINGIFY(REQ_SEARCH_DESCRIBE); - STRINGIFY(RESP_SEARCH_DESCRIBE); - STRINGIFY(REQ_GROUP_ATOMIC); - STRINGIFY(RESP_GROUP_ATOMIC); - STRINGIFY(CHAIN_OP); - STRINGIFY(CHAIN_SUBSPACE); - STRINGIFY(CHAIN_ACK); - STRINGIFY(XFER_OP); - STRINGIFY(XFER_ACK); - STRINGIFY(XFER_HS); - STRINGIFY(XFER_HSA); - STRINGIFY(XFER_HA); - STRINGIFY(XFER_HW); - STRINGIFY(BACKUP); - STRINGIFY(PERF_COUNTERS); - STRINGIFY(CONFIGMISMATCH); - STRINGIFY(PACKET_NOP); - default: - lhs << "unknown network_msgtype"; - break; - } - - return lhs; + switch (rhs) + { + STRINGIFY(REQ_GET); + STRINGIFY(RESP_GET); + STRINGIFY(REQ_GET_PARTIAL); + STRINGIFY(RESP_GET_PARTIAL); + STRINGIFY(REQ_ATOMIC); + STRINGIFY(RESP_ATOMIC); + STRINGIFY(REQ_SEARCH_START); + STRINGIFY(REQ_SEARCH_NEXT); + STRINGIFY(REQ_SEARCH_STOP); + STRINGIFY(RESP_SEARCH_ITEM); + STRINGIFY(RESP_SEARCH_DONE); + STRINGIFY(REQ_SORTED_SEARCH); + STRINGIFY(RESP_SORTED_SEARCH); + STRINGIFY(REQ_COUNT); + STRINGIFY(RESP_COUNT); + STRINGIFY(REQ_SUM); + STRINGIFY(RESP_SUM); + STRINGIFY(REQ_SEARCH_DESCRIBE); + STRINGIFY(RESP_SEARCH_DESCRIBE); + STRINGIFY(REQ_GROUP_ATOMIC); + STRINGIFY(RESP_GROUP_ATOMIC); + STRINGIFY(CHAIN_OP); + STRINGIFY(CHAIN_SUBSPACE); + STRINGIFY(CHAIN_ACK); + STRINGIFY(XFER_OP); + STRINGIFY(XFER_ACK); + STRINGIFY(XFER_HS); + STRINGIFY(XFER_HSA); + STRINGIFY(XFER_HA); + STRINGIFY(XFER_HW); + STRINGIFY(BACKUP); + STRINGIFY(PERF_COUNTERS); + STRINGIFY(CONFIGMISMATCH); + STRINGIFY(PACKET_NOP); + default: + lhs << "unknown network_msgtype"; + break; + } + return lhs; } diff --git a/common/network_msgtype.h b/common/network_msgtype.h index be48f483d..5a70e25e9 100644 --- a/common/network_msgtype.h +++ b/common/network_msgtype.h @@ -38,59 +38,59 @@ BEGIN_HYPERDEX_NAMESPACE enum network_msgtype { - REQ_GET = 8, - RESP_GET = 9, + REQ_GET = 8, + RESP_GET = 9, - REQ_GET_PARTIAL = 10, - RESP_GET_PARTIAL = 11, + REQ_GET_PARTIAL = 10, + RESP_GET_PARTIAL = 11, - REQ_ATOMIC = 16, - RESP_ATOMIC = 17, + REQ_ATOMIC = 16, + RESP_ATOMIC = 17, - REQ_SEARCH_START = 32, - REQ_SEARCH_NEXT = 33, - REQ_SEARCH_STOP = 34, - RESP_SEARCH_ITEM = 35, - RESP_SEARCH_DONE = 36, + REQ_SEARCH_START = 32, + REQ_SEARCH_NEXT = 33, + REQ_SEARCH_STOP = 34, + RESP_SEARCH_ITEM = 35, + RESP_SEARCH_DONE = 36, - REQ_SORTED_SEARCH = 40, - RESP_SORTED_SEARCH = 41, + REQ_SORTED_SEARCH = 40, + RESP_SORTED_SEARCH = 41, - /* 48, 49 retired */ + /* 48, 49 retired */ - REQ_COUNT = 50, - RESP_COUNT = 51, + REQ_COUNT = 50, + RESP_COUNT = 51, - REQ_SEARCH_DESCRIBE = 52, - RESP_SEARCH_DESCRIBE = 53, + REQ_SEARCH_DESCRIBE = 52, + RESP_SEARCH_DESCRIBE = 53, - REQ_GROUP_ATOMIC = 54, - RESP_GROUP_ATOMIC = 55, + REQ_GROUP_ATOMIC = 54, + RESP_GROUP_ATOMIC = 55, REQ_SUM = 58, RESP_SUM = 59, - CHAIN_OP = 64, - CHAIN_SUBSPACE = 65, - CHAIN_ACK = 66, - /* 67 retired */ + CHAIN_OP = 64, + CHAIN_SUBSPACE = 65, + CHAIN_ACK = 66, + /* 67 retired */ - XFER_OP = 80, - XFER_ACK = 81, - XFER_HS = 82, // handshake syn - XFER_HSA = 83, // handshake syn-ack - XFER_HA = 84, // handshake ack - XFER_HW = 85, // wiped + XFER_OP = 80, + XFER_ACK = 81, + XFER_HS = 82, // handshake syn + XFER_HSA = 83, // handshake syn-ack + XFER_HA = 84, // handshake ack + XFER_HW = 85, // wiped - BACKUP = 126, - PERF_COUNTERS = 127, + BACKUP = 126, + PERF_COUNTERS = 127, - CONFIGMISMATCH = 254, - PACKET_NOP = 255 + CONFIGMISMATCH = 254, + PACKET_NOP = 255 }; -std::ostream& -operator << (std::ostream& lhs, const network_msgtype& rhs); +std::ostream & +operator << (std::ostream &lhs, const network_msgtype &rhs); END_HYPERDEX_NAMESPACE diff --git a/common/network_returncode.h b/common/network_returncode.h old mode 100755 new mode 100644 index d2ea6d6d7..0b004ae1a --- a/common/network_returncode.h +++ b/common/network_returncode.h @@ -36,15 +36,15 @@ BEGIN_HYPERDEX_NAMESPACE // HyperDisk returncode occupies [8320, 8448) enum network_returncode { - NET_SUCCESS = 8320, - NET_NOTFOUND = 8321, - NET_BADDIMSPEC = 8322, - NET_NOTUS = 8323, - NET_SERVERERROR = 8324, - NET_CMPFAIL = 8325, - NET_READONLY = 8327, - NET_OVERFLOW = 8328, - NET_UNAUTHORIZED = 8329 + NET_SUCCESS = 8320, + NET_NOTFOUND = 8321, + NET_BADDIMSPEC = 8322, + NET_NOTUS = 8323, + NET_SERVERERROR = 8324, + NET_CMPFAIL = 8325, + NET_READONLY = 8327, + NET_OVERFLOW = 8328, + NET_UNAUTHORIZED = 8329 }; END_HYPERDEX_NAMESPACE diff --git a/common/ordered_encoding.cc b/common/ordered_encoding.cc index c1dd8471e..63fbf101f 100644 --- a/common/ordered_encoding.cc +++ b/common/ordered_encoding.cc @@ -43,17 +43,17 @@ uint64_t hyperdex :: ordered_encode_int64(int64_t x) { - uint64_t out = static_cast(x); - out += x >= 0 ? 0x8000000000000000ULL : INT64_MIN; - return out; + uint64_t out = static_cast(x); + out += x >= 0 ? 0x8000000000000000ULL : INT64_MIN; + return out; } int64_t hyperdex :: ordered_decode_int64(uint64_t x) { - uint64_t out = static_cast(x); - out -= x >= 0x8000000000000000ULL ? 0x8000000000000000ULL : INT64_MIN; - return out; + uint64_t out = static_cast(x); + out -= x >= 0x8000000000000000ULL ? 0x8000000000000000ULL : INT64_MIN; + return out; } // A little reminder about IEEE 754 doubles. Source Patterson&Hennessy 3ed. @@ -114,48 +114,44 @@ hyperdex :: ordered_decode_int64(uint64_t x) uint64_t hyperdex :: ordered_encode_double(double x) { - uint64_t out = 0xffffffffffffffffULL; - - if (std::isinf(x)) - { - if (x > 0) - { - out = 0xfff0000000000000ULL + 2; - } - else - { - out = 0; - } - } - else if (std::isnan(x)) - { - out = 0xfff0000000000000ULL + 3; - } - else if (x == 0) - { - out = 0x8000000000000000ULL + 1; - } - else - { - union { double d; ieee_double ieee; } d; - d.d = x; - uint64_t sign = d.ieee.dbl_sign ^ 0x1; - uint64_t exp = d.ieee.dbl_exp; - uint64_t frac = d.ieee.dbl_frach; - frac <<= 32; - frac |= d.ieee.dbl_fracl; - uint64_t shift = 2; - - if (x < 0) - { - exp ^= 0x7ffULL; - frac ^= 0xfffffffffffffULL; - shift = 1; - } - - out = (sign << 63) | (exp << 52) | (frac); - out += shift; - } - - return out; + uint64_t out = 0xffffffffffffffffULL; + if (std::isinf(x)) + { + if (x > 0) + { + out = 0xfff0000000000000ULL + 2; + } + else + { + out = 0; + } + } + else if (std::isnan(x)) + { + out = 0xfff0000000000000ULL + 3; + } + else if (x == 0) + { + out = 0x8000000000000000ULL + 1; + } + else + { + union { double d; ieee_double ieee; } d; + d.d = x; + uint64_t sign = d.ieee.dbl_sign ^ 0x1; + uint64_t exp = d.ieee.dbl_exp; + uint64_t frac = d.ieee.dbl_frach; + frac <<= 32; + frac |= d.ieee.dbl_fracl; + uint64_t shift = 2; + if (x < 0) + { + exp ^= 0x7ffULL; + frac ^= 0xfffffffffffffULL; + shift = 1; + } + out = (sign << 63) | (exp << 52) | (frac); + out += shift; + } + return out; } diff --git a/common/range.cc b/common/range.cc index 57e4d6008..857a5870f 100644 --- a/common/range.cc +++ b/common/range.cc @@ -33,24 +33,24 @@ using hyperdex::range; range :: range() - : attr(UINT16_MAX) - , type(HYPERDATATYPE_GARBAGE) - , start() - , end() - , has_start(false) - , has_end(false) - , invalid(true) + : attr(UINT16_MAX) + , type(HYPERDATATYPE_GARBAGE) + , start() + , end() + , has_start(false) + , has_end(false) + , invalid(true) { } -range :: range(const range& other) - : attr(other.attr) - , type(other.type) - , start(other.start) - , end(other.end) - , has_start(other.has_start) - , has_end(other.has_end) - , invalid(other.invalid) +range :: range(const range &other) + : attr(other.attr) + , type(other.type) + , start(other.start) + , end(other.end) + , has_start(other.has_start) + , has_end(other.has_end) + , invalid(other.invalid) { } @@ -58,22 +58,22 @@ range :: ~range() throw () { } -range& -range :: operator = (const range& rhs) +range & +range :: operator = (const range &rhs) { - attr = rhs.attr; - type = rhs.type; - start = rhs.start; - end = rhs.end; - has_start = rhs.has_start; - has_end = rhs.has_end; - invalid = rhs.invalid; - return *this; + attr = rhs.attr; + type = rhs.type; + start = rhs.start; + end = rhs.end; + has_start = rhs.has_start; + has_end = rhs.has_end; + invalid = rhs.invalid; + return *this; } bool -range :: operator < (const range& rhs) const +range :: operator < (const range &rhs) const { - const range& lhs(*this); - return lhs.attr < rhs.attr; + const range &lhs(*this); + return lhs.attr < rhs.attr; } diff --git a/common/range.h b/common/range.h index 6fac1bbe3..d3a85d924 100644 --- a/common/range.h +++ b/common/range.h @@ -40,23 +40,23 @@ BEGIN_HYPERDEX_NAMESPACE // a range is inclusive class range { - public: - range(); - range(const range& other); - ~range() throw (); +public: + range(); + range(const range &other); + ~range() throw (); - public: - range& operator = (const range& rhs); - bool operator < (const range& rhs) const; +public: + range &operator = (const range &rhs); + bool operator < (const range &rhs) const; - public: - uint16_t attr; - hyperdatatype type; // XXX remove - e::slice start; - e::slice end; - bool has_start; - bool has_end; - bool invalid; +public: + uint16_t attr; + hyperdatatype type; // XXX remove + e::slice start; + e::slice end; + bool has_start; + bool has_end; + bool invalid; }; END_HYPERDEX_NAMESPACE diff --git a/common/range_searches.cc b/common/range_searches.cc index aac97fa1c..25e0544dd 100644 --- a/common/range_searches.cc +++ b/common/range_searches.cc @@ -48,155 +48,140 @@ using hyperdex::range; // you will need to look at the way indices are picked in the data layer and the // way ranges are picked for hyperspace hashing. static bool -range_search(const attribute_check& check, range* r) +range_search(const attribute_check &check, range *r) { - switch (check.predicate) - { - case HYPERPREDICATE_EQUALS: - r->attr = check.attr; - r->type = check.datatype; - r->start = check.value; - r->end = check.value; - r->has_start = true; - r->has_end = true; - r->invalid = false; - return true; - case HYPERPREDICATE_LESS_THAN: - case HYPERPREDICATE_LESS_EQUAL: - r->attr = check.attr; - r->type = check.datatype; - r->end = check.value; - r->has_start = false; - r->has_end = true; - r->invalid = false; - return true; - case HYPERPREDICATE_GREATER_EQUAL: - case HYPERPREDICATE_GREATER_THAN: - r->attr = check.attr; - r->type = check.datatype; - r->start = check.value; - r->has_start = true; - r->has_end = false; - r->invalid = false; - return true; - case HYPERPREDICATE_FAIL: - case HYPERPREDICATE_CONTAINS_LESS_THAN: - case HYPERPREDICATE_REGEX: - case HYPERPREDICATE_LENGTH_EQUALS: - case HYPERPREDICATE_LENGTH_LESS_EQUAL: - case HYPERPREDICATE_LENGTH_GREATER_EQUAL: - case HYPERPREDICATE_CONTAINS: - default: - return false; - } + switch (check.predicate) + { + case HYPERPREDICATE_EQUALS: + r->attr = check.attr; + r->type = check.datatype; + r->start = check.value; + r->end = check.value; + r->has_start = true; + r->has_end = true; + r->invalid = false; + return true; + case HYPERPREDICATE_LESS_THAN: + case HYPERPREDICATE_LESS_EQUAL: + r->attr = check.attr; + r->type = check.datatype; + r->end = check.value; + r->has_start = false; + r->has_end = true; + r->invalid = false; + return true; + case HYPERPREDICATE_GREATER_EQUAL: + case HYPERPREDICATE_GREATER_THAN: + r->attr = check.attr; + r->type = check.datatype; + r->start = check.value; + r->has_start = true; + r->has_end = false; + r->invalid = false; + return true; + case HYPERPREDICATE_FAIL: + case HYPERPREDICATE_CONTAINS_LESS_THAN: + case HYPERPREDICATE_REGEX: + case HYPERPREDICATE_LENGTH_EQUALS: + case HYPERPREDICATE_LENGTH_LESS_EQUAL: + case HYPERPREDICATE_LENGTH_GREATER_EQUAL: + case HYPERPREDICATE_CONTAINS: + default: + return false; + } } static bool -compress_ranges(const range* range_ptr, const range* range_end, range* r) +compress_ranges(const range *range_ptr, const range *range_end, range *r) { - r->attr = range_ptr->attr; - r->type = range_ptr->type; - r->start = e::slice(); - r->end = e::slice(); - r->has_start = false; - r->has_end = false; - r->invalid = false; - datatype_info* di = datatype_info::lookup(range_ptr->type); - - if (!di) - { - return false; - } - - for (; range_ptr < range_end; ++range_ptr) - { - // bump/set the start if necessary - if (range_ptr->has_start && r->has_start) - { - if (di->compare(range_ptr->start, r->start) > 0) - { - r->start = range_ptr->start; - } - } - else if (range_ptr->has_start) - { - r->start = range_ptr->start; - r->has_start = true; - } - - // cut/set the end if necessary - if (range_ptr->has_end && r->has_end) - { - if (di->compare(range_ptr->end, r->end) < 0) - { - r->end = range_ptr->end; - } - } - else if (range_ptr->has_end) - { - r->end = range_ptr->end; - r->has_end = true; - } - } - - if (r->has_start && r->has_end && di->compare(r->start, r->end) > 0) - { - r->invalid = true; - } - - return true; + r->attr = range_ptr->attr; + r->type = range_ptr->type; + r->start = e::slice(); + r->end = e::slice(); + r->has_start = false; + r->has_end = false; + r->invalid = false; + datatype_info *di = datatype_info::lookup(range_ptr->type); + if (!di) + { + return false; + } + for (; range_ptr < range_end; ++range_ptr) + { + // bump/set the start if necessary + if (range_ptr->has_start && r->has_start) + { + if (di->compare(range_ptr->start, r->start) > 0) + { + r->start = range_ptr->start; + } + } + else if (range_ptr->has_start) + { + r->start = range_ptr->start; + r->has_start = true; + } + // cut/set the end if necessary + if (range_ptr->has_end && r->has_end) + { + if (di->compare(range_ptr->end, r->end) < 0) + { + r->end = range_ptr->end; + } + } + else if (range_ptr->has_end) + { + r->end = range_ptr->end; + r->has_end = true; + } + } + if (r->has_start && r->has_end && di->compare(r->start, r->end) > 0) + { + r->invalid = true; + } + return true; } void -hyperdex :: range_searches(const schema& sc, - const std::vector& checks, - std::vector* ranges) +hyperdex :: range_searches(const schema &sc, + const std::vector &checks, + std::vector *ranges) { - std::vector raw_ranges; - raw_ranges.reserve(checks.size()); - - for (size_t i = 0; i < checks.size(); ++i) - { - if (checks[i].attr >= sc.attrs_sz || - datatype_info::lookup(sc.attrs[checks[i].attr].type)->document()) - { - continue; - } - - range r; - - if (range_search(checks[i], &r)) - { - raw_ranges.push_back(r); - } - } - - std::sort(raw_ranges.begin(), raw_ranges.end()); - const range* range_ptr = &raw_ranges.front(); - const range* range_end = range_ptr + raw_ranges.size(); - ranges->clear(); - - while (range_ptr < range_end) - { - const range* tmp = range_ptr; - - while (tmp < range_end && range_ptr->attr == tmp->attr) - { - assert(range_ptr->attr == tmp->attr); - assert(range_ptr->type == tmp->type); - ++tmp; - } - - assert(tmp == range_end || range_ptr->attr < tmp->attr); - range r; - - if (compress_ranges(range_ptr, tmp, &r)) - { - ranges->push_back(r); - } - - range_ptr = tmp; - } - - assert(ranges->size() <= checks.size()); + std::vector raw_ranges; + raw_ranges.reserve(checks.size()); + for (size_t i = 0; i < checks.size(); ++i) + { + if (checks[i].attr >= sc.attrs_sz || + datatype_info::lookup(sc.attrs[checks[i].attr].type)->document()) + { + continue; + } + range r; + if (range_search(checks[i], &r)) + { + raw_ranges.push_back(r); + } + } + std::sort(raw_ranges.begin(), raw_ranges.end()); + const range *range_ptr = &raw_ranges.front(); + const range *range_end = range_ptr + raw_ranges.size(); + ranges->clear(); + while (range_ptr < range_end) + { + const range *tmp = range_ptr; + while (tmp < range_end && range_ptr->attr == tmp->attr) + { + assert(range_ptr->attr == tmp->attr); + assert(range_ptr->type == tmp->type); + ++tmp; + } + assert(tmp == range_end || range_ptr->attr < tmp->attr); + range r; + if (compress_ranges(range_ptr, tmp, &r)) + { + ranges->push_back(r); + } + range_ptr = tmp; + } + assert(ranges->size() <= checks.size()); } diff --git a/common/range_searches.h b/common/range_searches.h index ac4deeb42..5e664bdfd 100644 --- a/common/range_searches.h +++ b/common/range_searches.h @@ -39,9 +39,9 @@ BEGIN_HYPERDEX_NAMESPACE void -range_searches(const schema& sc, - const std::vector& checks, - std::vector* ranges); +range_searches(const schema &sc, + const std::vector &checks, + std::vector *ranges); END_HYPERDEX_NAMESPACE diff --git a/common/regex_match.cc b/common/regex_match.cc index bd914bf8a..f8b12d41e 100644 --- a/common/regex_match.cc +++ b/common/regex_match.cc @@ -5,103 +5,90 @@ #include "common/regex_match.h" static bool -anchored(const char* regex, const char* regex_end, - const char* text, const char* text_end); +anchored(const char *regex, const char *regex_end, + const char *text, const char *text_end); static bool starred(int c, - const char* regex, const char* regex_end, - const char* text, const char* text_end); + const char *regex, const char *regex_end, + const char *text, const char *text_end); bool -anchored(const char* regex, const char* regex_end, - const char* text, const char* text_end) +anchored(const char *regex, const char *regex_end, + const char *text, const char *text_end) { - assert(regex <= regex_end); - assert(text <= text_end); - - if (regex == regex_end) - { - return true; - } - - if (regex[0] == '\\') - { - if (regex + 1 < regex_end && - text < text_end && - regex[1] == text[0]) - { - return anchored(regex + 2, regex_end, text + 1, text_end); - } - - return false; - } - - if (regex + 1 < regex_end && regex[1] == '*') - { - return starred(regex[0], regex + 2, regex_end, text, text_end); - } - - if (regex[0] == '$' && regex + 1 == regex_end) - { - return text == text_end; - } - - if (text < text_end && (regex[0] == '.' || regex[0] == text[0])) - { - return anchored(regex + 1, regex_end, text + 1, text_end); - } - - return false; + assert(regex <= regex_end); + assert(text <= text_end); + if (regex == regex_end) + { + return true; + } + if (regex[0] == '\\') + { + if (regex + 1 < regex_end && + text < text_end && + regex[1] == text[0]) + { + return anchored(regex + 2, regex_end, text + 1, text_end); + } + return false; + } + if (regex + 1 < regex_end && regex[1] == '*') + { + return starred(regex[0], regex + 2, regex_end, text, text_end); + } + if (regex[0] == '$' && regex + 1 == regex_end) + { + return text == text_end; + } + if (text < text_end && (regex[0] == '.' || regex[0] == text[0])) + { + return anchored(regex + 1, regex_end, text + 1, text_end); + } + return false; } bool starred(int c, - const char* regex, const char* regex_end, - const char* text, const char* text_end) + const char *regex, const char *regex_end, + const char *text, const char *text_end) { - for (; text <= text_end; ++text) - { - if (anchored(regex, regex_end, text, text_end)) - { - return true; - } - - if (text < text_end && *text != c && c != '.') - { - break; - } - } - - return false; + for (; text <= text_end; ++text) + { + if (anchored(regex, regex_end, text, text_end)) + { + return true; + } + if (text < text_end && *text != c && c != '.') + { + break; + } + } + return false; } bool -hyperdex :: regex_match(const uint8_t* _regex, size_t regex_sz, - const uint8_t* _text, size_t text_sz) +hyperdex :: regex_match(const uint8_t *_regex, size_t regex_sz, + const uint8_t *_text, size_t text_sz) { - const char* regex = reinterpret_cast(_regex); - const char* text = reinterpret_cast(_text); - const char* regex_end = regex + regex_sz; - const char* text_end = text + text_sz; - - if (regex_sz == 0) - { - return true; - } - - if (regex[0] == '^') - { - return anchored(regex + 1, regex_end, text, text_end); - } - - for (; text <= text_end; ++text) - { - if (anchored(regex, regex_end, text, text_end)) - { - return true; - } - } - - return false; + const char *regex = reinterpret_cast(_regex); + const char *text = reinterpret_cast(_text); + const char *regex_end = regex + regex_sz; + const char *text_end = text + text_sz; + if (regex_sz == 0) + { + return true; + } + if (regex[0] == '^') + { + return anchored(regex + 1, regex_end, text, text_end); + } + for (; text <= text_end; ++text) + { + if (anchored(regex, regex_end, text, text_end)) + { + return true; + } + } + return false; } diff --git a/common/regex_match.h b/common/regex_match.h index 3d97c01dc..e38602b9a 100644 --- a/common/regex_match.h +++ b/common/regex_match.h @@ -38,8 +38,8 @@ BEGIN_HYPERDEX_NAMESPACE bool -regex_match(const uint8_t* regex, size_t regex_sz, - const uint8_t* text, size_t text_sz); +regex_match(const uint8_t *regex, size_t regex_sz, + const uint8_t *text, size_t text_sz); END_HYPERDEX_NAMESPACE diff --git a/common/schema.cc b/common/schema.cc index 74517e357..6c52d7aa1 100644 --- a/common/schema.cc +++ b/common/schema.cc @@ -34,22 +34,21 @@ using hyperdex::schema; schema :: schema() - : attrs_sz(0) - , attrs(NULL) - , authorization(false) + : attrs_sz(0) + , attrs(NULL) + , authorization(false) { } uint16_t -schema :: lookup_attr(const char* name) const +schema :: lookup_attr(const char *name) const { - for (uint16_t i = 0; i < attrs_sz; ++i) - { - if (strcmp(name, attrs[i].name) == 0) - { - return i; - } - } - - return attrs_sz; + for (uint16_t i = 0; i < attrs_sz; ++i) + { + if (strcmp(name, attrs[i].name) == 0) + { + return i; + } + } + return attrs_sz; } diff --git a/common/schema.h b/common/schema.h index ad613fd21..6fd4e54c4 100644 --- a/common/schema.h +++ b/common/schema.h @@ -39,16 +39,16 @@ BEGIN_HYPERDEX_NAMESPACE class schema { - public: - schema(); +public: + schema(); - public: - uint16_t lookup_attr(const char* name) const; +public: + uint16_t lookup_attr(const char *name) const; - public: - uint16_t attrs_sz; - const attribute* attrs; - bool authorization; +public: + uint16_t attrs_sz; + const attribute *attrs; + bool authorization; }; END_HYPERDEX_NAMESPACE diff --git a/common/serialization.cc b/common/serialization.cc index e075954d9..446e5b960 100644 --- a/common/serialization.cc +++ b/common/serialization.cc @@ -29,45 +29,45 @@ #include "common/serialization.h" e::packer -hyperdex :: operator << (e::packer lhs, const hyperdatatype& rhs) +hyperdex :: operator << (e::packer lhs, const hyperdatatype &rhs) { - uint16_t r = static_cast(rhs); - return lhs << r; + uint16_t r = static_cast(rhs); + return lhs << r; } e::unpacker -hyperdex :: operator >> (e::unpacker lhs, hyperdatatype& rhs) +hyperdex :: operator >> (e::unpacker lhs, hyperdatatype &rhs) { - uint16_t r; - lhs = lhs >> r; - rhs = static_cast(r); - return lhs; + uint16_t r; + lhs = lhs >> r; + rhs = static_cast(r); + return lhs; } size_t -hyperdex :: pack_size(const hyperdatatype&) +hyperdex :: pack_size(const hyperdatatype &) { - return sizeof(uint16_t); + return sizeof(uint16_t); } e::packer -hyperdex :: operator << (e::packer lhs, const hyperpredicate& rhs) +hyperdex :: operator << (e::packer lhs, const hyperpredicate &rhs) { - uint16_t r = static_cast(rhs); - return lhs << r; + uint16_t r = static_cast(rhs); + return lhs << r; } e::unpacker -hyperdex :: operator >> (e::unpacker lhs, hyperpredicate& rhs) +hyperdex :: operator >> (e::unpacker lhs, hyperpredicate &rhs) { - uint16_t r; - lhs = lhs >> r; - rhs = static_cast(r); - return lhs; + uint16_t r; + lhs = lhs >> r; + rhs = static_cast(r); + return lhs; } size_t -hyperdex :: pack_size(const hyperpredicate&) +hyperdex :: pack_size(const hyperpredicate &) { - return sizeof(uint16_t); + return sizeof(uint16_t); } diff --git a/common/serialization.h b/common/serialization.h index af8883f39..baa9c45f0 100644 --- a/common/serialization.h +++ b/common/serialization.h @@ -42,18 +42,18 @@ using ::pack_size; using e::pack_size; e::packer -operator << (e::packer lhs, const hyperdatatype& rhs); +operator << (e::packer lhs, const hyperdatatype &rhs); e::unpacker -operator >> (e::unpacker lhs, hyperdatatype& rhs); +operator >> (e::unpacker lhs, hyperdatatype &rhs); size_t -pack_size(const hyperdatatype& h); +pack_size(const hyperdatatype &h); e::packer -operator << (e::packer lhs, const hyperpredicate& rhs); +operator << (e::packer lhs, const hyperpredicate &rhs); e::unpacker -operator >> (e::unpacker lhs, hyperpredicate& rhs); +operator >> (e::unpacker lhs, hyperpredicate &rhs); size_t -pack_size(const hyperpredicate& p); +pack_size(const hyperpredicate &p); END_HYPERDEX_NAMESPACE diff --git a/common/server.cc b/common/server.cc index b5dbfa756..4e6a00235 100644 --- a/common/server.cc +++ b/common/server.cc @@ -31,66 +31,66 @@ using hyperdex::server; -const char* +const char * server :: to_string(state_t state) { - switch (state) - { - case ASSIGNED: - return "ASSIGNED"; - case NOT_AVAILABLE: - return "NOT_AVAILABLE"; - case AVAILABLE: - return "AVAILABLE"; - case SHUTDOWN: - return "SHUTDOWN"; - case KILLED: - return "KILLED"; - default: - return "UNKNOWN"; - } + switch (state) + { + case ASSIGNED: + return "ASSIGNED"; + case NOT_AVAILABLE: + return "NOT_AVAILABLE"; + case AVAILABLE: + return "AVAILABLE"; + case SHUTDOWN: + return "SHUTDOWN"; + case KILLED: + return "KILLED"; + default: + return "UNKNOWN"; + } } server :: server() - : state(KILLED) - , id() - , bind_to() + : state(KILLED) + , id() + , bind_to() { } -server :: server(const server_id& sid) - : state(ASSIGNED) - , id(sid) - , bind_to() +server :: server(const server_id &sid) + : state(ASSIGNED) + , id(sid) + , bind_to() { } bool -hyperdex :: operator < (const server& lhs, const server& rhs) +hyperdex :: operator < (const server &lhs, const server &rhs) { - return lhs.id < rhs.id; + return lhs.id < rhs.id; } e::packer -hyperdex :: operator << (e::packer lhs, const server& rhs) +hyperdex :: operator << (e::packer lhs, const server &rhs) { - uint8_t s = static_cast(rhs.state); - return lhs << s << rhs.id << rhs.bind_to; + uint8_t s = static_cast(rhs.state); + return lhs << s << rhs.id << rhs.bind_to; } e::unpacker -hyperdex :: operator >> (e::unpacker lhs, server& rhs) +hyperdex :: operator >> (e::unpacker lhs, server &rhs) { - uint8_t s; - lhs = lhs >> s >> rhs.id >> rhs.bind_to; - rhs.state = static_cast(s); - return lhs; + uint8_t s; + lhs = lhs >> s >> rhs.id >> rhs.bind_to; + rhs.state = static_cast(s); + return lhs; } size_t -hyperdex :: pack_size(const server& p) +hyperdex :: pack_size(const server &p) { - return sizeof(uint8_t) - + sizeof(uint64_t) - + pack_size(p.bind_to); + return sizeof(uint8_t) + + sizeof(uint64_t) + + pack_size(p.bind_to); } diff --git a/common/server.h b/common/server.h index f74dabf03..7c7e9e653 100644 --- a/common/server.h +++ b/common/server.h @@ -39,36 +39,36 @@ BEGIN_HYPERDEX_NAMESPACE class server { - public: - enum state_t - { - ASSIGNED = 1, - NOT_AVAILABLE = 2, - AVAILABLE = 3, - SHUTDOWN = 4, - KILLED = 5 - }; - static const char* to_string(state_t state); +public: + enum state_t + { + ASSIGNED = 1, + NOT_AVAILABLE = 2, + AVAILABLE = 3, + SHUTDOWN = 4, + KILLED = 5 + }; + static const char *to_string(state_t state); - public: - server(); - explicit server(const server_id&); +public: + server(); + explicit server(const server_id &); - public: - state_t state; - server_id id; - po6::net::location bind_to; +public: + state_t state; + server_id id; + po6::net::location bind_to; }; bool -operator < (const server& lhs, const server& rhs); +operator < (const server &lhs, const server &rhs); e::packer -operator << (e::packer lhs, const server& rhs); +operator << (e::packer lhs, const server &rhs); e::unpacker -operator >> (e::unpacker lhs, server& rhs); +operator >> (e::unpacker lhs, server &rhs); size_t -pack_size(const server& p); +pack_size(const server &p); END_HYPERDEX_NAMESPACE diff --git a/common/test/ordered_encoding.cc b/common/test/ordered_encoding.cc index 0093c16c5..aa197d5f4 100644 --- a/common/test/ordered_encoding.cc +++ b/common/test/ordered_encoding.cc @@ -41,83 +41,77 @@ using hyperdex::ordered_encode_double; TEST(OrderedEncoding, EncodeInt64) { - ASSERT_EQ(0xffffffffffffffffULL, ordered_encode_int64(INT64_MAX)); - ASSERT_EQ(0xfffffffffffffffeULL, ordered_encode_int64(INT64_MAX - 1)); - ASSERT_EQ(0x8000000000000001ULL, ordered_encode_int64(1)); - ASSERT_EQ(0x8000000000000000ULL, ordered_encode_int64(0)); - ASSERT_EQ(0x7fffffffffffffffULL, ordered_encode_int64(-1)); - ASSERT_EQ(0x0000000000000001ULL, ordered_encode_int64(INT64_MIN + 1)); - ASSERT_EQ(0x0000000000000000ULL, ordered_encode_int64(INT64_MIN)); + ASSERT_EQ(0xffffffffffffffffULL, ordered_encode_int64(INT64_MAX)); + ASSERT_EQ(0xfffffffffffffffeULL, ordered_encode_int64(INT64_MAX - 1)); + ASSERT_EQ(0x8000000000000001ULL, ordered_encode_int64(1)); + ASSERT_EQ(0x8000000000000000ULL, ordered_encode_int64(0)); + ASSERT_EQ(0x7fffffffffffffffULL, ordered_encode_int64(-1)); + ASSERT_EQ(0x0000000000000001ULL, ordered_encode_int64(INT64_MIN + 1)); + ASSERT_EQ(0x0000000000000000ULL, ordered_encode_int64(INT64_MIN)); } TEST(OrderedEncoding, DecodeInt64) { - ASSERT_EQ(INT64_MAX, ordered_decode_int64(0xffffffffffffffffULL)); - ASSERT_EQ(INT64_MAX - 1, ordered_decode_int64(0xfffffffffffffffeULL)); - ASSERT_EQ(1, ordered_decode_int64(0x8000000000000001ULL)); - ASSERT_EQ(0, ordered_decode_int64(0x8000000000000000ULL)); - ASSERT_EQ(-1, ordered_decode_int64(0x7fffffffffffffffULL)); - ASSERT_EQ(INT64_MIN + 1, ordered_decode_int64(0x0000000000000001ULL)); - ASSERT_EQ(INT64_MIN, ordered_decode_int64(0x0000000000000000ULL)); + ASSERT_EQ(INT64_MAX, ordered_decode_int64(0xffffffffffffffffULL)); + ASSERT_EQ(INT64_MAX - 1, ordered_decode_int64(0xfffffffffffffffeULL)); + ASSERT_EQ(1, ordered_decode_int64(0x8000000000000001ULL)); + ASSERT_EQ(0, ordered_decode_int64(0x8000000000000000ULL)); + ASSERT_EQ(-1, ordered_decode_int64(0x7fffffffffffffffULL)); + ASSERT_EQ(INT64_MIN + 1, ordered_decode_int64(0x0000000000000001ULL)); + ASSERT_EQ(INT64_MIN, ordered_decode_int64(0x0000000000000000ULL)); } TEST(IndexEncode, Double) { - ASSERT_EQ(0x0000000000000000ULL, ordered_encode_double(-INFINITY)); - ASSERT_EQ(0xfff0000000000002ULL, ordered_encode_double(INFINITY)); - ASSERT_EQ(0xfff0000000000003ULL, ordered_encode_double(NAN)); - ASSERT_EQ(0x8000000000000001ULL, ordered_encode_double(0.)); - - double old_d = -INFINITY; - uint64_t old_e = 0x0000000000000000ULL; - - for (size_t i = 0; i < 1000000; ++i) - { - double d = drand48() * mrand48() * mrand48(); - uint64_t e = ordered_encode_double(d); - - if (isinf(d) && d < 0) - { - ASSERT_EQ(0x0000000000000000ULL, e); - } - else if (isinf(d) && d > 0) - { - ASSERT_EQ(0xfff0000000000002ULL, e); - } - else if (isnan(d)) - { - ASSERT_EQ(0xfff0000000000003ULL, e); - } - else - { - ASSERT_TRUE(e > 0x0000000000000000ULL); - ASSERT_TRUE(e < 0xfff0000000000002ULL); - ASSERT_TRUE(e < 0xfff0000000000003ULL); - - if (d < 0) - { - ASSERT_TRUE(e < 0x8000000000000001ULL); - } - if (d > 0) - { - ASSERT_TRUE(e > 0x8000000000000001ULL); - } - - if (old_d < d) - { - ASSERT_TRUE(old_e < e); - } - else if (old_d > d) - { - ASSERT_TRUE(old_e > e); - } - else - { - ASSERT_TRUE(old_e == e); - } - - old_d = d; - old_e = e; - } - } + ASSERT_EQ(0x0000000000000000ULL, ordered_encode_double(-INFINITY)); + ASSERT_EQ(0xfff0000000000002ULL, ordered_encode_double(INFINITY)); + ASSERT_EQ(0xfff0000000000003ULL, ordered_encode_double(NAN)); + ASSERT_EQ(0x8000000000000001ULL, ordered_encode_double(0.)); + double old_d = -INFINITY; + uint64_t old_e = 0x0000000000000000ULL; + for (size_t i = 0; i < 1000000; ++i) + { + double d = drand48() * mrand48() * mrand48(); + uint64_t e = ordered_encode_double(d); + if (isinf(d) && d < 0) + { + ASSERT_EQ(0x0000000000000000ULL, e); + } + else if (isinf(d) && d > 0) + { + ASSERT_EQ(0xfff0000000000002ULL, e); + } + else if (isnan(d)) + { + ASSERT_EQ(0xfff0000000000003ULL, e); + } + else + { + ASSERT_TRUE(e > 0x0000000000000000ULL); + ASSERT_TRUE(e < 0xfff0000000000002ULL); + ASSERT_TRUE(e < 0xfff0000000000003ULL); + if (d < 0) + { + ASSERT_TRUE(e < 0x8000000000000001ULL); + } + if (d > 0) + { + ASSERT_TRUE(e > 0x8000000000000001ULL); + } + if (old_d < d) + { + ASSERT_TRUE(old_e < e); + } + else if (old_d > d) + { + ASSERT_TRUE(old_e > e); + } + else + { + ASSERT_TRUE(old_e == e); + } + old_d = d; + old_e = e; + } + } } diff --git a/common/transfer.cc b/common/transfer.cc index efe11d8d0..89e9c856e 100644 --- a/common/transfer.cc +++ b/common/transfer.cc @@ -31,37 +31,37 @@ using hyperdex::transfer; transfer :: transfer() - : id() - , rid() - , src() - , vsrc() - , dst() - , vdst() + : id() + , rid() + , src() + , vsrc() + , dst() + , vdst() { } -transfer :: transfer(const hyperdex::transfer_id& _id, - const hyperdex::region_id& _rid, - const hyperdex::server_id& _src, - const hyperdex::virtual_server_id& _vsrc, - const hyperdex::server_id& _dst, - const hyperdex::virtual_server_id& _vdst) - : id(_id) - , rid(_rid) - , src(_src) - , vsrc(_vsrc) - , dst(_dst) - , vdst(_vdst) +transfer :: transfer(const hyperdex::transfer_id &_id, + const hyperdex::region_id &_rid, + const hyperdex::server_id &_src, + const hyperdex::virtual_server_id &_vsrc, + const hyperdex::server_id &_dst, + const hyperdex::virtual_server_id &_vdst) + : id(_id) + , rid(_rid) + , src(_src) + , vsrc(_vsrc) + , dst(_dst) + , vdst(_vdst) { } -transfer :: transfer(const transfer& other) - : id(other.id) - , rid(other.rid) - , src(other.src) - , vsrc(other.vsrc) - , dst(other.dst) - , vdst(other.vdst) +transfer :: transfer(const transfer &other) + : id(other.id) + , rid(other.rid) + , src(other.src) + , vsrc(other.vsrc) + , dst(other.dst) + , vdst(other.vdst) { } @@ -69,94 +69,89 @@ transfer :: ~transfer() throw () { } -transfer& -transfer :: operator = (const transfer& rhs) +transfer & +transfer :: operator = (const transfer &rhs) { - id = rhs.id; - rid = rhs.rid; - src = rhs.src; - vsrc = rhs.vsrc; - dst = rhs.dst; - vdst = rhs.vdst; - return *this; + id = rhs.id; + rid = rhs.rid; + src = rhs.src; + vsrc = rhs.vsrc; + dst = rhs.dst; + vdst = rhs.vdst; + return *this; } bool -transfer :: operator < (const transfer& rhs) const +transfer :: operator < (const transfer &rhs) const { - if (id < rhs.id) - { - return true; - } - else if (id > rhs.id) - { - return false; - } - - if (rid < rhs.rid) - { - return true; - } - else if (rid > rhs.rid) - { - return false; - } - - if (src < rhs.src) - { - return true; - } - else if (src > rhs.src) - { - return false; - } - - if (vsrc < rhs.vsrc) - { - return true; - } - else if (vsrc > rhs.vsrc) - { - return false; - } - - if (dst < rhs.dst) - { - return true; - } - else if (dst > rhs.dst) - { - return false; - } - - return vdst < rhs.vdst; + if (id < rhs.id) + { + return true; + } + else if (id > rhs.id) + { + return false; + } + if (rid < rhs.rid) + { + return true; + } + else if (rid > rhs.rid) + { + return false; + } + if (src < rhs.src) + { + return true; + } + else if (src > rhs.src) + { + return false; + } + if (vsrc < rhs.vsrc) + { + return true; + } + else if (vsrc > rhs.vsrc) + { + return false; + } + if (dst < rhs.dst) + { + return true; + } + else if (dst > rhs.dst) + { + return false; + } + return vdst < rhs.vdst; } -std::ostream& -hyperdex :: operator << (std::ostream& lhs, const transfer& rhs) +std::ostream & +hyperdex :: operator << (std::ostream &lhs, const transfer &rhs) { - return lhs << "transfer(id=" << rhs.id - << ", region=" << rhs.rid - << ", src=" << rhs.src - << ", vsrc=" << rhs.vsrc - << ", dst=" << rhs.dst - << ", vdst=" << rhs.vdst << ")"; + return lhs << "transfer(id=" << rhs.id + << ", region=" << rhs.rid + << ", src=" << rhs.src + << ", vsrc=" << rhs.vsrc + << ", dst=" << rhs.dst + << ", vdst=" << rhs.vdst << ")"; } e::packer -hyperdex :: operator << (e::packer pa, const transfer& t) +hyperdex :: operator << (e::packer pa, const transfer &t) { - return pa << t.id << t.rid << t.src << t.vsrc << t.dst << t.vdst; + return pa << t.id << t.rid << t.src << t.vsrc << t.dst << t.vdst; } e::unpacker -hyperdex :: operator >> (e::unpacker up, transfer& t) +hyperdex :: operator >> (e::unpacker up, transfer &t) { - return up >> t.id >> t.rid >> t.src >> t.vsrc >> t.dst >> t.vdst; + return up >> t.id >> t.rid >> t.src >> t.vsrc >> t.dst >> t.vdst; } size_t -hyperdex :: pack_size(const transfer&) +hyperdex :: pack_size(const transfer &) { - return 6 * sizeof(uint64_t); + return 6 * sizeof(uint64_t); } diff --git a/common/transfer.h b/common/transfer.h index 88b852ad7..1fdd410c1 100644 --- a/common/transfer.h +++ b/common/transfer.h @@ -39,39 +39,39 @@ BEGIN_HYPERDEX_NAMESPACE class transfer { - public: - transfer(); - transfer(const transfer_id& id, - const region_id& rid, - const server_id& src, - const virtual_server_id& vsrc, - const server_id& dst, - const virtual_server_id& vdst); - transfer(const transfer&); - ~transfer() throw (); +public: + transfer(); + transfer(const transfer_id &id, + const region_id &rid, + const server_id &src, + const virtual_server_id &vsrc, + const server_id &dst, + const virtual_server_id &vdst); + transfer(const transfer &); + ~transfer() throw (); - public: - transfer& operator = (const transfer&); - bool operator < (const transfer&) const; +public: + transfer &operator = (const transfer &); + bool operator < (const transfer &) const; - public: - transfer_id id; - region_id rid; - server_id src; - virtual_server_id vsrc; - server_id dst; - virtual_server_id vdst; +public: + transfer_id id; + region_id rid; + server_id src; + virtual_server_id vsrc; + server_id dst; + virtual_server_id vdst; }; -std::ostream& -operator << (std::ostream& lhs, const transfer& rhs); +std::ostream & +operator << (std::ostream &lhs, const transfer &rhs); e::packer -operator << (e::packer, const transfer& t); +operator << (e::packer, const transfer &t); e::unpacker -operator >> (e::unpacker, transfer& t); +operator >> (e::unpacker, transfer &t); size_t -pack_size(const transfer& t); +pack_size(const transfer &t); END_HYPERDEX_NAMESPACE diff --git a/configure.ac b/configure.ac index 61dcde91f..a06553f4b 100755 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.59]) -AC_INIT([HyperDex], [1.8.dev], [robert@hyperdex.org]) +AC_INIT([HyperDex], [1.8.2], [robert@hyperdex.org]) m4_define([serial_tests], [ m4_esyscmd([case `automake --version | head -n 1` in *1.11*);; diff --git a/coordinator/coordinator.cc b/coordinator/coordinator.cc index 9def766db..1a3fb356a 100644 --- a/coordinator/coordinator.cc +++ b/coordinator/coordinator.cc @@ -61,105 +61,103 @@ namespace { std::string -to_string(const po6::net::location& loc) +to_string(const po6::net::location &loc) { - std::ostringstream oss; - oss << loc; - return oss.str(); + std::ostringstream oss; + oss << loc; + return oss.str(); } template void -shift_and_pop(size_t idx, std::vector* v) +shift_and_pop(size_t idx, std::vector *v) { - for (size_t i = idx + 1; i < v->size(); ++i) - { - (*v)[i - 1] = (*v)[i]; - } - - v->pop_back(); + for (size_t i = idx + 1; i < v->size(); ++i) + { + (*v)[i - 1] = (*v)[i]; + } + v->pop_back(); } template void -remove(const T& t, std::vector* v) +remove(const T &t, std::vector *v) { - for (size_t i = 0; i < v->size(); ) - { - if ((*v)[i] == t) - { - shift_and_pop(i, v); - } - else - { - ++i; - } - } + for (size_t i = 0; i < v->size(); ) + { + if ((*v)[i] == t) + { + shift_and_pop(i, v); + } + else + { + ++i; + } + } } template bool -find_id(const TID& id, std::vector& v, T** found) +find_id(const TID &id, std::vector &v, T **found) { - for (size_t i = 0; i < v.size(); ++i) - { - if (v[i].id == id) - { - *found = &v[i]; - return true; - } - } - - return false; + for (size_t i = 0; i < v.size(); ++i) + { + if (v[i].id == id) + { + *found = &v[i]; + return true; + } + } + return false; } template void -remove_id(const TID& id, std::vector* v) +remove_id(const TID &id, std::vector *v) { - for (size_t i = 0; i < v->size(); ) - { - if ((*v)[i].id == id) - { - shift_and_pop(i, v); - } - else - { - ++i; - } - } + for (size_t i = 0; i < v->size(); ) + { + if ((*v)[i].id == id) + { + shift_and_pop(i, v); + } + else + { + ++i; + } + } } } // namespace coordinator :: coordinator() - : m_cluster(0) - , m_counter(1) - , m_version(0) - , m_flags(0) - , m_servers() - , m_permutation() - , m_spares() - , m_desired_spares(0) - , m_spaces() - , m_intents() - , m_deferred_init() - , m_offline() - , m_transfers() - , m_config_ack_through(0) - , m_config_ack_barrier() - , m_config_stable_through(0) - , m_config_stable_barrier() - , m_checkpoint(0) - , m_checkpoint_stable_through(0) - , m_checkpoint_gc_through(0) - , m_checkpoint_stable_barrier() - , m_latest_config() - , m_response() -{ - assert(m_config_ack_through == m_config_ack_barrier.min_version()); - assert(m_config_stable_through == m_config_stable_barrier.min_version()); - assert(m_checkpoint_stable_through == m_checkpoint_stable_barrier.min_version()); + : m_cluster(0) + , m_counter(1) + , m_version(0) + , m_flags(0) + , m_servers() + , m_permutation() + , m_spares() + , m_desired_spares(0) + , m_spaces() + , m_intents() + , m_deferred_init() + , m_offline() + , m_transfers() + , m_config_ack_through(0) + , m_config_ack_barrier() + , m_config_stable_through(0) + , m_config_stable_barrier() + , m_checkpoint(0) + , m_checkpoint_stable_through(0) + , m_checkpoint_gc_through(0) + , m_checkpoint_stable_barrier() + , m_latest_config() + , m_response() +{ + assert(m_config_ack_through == m_config_ack_barrier.min_version()); + assert(m_config_stable_through == m_config_stable_barrier.min_version()); + assert(m_checkpoint_stable_through == m_checkpoint_stable_barrier.min_version()); } coordinator :: ~coordinator() throw () @@ -167,1966 +165,1750 @@ coordinator :: ~coordinator() throw () } void -coordinator :: init(rsm_context* ctx, uint64_t token) -{ - if (m_cluster != 0) - { - rsm_log(ctx, "cannot initialize HyperDex cluster with id %" PRIu64 " " - "because it is already initialized to %" PRIu64 "\n", token, m_cluster); - // we lie to the client and pretend all is well - return generate_response(ctx, COORD_SUCCESS); - } - - rsm_tick_interval(ctx, "periodic", ALARM_INTERVAL); - rsm_log(ctx, "initializing HyperDex cluster with id %" PRIu64 "\n", token); - m_cluster = token; - generate_next_configuration(ctx); - return generate_response(ctx, COORD_SUCCESS); +coordinator :: init(rsm_context *ctx, uint64_t token) +{ + if (m_cluster != 0) + { + rsm_log(ctx, "cannot initialize HyperDex cluster with id %" PRIu64 " " + "because it is already initialized to %" PRIu64 "\n", token, m_cluster); + // we lie to the client and pretend all is well + return generate_response(ctx, COORD_SUCCESS); + } + rsm_tick_interval(ctx, "periodic", ALARM_INTERVAL); + rsm_log(ctx, "initializing HyperDex cluster with id %" PRIu64 "\n", token); + m_cluster = token; + generate_next_configuration(ctx); + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: read_only(rsm_context* ctx, bool ro) -{ - uint64_t old_flags = m_flags; - - if (ro) - { - if ((m_flags & HYPERDEX_CONFIG_READ_ONLY)) - { - rsm_log(ctx, "cluster already in read-only mode\n"); - } - else - { - rsm_log(ctx, "putting cluster into read-only mode\n"); - } - - m_flags |= HYPERDEX_CONFIG_READ_ONLY; - } - else - { - if ((m_flags & HYPERDEX_CONFIG_READ_ONLY)) - { - rsm_log(ctx, "putting cluster into read-write mode\n"); - } - else - { - rsm_log(ctx, "cluster already in read-write mode\n"); - } - - uint64_t mask = HYPERDEX_CONFIG_READ_ONLY; - mask = ~mask; - m_flags &= mask; - } - - if (old_flags != m_flags) - { - generate_next_configuration(ctx); - } - - return generate_response(ctx, COORD_SUCCESS); +coordinator :: read_only(rsm_context *ctx, bool ro) +{ + uint64_t old_flags = m_flags; + if (ro) + { + if ((m_flags & HYPERDEX_CONFIG_READ_ONLY)) + { + rsm_log(ctx, "cluster already in read-only mode\n"); + } + else + { + rsm_log(ctx, "putting cluster into read-only mode\n"); + } + m_flags |= HYPERDEX_CONFIG_READ_ONLY; + } + else + { + if ((m_flags & HYPERDEX_CONFIG_READ_ONLY)) + { + rsm_log(ctx, "putting cluster into read-write mode\n"); + } + else + { + rsm_log(ctx, "cluster already in read-write mode\n"); + } + uint64_t mask = HYPERDEX_CONFIG_READ_ONLY; + mask = ~mask; + m_flags &= mask; + } + if (old_flags != m_flags) + { + generate_next_configuration(ctx); + } + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: fault_tolerance(rsm_context* ctx, - const char* space, uint64_t ft) -{ - uint64_t R = 0; - uint64_t P = 0; - std::vector replica_storage; - std::vector replica_sets; - space_ptr s; - - for (space_map_t::iterator it = m_spaces.begin(); - it != m_spaces.end(); ++it) - { - if (it->first == space) - { - s = it->second; - break; - } - } - - if (!s) - { - return; - } - - s->fault_tolerance = ft; - - R = ft + 1; - P = s->predecessor_width; - compute_replica_sets(R, P, m_permutation, m_servers, - &replica_storage, - &replica_sets); - - setup_intents(ctx, replica_sets, s.get(), false); - - generate_next_configuration(ctx); - return generate_response(ctx, COORD_SUCCESS); +coordinator :: fault_tolerance(rsm_context *ctx, + const char *space, uint64_t ft) +{ + uint64_t R = 0; + uint64_t P = 0; + std::vector replica_storage; + std::vector replica_sets; + space_ptr s; + for (space_map_t::iterator it = m_spaces.begin(); + it != m_spaces.end(); ++it) + { + if (it->first == space) + { + s = it->second; + break; + } + } + if (!s) + { + return; + } + s->fault_tolerance = ft; + R = ft + 1; + P = s->predecessor_width; + compute_replica_sets(R, P, m_permutation, m_servers, + &replica_storage, + &replica_sets); + setup_intents(ctx, replica_sets, s.get(), false); + generate_next_configuration(ctx); + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: server_register(rsm_context* ctx, - const server_id& sid, - const po6::net::location& bind_to) -{ - server* srv = get_server(sid); - - if (srv) - { - std::string str(to_string(srv->bind_to)); - rsm_log(ctx, "cannot register server(%" PRIu64 ") because the id belongs to " - "server(%" PRIu64 ", %s)\n", sid.get(), srv->id.get(), str.c_str()); - return generate_response(ctx, hyperdex::COORD_DUPLICATE); - } - - srv = new_server(sid); - srv->state = server::ASSIGNED; - srv->bind_to = bind_to; - rsm_log(ctx, "registered server(%" PRIu64 ")\n", sid.get()); - generate_next_configuration(ctx); - return generate_response(ctx, COORD_SUCCESS); +coordinator :: server_register(rsm_context *ctx, + const server_id &sid, + const po6::net::location &bind_to) +{ + server *srv = get_server(sid); + if (srv) + { + std::string str(to_string(srv->bind_to)); + rsm_log(ctx, "cannot register server(%" PRIu64 ") because the id belongs to " + "server(%" PRIu64 ", %s)\n", sid.get(), srv->id.get(), str.c_str()); + return generate_response(ctx, hyperdex::COORD_DUPLICATE); + } + srv = new_server(sid); + srv->state = server::ASSIGNED; + srv->bind_to = bind_to; + rsm_log(ctx, "registered server(%" PRIu64 ")\n", sid.get()); + generate_next_configuration(ctx); + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: server_online(rsm_context* ctx, - const server_id& sid, - const po6::net::location* bind_to) -{ - server* srv = get_server(sid); - - if (!srv) - { - rsm_log(ctx, "cannot bring server(%" PRIu64 ") online because " - "the server doesn't exist\n", sid.get()); - return generate_response(ctx, hyperdex::COORD_NOT_FOUND); - } - - if (srv->state != server::ASSIGNED && - srv->state != server::NOT_AVAILABLE && - srv->state != server::SHUTDOWN && - srv->state != server::AVAILABLE) - { - rsm_log(ctx, "cannot bring server(%" PRIu64 ") online because the server is " - "%s\n", sid.get(), server::to_string(srv->state)); - return generate_response(ctx, hyperdex::COORD_NO_CAN_DO); - } - - bool changed = false; - - if (bind_to && srv->bind_to != *bind_to) - { - std::string from(to_string(srv->bind_to)); - std::string to(to_string(*bind_to)); - - for (size_t i = 0; i < m_servers.size(); ++i) - { - if (m_servers[i].id != sid && - m_servers[i].bind_to == *bind_to) - { - rsm_log(ctx, "cannot change server(%" PRIu64 ") to %s " - "because that address is in use by " - "server(%" PRIu64 ")\n", sid.get(), to.c_str(), - m_servers[i].id.get()); - return generate_response(ctx, hyperdex::COORD_DUPLICATE); - } - } - - rsm_log(ctx, "changing server(%" PRIu64 ")'s address from %s to %s\n", - sid.get(), from.c_str(), to.c_str()); - srv->bind_to = *bind_to; - changed = true; - } - - if (srv->state != server::AVAILABLE) - { - rsm_log(ctx, "changing server(%" PRIu64 ") from %s to %s\n", - sid.get(), server::to_string(srv->state), - server::to_string(server::AVAILABLE)); - srv->state = server::AVAILABLE; - - if (!in_permutation(sid)) - { - add_permutation(sid); - } - - rebalance_replica_sets(ctx); - changed = true; - } - - if (changed) - { - generate_next_configuration(ctx); - } - - return generate_response(ctx, COORD_SUCCESS); +coordinator :: server_online(rsm_context *ctx, + const server_id &sid, + const po6::net::location *bind_to) +{ + server *srv = get_server(sid); + if (!srv) + { + rsm_log(ctx, "cannot bring server(%" PRIu64 ") online because " + "the server doesn't exist\n", sid.get()); + return generate_response(ctx, hyperdex::COORD_NOT_FOUND); + } + if (srv->state != server::ASSIGNED && + srv->state != server::NOT_AVAILABLE && + srv->state != server::SHUTDOWN && + srv->state != server::AVAILABLE) + { + rsm_log(ctx, "cannot bring server(%" PRIu64 ") online because the server is " + "%s\n", sid.get(), server::to_string(srv->state)); + return generate_response(ctx, hyperdex::COORD_NO_CAN_DO); + } + bool changed = false; + if (bind_to && srv->bind_to != *bind_to) + { + std::string from(to_string(srv->bind_to)); + std::string to(to_string(*bind_to)); + for (size_t i = 0; i < m_servers.size(); ++i) + { + if (m_servers[i].id != sid && + m_servers[i].bind_to == *bind_to) + { + rsm_log(ctx, "cannot change server(%" PRIu64 ") to %s " + "because that address is in use by " + "server(%" PRIu64 ")\n", sid.get(), to.c_str(), + m_servers[i].id.get()); + return generate_response(ctx, hyperdex::COORD_DUPLICATE); + } + } + rsm_log(ctx, "changing server(%" PRIu64 ")'s address from %s to %s\n", + sid.get(), from.c_str(), to.c_str()); + srv->bind_to = *bind_to; + changed = true; + } + if (srv->state != server::AVAILABLE) + { + rsm_log(ctx, "changing server(%" PRIu64 ") from %s to %s\n", + sid.get(), server::to_string(srv->state), + server::to_string(server::AVAILABLE)); + srv->state = server::AVAILABLE; + if (!in_permutation(sid)) + { + add_permutation(sid); + } + rebalance_replica_sets(ctx); + changed = true; + } + if (changed) + { + generate_next_configuration(ctx); + } + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: server_offline(rsm_context* ctx, - const server_id& sid) -{ - server* srv = get_server(sid); - - if (!srv) - { - rsm_log(ctx, "cannot bring server(%" PRIu64 ") offline because " - "the server doesn't exist\n", sid.get()); - return generate_response(ctx, hyperdex::COORD_NOT_FOUND); - } - - if (srv->state != server::ASSIGNED && - srv->state != server::NOT_AVAILABLE && - srv->state != server::AVAILABLE && - srv->state != server::SHUTDOWN) - { - rsm_log(ctx, "cannot bring server(%" PRIu64 ") offline because the server is " - "%s\n", sid.get(), server::to_string(srv->state)); - return generate_response(ctx, hyperdex::COORD_NO_CAN_DO); - } - - if (srv->state != server::NOT_AVAILABLE && srv->state != server::SHUTDOWN) - { - rsm_log(ctx, "changing server(%" PRIu64 ") from %s to %s\n", - sid.get(), server::to_string(srv->state), - server::to_string(server::NOT_AVAILABLE)); - srv->state = server::NOT_AVAILABLE; - rebalance_replica_sets(ctx); - generate_next_configuration(ctx); - } - - return generate_response(ctx, COORD_SUCCESS); +coordinator :: server_offline(rsm_context *ctx, + const server_id &sid) +{ + server *srv = get_server(sid); + if (!srv) + { + rsm_log(ctx, "cannot bring server(%" PRIu64 ") offline because " + "the server doesn't exist\n", sid.get()); + return generate_response(ctx, hyperdex::COORD_NOT_FOUND); + } + if (srv->state != server::ASSIGNED && + srv->state != server::NOT_AVAILABLE && + srv->state != server::AVAILABLE && + srv->state != server::SHUTDOWN) + { + rsm_log(ctx, "cannot bring server(%" PRIu64 ") offline because the server is " + "%s\n", sid.get(), server::to_string(srv->state)); + return generate_response(ctx, hyperdex::COORD_NO_CAN_DO); + } + if (srv->state != server::NOT_AVAILABLE && srv->state != server::SHUTDOWN) + { + rsm_log(ctx, "changing server(%" PRIu64 ") from %s to %s\n", + sid.get(), server::to_string(srv->state), + server::to_string(server::NOT_AVAILABLE)); + srv->state = server::NOT_AVAILABLE; + rebalance_replica_sets(ctx); + generate_next_configuration(ctx); + } + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: server_shutdown(rsm_context* ctx, - const server_id& sid) -{ - server* srv = get_server(sid); - - if (!srv) - { - rsm_log(ctx, "cannot shutdown server(%" PRIu64 ") because " - "the server doesn't exist\n", sid.get()); - return generate_response(ctx, hyperdex::COORD_NOT_FOUND); - } - - if (srv->state != server::ASSIGNED && - srv->state != server::NOT_AVAILABLE && - srv->state != server::AVAILABLE && - srv->state != server::SHUTDOWN) - { - rsm_log(ctx, "cannot shutdown server(%" PRIu64 ") because the server is " - "%s\n", sid.get(), server::to_string(srv->state)); - return generate_response(ctx, hyperdex::COORD_NO_CAN_DO); - } - - if (srv->state != server::SHUTDOWN) - { - rsm_log(ctx, "changing server(%" PRIu64 ") from %s to %s\n", - sid.get(), server::to_string(srv->state), - server::to_string(server::SHUTDOWN)); - srv->state = server::SHUTDOWN; - rebalance_replica_sets(ctx); - generate_next_configuration(ctx); - } - - return generate_response(ctx, COORD_SUCCESS); +coordinator :: server_shutdown(rsm_context *ctx, + const server_id &sid) +{ + server *srv = get_server(sid); + if (!srv) + { + rsm_log(ctx, "cannot shutdown server(%" PRIu64 ") because " + "the server doesn't exist\n", sid.get()); + return generate_response(ctx, hyperdex::COORD_NOT_FOUND); + } + if (srv->state != server::ASSIGNED && + srv->state != server::NOT_AVAILABLE && + srv->state != server::AVAILABLE && + srv->state != server::SHUTDOWN) + { + rsm_log(ctx, "cannot shutdown server(%" PRIu64 ") because the server is " + "%s\n", sid.get(), server::to_string(srv->state)); + return generate_response(ctx, hyperdex::COORD_NO_CAN_DO); + } + if (srv->state != server::SHUTDOWN) + { + rsm_log(ctx, "changing server(%" PRIu64 ") from %s to %s\n", + sid.get(), server::to_string(srv->state), + server::to_string(server::SHUTDOWN)); + srv->state = server::SHUTDOWN; + rebalance_replica_sets(ctx); + generate_next_configuration(ctx); + } + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: server_kill(rsm_context* ctx, - const server_id& sid) -{ - server* srv = get_server(sid); - - if (!srv) - { - rsm_log(ctx, "cannot kill server(%" PRIu64 ") because " - "the server doesn't exist\n", sid.get()); - return generate_response(ctx, hyperdex::COORD_NOT_FOUND); - } - - if (srv->state != server::KILLED) - { - rsm_log(ctx, "changing server(%" PRIu64 ") from %s to %s\n", - sid.get(), server::to_string(srv->state), - server::to_string(server::KILLED)); - srv->state = server::KILLED; - remove_permutation(sid); - remove_offline(sid); - rebalance_replica_sets(ctx); - generate_next_configuration(ctx); - } - - return generate_response(ctx, COORD_SUCCESS); +coordinator :: server_kill(rsm_context *ctx, + const server_id &sid) +{ + server *srv = get_server(sid); + if (!srv) + { + rsm_log(ctx, "cannot kill server(%" PRIu64 ") because " + "the server doesn't exist\n", sid.get()); + return generate_response(ctx, hyperdex::COORD_NOT_FOUND); + } + if (srv->state != server::KILLED) + { + rsm_log(ctx, "changing server(%" PRIu64 ") from %s to %s\n", + sid.get(), server::to_string(srv->state), + server::to_string(server::KILLED)); + srv->state = server::KILLED; + remove_permutation(sid); + remove_offline(sid); + rebalance_replica_sets(ctx); + generate_next_configuration(ctx); + } + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: server_forget(rsm_context* ctx, - const server_id& sid) -{ - server* srv = get_server(sid); - - if (!srv) - { - rsm_log(ctx, "cannot forget server(%" PRIu64 ") because " - "the server doesn't exist\n", sid.get()); - return generate_response(ctx, hyperdex::COORD_NOT_FOUND); - } - - for (size_t i = 0; i < m_servers.size(); ++i) - { - if (m_servers[i].id == sid) - { - std::swap(m_servers[i], m_servers[m_servers.size() - 1]); - m_servers.pop_back(); - } - } - - std::stable_sort(m_servers.begin(), m_servers.end()); - remove_permutation(sid); - remove_offline(sid); - rebalance_replica_sets(ctx); - generate_next_configuration(ctx); - return generate_response(ctx, COORD_SUCCESS); +coordinator :: server_forget(rsm_context *ctx, + const server_id &sid) +{ + server *srv = get_server(sid); + if (!srv) + { + rsm_log(ctx, "cannot forget server(%" PRIu64 ") because " + "the server doesn't exist\n", sid.get()); + return generate_response(ctx, hyperdex::COORD_NOT_FOUND); + } + for (size_t i = 0; i < m_servers.size(); ++i) + { + if (m_servers[i].id == sid) + { + std::swap(m_servers[i], m_servers[m_servers.size() - 1]); + m_servers.pop_back(); + } + } + std::stable_sort(m_servers.begin(), m_servers.end()); + remove_permutation(sid); + remove_offline(sid); + rebalance_replica_sets(ctx); + generate_next_configuration(ctx); + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: server_suspect(rsm_context* ctx, - const server_id& sid) -{ - server* srv = get_server(sid); - - if (!srv) - { - rsm_log(ctx, "cannot suspect server(%" PRIu64 ") because " - "the server doesn't exist\n", sid.get()); - return generate_response(ctx, hyperdex::COORD_NOT_FOUND); - } - - if (srv->state == server::SHUTDOWN) - { - return generate_response(ctx, COORD_SUCCESS); - } - - if (srv->state != server::ASSIGNED && - srv->state != server::NOT_AVAILABLE && - srv->state != server::AVAILABLE) - { - rsm_log(ctx, "cannot suspect server(%" PRIu64 ") because the server is " - "%s\n", sid.get(), server::to_string(srv->state)); - return generate_response(ctx, hyperdex::COORD_NO_CAN_DO); - } - - if (srv->state != server::NOT_AVAILABLE && srv->state != server::SHUTDOWN) - { - rsm_log(ctx, "changing server(%" PRIu64 ") from %s to %s because we suspect it failed\n", - sid.get(), server::to_string(srv->state), - server::to_string(server::NOT_AVAILABLE)); - srv->state = server::NOT_AVAILABLE; - rebalance_replica_sets(ctx); - generate_next_configuration(ctx); - } - - return generate_response(ctx, COORD_SUCCESS); +coordinator :: server_suspect(rsm_context *ctx, + const server_id &sid) +{ + server *srv = get_server(sid); + if (!srv) + { + rsm_log(ctx, "cannot suspect server(%" PRIu64 ") because " + "the server doesn't exist\n", sid.get()); + return generate_response(ctx, hyperdex::COORD_NOT_FOUND); + } + if (srv->state == server::SHUTDOWN) + { + return generate_response(ctx, COORD_SUCCESS); + } + if (srv->state != server::ASSIGNED && + srv->state != server::NOT_AVAILABLE && + srv->state != server::AVAILABLE) + { + rsm_log(ctx, "cannot suspect server(%" PRIu64 ") because the server is " + "%s\n", sid.get(), server::to_string(srv->state)); + return generate_response(ctx, hyperdex::COORD_NO_CAN_DO); + } + if (srv->state != server::NOT_AVAILABLE && srv->state != server::SHUTDOWN) + { + rsm_log(ctx, "changing server(%" PRIu64 ") from %s to %s because we suspect it failed\n", + sid.get(), server::to_string(srv->state), + server::to_string(server::NOT_AVAILABLE)); + srv->state = server::NOT_AVAILABLE; + rebalance_replica_sets(ctx); + generate_next_configuration(ctx); + } + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: report_disconnect(rsm_context* ctx, - const server_id& sid, uint64_t version) +coordinator :: report_disconnect(rsm_context *ctx, + const server_id &sid, uint64_t version) { - if (m_version != version) - { - return; - } - - return server_suspect(ctx, sid); + if (m_version != version) + { + return; + } + return server_suspect(ctx, sid); } static bool -is_space_name(const char* str) +is_space_name(const char *str) { - size_t i = 0; - - for (i = 0; str[i]; ++i) - { - if (!(i > 0 && isdigit(str[i])) && - !(isalpha(str[i])) && - str[i] != '_') - { - return false; - } - } - - return i > 0; + size_t i = 0; + for (i = 0; str[i]; ++i) + { + if (!(i > 0 && isdigit(str[i])) && + !(isalpha(str[i])) && + str[i] != '_') + { + return false; + } + } + return i > 0; } void -coordinator :: space_add(rsm_context* ctx, const space& _s) -{ - - if (!_s.validate()) - { - rsm_log(ctx, "could not add space \"%s\" because the space does not validate\n", _s.name); - return generate_response(ctx, COORD_MALFORMED); - } - - if (m_spaces.find(std::string(_s.name)) != m_spaces.end()) - { - rsm_log(ctx, "could not add space \"%s\" because there is already a space with that name\n", _s.name); - return generate_response(ctx, COORD_DUPLICATE); - } - - // Assign unique ids throughout the space - e::compat::shared_ptr s(new space(_s)); - s->id = space_id(m_counter); - ++m_counter; - - for (size_t i = 0; i < s->subspaces.size(); ++i) - { - s->subspaces[i].id = subspace_id(m_counter); - ++m_counter; - - for (size_t j = 0; j < s->subspaces[i].regions.size(); ++j) - { - s->subspaces[i].regions[j].id = region_id(m_counter); - ++m_counter; - s->subspaces[i].regions[j].replicas.clear(); - } - } - - for (size_t i = 0; i < s->indices.size(); ++i) - { - s->indices[i].id = index_id(m_counter); - ++m_counter; - } - - std::pair x; - x = m_spaces.insert(std::make_pair(std::string(s->name), s)); - assert(x.second); - s->name = x.first->first.c_str(); - rsm_log(ctx, "successfully added space \"%s\" with space(%" PRIu64 ")\n", s->name, s->id.get()); - initial_space_layout(ctx, s.get()); - generate_next_configuration(ctx); - return generate_response(ctx, COORD_SUCCESS); +coordinator :: space_add(rsm_context *ctx, const space &_s) +{ + if (!_s.validate()) + { + rsm_log(ctx, "could not add space \"%s\" because the space does not validate\n", _s.name); + return generate_response(ctx, COORD_MALFORMED); + } + if (m_spaces.find(std::string(_s.name)) != m_spaces.end()) + { + rsm_log(ctx, "could not add space \"%s\" because there is already a space with that name\n", _s.name); + return generate_response(ctx, COORD_DUPLICATE); + } + // Assign unique ids throughout the space + e::compat::shared_ptr s(new space(_s)); + s->id = space_id(m_counter); + ++m_counter; + for (size_t i = 0; i < s->subspaces.size(); ++i) + { + s->subspaces[i].id = subspace_id(m_counter); + ++m_counter; + for (size_t j = 0; j < s->subspaces[i].regions.size(); ++j) + { + s->subspaces[i].regions[j].id = region_id(m_counter); + ++m_counter; + s->subspaces[i].regions[j].replicas.clear(); + } + } + for (size_t i = 0; i < s->indices.size(); ++i) + { + s->indices[i].id = index_id(m_counter); + ++m_counter; + } + std::pair x; + x = m_spaces.insert(std::make_pair(std::string(s->name), s)); + assert(x.second); + s->name = x.first->first.c_str(); + rsm_log(ctx, "successfully added space \"%s\" with space(%" PRIu64 ")\n", s->name, s->id.get()); + initial_space_layout(ctx, s.get()); + generate_next_configuration(ctx); + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: space_rm(rsm_context* ctx, const char* name) -{ - space_map_t::iterator it; - it = m_spaces.find(std::string(name)); - - if (it == m_spaces.end()) - { - rsm_log(ctx, "could not remove space \"%s\" because it doesn't exist\n", name); - return generate_response(ctx, COORD_NOT_FOUND); - } - else - { - space_id sid(it->second->id.get()); - rsm_log(ctx, "successfully removed space \"%s\"/space(%" PRIu64 ")\n", name, sid.get()); - std::vector rids; - regions_in_space(it->second, &rids); - std::sort(rids.begin(), rids.end()); - m_spaces.erase(it); - - for (size_t i = 0; i < m_intents.size(); ) - { - if (std::binary_search(rids.begin(), rids.end(), m_intents[i].id)) - { - std::swap(m_intents[i], m_intents.back()); - m_intents.pop_back(); - } - else - { - ++i; - } - } - - for (size_t i = 0; i < m_transfers.size(); ) - { - if (std::binary_search(rids.begin(), rids.end(), m_transfers[i].rid)) - { - std::swap(m_transfers[i], m_transfers.back()); - m_transfers.pop_back(); - } - else - { - ++i; - } - } - - remove(sid, &m_deferred_init); - generate_next_configuration(ctx); - return generate_response(ctx, COORD_SUCCESS); - } +coordinator :: space_rm(rsm_context *ctx, const char *name) +{ + space_map_t::iterator it; + it = m_spaces.find(std::string(name)); + if (it == m_spaces.end()) + { + rsm_log(ctx, "could not remove space \"%s\" because it doesn't exist\n", name); + return generate_response(ctx, COORD_NOT_FOUND); + } + else + { + space_id sid(it->second->id.get()); + rsm_log(ctx, "successfully removed space \"%s\"/space(%" PRIu64 ")\n", name, sid.get()); + std::vector rids; + regions_in_space(it->second, &rids); + std::sort(rids.begin(), rids.end()); + m_spaces.erase(it); + for (size_t i = 0; i < m_intents.size(); ) + { + if (std::binary_search(rids.begin(), rids.end(), m_intents[i].id)) + { + std::swap(m_intents[i], m_intents.back()); + m_intents.pop_back(); + } + else + { + ++i; + } + } + for (size_t i = 0; i < m_transfers.size(); ) + { + if (std::binary_search(rids.begin(), rids.end(), m_transfers[i].rid)) + { + std::swap(m_transfers[i], m_transfers.back()); + m_transfers.pop_back(); + } + else + { + ++i; + } + } + remove(sid, &m_deferred_init); + generate_next_configuration(ctx); + return generate_response(ctx, COORD_SUCCESS); + } } void -coordinator :: space_mv(rsm_context* ctx, const char* src, const char* dst) -{ - space_map_t::iterator it; - it = m_spaces.find(std::string(src)); - - if (it == m_spaces.end()) - { - rsm_log(ctx, "could not rename space \"%s\" because it doesn't exist\n", src); - return generate_response(ctx, COORD_NOT_FOUND); - } - else if (m_spaces.find(std::string(dst)) != m_spaces.end()) - { - rsm_log(ctx, "could not rename space \"%s\" to \"%s\" because there is already a space \"%s\"\n", src, dst, dst); - return generate_response(ctx, COORD_DUPLICATE); - } - else if (!is_space_name(dst)) - { - rsm_log(ctx, "could not rename space \"%s\" to \"%s\" because \"%s\" is an invalid space name\n", src, dst, dst); - return generate_response(ctx, COORD_NO_CAN_DO); - } - else - { - space_ptr sp(it->second); - space_id sid(sp->id.get()); - rsm_log(ctx, "renaming space \"%s\" (%" PRIu64 ") to \"%s\"\n", src, sid.get(), dst); - m_spaces.erase(it); - std::pair x; - x = m_spaces.insert(std::make_pair(std::string(dst), sp)); - assert(x.second); - sp->name = x.first->first.c_str(); - generate_next_configuration(ctx); - return generate_response(ctx, COORD_SUCCESS); - } +coordinator :: space_mv(rsm_context *ctx, const char *src, const char *dst) +{ + space_map_t::iterator it; + it = m_spaces.find(std::string(src)); + if (it == m_spaces.end()) + { + rsm_log(ctx, "could not rename space \"%s\" because it doesn't exist\n", src); + return generate_response(ctx, COORD_NOT_FOUND); + } + else if (m_spaces.find(std::string(dst)) != m_spaces.end()) + { + rsm_log(ctx, "could not rename space \"%s\" to \"%s\" because there is already a space \"%s\"\n", src, dst, dst); + return generate_response(ctx, COORD_DUPLICATE); + } + else if (!is_space_name(dst)) + { + rsm_log(ctx, "could not rename space \"%s\" to \"%s\" because \"%s\" is an invalid space name\n", src, dst, dst); + return generate_response(ctx, COORD_NO_CAN_DO); + } + else + { + space_ptr sp(it->second); + space_id sid(sp->id.get()); + rsm_log(ctx, "renaming space \"%s\" (%" PRIu64 ") to \"%s\"\n", src, sid.get(), dst); + m_spaces.erase(it); + std::pair x; + x = m_spaces.insert(std::make_pair(std::string(dst), sp)); + assert(x.second); + sp->name = x.first->first.c_str(); + generate_next_configuration(ctx); + return generate_response(ctx, COORD_SUCCESS); + } } void -coordinator :: index_add(rsm_context* ctx, - const char* space, const char* what) -{ - space_map_t::iterator it; - it = m_spaces.find(std::string(space)); - - if (it == m_spaces.end()) - { - rsm_log(ctx, "could not create index on \"%s\" on space \"%s\" because the space doesn't exist\n", what, space); - return generate_response(ctx, COORD_NOT_FOUND); - } - - hyperdex::space* sp = it->second.get(); - - // split the attr into "attr" and "dotpath" components - const size_t what_sz = strlen(what); - std::string attr; - std::string dotpath; - index::index_t type; - const char* ptr = strchr(what, '.'); - - if (ptr) - { - type = index::DOCUMENT; - attr.assign(what, ptr - what); - dotpath.assign(ptr + 1, what_sz - (ptr - what) - 1); - } - else - { - type = index::NORMAL; - attr.assign(what, what_sz); - dotpath.assign("", 0); - } - - uint16_t attr_num = sp->sc.lookup_attr(attr.c_str()); - - if (attr_num >= sp->sc.attrs_sz) - { - rsm_log(ctx, "could not create index on \"%s\" on space \"%s\" because the attribute doesn't exist\n", what, space); - return generate_response(ctx, COORD_NOT_FOUND); - } - - if (type == index::NORMAL && - sp->sc.attrs[attr_num].type == HYPERDATATYPE_DOCUMENT) - { - rsm_log(ctx, "could not create index on \"%s\" on space \"%s\" because " - "it is a document and no dotted path was provided\n", what, space); - return generate_response(ctx, COORD_NO_CAN_DO); - } - - if (type == index::DOCUMENT && - sp->sc.attrs[attr_num].type != HYPERDATATYPE_DOCUMENT) - { - rsm_log(ctx, "could not create index on \"%s\" on space \"%s\" because " - "it is a not document and a dotted path was provided\n", what, space); - return generate_response(ctx, COORD_NO_CAN_DO); - } - - for (size_t i = 0; i < sp->indices.size(); ++i) - { - if (sp->indices[i].type == type && - sp->indices[i].attr == attr_num && - sp->indices[i].extra == e::slice(dotpath)) - { - rsm_log(ctx, "did not create index on \"%s\" on space \"%s\" because it is already indexed\n", what, space); - return generate_response(ctx, COORD_DUPLICATE); - } - } - - rsm_log(ctx, "creating index on \"%s\" on space \"%s\"\n", what, space); - index_id id(m_counter); - ++m_counter; - sp->indices.push_back(index(type, id, attr_num, e::slice(dotpath))); - sp->reestablish_backing(); - generate_next_configuration(ctx); - return generate_response(ctx, COORD_SUCCESS); +coordinator :: index_add(rsm_context *ctx, + const char *space, const char *what) +{ + space_map_t::iterator it; + it = m_spaces.find(std::string(space)); + if (it == m_spaces.end()) + { + rsm_log(ctx, "could not create index on \"%s\" on space \"%s\" because the space doesn't exist\n", what, space); + return generate_response(ctx, COORD_NOT_FOUND); + } + hyperdex::space *sp = it->second.get(); + // split the attr into "attr" and "dotpath" components + const size_t what_sz = strlen(what); + std::string attr; + std::string dotpath; + index::index_t type; + const char *ptr = strchr(what, '.'); + if (ptr) + { + type = index::DOCUMENT; + attr.assign(what, ptr - what); + dotpath.assign(ptr + 1, what_sz - (ptr - what) - 1); + } + else + { + type = index::NORMAL; + attr.assign(what, what_sz); + dotpath.assign("", 0); + } + uint16_t attr_num = sp->sc.lookup_attr(attr.c_str()); + if (attr_num >= sp->sc.attrs_sz) + { + rsm_log(ctx, "could not create index on \"%s\" on space \"%s\" because the attribute doesn't exist\n", what, space); + return generate_response(ctx, COORD_NOT_FOUND); + } + if (type == index::NORMAL && + sp->sc.attrs[attr_num].type == HYPERDATATYPE_DOCUMENT) + { + rsm_log(ctx, "could not create index on \"%s\" on space \"%s\" because " + "it is a document and no dotted path was provided\n", what, space); + return generate_response(ctx, COORD_NO_CAN_DO); + } + if (type == index::DOCUMENT && + sp->sc.attrs[attr_num].type != HYPERDATATYPE_DOCUMENT) + { + rsm_log(ctx, "could not create index on \"%s\" on space \"%s\" because " + "it is a not document and a dotted path was provided\n", what, space); + return generate_response(ctx, COORD_NO_CAN_DO); + } + for (size_t i = 0; i < sp->indices.size(); ++i) + { + if (sp->indices[i].type == type && + sp->indices[i].attr == attr_num && + sp->indices[i].extra == e::slice(dotpath)) + { + rsm_log(ctx, "did not create index on \"%s\" on space \"%s\" because it is already indexed\n", what, space); + return generate_response(ctx, COORD_DUPLICATE); + } + } + rsm_log(ctx, "creating index on \"%s\" on space \"%s\"\n", what, space); + index_id id(m_counter); + ++m_counter; + sp->indices.push_back(index(type, id, attr_num, e::slice(dotpath))); + sp->reestablish_backing(); + generate_next_configuration(ctx); + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: index_rm(rsm_context* ctx, index_id ii) -{ - e::compat::shared_ptr s; - index* idx; - - for (space_map_t::iterator it = m_spaces.begin(); - it != m_spaces.end(); ++it) - { - if (find_id(ii, it->second->indices, &idx)) - { - s = it->second; - break; - } - } - - if (!s.get() || !idx) - { - rsm_log(ctx, "could not remove index %lu because it doesn't exist\n", ii.get()); - return generate_response(ctx, COORD_NOT_FOUND); - } - - for (std::vector::iterator it = s->subspaces.begin(); - it != s->subspaces.end(); ++it) - { - for (size_t a = 0; a < it->attrs.size(); ++a) - { - if (it->attrs[a] == idx->attr) - { - rsm_log(ctx, "could not remove index %lu because it's in use by subspace \"%lu\"\n", - ii.get(), it->id.get()); - return generate_response(ctx, COORD_NO_CAN_DO); - } - } - } - - remove_id(ii, &s->indices); - rsm_log(ctx, "removed index %lu from space \"%s\"\n", ii.get(), s->name); - generate_next_configuration(ctx); - return generate_response(ctx, COORD_SUCCESS); +coordinator :: index_rm(rsm_context *ctx, index_id ii) +{ + e::compat::shared_ptr s; + index *idx; + for (space_map_t::iterator it = m_spaces.begin(); + it != m_spaces.end(); ++it) + { + if (find_id(ii, it->second->indices, &idx)) + { + s = it->second; + break; + } + } + if (!s.get() || !idx) + { + rsm_log(ctx, "could not remove index %lu because it doesn't exist\n", ii.get()); + return generate_response(ctx, COORD_NOT_FOUND); + } + for (std::vector::iterator it = s->subspaces.begin(); + it != s->subspaces.end(); ++it) + { + for (size_t a = 0; a < it->attrs.size(); ++a) + { + if (it->attrs[a] == idx->attr) + { + rsm_log(ctx, "could not remove index %lu because it's in use by subspace \"%lu\"\n", + ii.get(), it->id.get()); + return generate_response(ctx, COORD_NO_CAN_DO); + } + } + } + remove_id(ii, &s->indices); + rsm_log(ctx, "removed index %lu from space \"%s\"\n", ii.get(), s->name); + generate_next_configuration(ctx); + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: transfer_go_live(rsm_context* ctx, - const transfer_id& xid) -{ - transfer* xfer = get_transfer(xid); - - if (!xfer) - { - return; - } - - region* reg = get_region(xfer->rid); - - if (!reg) - { - rsm_log(ctx, "cannot make transfer(%" PRIu64 ") live because it doesn't exist\n", xid.get()); - INVARIANT_BROKEN("transfer refers to nonexistent region"); - return generate_response(ctx, COORD_SUCCESS); - } - - // If the transfer is already live - if (reg->replicas.size() > 1 && - reg->replicas[reg->replicas.size() - 2].si == xfer->src && - reg->replicas[reg->replicas.size() - 1].si == xfer->dst) - { - return generate_response(ctx, COORD_SUCCESS); - } - - if (reg->replicas.empty() || reg->replicas.back().si != xfer->src) - { - INVARIANT_BROKEN("transfer in a bad state"); - return generate_response(ctx, COORD_SUCCESS); - } - - reg->replicas.push_back(replica(xfer->dst, xfer->vdst)); - rsm_log(ctx, "transfer(%" PRIu64 ") is live\n", xid.get()); - generate_next_configuration(ctx); - return generate_response(ctx, COORD_SUCCESS); +coordinator :: transfer_go_live(rsm_context *ctx, + const transfer_id &xid) +{ + transfer *xfer = get_transfer(xid); + if (!xfer) + { + return; + } + region *reg = get_region(xfer->rid); + if (!reg) + { + rsm_log(ctx, "cannot make transfer(%" PRIu64 ") live because it doesn't exist\n", xid.get()); + INVARIANT_BROKEN("transfer refers to nonexistent region"); + return generate_response(ctx, COORD_SUCCESS); + } + // If the transfer is already live + if (reg->replicas.size() > 1 && + reg->replicas[reg->replicas.size() - 2].si == xfer->src && + reg->replicas[reg->replicas.size() - 1].si == xfer->dst) + { + return generate_response(ctx, COORD_SUCCESS); + } + if (reg->replicas.empty() || reg->replicas.back().si != xfer->src) + { + INVARIANT_BROKEN("transfer in a bad state"); + return generate_response(ctx, COORD_SUCCESS); + } + reg->replicas.push_back(replica(xfer->dst, xfer->vdst)); + rsm_log(ctx, "transfer(%" PRIu64 ") is live\n", xid.get()); + generate_next_configuration(ctx); + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: transfer_complete(rsm_context* ctx, - const transfer_id& xid) -{ - transfer* xfer = get_transfer(xid); - - if (!xfer) - { - return; - } - - region* reg = get_region(xfer->rid); - - if (!reg) - { - rsm_log(ctx, "cannot complete transfer(%" PRIu64 ") because it doesn't exist\n", xid.get()); - INVARIANT_BROKEN("transfer refers to nonexistent region"); - return generate_response(ctx, COORD_SUCCESS); - } - - if (!(reg->replicas.size() > 1 && - reg->replicas[reg->replicas.size() - 2].si == xfer->src && - reg->replicas[reg->replicas.size() - 1].si == xfer->dst)) - { - rsm_log(ctx, "cannot complete transfer(%" PRIu64 ") because it is not live\n", xid.get()); - return generate_response(ctx, COORD_SUCCESS); - } - - del_transfer(xfer->id); - rsm_log(ctx, "transfer(%" PRIu64 ") is complete\n", xid.get()); - converge_intent(ctx, reg); - generate_next_configuration(ctx); - return generate_response(ctx, COORD_SUCCESS); +coordinator :: transfer_complete(rsm_context *ctx, + const transfer_id &xid) +{ + transfer *xfer = get_transfer(xid); + if (!xfer) + { + return; + } + region *reg = get_region(xfer->rid); + if (!reg) + { + rsm_log(ctx, "cannot complete transfer(%" PRIu64 ") because it doesn't exist\n", xid.get()); + INVARIANT_BROKEN("transfer refers to nonexistent region"); + return generate_response(ctx, COORD_SUCCESS); + } + if (!(reg->replicas.size() > 1 && + reg->replicas[reg->replicas.size() - 2].si == xfer->src && + reg->replicas[reg->replicas.size() - 1].si == xfer->dst)) + { + rsm_log(ctx, "cannot complete transfer(%" PRIu64 ") because it is not live\n", xid.get()); + return generate_response(ctx, COORD_SUCCESS); + } + del_transfer(xfer->id); + rsm_log(ctx, "transfer(%" PRIu64 ") is complete\n", xid.get()); + converge_intent(ctx, reg); + generate_next_configuration(ctx); + return generate_response(ctx, COORD_SUCCESS); } void -coordinator :: config_get(rsm_context* ctx) +coordinator :: config_get(rsm_context *ctx) { - assert(m_cluster != 0 && m_version != 0); - assert(m_latest_config.get()); - const char* output = reinterpret_cast(m_latest_config->data()); - size_t output_sz = m_latest_config->size(); - rsm_set_output(ctx, output, output_sz); + assert(m_cluster != 0 && m_version != 0); + assert(m_latest_config.get()); + const char *output = reinterpret_cast(m_latest_config->data()); + size_t output_sz = m_latest_config->size(); + rsm_set_output(ctx, output, output_sz); } void -coordinator :: config_ack(rsm_context* ctx, - const server_id& sid, uint64_t version) +coordinator :: config_ack(rsm_context *ctx, + const server_id &sid, uint64_t version) { - m_config_ack_barrier.pass(version, sid); - check_ack_condition(ctx); + m_config_ack_barrier.pass(version, sid); + check_ack_condition(ctx); } void -coordinator :: config_stable(rsm_context* ctx, - const server_id& sid, uint64_t version) +coordinator :: config_stable(rsm_context *ctx, + const server_id &sid, uint64_t version) { - m_config_stable_barrier.pass(version, sid); - check_stable_condition(ctx); + m_config_stable_barrier.pass(version, sid); + check_stable_condition(ctx); } void -coordinator :: checkpoint(rsm_context* ctx) +coordinator :: checkpoint(rsm_context *ctx) { - ++m_checkpoint; - broadcast_checkpoint_information(ctx); - rsm_log(ctx, "establishing checkpoint %" PRIu64 "\n", m_checkpoint); - assert(m_checkpoint_stable_through <= m_checkpoint); - std::vector sids; - servers_in_configuration(&sids); - m_checkpoint_stable_barrier.new_version(m_checkpoint, sids); - check_checkpoint_stable_condition(ctx, true); + ++m_checkpoint; + broadcast_checkpoint_information(ctx); + rsm_log(ctx, "establishing checkpoint %" PRIu64 "\n", m_checkpoint); + assert(m_checkpoint_stable_through <= m_checkpoint); + std::vector sids; + servers_in_configuration(&sids); + m_checkpoint_stable_barrier.new_version(m_checkpoint, sids); + check_checkpoint_stable_condition(ctx, true); } void -coordinator :: checkpoint_stable(rsm_context* ctx, - const server_id& sid, +coordinator :: checkpoint_stable(rsm_context *ctx, + const server_id &sid, uint64_t config, uint64_t number) { - if (config < m_version) - { - return generate_response(ctx, COORD_NO_CAN_DO); - } - - m_checkpoint_stable_barrier.pass(number, sid); - check_checkpoint_stable_condition(ctx, false); - generate_response(ctx, COORD_SUCCESS); + if (config < m_version) + { + return generate_response(ctx, COORD_NO_CAN_DO); + } + m_checkpoint_stable_barrier.pass(number, sid); + check_checkpoint_stable_condition(ctx, false); + generate_response(ctx, COORD_SUCCESS); } void -coordinator :: checkpoints(rsm_context* ctx) +coordinator :: checkpoints(rsm_context *ctx) { - const size_t sz = sizeof(uint16_t) + 3 * sizeof(uint64_t); - m_response.reset(e::buffer::create(sz)); - uint8_t* ptr = m_response->data(); - ptr = e::pack16be(COORD_SUCCESS, ptr); - ptr = e::pack64be(m_checkpoint, ptr); - ptr = e::pack64be(m_checkpoint_stable_through, ptr); - ptr = e::pack64be(m_checkpoint_gc_through, ptr); - rsm_set_output(ctx, reinterpret_cast(m_response->data()), sz); + const size_t sz = sizeof(uint16_t) + 3 * sizeof(uint64_t); + m_response.reset(e::buffer::create(sz)); + uint8_t *ptr = m_response->data(); + ptr = e::pack16be(COORD_SUCCESS, ptr); + ptr = e::pack64be(m_checkpoint, ptr); + ptr = e::pack64be(m_checkpoint_stable_through, ptr); + ptr = e::pack64be(m_checkpoint_gc_through, ptr); + rsm_set_output(ctx, reinterpret_cast(m_response->data()), sz); } void -coordinator :: periodic(rsm_context* ctx) +coordinator :: periodic(rsm_context *ctx) { - checkpoint(ctx); + checkpoint(ctx); } void -coordinator :: debug_dump(rsm_context* ctx) -{ - rsm_log(ctx, "=== begin debug dump ===========================================================\n"); - rsm_log(ctx, "permutation:\n"); - - for (size_t i = 0; i < m_permutation.size(); ++i) - { - rsm_log(ctx, " - %" PRIu64 "\n", m_permutation[i].get()); - } - - rsm_log(ctx, "spares (desire %" PRIu64 "):\n", m_desired_spares); - - for (size_t i = 0; i < m_spares.size(); ++i) - { - rsm_log(ctx, " - %" PRIu64 "\n", m_spares[i].get()); - } - - rsm_log(ctx, "intents:\n"); - - for (size_t i = 0; i < m_intents.size(); ++i) - { - rsm_log(ctx, " - region=%" PRIu64 ", checkpoint=%" PRIu64 " replicas=[", m_intents[i].id.get(), m_intents[i].checkpoint); - - for (size_t j = 0; j < m_intents[i].replicas.size(); ++j) - { - if (j == 0) - { - rsm_log(ctx, "%" PRIu64 "", m_intents[i].replicas[j].get()); - } - else - { - rsm_log(ctx, ", %" PRIu64 "", m_intents[i].replicas[j].get()); - } - } - - rsm_log(ctx, "]\n"); - } - - rsm_log(ctx, "transfers:\n"); - - for (size_t i = 0; i < m_transfers.size(); ++i) - { - rsm_log(ctx, " - id=%" PRIu64 " rid=%" PRIu64 " src=%" PRIu64 " vsrc=%" PRIu64 " dst=%" PRIu64 " vdst=%" PRIu64 "\n", - m_transfers[i].id.get(), m_transfers[i].rid.get(), - m_transfers[i].src.get(), m_transfers[i].vsrc.get(), - m_transfers[i].dst.get(), m_transfers[i].vdst.get()); - } - - rsm_log(ctx, "offline servers:\n"); - - for (size_t i = 0; i < m_offline.size(); ++i) - { - rsm_log(ctx, " - rid=%" PRIu64 " sid=%" PRIu64 "\n", - m_offline[i].id.get(), m_offline[i].sid.get()); - } - - rsm_log(ctx, "config ack through: %" PRIu64 "\n", m_config_ack_through); - rsm_log(ctx, "config stable through: %" PRIu64 "\n", m_config_stable_through); - rsm_log(ctx, "checkpoint: latest=%" PRIu64 ", stable=%" PRIu64 ", gc=%" PRIu64 "\n", - m_checkpoint, m_checkpoint_stable_through, m_checkpoint_gc_through); - rsm_log(ctx, "=== end debug dump =============================================================\n"); -} - -coordinator* -coordinator :: recreate(rsm_context* ctx, - const char* data, size_t data_sz) -{ - std::auto_ptr c(new coordinator()); - - if (!c.get()) - { - rsm_log(ctx, "memory allocation failed\n"); - return NULL; - } - - e::unpacker up(data, data_sz); - up = up >> c->m_cluster >> c->m_counter >> c->m_version >> c->m_flags >> c->m_servers - >> c->m_permutation >> c->m_spares >> c->m_desired_spares >> c->m_intents - >> c->m_deferred_init >> c->m_offline >> c->m_transfers - >> c->m_config_ack_through >> c->m_config_ack_barrier - >> c->m_config_stable_through >> c->m_config_stable_barrier - >> c->m_checkpoint >> c->m_checkpoint_stable_through - >> c->m_checkpoint_gc_through >> c->m_checkpoint_stable_barrier; - - while (!up.error() && up.remain()) - { - e::slice name; - space_ptr ptr(new space()); - up = up >> name >> *ptr; - c->m_spaces[std::string(reinterpret_cast(name.data()), name.size())] = ptr; - } - - if (up.error()) - { - rsm_log(ctx, "unpacking failed\n"); - return NULL; - } - - std::vector > region_tails; - - for (space_map_t::iterator it = c->m_spaces.begin(); - it != c->m_spaces.end(); ++it) - { - space* s(it->second.get()); - - for (size_t ss_idx = 0; ss_idx < s->subspaces.size(); ++ss_idx) - { - subspace* ss(&s->subspaces[ss_idx]); - - for (size_t reg_idx = 0; reg_idx < ss->regions.size(); ++reg_idx) - { - region* reg = &ss->regions[reg_idx]; - - if (!reg->replicas.empty()) - { - region_tails.push_back(std::make_pair(reg->replicas.back().si, - reg->replicas.back().vsi)); - } - } - } - } - - std::sort(region_tails.begin(), region_tails.end()); - - for (size_t i = 0; i < c->m_transfers.size(); ) - { - const transfer* t = &c->m_transfers[i]; - std::pair src(std::make_pair(t->src, t->vsrc)); - std::pair dst(std::make_pair(t->dst, t->vdst)); - - if (!std::binary_search(region_tails.begin(), region_tails.end(), src) && - !std::binary_search(region_tails.begin(), region_tails.end(), dst)) - { - for (size_t j = i + 1; j < c->m_transfers.size(); ++j) - { - c->m_transfers[j - 1] = c->m_transfers[j]; - } - - c->m_transfers.pop_back(); - } - else - { - ++i; - } - } - - c->generate_cached_configuration(ctx); - return c.release(); +coordinator :: debug_dump(rsm_context *ctx) +{ + rsm_log(ctx, "=== begin debug dump ===========================================================\n"); + rsm_log(ctx, "permutation:\n"); + for (size_t i = 0; i < m_permutation.size(); ++i) + { + rsm_log(ctx, " - %" PRIu64 "\n", m_permutation[i].get()); + } + rsm_log(ctx, "spares (desire %" PRIu64 "):\n", m_desired_spares); + for (size_t i = 0; i < m_spares.size(); ++i) + { + rsm_log(ctx, " - %" PRIu64 "\n", m_spares[i].get()); + } + rsm_log(ctx, "intents:\n"); + for (size_t i = 0; i < m_intents.size(); ++i) + { + rsm_log(ctx, " - region=%" PRIu64 ", checkpoint=%" PRIu64 " replicas=[", m_intents[i].id.get(), m_intents[i].checkpoint); + for (size_t j = 0; j < m_intents[i].replicas.size(); ++j) + { + if (j == 0) + { + rsm_log(ctx, "%" PRIu64 "", m_intents[i].replicas[j].get()); + } + else + { + rsm_log(ctx, ", %" PRIu64 "", m_intents[i].replicas[j].get()); + } + } + rsm_log(ctx, "]\n"); + } + rsm_log(ctx, "transfers:\n"); + for (size_t i = 0; i < m_transfers.size(); ++i) + { + rsm_log(ctx, " - id=%" PRIu64 " rid=%" PRIu64 " src=%" PRIu64 " vsrc=%" PRIu64 " dst=%" PRIu64 " vdst=%" PRIu64 "\n", + m_transfers[i].id.get(), m_transfers[i].rid.get(), + m_transfers[i].src.get(), m_transfers[i].vsrc.get(), + m_transfers[i].dst.get(), m_transfers[i].vdst.get()); + } + rsm_log(ctx, "offline servers:\n"); + for (size_t i = 0; i < m_offline.size(); ++i) + { + rsm_log(ctx, " - rid=%" PRIu64 " sid=%" PRIu64 "\n", + m_offline[i].id.get(), m_offline[i].sid.get()); + } + rsm_log(ctx, "config ack through: %" PRIu64 "\n", m_config_ack_through); + rsm_log(ctx, "config stable through: %" PRIu64 "\n", m_config_stable_through); + rsm_log(ctx, "checkpoint: latest=%" PRIu64 ", stable=%" PRIu64 ", gc=%" PRIu64 "\n", + m_checkpoint, m_checkpoint_stable_through, m_checkpoint_gc_through); + rsm_log(ctx, "=== end debug dump =============================================================\n"); +} + +coordinator * +coordinator :: recreate(rsm_context *ctx, + const char *data, size_t data_sz) +{ + std::auto_ptr c(new coordinator()); + if (!c.get()) + { + rsm_log(ctx, "memory allocation failed\n"); + return NULL; + } + e::unpacker up(data, data_sz); + up = up >> c->m_cluster >> c->m_counter >> c->m_version >> c->m_flags >> c->m_servers + >> c->m_permutation >> c->m_spares >> c->m_desired_spares >> c->m_intents + >> c->m_deferred_init >> c->m_offline >> c->m_transfers + >> c->m_config_ack_through >> c->m_config_ack_barrier + >> c->m_config_stable_through >> c->m_config_stable_barrier + >> c->m_checkpoint >> c->m_checkpoint_stable_through + >> c->m_checkpoint_gc_through >> c->m_checkpoint_stable_barrier; + while (!up.error() && up.remain()) + { + e::slice name; + space_ptr ptr(new space()); + up = up >> name >> *ptr; + c->m_spaces[std::string(reinterpret_cast(name.data()), name.size())] = ptr; + } + if (up.error()) + { + rsm_log(ctx, "unpacking failed\n"); + return NULL; + } + std::vector > region_tails; + for (space_map_t::iterator it = c->m_spaces.begin(); + it != c->m_spaces.end(); ++it) + { + space *s(it->second.get()); + for (size_t ss_idx = 0; ss_idx < s->subspaces.size(); ++ss_idx) + { + subspace *ss(&s->subspaces[ss_idx]); + for (size_t reg_idx = 0; reg_idx < ss->regions.size(); ++reg_idx) + { + region *reg = &ss->regions[reg_idx]; + if (!reg->replicas.empty()) + { + region_tails.push_back(std::make_pair(reg->replicas.back().si, + reg->replicas.back().vsi)); + } + } + } + } + std::sort(region_tails.begin(), region_tails.end()); + for (size_t i = 0; i < c->m_transfers.size(); ) + { + const transfer *t = &c->m_transfers[i]; + std::pair src(std::make_pair(t->src, t->vsrc)); + std::pair dst(std::make_pair(t->dst, t->vdst)); + if (!std::binary_search(region_tails.begin(), region_tails.end(), src) && + !std::binary_search(region_tails.begin(), region_tails.end(), dst)) + { + for (size_t j = i + 1; j < c->m_transfers.size(); ++j) + { + c->m_transfers[j - 1] = c->m_transfers[j]; + } + c->m_transfers.pop_back(); + } + else + { + ++i; + } + } + c->generate_cached_configuration(ctx); + return c.release(); } int -coordinator :: snapshot(rsm_context* /*ctx*/, - char** data, size_t* data_sz) -{ - size_t sz = sizeof(m_cluster) - + sizeof(m_counter) - + sizeof(m_version) - + sizeof(m_flags) - + pack_size(m_servers) - + pack_size(m_permutation) - + pack_size(m_spares) - + sizeof(m_desired_spares) - + pack_size(m_intents) - + pack_size(m_deferred_init) - + pack_size(m_offline) - + pack_size(m_transfers) - + sizeof(m_config_ack_through) - + pack_size(m_config_ack_barrier) - + sizeof(m_config_stable_through) - + pack_size(m_config_stable_barrier) - + sizeof(m_checkpoint) - + sizeof(m_checkpoint_stable_through) - + sizeof(m_checkpoint_gc_through) - + pack_size(m_checkpoint_stable_barrier); - - for (space_map_t::iterator it = m_spaces.begin(); - it != m_spaces.end(); ++it) - { - e::slice name(it->first); - sz += pack_size(name) + pack_size(*it->second); - } - - std::auto_ptr buf(e::buffer::create(sz)); - e::packer pa = buf->pack_at(0); - pa = pa << m_cluster << m_counter << m_version << m_flags << m_servers - << m_permutation << m_spares << m_desired_spares << m_intents - << m_deferred_init << m_offline << m_transfers - << m_config_ack_through << m_config_ack_barrier - << m_config_stable_through << m_config_stable_barrier - << m_checkpoint << m_checkpoint_stable_through - << m_checkpoint_gc_through << m_checkpoint_stable_barrier; - - for (space_map_t::iterator it = m_spaces.begin(); - it != m_spaces.end(); ++it) - { - e::slice name(it->first); - pa = pa << name << (*it->second); - } - - char* ptr = static_cast(malloc(buf->size())); - *data = ptr; - *data_sz = buf->size(); - - if (*data) - { - memmove(ptr, buf->data(), buf->size()); - } - - return 0; -} - -server* -coordinator :: new_server(const server_id& sid) -{ - size_t idx = m_servers.size(); - m_servers.push_back(server(sid)); - - for (; idx > 0; --idx) - { - if (m_servers[idx - 1].id < m_servers[idx].id) - { - break; - } - - std::swap(m_servers[idx - 1], m_servers[idx]); - } - - return &m_servers[idx]; -} - -server* -coordinator :: get_server(const server_id& sid) -{ - for (size_t i = 0; i < m_servers.size(); ++i) - { - if (m_servers[i].id == sid) - { - return &m_servers[i]; - } - } - - return NULL; +coordinator :: snapshot(rsm_context * /*ctx*/, + char **data, size_t *data_sz) +{ + size_t sz = sizeof(m_cluster) + + sizeof(m_counter) + + sizeof(m_version) + + sizeof(m_flags) + + pack_size(m_servers) + + pack_size(m_permutation) + + pack_size(m_spares) + + sizeof(m_desired_spares) + + pack_size(m_intents) + + pack_size(m_deferred_init) + + pack_size(m_offline) + + pack_size(m_transfers) + + sizeof(m_config_ack_through) + + pack_size(m_config_ack_barrier) + + sizeof(m_config_stable_through) + + pack_size(m_config_stable_barrier) + + sizeof(m_checkpoint) + + sizeof(m_checkpoint_stable_through) + + sizeof(m_checkpoint_gc_through) + + pack_size(m_checkpoint_stable_barrier); + for (space_map_t::iterator it = m_spaces.begin(); + it != m_spaces.end(); ++it) + { + e::slice name(it->first); + sz += pack_size(name) + pack_size(*it->second); + } + std::auto_ptr buf(e::buffer::create(sz)); + e::packer pa = buf->pack_at(0); + pa = pa << m_cluster << m_counter << m_version << m_flags << m_servers + << m_permutation << m_spares << m_desired_spares << m_intents + << m_deferred_init << m_offline << m_transfers + << m_config_ack_through << m_config_ack_barrier + << m_config_stable_through << m_config_stable_barrier + << m_checkpoint << m_checkpoint_stable_through + << m_checkpoint_gc_through << m_checkpoint_stable_barrier; + for (space_map_t::iterator it = m_spaces.begin(); + it != m_spaces.end(); ++it) + { + e::slice name(it->first); + pa = pa << name << (*it->second); + } + char *ptr = static_cast(malloc(buf->size())); + *data = ptr; + *data_sz = buf->size(); + if (*data) + { + memmove(ptr, buf->data(), buf->size()); + } + return 0; +} + +server * +coordinator :: new_server(const server_id &sid) +{ + size_t idx = m_servers.size(); + m_servers.push_back(server(sid)); + for (; idx > 0; --idx) + { + if (m_servers[idx - 1].id < m_servers[idx].id) + { + break; + } + std::swap(m_servers[idx - 1], m_servers[idx]); + } + return &m_servers[idx]; +} + +server * +coordinator :: get_server(const server_id &sid) +{ + for (size_t i = 0; i < m_servers.size(); ++i) + { + if (m_servers[i].id == sid) + { + return &m_servers[i]; + } + } + return NULL; } bool -coordinator :: in_permutation(const server_id& sid) -{ - for (size_t i = 0; i < m_permutation.size(); ++i) - { - if (m_permutation[i] == sid) - { - return true; - } - } - - for (size_t i = 0; i < m_spares.size(); ++i) - { - if (m_spares[i] == sid) - { - return true; - } - } - - return false; +coordinator :: in_permutation(const server_id &sid) +{ + for (size_t i = 0; i < m_permutation.size(); ++i) + { + if (m_permutation[i] == sid) + { + return true; + } + } + for (size_t i = 0; i < m_spares.size(); ++i) + { + if (m_spares[i] == sid) + { + return true; + } + } + return false; } void -coordinator :: add_permutation(const server_id& sid) +coordinator :: add_permutation(const server_id &sid) { - if (m_spares.size() < m_desired_spares) - { - m_spares.push_back(sid); - } - else - { - m_permutation.push_back(sid); - } + if (m_spares.size() < m_desired_spares) + { + m_spares.push_back(sid); + } + else + { + m_permutation.push_back(sid); + } } void -coordinator :: remove_permutation(const server_id& sid) -{ - remove(sid, &m_spares); - - for (size_t i = 0; i < m_permutation.size(); ++i) - { - if (m_permutation[i] != sid) - { - continue; - } - - if (m_spares.empty()) - { - shift_and_pop(i, &m_permutation); - } - else - { - m_permutation[i] = m_spares.back(); - m_spares.pop_back(); - } - - break; - } +coordinator :: remove_permutation(const server_id &sid) +{ + remove(sid, &m_spares); + for (size_t i = 0; i < m_permutation.size(); ++i) + { + if (m_permutation[i] != sid) + { + continue; + } + if (m_spares.empty()) + { + shift_and_pop(i, &m_permutation); + } + else + { + m_permutation[i] = m_spares.back(); + m_spares.pop_back(); + } + break; + } } namespace { bool -compare_space_ptr_by_r_p(const e::compat::shared_ptr& lhs, - const e::compat::shared_ptr& rhs) -{ - if (lhs->fault_tolerance < rhs->fault_tolerance) - { - return true; - } - else if (lhs->fault_tolerance == rhs->fault_tolerance) - { - return lhs->predecessor_width < rhs->predecessor_width; - } - else - { - return false; - } +compare_space_ptr_by_r_p(const e::compat::shared_ptr &lhs, + const e::compat::shared_ptr &rhs) +{ + if (lhs->fault_tolerance < rhs->fault_tolerance) + { + return true; + } + else if (lhs->fault_tolerance == rhs->fault_tolerance) + { + return lhs->predecessor_width < rhs->predecessor_width; + } + else + { + return false; + } } } // namespace void -coordinator :: rebalance_replica_sets(rsm_context* ctx) -{ - uint64_t R = 0; - uint64_t P = 0; - std::vector replica_storage; - std::vector replica_sets; - std::vector spaces; - spaces.reserve(m_spaces.size()); - - for (space_map_t::iterator it = m_spaces.begin(); - it != m_spaces.end(); ++it) - { - spaces.push_back(it->second); - } - - std::sort(spaces.begin(), spaces.end(), compare_space_ptr_by_r_p); - - for (size_t i = 0; i < spaces.size(); ++i) - { - if (std::find(m_deferred_init.begin(), - m_deferred_init.end(), - spaces[i]->id) != m_deferred_init.end()) - { - remove(spaces[i]->id, &m_deferred_init); - initial_space_layout(ctx, spaces[i].get()); - continue; - } - - if (spaces[i]->fault_tolerance + 1 != R || - spaces[i]->predecessor_width != P) - { - R = spaces[i]->fault_tolerance + 1; - P = spaces[i]->predecessor_width; - compute_replica_sets(R, P, m_permutation, m_servers, - &replica_storage, - &replica_sets); - } - - setup_intents(ctx, replica_sets, spaces[i].get(), false); - } +coordinator :: rebalance_replica_sets(rsm_context *ctx) +{ + uint64_t R = 0; + uint64_t P = 0; + std::vector replica_storage; + std::vector replica_sets; + std::vector spaces; + spaces.reserve(m_spaces.size()); + for (space_map_t::iterator it = m_spaces.begin(); + it != m_spaces.end(); ++it) + { + spaces.push_back(it->second); + } + std::sort(spaces.begin(), spaces.end(), compare_space_ptr_by_r_p); + for (size_t i = 0; i < spaces.size(); ++i) + { + if (std::find(m_deferred_init.begin(), + m_deferred_init.end(), + spaces[i]->id) != m_deferred_init.end()) + { + remove(spaces[i]->id, &m_deferred_init); + initial_space_layout(ctx, spaces[i].get()); + continue; + } + if (spaces[i]->fault_tolerance + 1 != R || + spaces[i]->predecessor_width != P) + { + R = spaces[i]->fault_tolerance + 1; + P = spaces[i]->predecessor_width; + compute_replica_sets(R, P, m_permutation, m_servers, + &replica_storage, + &replica_sets); + } + setup_intents(ctx, replica_sets, spaces[i].get(), false); + } } void -coordinator :: initial_space_layout(rsm_context* ctx, - space* s) -{ - if (m_permutation.empty()) - { - m_deferred_init.push_back(s->id); - return; - } - - uint64_t R = s->fault_tolerance + 1; - uint64_t P = s->predecessor_width; - std::vector replica_storage; - std::vector replica_sets; - compute_replica_sets(R, P, m_permutation, m_servers, - &replica_storage, - &replica_sets); - setup_intents(ctx, replica_sets, s, true); -} - -region* -coordinator :: get_region(const region_id& rid) -{ - for (space_map_t::iterator it = m_spaces.begin(); - it != m_spaces.end(); ++it) - { - space& s(*it->second); - - for (size_t i = 0; i < s.subspaces.size(); ++i) - { - subspace& ss(s.subspaces[i]); - - for (size_t j = 0; j < ss.regions.size(); ++j) - { - if (ss.regions[j].id == rid) - { - return &ss.regions[j]; - } - } - } - } - - return NULL; +coordinator :: initial_space_layout(rsm_context *ctx, + space *s) +{ + if (m_permutation.empty()) + { + m_deferred_init.push_back(s->id); + return; + } + uint64_t R = s->fault_tolerance + 1; + uint64_t P = s->predecessor_width; + std::vector replica_storage; + std::vector replica_sets; + compute_replica_sets(R, P, m_permutation, m_servers, + &replica_storage, + &replica_sets); + setup_intents(ctx, replica_sets, s, true); +} + +region * +coordinator :: get_region(const region_id &rid) +{ + for (space_map_t::iterator it = m_spaces.begin(); + it != m_spaces.end(); ++it) + { + space &s(*it->second); + for (size_t i = 0; i < s.subspaces.size(); ++i) + { + subspace &ss(s.subspaces[i]); + for (size_t j = 0; j < ss.regions.size(); ++j) + { + if (ss.regions[j].id == rid) + { + return &ss.regions[j]; + } + } + } + } + return NULL; } void -coordinator :: setup_intents(rsm_context* ctx, - const std::vector& replica_sets, - space* s, bool skip_transfers) -{ - if (replica_sets.size() == 0) - { - return; - } - - for (size_t ss_idx = 0; ss_idx < s->subspaces.size(); ++ss_idx) - { - subspace& ss(s->subspaces[ss_idx]); - - for (size_t reg_idx = 0; reg_idx < ss.regions.size(); ++reg_idx) - { - region* reg = &ss.regions[reg_idx]; - size_t idx = (reg_idx * replica_sets.size()) / ss.regions.size(); - assert(idx < replica_sets.size()); - bool need_change = replica_sets[idx].size() != reg->replicas.size(); - - for (size_t i = 0; !need_change && i < replica_sets[idx].size(); ++i) - { - need_change = replica_sets[idx][i] != reg->replicas[i].si; - } - - if (!need_change) - { - del_region_intent(reg->id); - transfer* xfer = get_transfer(reg->id); - - // delete the transfer if we're OK with 0 replicas, or the - // transfer is adding a replica (that is, it's not gone-live - // yet). - if (xfer && (reg->replicas.empty() || xfer->dst != reg->replicas.back().si)) - { - del_transfer(xfer->id); - } - - continue; - } - - if (skip_transfers) - { - assert(reg->replicas.empty()); - - for (size_t i = 0; i < replica_sets[idx].size(); ++i) - { - reg->replicas.push_back(replica(replica_sets[idx][i], virtual_server_id(m_counter))); - ++m_counter; - } - } - else - { - region_intent* ri = get_region_intent(reg->id); - - if (!ri) - { - ri = new_region_intent(reg->id); - } - - ri->replicas.resize(replica_sets[idx].size()); - ri->checkpoint = 0; - - for (size_t i = 0; i < replica_sets[idx].size(); ++i) - { - ri->replicas[i] = replica_sets[idx][i]; - } - - converge_intent(ctx, reg, ri); - } - } - } +coordinator :: setup_intents(rsm_context *ctx, + const std::vector &replica_sets, + space *s, bool skip_transfers) +{ + if (replica_sets.size() == 0) + { + return; + } + for (size_t ss_idx = 0; ss_idx < s->subspaces.size(); ++ss_idx) + { + subspace &ss(s->subspaces[ss_idx]); + for (size_t reg_idx = 0; reg_idx < ss.regions.size(); ++reg_idx) + { + region *reg = &ss.regions[reg_idx]; + size_t idx = (reg_idx * replica_sets.size()) / ss.regions.size(); + assert(idx < replica_sets.size()); + bool need_change = replica_sets[idx].size() != reg->replicas.size(); + for (size_t i = 0; !need_change && i < replica_sets[idx].size(); ++i) + { + need_change = replica_sets[idx][i] != reg->replicas[i].si; + } + if (!need_change) + { + del_region_intent(reg->id); + transfer *xfer = get_transfer(reg->id); + // delete the transfer if we're OK with 0 replicas, or the + // transfer is adding a replica (that is, it's not gone-live + // yet). + if (xfer && (reg->replicas.empty() || xfer->dst != reg->replicas.back().si)) + { + del_transfer(xfer->id); + } + continue; + } + if (skip_transfers) + { + assert(reg->replicas.empty()); + for (size_t i = 0; i < replica_sets[idx].size(); ++i) + { + reg->replicas.push_back(replica(replica_sets[idx][i], virtual_server_id(m_counter))); + ++m_counter; + } + } + else + { + region_intent *ri = get_region_intent(reg->id); + if (!ri) + { + ri = new_region_intent(reg->id); + } + ri->replicas.resize(replica_sets[idx].size()); + ri->checkpoint = 0; + for (size_t i = 0; i < replica_sets[idx].size(); ++i) + { + ri->replicas[i] = replica_sets[idx][i]; + } + converge_intent(ctx, reg, ri); + } + } + } } void -coordinator :: converge_intent(rsm_context* ctx, - region* reg) +coordinator :: converge_intent(rsm_context *ctx, + region *reg) { - region_intent* ri = get_region_intent(reg->id); - - if (ri) - { - converge_intent(ctx, reg, ri); - } + region_intent *ri = get_region_intent(reg->id); + if (ri) + { + converge_intent(ctx, reg, ri); + } } void -coordinator :: converge_intent(rsm_context* ctx, - region* reg, region_intent* ri) -{ - // if there is a transfer - transfer* xfer = get_transfer(reg->id); - - if (xfer) - { - for (size_t i = 0; i < ri->replicas.size(); ++i) - { - // there's already a transfer in progress that's helping this region - // converge to the region_intent - if (xfer->dst == ri->replicas[i]) - { - return; - } - } - - del_transfer(xfer->id); - xfer = NULL; - } - - // there are no transfers for this region at this point - - if (!reg->replicas.empty() && - !((m_flags & HYPERDEX_CONFIG_READ_ONLY) && m_version == m_config_stable_through)) - { - remove_offline(reg->id); - } - - // remove every server that is not AVAILABLE - for (size_t i = 0; i < reg->replicas.size(); ) - { - server* s = get_server(reg->replicas[i].si); - - if (!s) - { - INVARIANT_BROKEN("server referenced but not found"); - continue; - } - - if (s->state != server::AVAILABLE) - { - if ((reg->replicas.size() == 1 || - ((m_flags & HYPERDEX_CONFIG_READ_ONLY) && m_version == m_config_stable_through)) && - s->state == server::SHUTDOWN) - { - m_offline.push_back(offline_server(reg->id, s->id)); - } - else if (reg->replicas.size() == 1) - { - rsm_log(ctx, "refusing to remove the last server from " - "region(%" PRIu64 ") because it was not a clean shutdown\n", - reg->id.get()); - return; - } - - rsm_log(ctx, "removing server(%" PRIu64 ") from region(%" PRIu64 ") " - "because it is in state %s\n", - reg->replicas[i].si.get(), reg->id.get(), - server::to_string(s->state)); - shift_and_pop(i, ®->replicas); - } - else - { - ++i; - } - } - - // now remove any excess replicas - for (size_t i = 0; i < reg->replicas.size(); ) - { - // no excess exist yet - if (reg->replicas.size() <= ri->replicas.size()) - { - break; - } - - // if we don't intend to converge with this replica, remove it - if (std::find(ri->replicas.begin(), - ri->replicas.end(), - reg->replicas[i].si) == ri->replicas.end()) - { - if (reg->replicas.size() == 1) - { - rsm_log(ctx, "refusing to remove the last server from " - "region(%" PRIu64 ") because we need it to transfer data\n", - reg->id.get()); - return; - } - - rsm_log(ctx, "removing server(%" PRIu64 ") from region(%" PRIu64 ") " - "to make progress toward desired state\n", - reg->replicas[i].si.get(), reg->id.get()); - shift_and_pop(i, ®->replicas); - } - else - { - ++i; - } - } - - if (reg->replicas.empty() && ri->replicas.empty()) - { - del_region_intent(reg->id); - return; - } - - if (reg->replicas.empty()) - { - for (size_t i = 0; i < m_offline.size(); ++i) - { - if (m_offline[i].id != reg->id) - { - continue; - } - - server* s = get_server(m_offline[i].sid); - - if (s && s->state == server::AVAILABLE) - { - reg->replicas.push_back(replica(m_offline[i].sid, virtual_server_id(m_counter))); - ++m_counter; - rsm_log(ctx, "restoring offline server(%" PRIu64 ") to region(%" PRIu64 ")\n", - m_offline[i].sid.get(), reg->id.get()); - remove_offline(reg->id); - break; - } - } - } - - if (reg->replicas.empty()) - { - rsm_log(ctx, "cannot transfer state to new servers in " - "region(%" PRIu64 ") because all servers are offline\n", - reg->id.get()); - return; - } - - // add up to one server from the region_intent - for (size_t i = 0; i < ri->replicas.size(); ++i) - { - bool found = false; - - for (size_t j = 0; j < reg->replicas.size(); ++j) - { - if (ri->replicas[i] == reg->replicas[j].si) - { - found = true; - break; - } - } - - if (found) - { - continue; - } - - xfer = new_transfer(reg, ri->replicas[i]); - assert(xfer); - rsm_log(ctx, "adding server(%" PRIu64 ") to region(%" PRIu64 ") " - "copying from server(%" PRIu64 ")/virtual_server(%" PRIu64 ") " - "using transfer(%" PRIu64 ")/virtual_server(%" PRIu64 ")\n", - xfer->dst.get(), reg->id.get(), - xfer->src.get(), xfer->vsrc.get(), - xfer->id.get(), xfer->vdst.get()); - return; - } - - if (ri->checkpoint == 0) - { - ri->checkpoint = m_checkpoint > 0 ? m_checkpoint : 1; - } - - // now shuffle to make the order consistent with ri->replicas - for (size_t i = 1; i < reg->replicas.size(); ++i) - { - server_id* start = &ri->replicas[0]; - server_id* limit = start + ri->replicas.size(); - // idx1 is the index of reg->replicas[i - 1] in ri->replicas - size_t idx1 = std::find(start, limit, reg->replicas[i - 1].si) - start; - // idx2 is the index of reg->replicas[i - 0] in ri->replicas - size_t idx2 = std::find(start, limit, reg->replicas[i - 0].si) - start; - - if (idx1 < idx2) - { - continue; - } - - if (ri->checkpoint >= m_checkpoint_stable_through) - { - rsm_log(ctx, "postponing convergence until after checkpoint %" PRIu64 " is stable\n", ri->checkpoint); - return; - } - - // grab the server id - server_id sid = reg->replicas[i - 1].si; - // remove the idx1 replica - shift_and_pop(i - 1, ®->replicas); - // now do a transfer to roll it to the end - ri->checkpoint = 0; - xfer = new_transfer(reg, sid); - assert(xfer); - rsm_log(ctx, "rolling server(%" PRIu64 ") to the back of region(%" PRIu64 ") " - "using transfer(%" PRIu64 ")/virtual_server(%" PRIu64 ")\n", - xfer->dst.get(), reg->id.get(), - xfer->id.get(), xfer->vdst.get()); - return; - } - - del_region_intent(reg->id); -} - -region_intent* -coordinator :: new_region_intent(const region_id& rid) -{ - size_t idx = m_intents.size(); - m_intents.push_back(region_intent(rid)); - - for (; idx > 0; --idx) - { - if (m_intents[idx - 1].id < m_intents[idx].id) - { - break; - } - - std::swap(m_intents[idx - 1], m_intents[idx]); - } - - return &m_intents[idx]; -} - -region_intent* -coordinator :: get_region_intent(const region_id& rid) -{ - for (size_t i = 0; i < m_intents.size(); ++i) - { - if (m_intents[i].id == rid) - { - return &m_intents[i]; - } - } - - return NULL; +coordinator :: converge_intent(rsm_context *ctx, + region *reg, region_intent *ri) +{ + // if there is a transfer + transfer *xfer = get_transfer(reg->id); + if (xfer) + { + for (size_t i = 0; i < ri->replicas.size(); ++i) + { + // there's already a transfer in progress that's helping this region + // converge to the region_intent + if (xfer->dst == ri->replicas[i]) + { + return; + } + } + del_transfer(xfer->id); + xfer = NULL; + } + // there are no transfers for this region at this point + if (!reg->replicas.empty() && + !((m_flags & HYPERDEX_CONFIG_READ_ONLY) && m_version == m_config_stable_through)) + { + remove_offline(reg->id); + } + // remove every server that is not AVAILABLE + for (size_t i = 0; i < reg->replicas.size(); ) + { + server *s = get_server(reg->replicas[i].si); + if (!s) + { + INVARIANT_BROKEN("server referenced but not found"); + continue; + } + if (s->state != server::AVAILABLE) + { + if ((reg->replicas.size() == 1 || + ((m_flags & HYPERDEX_CONFIG_READ_ONLY) && m_version == m_config_stable_through)) && + s->state == server::SHUTDOWN) + { + m_offline.push_back(offline_server(reg->id, s->id)); + } + else if (reg->replicas.size() == 1) + { + rsm_log(ctx, "refusing to remove the last server from " + "region(%" PRIu64 ") because it was not a clean shutdown\n", + reg->id.get()); + return; + } + rsm_log(ctx, "removing server(%" PRIu64 ") from region(%" PRIu64 ") " + "because it is in state %s\n", + reg->replicas[i].si.get(), reg->id.get(), + server::to_string(s->state)); + shift_and_pop(i, ®->replicas); + } + else + { + ++i; + } + } + // now remove any excess replicas + for (size_t i = 0; i < reg->replicas.size(); ) + { + // no excess exist yet + if (reg->replicas.size() <= ri->replicas.size()) + { + break; + } + // if we don't intend to converge with this replica, remove it + if (std::find(ri->replicas.begin(), + ri->replicas.end(), + reg->replicas[i].si) == ri->replicas.end()) + { + if (reg->replicas.size() == 1) + { + rsm_log(ctx, "refusing to remove the last server from " + "region(%" PRIu64 ") because we need it to transfer data\n", + reg->id.get()); + return; + } + rsm_log(ctx, "removing server(%" PRIu64 ") from region(%" PRIu64 ") " + "to make progress toward desired state\n", + reg->replicas[i].si.get(), reg->id.get()); + shift_and_pop(i, ®->replicas); + } + else + { + ++i; + } + } + if (reg->replicas.empty() && ri->replicas.empty()) + { + del_region_intent(reg->id); + return; + } + if (reg->replicas.empty()) + { + for (size_t i = 0; i < m_offline.size(); ++i) + { + if (m_offline[i].id != reg->id) + { + continue; + } + server *s = get_server(m_offline[i].sid); + if (s && s->state == server::AVAILABLE) + { + reg->replicas.push_back(replica(m_offline[i].sid, virtual_server_id(m_counter))); + ++m_counter; + rsm_log(ctx, "restoring offline server(%" PRIu64 ") to region(%" PRIu64 ")\n", + m_offline[i].sid.get(), reg->id.get()); + remove_offline(reg->id); + break; + } + } + } + if (reg->replicas.empty()) + { + rsm_log(ctx, "cannot transfer state to new servers in " + "region(%" PRIu64 ") because all servers are offline\n", + reg->id.get()); + return; + } + // add up to one server from the region_intent + for (size_t i = 0; i < ri->replicas.size(); ++i) + { + bool found = false; + for (size_t j = 0; j < reg->replicas.size(); ++j) + { + if (ri->replicas[i] == reg->replicas[j].si) + { + found = true; + break; + } + } + if (found) + { + continue; + } + xfer = new_transfer(reg, ri->replicas[i]); + assert(xfer); + rsm_log(ctx, "adding server(%" PRIu64 ") to region(%" PRIu64 ") " + "copying from server(%" PRIu64 ")/virtual_server(%" PRIu64 ") " + "using transfer(%" PRIu64 ")/virtual_server(%" PRIu64 ")\n", + xfer->dst.get(), reg->id.get(), + xfer->src.get(), xfer->vsrc.get(), + xfer->id.get(), xfer->vdst.get()); + return; + } + if (ri->checkpoint == 0) + { + ri->checkpoint = m_checkpoint > 0 ? m_checkpoint : 1; + } + // now shuffle to make the order consistent with ri->replicas + for (size_t i = 1; i < reg->replicas.size(); ++i) + { + server_id *start = &ri->replicas[0]; + server_id *limit = start + ri->replicas.size(); + // idx1 is the index of reg->replicas[i - 1] in ri->replicas + size_t idx1 = std::find(start, limit, reg->replicas[i - 1].si) - start; + // idx2 is the index of reg->replicas[i - 0] in ri->replicas + size_t idx2 = std::find(start, limit, reg->replicas[i - 0].si) - start; + if (idx1 < idx2) + { + continue; + } + if (ri->checkpoint >= m_checkpoint_stable_through) + { + rsm_log(ctx, "postponing convergence until after checkpoint %" PRIu64 " is stable\n", ri->checkpoint); + return; + } + // grab the server id + server_id sid = reg->replicas[i - 1].si; + // remove the idx1 replica + shift_and_pop(i - 1, ®->replicas); + // now do a transfer to roll it to the end + ri->checkpoint = 0; + xfer = new_transfer(reg, sid); + assert(xfer); + rsm_log(ctx, "rolling server(%" PRIu64 ") to the back of region(%" PRIu64 ") " + "using transfer(%" PRIu64 ")/virtual_server(%" PRIu64 ")\n", + xfer->dst.get(), reg->id.get(), + xfer->id.get(), xfer->vdst.get()); + return; + } + del_region_intent(reg->id); +} + +region_intent * +coordinator :: new_region_intent(const region_id &rid) +{ + size_t idx = m_intents.size(); + m_intents.push_back(region_intent(rid)); + for (; idx > 0; --idx) + { + if (m_intents[idx - 1].id < m_intents[idx].id) + { + break; + } + std::swap(m_intents[idx - 1], m_intents[idx]); + } + return &m_intents[idx]; +} + +region_intent * +coordinator :: get_region_intent(const region_id &rid) +{ + for (size_t i = 0; i < m_intents.size(); ++i) + { + if (m_intents[i].id == rid) + { + return &m_intents[i]; + } + } + return NULL; } void -coordinator :: del_region_intent(const region_id& rid) +coordinator :: del_region_intent(const region_id &rid) { - remove_id(rid, &m_intents); + remove_id(rid, &m_intents); } void -coordinator :: remove_offline(const region_id& rid) +coordinator :: remove_offline(const region_id &rid) { - for (size_t i = 0; i < m_offline.size(); ) - { - if (m_offline[i].id == rid) - { - shift_and_pop(i, &m_offline); - } - else - { - ++i; - } - } + for (size_t i = 0; i < m_offline.size(); ) + { + if (m_offline[i].id == rid) + { + shift_and_pop(i, &m_offline); + } + else + { + ++i; + } + } } void -coordinator :: remove_offline(const server_id& sid) -{ - for (size_t i = 0; i < m_offline.size(); ) - { - if (m_offline[i].sid == sid) - { - shift_and_pop(i, &m_offline); - } - else - { - ++i; - } - } -} - -transfer* -coordinator :: new_transfer(region* reg, - const server_id& sid) -{ - assert(!reg->replicas.empty()); - m_transfers.push_back(transfer()); - transfer* t = &m_transfers.back(); - t->id = transfer_id(m_counter); - ++m_counter; - t->rid = reg->id; - t->src = reg->replicas.back().si; - t->vsrc = reg->replicas.back().vsi; - t->dst = sid; - t->vdst = virtual_server_id(m_counter); - ++m_counter; - return t; -} - -transfer* -coordinator :: get_transfer(const region_id& rid) -{ - for (size_t i = 0; i < m_transfers.size(); ++i) - { - if (m_transfers[i].rid == rid) - { - return &m_transfers[i]; - } - } - - return NULL; -} - -transfer* -coordinator :: get_transfer(const transfer_id& xid) -{ - for (size_t i = 0; i < m_transfers.size(); ++i) - { - if (m_transfers[i].id == xid) - { - return &m_transfers[i]; - } - } - - return NULL; +coordinator :: remove_offline(const server_id &sid) +{ + for (size_t i = 0; i < m_offline.size(); ) + { + if (m_offline[i].sid == sid) + { + shift_and_pop(i, &m_offline); + } + else + { + ++i; + } + } +} + +transfer * +coordinator :: new_transfer(region *reg, + const server_id &sid) +{ + assert(!reg->replicas.empty()); + m_transfers.push_back(transfer()); + transfer *t = &m_transfers.back(); + t->id = transfer_id(m_counter); + ++m_counter; + t->rid = reg->id; + t->src = reg->replicas.back().si; + t->vsrc = reg->replicas.back().vsi; + t->dst = sid; + t->vdst = virtual_server_id(m_counter); + ++m_counter; + return t; +} + +transfer * +coordinator :: get_transfer(const region_id &rid) +{ + for (size_t i = 0; i < m_transfers.size(); ++i) + { + if (m_transfers[i].rid == rid) + { + return &m_transfers[i]; + } + } + return NULL; +} + +transfer * +coordinator :: get_transfer(const transfer_id &xid) +{ + for (size_t i = 0; i < m_transfers.size(); ++i) + { + if (m_transfers[i].id == xid) + { + return &m_transfers[i]; + } + } + return NULL; } void -coordinator :: del_transfer(const transfer_id& xid) -{ - for (size_t i = 0; i < m_transfers.size(); ++i) - { - if (m_transfers[i].id != xid) - { - continue; - } - - for (size_t j = i + 1; j < m_transfers.size(); ++j) - { - m_transfers[j - 1] = m_transfers[j]; - } - - m_transfers.pop_back(); - break; - } +coordinator :: del_transfer(const transfer_id &xid) +{ + for (size_t i = 0; i < m_transfers.size(); ++i) + { + if (m_transfers[i].id != xid) + { + continue; + } + for (size_t j = i + 1; j < m_transfers.size(); ++j) + { + m_transfers[j - 1] = m_transfers[j]; + } + m_transfers.pop_back(); + break; + } } void -coordinator :: check_ack_condition(rsm_context* ctx) +coordinator :: check_ack_condition(rsm_context *ctx) { - if (m_config_ack_through < m_config_ack_barrier.min_version()) - { - rsm_log(ctx, "acked through version %" PRIu64 "\n", m_config_ack_barrier.min_version()); - } - - while (m_config_ack_through < m_config_ack_barrier.min_version()) - { - rsm_cond_broadcast(ctx, "ack"); - ++m_config_ack_through; - } + if (m_config_ack_through < m_config_ack_barrier.min_version()) + { + rsm_log(ctx, "acked through version %" PRIu64 "\n", m_config_ack_barrier.min_version()); + } + while (m_config_ack_through < m_config_ack_barrier.min_version()) + { + rsm_cond_broadcast(ctx, "ack"); + ++m_config_ack_through; + } } void -coordinator :: check_stable_condition(rsm_context* ctx) +coordinator :: check_stable_condition(rsm_context *ctx) { - if (m_config_stable_through < m_config_stable_barrier.min_version()) - { - rsm_log(ctx, "stable through version %" PRIu64 "\n", m_config_stable_barrier.min_version()); - } - - while (m_intents.empty() && m_deferred_init.empty() && - m_config_stable_through < m_config_stable_barrier.min_version()) - { - rsm_cond_broadcast(ctx, "stable"); - ++m_config_stable_through; - } + if (m_config_stable_through < m_config_stable_barrier.min_version()) + { + rsm_log(ctx, "stable through version %" PRIu64 "\n", m_config_stable_barrier.min_version()); + } + while (m_intents.empty() && m_deferred_init.empty() && + m_config_stable_through < m_config_stable_barrier.min_version()) + { + rsm_cond_broadcast(ctx, "stable"); + ++m_config_stable_through; + } } void -coordinator :: generate_next_configuration(rsm_context* ctx) +coordinator :: generate_next_configuration(rsm_context *ctx) { - ++m_version; - rsm_log(ctx, "issuing new configuration version %" PRIu64 "\n", m_version); - std::vector sids; - servers_in_configuration(&sids); - m_config_ack_barrier.new_version(m_version, sids); - m_config_stable_barrier.new_version(m_version, sids); - check_ack_condition(ctx); - check_stable_condition(ctx); - generate_cached_configuration(ctx); - rsm_cond_broadcast_data(ctx, "config", m_latest_config->cdata(), m_latest_config->size()); - broadcast_checkpoint_information(ctx); + ++m_version; + rsm_log(ctx, "issuing new configuration version %" PRIu64 "\n", m_version); + std::vector sids; + servers_in_configuration(&sids); + m_config_ack_barrier.new_version(m_version, sids); + m_config_stable_barrier.new_version(m_version, sids); + check_ack_condition(ctx); + check_stable_condition(ctx); + generate_cached_configuration(ctx); + rsm_cond_broadcast_data(ctx, "config", m_latest_config->cdata(), m_latest_config->size()); + broadcast_checkpoint_information(ctx); } void -coordinator :: generate_cached_configuration(rsm_context*) -{ - m_latest_config.reset(); - size_t sz = 7 * sizeof(uint64_t); - - for (size_t i = 0; i < m_servers.size(); ++i) - { - sz += pack_size(m_servers[i]); - } - - for (std::map >::iterator it = m_spaces.begin(); - it != m_spaces.end(); ++it) - { - sz += pack_size(*it->second); - } - - for (size_t i = 0; i < m_transfers.size(); ++i) - { - sz += pack_size(m_transfers[i]); - } - - std::vector transfers_subset; - prioritized_transfer_subset(&transfers_subset); - - std::auto_ptr new_config(e::buffer::create(sz)); - e::packer pa = new_config->pack_at(0); - pa = pa << m_cluster << m_version << m_flags - << uint64_t(m_servers.size()) - << uint64_t(m_spaces.size()) - << uint64_t(transfers_subset.size()); - - for (size_t i = 0; i < m_servers.size(); ++i) - { - pa = pa << m_servers[i]; - } - - for (std::map >::iterator it = m_spaces.begin(); - it != m_spaces.end(); ++it) - { - pa = pa << *it->second; - } - - for (size_t i = 0; i < transfers_subset.size(); ++i) - { - pa = pa << transfers_subset[i]; - } - - m_latest_config = new_config; +coordinator :: generate_cached_configuration(rsm_context *) +{ + m_latest_config.reset(); + size_t sz = 7 * sizeof(uint64_t); + for (size_t i = 0; i < m_servers.size(); ++i) + { + sz += pack_size(m_servers[i]); + } + for (std::map >::iterator it = m_spaces.begin(); + it != m_spaces.end(); ++it) + { + sz += pack_size(*it->second); + } + for (size_t i = 0; i < m_transfers.size(); ++i) + { + sz += pack_size(m_transfers[i]); + } + std::vector transfers_subset; + prioritized_transfer_subset(&transfers_subset); + std::auto_ptr new_config(e::buffer::create(sz)); + e::packer pa = new_config->pack_at(0); + pa = pa << m_cluster << m_version << m_flags + << uint64_t(m_servers.size()) + << uint64_t(m_spaces.size()) + << uint64_t(transfers_subset.size()); + for (size_t i = 0; i < m_servers.size(); ++i) + { + pa = pa << m_servers[i]; + } + for (std::map >::iterator it = m_spaces.begin(); + it != m_spaces.end(); ++it) + { + pa = pa << *it->second; + } + for (size_t i = 0; i < transfers_subset.size(); ++i) + { + pa = pa << transfers_subset[i]; + } + m_latest_config = new_config; } struct coordinator::transfer_sorter { - transfer_sorter(coordinator* c) : coord(c) {} - transfer_sorter(const transfer_sorter& other) : coord(other.coord) {} - bool operator () (const transfer& lhs, const transfer& rhs) const; - coordinator* coord; + transfer_sorter(coordinator *c) : coord(c) {} + transfer_sorter(const transfer_sorter &other) : coord(other.coord) {} + bool operator () (const transfer &lhs, const transfer &rhs) const; + coordinator *coord; - private: - transfer_sorter& operator = (const transfer_sorter&); +private: + transfer_sorter &operator = (const transfer_sorter &); }; bool -coordinator :: transfer_sorter :: operator () (const transfer& lhs, const transfer& rhs) const -{ - region* rlhs = coord->get_region(lhs.rid); - region* rrhs = coord->get_region(rhs.rid); - bool live_lhs = !rlhs->replicas.empty() && rlhs->replicas.back().vsi == lhs.vdst; - bool live_rhs = !rrhs->replicas.empty() && rrhs->replicas.back().vsi == rhs.vdst; - - if (live_lhs && !live_rhs) - { - return true; - } - else if (live_rhs && !live_lhs) - { - return false; - } - else - { - return rlhs->replicas.size() < rrhs->replicas.size(); - } +coordinator :: transfer_sorter :: operator () (const transfer &lhs, const transfer &rhs) const +{ + region *rlhs = coord->get_region(lhs.rid); + region *rrhs = coord->get_region(rhs.rid); + bool live_lhs = !rlhs->replicas.empty() && rlhs->replicas.back().vsi == lhs.vdst; + bool live_rhs = !rrhs->replicas.empty() && rrhs->replicas.back().vsi == rhs.vdst; + if (live_lhs && !live_rhs) + { + return true; + } + else if (live_rhs && !live_lhs) + { + return false; + } + else + { + return rlhs->replicas.size() < rrhs->replicas.size(); + } } void -coordinator :: prioritized_transfer_subset(std::vector* transfers) -{ - std::vector seen_src; - std::vector seen_dst; - std::vector tmp_transfers(m_transfers); - transfer_sorter ts(this); - std::stable_sort(tmp_transfers.begin(), tmp_transfers.end(), ts); - transfers->clear(); - transfers->reserve(std::min(m_servers.size(), m_transfers.size())); - - for (size_t i = 0; i < tmp_transfers.size(); ++i) - { - // if the src is not the dst of a transfer, and the dst is not a src of - // a transfer, then add the transfer - if (std::find(seen_dst.begin(), seen_dst.end(), tmp_transfers[i].src) == seen_dst.end() && - std::find(seen_src.begin(), seen_src.end(), tmp_transfers[i].dst) == seen_src.end()) - { - seen_src.push_back(tmp_transfers[i].src); - seen_dst.push_back(tmp_transfers[i].dst); - transfers->push_back(tmp_transfers[i]); - } - } +coordinator :: prioritized_transfer_subset(std::vector *transfers) +{ + std::vector seen_src; + std::vector seen_dst; + std::vector tmp_transfers(m_transfers); + transfer_sorter ts(this); + std::stable_sort(tmp_transfers.begin(), tmp_transfers.end(), ts); + transfers->clear(); + transfers->reserve(std::min(m_servers.size(), m_transfers.size())); + for (size_t i = 0; i < tmp_transfers.size(); ++i) + { + // if the src is not the dst of a transfer, and the dst is not a src of + // a transfer, then add the transfer + if (std::find(seen_dst.begin(), seen_dst.end(), tmp_transfers[i].src) == seen_dst.end() && + std::find(seen_src.begin(), seen_src.end(), tmp_transfers[i].dst) == seen_src.end()) + { + seen_src.push_back(tmp_transfers[i].src); + seen_dst.push_back(tmp_transfers[i].dst); + transfers->push_back(tmp_transfers[i]); + } + } } void -coordinator :: servers_in_configuration(std::vector* sids) -{ - for (std::map >::iterator it = m_spaces.begin(); - it != m_spaces.end(); ++it) - { - space& s(*it->second); - - for (size_t i = 0; i < s.subspaces.size(); ++i) - { - subspace& ss(s.subspaces[i]); - - for (size_t j = 0; j < ss.regions.size(); ++j) - { - region& reg(ss.regions[j]); - - for (size_t k = 0; k < reg.replicas.size(); ++k) - { - sids->push_back(reg.replicas[k].si); - } - } - } - } - - for (size_t i = 0; i < m_transfers.size(); ++i) - { - sids->push_back(m_transfers[i].src); - sids->push_back(m_transfers[i].dst); - } - - std::sort(sids->begin(), sids->end()); - std::vector::iterator sit; - sit = std::unique(sids->begin(), sids->end()); - sids->resize(sit - sids->begin()); +coordinator :: servers_in_configuration(std::vector *sids) +{ + for (std::map >::iterator it = m_spaces.begin(); + it != m_spaces.end(); ++it) + { + space &s(*it->second); + for (size_t i = 0; i < s.subspaces.size(); ++i) + { + subspace &ss(s.subspaces[i]); + for (size_t j = 0; j < ss.regions.size(); ++j) + { + region ®(ss.regions[j]); + for (size_t k = 0; k < reg.replicas.size(); ++k) + { + sids->push_back(reg.replicas[k].si); + } + } + } + } + for (size_t i = 0; i < m_transfers.size(); ++i) + { + sids->push_back(m_transfers[i].src); + sids->push_back(m_transfers[i].dst); + } + std::sort(sids->begin(), sids->end()); + std::vector::iterator sit; + sit = std::unique(sids->begin(), sids->end()); + sids->resize(sit - sids->begin()); } void -coordinator :: regions_in_space(space_ptr s, std::vector* rids) +coordinator :: regions_in_space(space_ptr s, std::vector *rids) { - for (size_t i = 0; i < s->subspaces.size(); ++i) - { - subspace& ss(s->subspaces[i]); - - for (size_t j = 0; j < ss.regions.size(); ++j) - { - rids->push_back(ss.regions[j].id); - } - } + for (size_t i = 0; i < s->subspaces.size(); ++i) + { + subspace &ss(s->subspaces[i]); + for (size_t j = 0; j < ss.regions.size(); ++j) + { + rids->push_back(ss.regions[j].id); + } + } } void -coordinator :: check_checkpoint_stable_condition(rsm_context* ctx, bool reissue) -{ - assert(m_checkpoint_stable_through <= m_checkpoint); - - if (m_checkpoint_stable_through < m_checkpoint_stable_barrier.min_version()) - { - rsm_log(ctx, "checkpoint %" PRIu64 " done\n", m_checkpoint_stable_barrier.min_version()); - } - - bool stabilized = false; - - while (m_checkpoint_stable_through < m_checkpoint_stable_barrier.min_version()) - { - stabilized = true; - ++m_checkpoint_stable_through; - broadcast_checkpoint_information(ctx); - } - - bool gc = false; - uint64_t outstanding_checkpoints = 120; - - if (m_intents.empty()) - { - bool all_available = true; - - for (size_t i = 0; i < m_servers.size(); ++i) - { - if (m_servers[i].state != server::AVAILABLE) - { - all_available = false; - break; - } - } - - if (all_available) - { - outstanding_checkpoints = 1; - } - } - - while (m_checkpoint_gc_through + outstanding_checkpoints < m_checkpoint_stable_barrier.min_version()) - { - gc = true; - ++m_checkpoint_gc_through; - broadcast_checkpoint_information(ctx); - } - - if (gc && m_checkpoint_gc_through > 0) - { - rsm_log(ctx, "garbage collect <= checkpoint %" PRIu64 "\n", m_checkpoint_gc_through); - } - - assert(m_checkpoint_gc_through <= m_checkpoint_stable_through); - assert(m_checkpoint_stable_through <= m_checkpoint); - - if (stabilized) - { - std::vector rids; - rids.reserve(m_intents.size()); - - // two pass because converge_intent can alter m_intents - for (size_t i = 0; i < m_intents.size(); ++i) - { - if (m_intents[i].checkpoint > 0 && - m_intents[i].checkpoint < m_checkpoint_stable_through) - { - rids.push_back(m_intents[i].id); - } - } - - for (size_t i = 0; i < rids.size(); ++i) - { - region* reg = get_region(rids[i]); - converge_intent(ctx, reg); - } - - if (!rids.empty()) - { - generate_next_configuration(ctx); - } - } - - if (reissue && m_checkpoint_stable_through + 1 < m_checkpoint) - { - generate_next_configuration(ctx); - } +coordinator :: check_checkpoint_stable_condition(rsm_context *ctx, bool reissue) +{ + assert(m_checkpoint_stable_through <= m_checkpoint); + if (m_checkpoint_stable_through < m_checkpoint_stable_barrier.min_version()) + { + rsm_log(ctx, "checkpoint %" PRIu64 " done\n", m_checkpoint_stable_barrier.min_version()); + } + bool stabilized = false; + while (m_checkpoint_stable_through < m_checkpoint_stable_barrier.min_version()) + { + stabilized = true; + ++m_checkpoint_stable_through; + broadcast_checkpoint_information(ctx); + } + bool gc = false; + uint64_t outstanding_checkpoints = 120; + if (m_intents.empty()) + { + bool all_available = true; + for (size_t i = 0; i < m_servers.size(); ++i) + { + if (m_servers[i].state != server::AVAILABLE) + { + all_available = false; + break; + } + } + if (all_available) + { + outstanding_checkpoints = 1; + } + } + while (m_checkpoint_gc_through + outstanding_checkpoints < m_checkpoint_stable_barrier.min_version()) + { + gc = true; + ++m_checkpoint_gc_through; + broadcast_checkpoint_information(ctx); + } + if (gc && m_checkpoint_gc_through > 0) + { + rsm_log(ctx, "garbage collect <= checkpoint %" PRIu64 "\n", m_checkpoint_gc_through); + } + assert(m_checkpoint_gc_through <= m_checkpoint_stable_through); + assert(m_checkpoint_stable_through <= m_checkpoint); + if (stabilized) + { + std::vector rids; + rids.reserve(m_intents.size()); + // two pass because converge_intent can alter m_intents + for (size_t i = 0; i < m_intents.size(); ++i) + { + if (m_intents[i].checkpoint > 0 && + m_intents[i].checkpoint < m_checkpoint_stable_through) + { + rids.push_back(m_intents[i].id); + } + } + for (size_t i = 0; i < rids.size(); ++i) + { + region *reg = get_region(rids[i]); + converge_intent(ctx, reg); + } + if (!rids.empty()) + { + generate_next_configuration(ctx); + } + } + if (reissue && m_checkpoint_stable_through + 1 < m_checkpoint) + { + generate_next_configuration(ctx); + } } void -coordinator :: broadcast_checkpoint_information(rsm_context* ctx) -{ - std::string input; - e::packer(&input) << m_version - << m_checkpoint - << m_checkpoint_stable_through - << m_checkpoint_gc_through; - rsm_cond_broadcast_data(ctx, "checkpoint", input.data(), input.size()); +coordinator :: broadcast_checkpoint_information(rsm_context *ctx) +{ + std::string input; + e::packer(&input) << m_version + << m_checkpoint + << m_checkpoint_stable_through + << m_checkpoint_gc_through; + rsm_cond_broadcast_data(ctx, "checkpoint", input.data(), input.size()); } diff --git a/coordinator/coordinator.h b/coordinator/coordinator.h index 9b2a05ba8..e4330dd90 100644 --- a/coordinator/coordinator.h +++ b/coordinator/coordinator.h @@ -55,181 +55,181 @@ BEGIN_HYPERDEX_NAMESPACE class coordinator { - public: - coordinator(); - ~coordinator() throw (); - - // identity - public: - void init(rsm_context* ctx, uint64_t token); - uint64_t cluster() const { return m_cluster; } - - // cluster management - public: - void read_only(rsm_context* ctx, bool ro); - void fault_tolerance(rsm_context* ctx, - const char* space, uint64_t consistency); - - // server management - public: - void server_register(rsm_context* ctx, - const server_id& sid, - const po6::net::location& bind_to); - void server_online(rsm_context* ctx, - const server_id& sid, - const po6::net::location* bind_to); - void server_offline(rsm_context* ctx, - const server_id& sid); - void server_shutdown(rsm_context* ctx, - const server_id& sid); - void server_kill(rsm_context* ctx, - const server_id& sid); - void server_forget(rsm_context* ctx, - const server_id& sid); - void server_suspect(rsm_context* ctx, - const server_id& sid); - void report_disconnect(rsm_context* ctx, - const server_id& sid, uint64_t version); - - // space management - public: - void space_add(rsm_context* ctx, const space& s); - void space_rm(rsm_context* ctx, const char* name); - void space_mv(rsm_context* ctx, const char* src, const char* dst); - - // index management - public: - void index_add(rsm_context* ctx, const char* space, const char* attr); - void index_rm(rsm_context* ctx, index_id ii); - - // transfers management - public: - void transfer_go_live(rsm_context* ctx, - const transfer_id& xid); - void transfer_complete(rsm_context* ctx, - const transfer_id& xid); - - // config management - public: - void config_get(rsm_context* ctx); - void config_ack(rsm_context* ctx, - const server_id& sid, uint64_t version); - void config_stable(rsm_context* ctx, - const server_id& sid, uint64_t version); - - // checkpoint management - public: - void checkpoint(rsm_context* ctx); - void checkpoint_stable(rsm_context* ctx, - const server_id& sid, - uint64_t config, - uint64_t number); - void checkpoints(rsm_context* ctx); - - // periodic - public: - void periodic(rsm_context* ctx); - - // debug - public: - void debug_dump(rsm_context* ctx); - - // backup/restore - public: - static coordinator* recreate(rsm_context* ctx, - const char* data, size_t data_sz); - int snapshot(rsm_context* ctx, - char** data, size_t* data_sz); - - private: - typedef e::compat::shared_ptr space_ptr; - typedef std::map space_map_t; - struct transfer_sorter; - - // utilities - private: - // servers - server* new_server(const server_id& sid); - server* get_server(const server_id& sid); - // replica sets - bool in_permutation(const server_id& sid); - void add_permutation(const server_id& sid); - void remove_permutation(const server_id& sid); - void rebalance_replica_sets(rsm_context* ctx); - // hyperspace - void initial_space_layout(rsm_context* ctx, - space* s); - region* get_region(const region_id& rid); - // intents - void setup_intents(rsm_context* ctx, - const std::vector& replica_sets, - space* s, bool skip_transfers); - // looks up region_intent* ri, removing any possibility of the user - // using an invalid pointer - void converge_intent(rsm_context* ctx, - region* reg); - // ri and m_intents may be changed after this call - void converge_intent(rsm_context* ctx, - region* reg, region_intent* ri); - region_intent* new_region_intent(const region_id& rid); - region_intent* get_region_intent(const region_id& rid); - void del_region_intent(const region_id& rid); - void remove_offline(const region_id& rid); - void remove_offline(const server_id& sid); - // transfers - transfer* new_transfer(region* reg, const server_id& si); - transfer* get_transfer(const region_id& rid); - transfer* get_transfer(const transfer_id& xid); - void del_transfer(const transfer_id& xid); - // configuration - void check_ack_condition(rsm_context* ctx); - void check_stable_condition(rsm_context* ctx); - void generate_next_configuration(rsm_context* ctx); - void generate_cached_configuration(rsm_context* ctx); - void prioritized_transfer_subset(std::vector* transfers); - void servers_in_configuration(std::vector* sids); - void regions_in_space(space_ptr s, std::vector* rids); - // checkpoints - void check_checkpoint_stable_condition(rsm_context* ctx, bool reissue); - void broadcast_checkpoint_information(rsm_context* ctx); - - private: - // meta state - uint64_t m_cluster; - uint64_t m_counter; - uint64_t m_version; - uint64_t m_flags; - // servers - std::vector m_servers; - // replica sets - std::vector m_permutation; - std::vector m_spares; - uint64_t m_desired_spares; - // spaces - space_map_t m_spaces; - // intents - std::vector m_intents; - std::vector m_deferred_init; - std::vector m_offline; - // transfers - std::vector m_transfers; - // barriers - uint64_t m_config_ack_through; - server_barrier m_config_ack_barrier; - uint64_t m_config_stable_through; - server_barrier m_config_stable_barrier; - // checkpoints - uint64_t m_checkpoint; - uint64_t m_checkpoint_stable_through; - uint64_t m_checkpoint_gc_through; - server_barrier m_checkpoint_stable_barrier; - // cached config - std::auto_ptr m_latest_config; - std::auto_ptr m_response; - - private: - coordinator(const coordinator&); - coordinator& operator = (const coordinator&); +public: + coordinator(); + ~coordinator() throw (); + + // identity +public: + void init(rsm_context *ctx, uint64_t token); + uint64_t cluster() const { return m_cluster; } + + // cluster management +public: + void read_only(rsm_context *ctx, bool ro); + void fault_tolerance(rsm_context *ctx, + const char *space, uint64_t consistency); + + // server management +public: + void server_register(rsm_context *ctx, + const server_id &sid, + const po6::net::location &bind_to); + void server_online(rsm_context *ctx, + const server_id &sid, + const po6::net::location *bind_to); + void server_offline(rsm_context *ctx, + const server_id &sid); + void server_shutdown(rsm_context *ctx, + const server_id &sid); + void server_kill(rsm_context *ctx, + const server_id &sid); + void server_forget(rsm_context *ctx, + const server_id &sid); + void server_suspect(rsm_context *ctx, + const server_id &sid); + void report_disconnect(rsm_context *ctx, + const server_id &sid, uint64_t version); + + // space management +public: + void space_add(rsm_context *ctx, const space &s); + void space_rm(rsm_context *ctx, const char *name); + void space_mv(rsm_context *ctx, const char *src, const char *dst); + + // index management +public: + void index_add(rsm_context *ctx, const char *space, const char *attr); + void index_rm(rsm_context *ctx, index_id ii); + + // transfers management +public: + void transfer_go_live(rsm_context *ctx, + const transfer_id &xid); + void transfer_complete(rsm_context *ctx, + const transfer_id &xid); + + // config management +public: + void config_get(rsm_context *ctx); + void config_ack(rsm_context *ctx, + const server_id &sid, uint64_t version); + void config_stable(rsm_context *ctx, + const server_id &sid, uint64_t version); + + // checkpoint management +public: + void checkpoint(rsm_context *ctx); + void checkpoint_stable(rsm_context *ctx, + const server_id &sid, + uint64_t config, + uint64_t number); + void checkpoints(rsm_context *ctx); + + // periodic +public: + void periodic(rsm_context *ctx); + + // debug +public: + void debug_dump(rsm_context *ctx); + + // backup/restore +public: + static coordinator *recreate(rsm_context *ctx, + const char *data, size_t data_sz); + int snapshot(rsm_context *ctx, + char **data, size_t *data_sz); + +private: + typedef e::compat::shared_ptr space_ptr; + typedef std::map space_map_t; + struct transfer_sorter; + + // utilities +private: + // servers + server *new_server(const server_id &sid); + server *get_server(const server_id &sid); + // replica sets + bool in_permutation(const server_id &sid); + void add_permutation(const server_id &sid); + void remove_permutation(const server_id &sid); + void rebalance_replica_sets(rsm_context *ctx); + // hyperspace + void initial_space_layout(rsm_context *ctx, + space *s); + region *get_region(const region_id &rid); + // intents + void setup_intents(rsm_context *ctx, + const std::vector &replica_sets, + space *s, bool skip_transfers); + // looks up region_intent* ri, removing any possibility of the user + // using an invalid pointer + void converge_intent(rsm_context *ctx, + region *reg); + // ri and m_intents may be changed after this call + void converge_intent(rsm_context *ctx, + region *reg, region_intent *ri); + region_intent *new_region_intent(const region_id &rid); + region_intent *get_region_intent(const region_id &rid); + void del_region_intent(const region_id &rid); + void remove_offline(const region_id &rid); + void remove_offline(const server_id &sid); + // transfers + transfer *new_transfer(region *reg, const server_id &si); + transfer *get_transfer(const region_id &rid); + transfer *get_transfer(const transfer_id &xid); + void del_transfer(const transfer_id &xid); + // configuration + void check_ack_condition(rsm_context *ctx); + void check_stable_condition(rsm_context *ctx); + void generate_next_configuration(rsm_context *ctx); + void generate_cached_configuration(rsm_context *ctx); + void prioritized_transfer_subset(std::vector *transfers); + void servers_in_configuration(std::vector *sids); + void regions_in_space(space_ptr s, std::vector *rids); + // checkpoints + void check_checkpoint_stable_condition(rsm_context *ctx, bool reissue); + void broadcast_checkpoint_information(rsm_context *ctx); + +private: + // meta state + uint64_t m_cluster; + uint64_t m_counter; + uint64_t m_version; + uint64_t m_flags; + // servers + std::vector m_servers; + // replica sets + std::vector m_permutation; + std::vector m_spares; + uint64_t m_desired_spares; + // spaces + space_map_t m_spaces; + // intents + std::vector m_intents; + std::vector m_deferred_init; + std::vector m_offline; + // transfers + std::vector m_transfers; + // barriers + uint64_t m_config_ack_through; + server_barrier m_config_ack_barrier; + uint64_t m_config_stable_through; + server_barrier m_config_stable_barrier; + // checkpoints + uint64_t m_checkpoint; + uint64_t m_checkpoint_stable_through; + uint64_t m_checkpoint_gc_through; + server_barrier m_checkpoint_stable_barrier; + // cached config + std::auto_ptr m_latest_config; + std::auto_ptr m_response; + +private: + coordinator(const coordinator &); + coordinator &operator = (const coordinator &); }; END_HYPERDEX_NAMESPACE diff --git a/coordinator/offline_server.h b/coordinator/offline_server.h index ded70552e..1ccc34317 100644 --- a/coordinator/offline_server.h +++ b/coordinator/offline_server.h @@ -35,52 +35,52 @@ BEGIN_HYPERDEX_NAMESPACE class offline_server { - public: - offline_server(); - offline_server(const region_id& id, const server_id& sid); - offline_server(const offline_server& other); +public: + offline_server(); + offline_server(const region_id &id, const server_id &sid); + offline_server(const offline_server &other); - public: - region_id id; - server_id sid; +public: + region_id id; + server_id sid; }; inline size_t -pack_size(const offline_server& os) +pack_size(const offline_server &os) { - return pack_size(os.id) + pack_size(os.sid); + return pack_size(os.id) + pack_size(os.sid); } inline e::packer -operator << (e::packer pa, const offline_server& os) +operator << (e::packer pa, const offline_server &os) { - return pa << os.id << os.sid; + return pa << os.id << os.sid; } inline e::unpacker -operator >> (e::unpacker up, offline_server& os) +operator >> (e::unpacker up, offline_server &os) { - return up >> os.id >> os.sid; + return up >> os.id >> os.sid; } inline offline_server :: offline_server() - : id() - , sid() + : id() + , sid() { } inline -offline_server :: offline_server(const region_id& _id, const server_id& _sid) - : id(_id) - , sid(_sid) +offline_server :: offline_server(const region_id &_id, const server_id &_sid) + : id(_id) + , sid(_sid) { } inline -offline_server :: offline_server(const offline_server& other) - : id(other.id) - , sid(other.sid) +offline_server :: offline_server(const offline_server &other) + : id(other.id) + , sid(other.sid) { } diff --git a/coordinator/region_intent.h b/coordinator/region_intent.h index 270dc3ba9..d1e871963 100644 --- a/coordinator/region_intent.h +++ b/coordinator/region_intent.h @@ -35,73 +35,72 @@ BEGIN_HYPERDEX_NAMESPACE class region_intent { - public: - region_intent(); - region_intent(const region_id& id); - region_intent(const region_intent&); - - public: - region_intent& operator = (const region_intent&); - - public: - region_id id; - std::vector replicas; - uint64_t checkpoint; +public: + region_intent(); + region_intent(const region_id &id); + region_intent(const region_intent &); + +public: + region_intent &operator = (const region_intent &); + +public: + region_id id; + std::vector replicas; + uint64_t checkpoint; }; inline size_t -pack_size(const region_intent& ri) +pack_size(const region_intent &ri) { - return pack_size(ri.id) + pack_size(ri.replicas) + sizeof(ri.checkpoint); + return pack_size(ri.id) + pack_size(ri.replicas) + sizeof(ri.checkpoint); } inline e::packer -operator << (e::packer pa, const region_intent& ri) +operator << (e::packer pa, const region_intent &ri) { - return pa << ri.id << ri.replicas << ri.checkpoint; + return pa << ri.id << ri.replicas << ri.checkpoint; } inline e::unpacker -operator >> (e::unpacker up, region_intent& ri) +operator >> (e::unpacker up, region_intent &ri) { - return up >> ri.id >> ri.replicas >> ri.checkpoint; + return up >> ri.id >> ri.replicas >> ri.checkpoint; } inline region_intent :: region_intent() - : id() - , replicas() - , checkpoint(0) + : id() + , replicas() + , checkpoint(0) { } inline -region_intent :: region_intent(const region_id& ri) - : id(ri) - , replicas() - , checkpoint(0) +region_intent :: region_intent(const region_id &ri) + : id(ri) + , replicas() + , checkpoint(0) { } inline -region_intent :: region_intent(const region_intent& other) - : id(other.id) - , replicas(other.replicas) - , checkpoint(other.checkpoint) +region_intent :: region_intent(const region_intent &other) + : id(other.id) + , replicas(other.replicas) + , checkpoint(other.checkpoint) { } -inline region_intent& -region_intent :: operator = (const region_intent& rhs) +inline region_intent & +region_intent :: operator = (const region_intent &rhs) { - if (this != &rhs) - { - id = rhs.id; - replicas = rhs.replicas; - checkpoint = rhs.checkpoint; - } - - return *this; + if (this != &rhs) + { + id = rhs.id; + replicas = rhs.replicas; + checkpoint = rhs.checkpoint; + } + return *this; } END_HYPERDEX_NAMESPACE diff --git a/coordinator/replica_sets.cc b/coordinator/replica_sets.cc index 58f125fee..9e721691c 100644 --- a/coordinator/replica_sets.cc +++ b/coordinator/replica_sets.cc @@ -40,145 +40,134 @@ namespace void _small_replica_sets(uint64_t, uint64_t, - const std::vector& permutation, - const std::vector& servers, - std::vector* replica_storage, - std::vector* replica_sets) + const std::vector &permutation, + const std::vector &servers, + std::vector *replica_storage, + std::vector *replica_sets) { - for (size_t i = 0; i < permutation.size(); ++i) - { - size_t repls = 0; - size_t start = replica_storage->size(); - - for (size_t j = 0; j < permutation.size(); ++j) - { - size_t idx = (i + j) % permutation.size(); - - if (std::binary_search(servers.begin(), - servers.end(), - permutation[idx])) - { - replica_storage->push_back(permutation[idx]); - ++repls; - } - } - - replica_sets->push_back(replica_set(start, repls, replica_storage)); - } + for (size_t i = 0; i < permutation.size(); ++i) + { + size_t repls = 0; + size_t start = replica_storage->size(); + for (size_t j = 0; j < permutation.size(); ++j) + { + size_t idx = (i + j) % permutation.size(); + if (std::binary_search(servers.begin(), + servers.end(), + permutation[idx])) + { + replica_storage->push_back(permutation[idx]); + ++repls; + } + } + replica_sets->push_back(replica_set(start, repls, replica_storage)); + } } void _permutation_replica_sets(uint64_t R, uint64_t P, - const std::vector& permutation, - const std::vector& servers, - std::vector* replica_storage, - std::vector* replica_sets) + const std::vector &permutation, + const std::vector &servers, + std::vector *replica_storage, + std::vector *replica_sets) { - for (size_t n = 0; n < permutation.size(); ++n) - { - for (size_t p = 1; p <= P; ++p) - { - if (n + p * (R - 1) >= permutation.size()) - { - break; - } - - size_t repls = 0; - size_t start = replica_storage->size(); - - for (size_t r = 0; r < R; ++r) - { - size_t idx = n + p * r; - - if (std::binary_search(servers.begin(), - servers.end(), - permutation[idx])) - { - replica_storage->push_back(permutation[idx]); - ++repls; - } - } - - replica_sets->push_back(replica_set(start, repls, replica_storage)); - } - } + for (size_t n = 0; n < permutation.size(); ++n) + { + for (size_t p = 1; p <= P; ++p) + { + if (n + p * (R - 1) >= permutation.size()) + { + break; + } + size_t repls = 0; + size_t start = replica_storage->size(); + for (size_t r = 0; r < R; ++r) + { + size_t idx = n + p * r; + if (std::binary_search(servers.begin(), + servers.end(), + permutation[idx])) + { + replica_storage->push_back(permutation[idx]); + ++repls; + } + } + replica_sets->push_back(replica_set(start, repls, replica_storage)); + } + } } } // namespace replica_set :: replica_set() - : m_start(0) - , m_size(0) - , m_storage(NULL) + : m_start(0) + , m_size(0) + , m_storage(NULL) { } replica_set :: replica_set(size_t start, size_t sz, - std::vector* storage) - : m_start(start) - , m_size(sz) - , m_storage(storage) + std::vector *storage) + : m_start(start) + , m_size(sz) + , m_storage(storage) { } -replica_set :: replica_set(const replica_set& other) - : m_start(other.m_start) - , m_size(other.m_size) - , m_storage(other.m_storage) +replica_set :: replica_set(const replica_set &other) + : m_start(other.m_start) + , m_size(other.m_size) + , m_storage(other.m_storage) { } size_t replica_set :: size() const { - return m_size; + return m_size; } server_id replica_set :: operator [] (size_t idx) const { - assert(idx < m_size); - return (*m_storage)[m_start + idx]; + assert(idx < m_size); + return (*m_storage)[m_start + idx]; } -replica_set& -replica_set :: operator = (const replica_set& rhs) +replica_set & +replica_set :: operator = (const replica_set &rhs) { - m_start = rhs.m_start; - m_size = rhs.m_size; - m_storage = rhs.m_storage; - return *this; + m_start = rhs.m_start; + m_size = rhs.m_size; + m_storage = rhs.m_storage; + return *this; } void hyperdex :: compute_replica_sets(uint64_t R, uint64_t P, - const std::vector& permutation, - const std::vector& _servers, - std::vector* replica_storage, - std::vector* replica_sets) + const std::vector &permutation, + const std::vector &_servers, + std::vector *replica_storage, + std::vector *replica_sets) { - assert(R > 0); - replica_storage->clear(); - replica_sets->clear(); - - std::vector servers; - - for (size_t i = 0; i < _servers.size(); ++i) - { - if (_servers[i].state == server::AVAILABLE) - { - servers.push_back(_servers[i].id); - } - } - - std::sort(servers.begin(), servers.end()); - - if (permutation.size() <= R) - { - _small_replica_sets(R, P, permutation, servers, replica_storage, replica_sets); - } - else - { - _permutation_replica_sets(R, P, permutation, servers, replica_storage, replica_sets); - } + assert(R > 0); + replica_storage->clear(); + replica_sets->clear(); + std::vector servers; + for (size_t i = 0; i < _servers.size(); ++i) + { + if (_servers[i].state == server::AVAILABLE) + { + servers.push_back(_servers[i].id); + } + } + std::sort(servers.begin(), servers.end()); + if (permutation.size() <= R) + { + _small_replica_sets(R, P, permutation, servers, replica_storage, replica_sets); + } + else + { + _permutation_replica_sets(R, P, permutation, servers, replica_storage, replica_sets); + } } diff --git a/coordinator/replica_sets.h b/coordinator/replica_sets.h index c7e366d9d..0c6ae0ddd 100644 --- a/coordinator/replica_sets.h +++ b/coordinator/replica_sets.h @@ -37,31 +37,31 @@ BEGIN_HYPERDEX_NAMESPACE class replica_set { - public: - replica_set(); - replica_set(size_t start, size_t size, - std::vector* storage); - replica_set(const replica_set&); +public: + replica_set(); + replica_set(size_t start, size_t size, + std::vector *storage); + replica_set(const replica_set &); - public: - size_t size() const; +public: + size_t size() const; - public: - server_id operator [] (size_t idx) const; - replica_set& operator = (const replica_set&); +public: + server_id operator [] (size_t idx) const; + replica_set &operator = (const replica_set &); - private: - size_t m_start; - size_t m_size; - std::vector* m_storage; +private: + size_t m_start; + size_t m_size; + std::vector *m_storage; }; void compute_replica_sets(uint64_t R, uint64_t P, - const std::vector& permutation, - const std::vector& servers, - std::vector* replica_storage, - std::vector* replica_sets); + const std::vector &permutation, + const std::vector &servers, + std::vector *replica_storage, + std::vector *replica_sets); END_HYPERDEX_NAMESPACE diff --git a/coordinator/server_barrier.cc b/coordinator/server_barrier.cc index 705998846..4847dc997 100644 --- a/coordinator/server_barrier.cc +++ b/coordinator/server_barrier.cc @@ -31,9 +31,9 @@ using hyperdex::server_barrier; server_barrier :: server_barrier() - : m_versions() + : m_versions() { - m_versions.push_back(std::make_pair(uint64_t(0), std::vector())); + m_versions.push_back(std::make_pair(uint64_t(0), std::vector())); } server_barrier :: ~server_barrier() throw () @@ -43,122 +43,111 @@ server_barrier :: ~server_barrier() throw () uint64_t server_barrier :: min_version() const { - return m_versions.front().first; + return m_versions.front().first; } void server_barrier :: new_version(uint64_t version, - const std::vector& servers) + const std::vector &servers) { - assert(!m_versions.empty()); - assert(version > 0); - assert(m_versions.back().first < version); - m_versions.push_back(std::make_pair(version, servers)); - maybe_clear_prefix(); + assert(!m_versions.empty()); + assert(version > 0); + assert(m_versions.back().first < version); + m_versions.push_back(std::make_pair(version, servers)); + maybe_clear_prefix(); } void -server_barrier :: pass(uint64_t version, const server_id& sid) +server_barrier :: pass(uint64_t version, const server_id &sid) { - for (version_list_t::iterator it = m_versions.begin(); - it != m_versions.end(); ++it) - { - if (it->first < version) - { - continue; - } - else if (it->first > version) - { - break; - } - - assert(it->first == version); - - for (size_t i = 0; i < it->second.size(); ) - { - if (it->second[i] == sid) - { - it->second[i] = it->second.back(); - it->second.pop_back(); - } - else - { - ++i; - } - } - - maybe_clear_prefix(); - return; - } + for (version_list_t::iterator it = m_versions.begin(); + it != m_versions.end(); ++it) + { + if (it->first < version) + { + continue; + } + else if (it->first > version) + { + break; + } + assert(it->first == version); + for (size_t i = 0; i < it->second.size(); ) + { + if (it->second[i] == sid) + { + it->second[i] = it->second.back(); + it->second.pop_back(); + } + else + { + ++i; + } + } + maybe_clear_prefix(); + return; + } } void server_barrier :: maybe_clear_prefix() { - version_list_t::iterator last_empty = m_versions.end(); - - for (version_list_t::iterator it = m_versions.begin(); - it != m_versions.end(); ++it) - { - if (it->second.empty()) - { - last_empty = it; - } - } - - if (last_empty != m_versions.end()) - { - while (m_versions.begin() != last_empty) - { - m_versions.pop_front(); - } - } + version_list_t::iterator last_empty = m_versions.end(); + for (version_list_t::iterator it = m_versions.begin(); + it != m_versions.end(); ++it) + { + if (it->second.empty()) + { + last_empty = it; + } + } + if (last_empty != m_versions.end()) + { + while (m_versions.begin() != last_empty) + { + m_versions.pop_front(); + } + } } size_t -hyperdex :: pack_size(const server_barrier& ri) +hyperdex :: pack_size(const server_barrier &ri) { - typedef server_barrier::version_list_t version_list_t; - size_t sz = sizeof(uint32_t); - - for (version_list_t::const_iterator it = ri.m_versions.begin(); - it != ri.m_versions.end(); ++it) - { - sz += sizeof(uint64_t) + pack_size(it->second); - } - - return sz; + typedef server_barrier::version_list_t version_list_t; + size_t sz = sizeof(uint32_t); + for (version_list_t::const_iterator it = ri.m_versions.begin(); + it != ri.m_versions.end(); ++it) + { + sz += sizeof(uint64_t) + pack_size(it->second); + } + return sz; } e::packer -hyperdex :: operator << (e::packer pa, const server_barrier& ri) +hyperdex :: operator << (e::packer pa, const server_barrier &ri) { - typedef server_barrier::version_list_t version_list_t; - uint32_t x = ri.m_versions.size(); - pa = pa << x; - - for (version_list_t::const_iterator it = ri.m_versions.begin(); - it != ri.m_versions.end(); ++it) - { - pa = pa << it->first << it->second; - } - - return pa; + typedef server_barrier::version_list_t version_list_t; + uint32_t x = ri.m_versions.size(); + pa = pa << x; + for (version_list_t::const_iterator it = ri.m_versions.begin(); + it != ri.m_versions.end(); ++it) + { + pa = pa << it->first << it->second; + } + return pa; } e::unpacker -hyperdex :: operator >> (e::unpacker up, server_barrier& ri) +hyperdex :: operator >> (e::unpacker up, server_barrier &ri) { - typedef server_barrier::version_t version_t; - uint32_t x = 0; - up = up >> x; - - for (size_t i = 0; i < x && !up.error(); ++i) - { - ri.m_versions.push_back(version_t()); - version_t& v(ri.m_versions.back()); - up = up >> v.first >> v.second; - } - - return up; + typedef server_barrier::version_t version_t; + uint32_t x = 0; + up = up >> x; + for (size_t i = 0; i < x && !up.error(); ++i) + { + ri.m_versions.push_back(version_t()); + version_t &v(ri.m_versions.back()); + up = up >> v.first >> v.second; + } + return up; } diff --git a/coordinator/server_barrier.h b/coordinator/server_barrier.h index 54bbb94b8..551ec8e51 100644 --- a/coordinator/server_barrier.h +++ b/coordinator/server_barrier.h @@ -42,34 +42,34 @@ BEGIN_HYPERDEX_NAMESPACE class server_barrier { - public: - server_barrier(); - ~server_barrier() throw (); +public: + server_barrier(); + ~server_barrier() throw (); - public: - uint64_t min_version() const; - void new_version(uint64_t version, - const std::vector& servers); - void pass(uint64_t version, const server_id& sid); +public: + uint64_t min_version() const; + void new_version(uint64_t version, + const std::vector &servers); + void pass(uint64_t version, const server_id &sid); - private: - void maybe_clear_prefix(); +private: + void maybe_clear_prefix(); - private: - friend size_t pack_size(const server_barrier& ri); - friend e::packer operator << (e::packer pa, const server_barrier& ri); - friend e::unpacker operator >> (e::unpacker up, server_barrier& ri); - typedef std::pair > version_t; - typedef std::list version_list_t; - version_list_t m_versions; +private: + friend size_t pack_size(const server_barrier &ri); + friend e::packer operator << (e::packer pa, const server_barrier &ri); + friend e::unpacker operator >> (e::unpacker up, server_barrier &ri); + typedef std::pair > version_t; + typedef std::list version_list_t; + version_list_t m_versions; }; size_t -pack_size(const server_barrier& ri); +pack_size(const server_barrier &ri); e::packer -operator << (e::packer pa, const server_barrier& ri); +operator << (e::packer pa, const server_barrier &ri); e::unpacker -operator >> (e::unpacker up, server_barrier& ri); +operator >> (e::unpacker up, server_barrier &ri); END_HYPERDEX_NAMESPACE diff --git a/coordinator/symtable.c b/coordinator/symtable.c index ae124b71c..8f0066ae0 100644 --- a/coordinator/symtable.c +++ b/coordinator/symtable.c @@ -36,36 +36,38 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-pedantic" -struct state_machine HYPERDEX_API rsm = { - hyperdex_coordinator_create, - hyperdex_coordinator_recreate, - hyperdex_coordinator_snapshot, - {{"config_get", hyperdex_coordinator_config_get}, - {"config_ack", hyperdex_coordinator_config_ack}, - {"config_stable", hyperdex_coordinator_config_stable}, - {"server_register", hyperdex_coordinator_server_register}, - {"server_online", hyperdex_coordinator_server_online}, - {"server_offline", hyperdex_coordinator_server_offline}, - {"server_shutdown", hyperdex_coordinator_server_shutdown}, - {"server_kill", hyperdex_coordinator_server_kill}, - {"server_forget", hyperdex_coordinator_server_forget}, - {"server_suspect", hyperdex_coordinator_server_suspect}, - {"report_disconnect", hyperdex_coordinator_report_disconnect}, - {"space_add", hyperdex_coordinator_space_add}, - {"space_rm", hyperdex_coordinator_space_rm}, - {"space_mv", hyperdex_coordinator_space_mv}, - {"index_add", hyperdex_coordinator_index_add}, - {"index_rm", hyperdex_coordinator_index_rm}, - {"transfer_go_live", hyperdex_coordinator_transfer_go_live}, - {"transfer_complete", hyperdex_coordinator_transfer_complete}, - {"checkpoint_stable", hyperdex_coordinator_checkpoint_stable}, - {"periodic", hyperdex_coordinator_periodic}, - {"read_only", hyperdex_coordinator_read_only}, - {"fault_tolerance", hyperdex_coordinator_fault_tolerance}, - {"checkpoints", hyperdex_coordinator_checkpoints}, - {"debug_dump", hyperdex_coordinator_debug_dump}, - {"init", hyperdex_coordinator_init}, - {NULL, NULL}} +struct state_machine HYPERDEX_API rsm = +{ + hyperdex_coordinator_create, + hyperdex_coordinator_recreate, + hyperdex_coordinator_snapshot, + { {"config_get", hyperdex_coordinator_config_get}, + {"config_ack", hyperdex_coordinator_config_ack}, + {"config_stable", hyperdex_coordinator_config_stable}, + {"server_register", hyperdex_coordinator_server_register}, + {"server_online", hyperdex_coordinator_server_online}, + {"server_offline", hyperdex_coordinator_server_offline}, + {"server_shutdown", hyperdex_coordinator_server_shutdown}, + {"server_kill", hyperdex_coordinator_server_kill}, + {"server_forget", hyperdex_coordinator_server_forget}, + {"server_suspect", hyperdex_coordinator_server_suspect}, + {"report_disconnect", hyperdex_coordinator_report_disconnect}, + {"space_add", hyperdex_coordinator_space_add}, + {"space_rm", hyperdex_coordinator_space_rm}, + {"space_mv", hyperdex_coordinator_space_mv}, + {"index_add", hyperdex_coordinator_index_add}, + {"index_rm", hyperdex_coordinator_index_rm}, + {"transfer_go_live", hyperdex_coordinator_transfer_go_live}, + {"transfer_complete", hyperdex_coordinator_transfer_complete}, + {"checkpoint_stable", hyperdex_coordinator_checkpoint_stable}, + {"periodic", hyperdex_coordinator_periodic}, + {"read_only", hyperdex_coordinator_read_only}, + {"fault_tolerance", hyperdex_coordinator_fault_tolerance}, + {"checkpoints", hyperdex_coordinator_checkpoints}, + {"debug_dump", hyperdex_coordinator_debug_dump}, + {"init", hyperdex_coordinator_init}, + {NULL, NULL} + } }; #pragma GCC diagnostic pop diff --git a/coordinator/transitions.cc b/coordinator/transitions.cc index 3aa22de6e..42123f8d1 100644 --- a/coordinator/transitions.cc +++ b/coordinator/transitions.cc @@ -42,382 +42,370 @@ using namespace hyperdex; #define PROTECT_UNINITIALIZED \ - coordinator* c = static_cast(obj); \ - do \ - { \ - if (c->cluster() == 0) \ - { \ - rsm_log(ctx, "cluster not initialized\n"); \ - return generate_response(ctx, hyperdex::COORD_UNINITIALIZED); \ - } \ - } \ - while (0) + coordinator* c = static_cast(obj); \ + do \ + { \ + if (c->cluster() == 0) \ + { \ + rsm_log(ctx, "cluster not initialized\n"); \ + return generate_response(ctx, hyperdex::COORD_UNINITIALIZED); \ + } \ + } \ + while (0) #define CHECK_UNPACK(MSGTYPE) \ - do \ - { \ - if (up.error() || up.remain()) \ - { \ - rsm_log(ctx, "received malformed \"" #MSGTYPE "\" message\n"); \ - return generate_response(ctx, hyperdex::COORD_MALFORMED); \ - } \ - } while (0) + do \ + { \ + if (up.error() || up.remain()) \ + { \ + rsm_log(ctx, "received malformed \"" #MSGTYPE "\" message\n"); \ + return generate_response(ctx, hyperdex::COORD_MALFORMED); \ + } \ + } while (0) extern "C" { -void* -hyperdex_coordinator_create(struct rsm_context* ctx) -{ - rsm_cond_create(ctx, "config"); - rsm_cond_create(ctx, "ack"); - rsm_cond_create(ctx, "stable"); - rsm_cond_create(ctx, "checkpoint"); - return new (std::nothrow) coordinator(); -} - -void* -hyperdex_coordinator_recreate(struct rsm_context* ctx, - const char* data, size_t data_sz) -{ - return coordinator::recreate(ctx, data, data_sz); -} - -int -hyperdex_coordinator_snapshot(struct rsm_context* ctx, - void* obj, char** data, size_t* data_sz) -{ - coordinator* c = static_cast(obj); - return c->snapshot(ctx, data, data_sz); -} - -void -hyperdex_coordinator_init(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - coordinator* c = static_cast(obj); - - std::string id(data, data_sz); - uint64_t cluster = strtoull(id.c_str(), NULL, 0); - c->init(ctx, cluster); -} - -void -hyperdex_coordinator_read_only(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - uint8_t set; - e::unpacker up(data, data_sz); - up = up >> set; - CHECK_UNPACK(read_only); - c->read_only(ctx, set != 0); -} - -void -hyperdex_coordinator_fault_tolerance(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - uint64_t ft; - const char* ft_ptr = data + data_sz - sizeof(uint64_t); - e::unpacker up(ft_ptr, sizeof(uint64_t)); - up = up >> ft; - CHECK_UNPACK(fault_tolerance); - c->fault_tolerance(ctx, data, ft); -} - -void -hyperdex_coordinator_config_get(struct rsm_context* ctx, - void* obj, const char*, size_t) -{ - PROTECT_UNINITIALIZED; - c->config_get(ctx); -} - -void -hyperdex_coordinator_config_ack(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - server_id sid; - uint64_t version; - e::unpacker up(data, data_sz); - up = up >> sid >> version; - CHECK_UNPACK(config_ack); - c->config_ack(ctx, sid, version); -} - -void -hyperdex_coordinator_config_stable(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - server_id sid; - uint64_t version; - e::unpacker up(data, data_sz); - up = up >> sid >> version; - CHECK_UNPACK(config_stable); - c->config_stable(ctx, sid, version); -} - -void -hyperdex_coordinator_server_register(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - server_id sid; - po6::net::location bind_to; - e::unpacker up(data, data_sz); - up = up >> sid >> bind_to; - CHECK_UNPACK(server_register); - c->server_register(ctx, sid, bind_to); -} - -void -hyperdex_coordinator_server_online(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - server_id sid; - po6::net::location bind_to; - e::unpacker up(data, data_sz); - up = up >> sid; - - if (!up.error() && !up.remain()) - { - c->server_online(ctx, sid, NULL); - } - else - { - up = up >> bind_to; - CHECK_UNPACK(server_online); - c->server_online(ctx, sid, &bind_to); - } -} - -void -hyperdex_coordinator_server_offline(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - server_id sid; - e::unpacker up(data, data_sz); - up = up >> sid; - CHECK_UNPACK(server_offline); - c->server_offline(ctx, sid); -} - -void -hyperdex_coordinator_server_shutdown(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - server_id sid; - e::unpacker up(data, data_sz); - up = up >> sid; - CHECK_UNPACK(server_shutdown); - c->server_shutdown(ctx, sid); -} - -void -hyperdex_coordinator_server_kill(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - server_id sid; - e::unpacker up(data, data_sz); - up = up >> sid; - CHECK_UNPACK(server_kill); - c->server_kill(ctx, sid); -} - -void -hyperdex_coordinator_server_forget(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - server_id sid; - e::unpacker up(data, data_sz); - up = up >> sid; - CHECK_UNPACK(server_forget); - c->server_forget(ctx, sid); -} - -void -hyperdex_coordinator_server_suspect(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - server_id sid; - e::unpacker up(data, data_sz); - up = up >> sid; - CHECK_UNPACK(server_suspect); - c->server_suspect(ctx, sid); -} - -void -hyperdex_coordinator_report_disconnect(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - server_id sid; - uint64_t version; - e::unpacker up(data, data_sz); - up = up >> sid >> version; - CHECK_UNPACK(report_disconnect); - c->report_disconnect(ctx, sid, version); -} - -void -hyperdex_coordinator_space_add(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - space s; - e::unpacker up(data, data_sz); - up = up >> s; - CHECK_UNPACK(space_add); - c->space_add(ctx, s); -} - -void -hyperdex_coordinator_space_rm(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - - if (data_sz == 0 || data[data_sz - 1] != '\0') - { - rsm_log(ctx, "received malformed \"rm_space\" message\n"); - return generate_response(ctx, COORD_MALFORMED); - } - - c->space_rm(ctx, data); -} - -void -hyperdex_coordinator_space_mv(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - - if (data_sz < 2 || data[data_sz - 1] != '\0') - { - rsm_log(ctx, "received malformed \"mv_space\" message\n"); - return generate_response(ctx, COORD_MALFORMED); - } - - const char* src = data; - const char* dst = data + strlen(data) + 1; - - if (dst >= data + data_sz) - { - rsm_log(ctx, "received malformed \"mv_space\" message\n"); - return generate_response(ctx, COORD_MALFORMED); - } - - c->space_mv(ctx, src, dst); -} - -void -hyperdex_coordinator_index_add(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - const char* space = data; - size_t space_sz = strnlen(data, data_sz); - - if (data_sz == 0 || data[data_sz - 1] != '\0' || space_sz + 2 >= data_sz) - { - rsm_log(ctx, "received malformed \"add_index\" message\n"); - return generate_response(ctx, COORD_MALFORMED); - } - - const char* attr = data + space_sz + 1; - size_t attr_sz = strnlen(attr, data_sz - space_sz - 1); - - if (space_sz + attr_sz + 2 != data_sz) - { - rsm_log(ctx, "received malformed \"add_index\" message\n"); - return generate_response(ctx, COORD_MALFORMED); - } - - c->index_add(ctx, space, attr); -} - -void -hyperdex_coordinator_index_rm(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - index_id ii; - e::unpacker up(data, data_sz); - up = up >> ii; - CHECK_UNPACK(index_rm); - c->index_rm(ctx, ii); -} - -void -hyperdex_coordinator_transfer_go_live(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - transfer_id xid; - e::unpacker up(data, data_sz); - up = up >> xid; - CHECK_UNPACK(transfer_go_live); - c->transfer_go_live(ctx, xid); -} - -void -hyperdex_coordinator_transfer_complete(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - transfer_id xid; - e::unpacker up(data, data_sz); - up = up >> xid; - CHECK_UNPACK(transfer_complete); - c->transfer_complete(ctx, xid); -} - -void -hyperdex_coordinator_checkpoint_stable(struct rsm_context* ctx, - void* obj, const char* data, size_t data_sz) -{ - PROTECT_UNINITIALIZED; - server_id sid; - uint64_t config; - uint64_t checkpoint; - e::unpacker up(data, data_sz); - up = up >> sid >> config >> checkpoint; - CHECK_UNPACK(checkpoint_stable); - c->checkpoint_stable(ctx, sid, config, checkpoint); -} - -void -hyperdex_coordinator_checkpoints(struct rsm_context* ctx, - void* obj, const char*, size_t) -{ - PROTECT_UNINITIALIZED; - c->checkpoints(ctx); -} - -void -hyperdex_coordinator_periodic(struct rsm_context* ctx, - void* obj, const char*, size_t) -{ - PROTECT_UNINITIALIZED; - c->periodic(ctx); -} - -void -hyperdex_coordinator_debug_dump(struct rsm_context* ctx, - void* obj, const char*, size_t) -{ - PROTECT_UNINITIALIZED; - c->debug_dump(ctx); -} + void * + hyperdex_coordinator_create(struct rsm_context *ctx) + { + rsm_cond_create(ctx, "config"); + rsm_cond_create(ctx, "ack"); + rsm_cond_create(ctx, "stable"); + rsm_cond_create(ctx, "checkpoint"); + return new (std::nothrow) coordinator(); + } + + void * + hyperdex_coordinator_recreate(struct rsm_context *ctx, + const char *data, size_t data_sz) + { + return coordinator::recreate(ctx, data, data_sz); + } + + int + hyperdex_coordinator_snapshot(struct rsm_context *ctx, + void *obj, char **data, size_t *data_sz) + { + coordinator *c = static_cast(obj); + return c->snapshot(ctx, data, data_sz); + } + + void + hyperdex_coordinator_init(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + coordinator *c = static_cast(obj); + std::string id(data, data_sz); + uint64_t cluster = strtoull(id.c_str(), NULL, 0); + c->init(ctx, cluster); + } + + void + hyperdex_coordinator_read_only(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + uint8_t set; + e::unpacker up(data, data_sz); + up = up >> set; + CHECK_UNPACK(read_only); + c->read_only(ctx, set != 0); + } + + void + hyperdex_coordinator_fault_tolerance(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + uint64_t ft; + const char *ft_ptr = data + data_sz - sizeof(uint64_t); + e::unpacker up(ft_ptr, sizeof(uint64_t)); + up = up >> ft; + CHECK_UNPACK(fault_tolerance); + c->fault_tolerance(ctx, data, ft); + } + + void + hyperdex_coordinator_config_get(struct rsm_context *ctx, + void *obj, const char *, size_t) + { + PROTECT_UNINITIALIZED; + c->config_get(ctx); + } + + void + hyperdex_coordinator_config_ack(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + server_id sid; + uint64_t version; + e::unpacker up(data, data_sz); + up = up >> sid >> version; + CHECK_UNPACK(config_ack); + c->config_ack(ctx, sid, version); + } + + void + hyperdex_coordinator_config_stable(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + server_id sid; + uint64_t version; + e::unpacker up(data, data_sz); + up = up >> sid >> version; + CHECK_UNPACK(config_stable); + c->config_stable(ctx, sid, version); + } + + void + hyperdex_coordinator_server_register(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + server_id sid; + po6::net::location bind_to; + e::unpacker up(data, data_sz); + up = up >> sid >> bind_to; + CHECK_UNPACK(server_register); + c->server_register(ctx, sid, bind_to); + } + + void + hyperdex_coordinator_server_online(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + server_id sid; + po6::net::location bind_to; + e::unpacker up(data, data_sz); + up = up >> sid; + if (!up.error() && !up.remain()) + { + c->server_online(ctx, sid, NULL); + } + else + { + up = up >> bind_to; + CHECK_UNPACK(server_online); + c->server_online(ctx, sid, &bind_to); + } + } + + void + hyperdex_coordinator_server_offline(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + server_id sid; + e::unpacker up(data, data_sz); + up = up >> sid; + CHECK_UNPACK(server_offline); + c->server_offline(ctx, sid); + } + + void + hyperdex_coordinator_server_shutdown(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + server_id sid; + e::unpacker up(data, data_sz); + up = up >> sid; + CHECK_UNPACK(server_shutdown); + c->server_shutdown(ctx, sid); + } + + void + hyperdex_coordinator_server_kill(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + server_id sid; + e::unpacker up(data, data_sz); + up = up >> sid; + CHECK_UNPACK(server_kill); + c->server_kill(ctx, sid); + } + + void + hyperdex_coordinator_server_forget(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + server_id sid; + e::unpacker up(data, data_sz); + up = up >> sid; + CHECK_UNPACK(server_forget); + c->server_forget(ctx, sid); + } + + void + hyperdex_coordinator_server_suspect(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + server_id sid; + e::unpacker up(data, data_sz); + up = up >> sid; + CHECK_UNPACK(server_suspect); + c->server_suspect(ctx, sid); + } + + void + hyperdex_coordinator_report_disconnect(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + server_id sid; + uint64_t version; + e::unpacker up(data, data_sz); + up = up >> sid >> version; + CHECK_UNPACK(report_disconnect); + c->report_disconnect(ctx, sid, version); + } + + void + hyperdex_coordinator_space_add(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + space s; + e::unpacker up(data, data_sz); + up = up >> s; + CHECK_UNPACK(space_add); + c->space_add(ctx, s); + } + + void + hyperdex_coordinator_space_rm(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + if (data_sz == 0 || data[data_sz - 1] != '\0') + { + rsm_log(ctx, "received malformed \"rm_space\" message\n"); + return generate_response(ctx, COORD_MALFORMED); + } + c->space_rm(ctx, data); + } + + void + hyperdex_coordinator_space_mv(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + if (data_sz < 2 || data[data_sz - 1] != '\0') + { + rsm_log(ctx, "received malformed \"mv_space\" message\n"); + return generate_response(ctx, COORD_MALFORMED); + } + const char *src = data; + const char *dst = data + strlen(data) + 1; + if (dst >= data + data_sz) + { + rsm_log(ctx, "received malformed \"mv_space\" message\n"); + return generate_response(ctx, COORD_MALFORMED); + } + c->space_mv(ctx, src, dst); + } + + void + hyperdex_coordinator_index_add(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + const char *space = data; + size_t space_sz = strnlen(data, data_sz); + if (data_sz == 0 || data[data_sz - 1] != '\0' || space_sz + 2 >= data_sz) + { + rsm_log(ctx, "received malformed \"add_index\" message\n"); + return generate_response(ctx, COORD_MALFORMED); + } + const char *attr = data + space_sz + 1; + size_t attr_sz = strnlen(attr, data_sz - space_sz - 1); + if (space_sz + attr_sz + 2 != data_sz) + { + rsm_log(ctx, "received malformed \"add_index\" message\n"); + return generate_response(ctx, COORD_MALFORMED); + } + c->index_add(ctx, space, attr); + } + + void + hyperdex_coordinator_index_rm(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + index_id ii; + e::unpacker up(data, data_sz); + up = up >> ii; + CHECK_UNPACK(index_rm); + c->index_rm(ctx, ii); + } + + void + hyperdex_coordinator_transfer_go_live(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + transfer_id xid; + e::unpacker up(data, data_sz); + up = up >> xid; + CHECK_UNPACK(transfer_go_live); + c->transfer_go_live(ctx, xid); + } + + void + hyperdex_coordinator_transfer_complete(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + transfer_id xid; + e::unpacker up(data, data_sz); + up = up >> xid; + CHECK_UNPACK(transfer_complete); + c->transfer_complete(ctx, xid); + } + + void + hyperdex_coordinator_checkpoint_stable(struct rsm_context *ctx, + void *obj, const char *data, size_t data_sz) + { + PROTECT_UNINITIALIZED; + server_id sid; + uint64_t config; + uint64_t checkpoint; + e::unpacker up(data, data_sz); + up = up >> sid >> config >> checkpoint; + CHECK_UNPACK(checkpoint_stable); + c->checkpoint_stable(ctx, sid, config, checkpoint); + } + + void + hyperdex_coordinator_checkpoints(struct rsm_context *ctx, + void *obj, const char *, size_t) + { + PROTECT_UNINITIALIZED; + c->checkpoints(ctx); + } + + void + hyperdex_coordinator_periodic(struct rsm_context *ctx, + void *obj, const char *, size_t) + { + PROTECT_UNINITIALIZED; + c->periodic(ctx); + } + + void + hyperdex_coordinator_debug_dump(struct rsm_context *ctx, + void *obj, const char *, size_t) + { + PROTECT_UNINITIALIZED; + c->debug_dump(ctx); + } } // extern "C" diff --git a/coordinator/transitions.h b/coordinator/transitions.h index 08199fc34..f9b4b1dcc 100644 --- a/coordinator/transitions.h +++ b/coordinator/transitions.h @@ -36,20 +36,20 @@ extern "C" /* Replicant */ #include -void* -hyperdex_coordinator_create(struct rsm_context* ctx); +void * +hyperdex_coordinator_create(struct rsm_context *ctx); -void* -hyperdex_coordinator_recreate(struct rsm_context* ctx, - const char* data, size_t data_sz); +void * +hyperdex_coordinator_recreate(struct rsm_context *ctx, + const char *data, size_t data_sz); int -hyperdex_coordinator_snapshot(struct rsm_context* ctx, - void* obj, char** data, size_t* sz); +hyperdex_coordinator_snapshot(struct rsm_context *ctx, + void *obj, char **data, size_t *sz); #define TRANSITION(X) void \ - hyperdex_coordinator_ ## X(struct rsm_context* ctx, \ - void* obj, const char* data, size_t data_sz) + hyperdex_coordinator_ ## X(struct rsm_context* ctx, \ + void* obj, const char* data, size_t data_sz) TRANSITION(init); diff --git a/coordinator/util.h b/coordinator/util.h index 72ccda061..d874dbda5 100644 --- a/coordinator/util.h +++ b/coordinator/util.h @@ -35,40 +35,38 @@ BEGIN_HYPERDEX_NAMESPACE static inline void -generate_response(rsm_context* ctx, coordinator_returncode x) +generate_response(rsm_context *ctx, coordinator_returncode x) { - const char* ptr = NULL; - - switch (x) - { - case COORD_SUCCESS: - ptr = "\x22\x80"; - break; - case COORD_MALFORMED: - ptr = "\x22\x81"; - break; - case COORD_DUPLICATE: - ptr = "\x22\x82"; - break; - case COORD_NOT_FOUND: - ptr = "\x22\x83"; - break; - case COORD_UNINITIALIZED: - ptr = "\x22\x85"; - break; - case COORD_NO_CAN_DO: - ptr = "\x22\x87"; - break; - default: - ptr = "\xff\xff"; - break; - } - - rsm_set_output(ctx, ptr, 2); + const char *ptr = NULL; + switch (x) + { + case COORD_SUCCESS: + ptr = "\x22\x80"; + break; + case COORD_MALFORMED: + ptr = "\x22\x81"; + break; + case COORD_DUPLICATE: + ptr = "\x22\x82"; + break; + case COORD_NOT_FOUND: + ptr = "\x22\x83"; + break; + case COORD_UNINITIALIZED: + ptr = "\x22\x85"; + break; + case COORD_NO_CAN_DO: + ptr = "\x22\x87"; + break; + default: + ptr = "\xff\xff"; + break; + } + rsm_set_output(ctx, ptr, 2); } #define INVARIANT_BROKEN(X) \ - rsm_log(ctx, "invariant broken at " __FILE__ ":%d: %s\n", __LINE__, X "\n") + rsm_log(ctx, "invariant broken at " __FILE__ ":%d: %s\n", __LINE__, X "\n") END_HYPERDEX_NAMESPACE diff --git a/daemon/auth.cc b/daemon/auth.cc index 304f56a85..9739de709 100644 --- a/daemon/auth.cc +++ b/daemon/auth.cc @@ -37,185 +37,164 @@ BEGIN_HYPERDEX_NAMESPACE struct general_caveat { - general_caveat() : check(NULL), ptr(NULL) {} - general_caveat(int (*c)(void* f, const unsigned char* pred, size_t pred_sz), void* p) : check(c), ptr(p) {} - int (*check)(void* f, const unsigned char* pred, size_t pred_sz); - void* ptr; + general_caveat() : check(NULL), ptr(NULL) {} + general_caveat(int (*c)(void *f, const unsigned char *pred, size_t pred_sz), void *p) : check(c), ptr(p) {} + int (*check)(void *f, const unsigned char *pred, size_t pred_sz); + void *ptr; }; END_HYPERDEX_NAMESPACE void -hyperdex :: sanitize_secrets(const schema& sc, std::vector* value) +hyperdex :: sanitize_secrets(const schema &sc, std::vector *value) { - for (size_t i = 1; i < sc.attrs_sz; ++i) - { - if (sc.attrs[i].type == HYPERDATATYPE_MACAROON_SECRET && i <= value->size()) - { - (*value)[i - 1] = e::slice(); - } - } + for (size_t i = 1; i < sc.attrs_sz; ++i) + { + if (sc.attrs[i].type == HYPERDATATYPE_MACAROON_SECRET && i <= value->size()) + { + (*value)[i - 1] = e::slice(); + } + } } static void -destroy_macaroons(std::vector* MS) +destroy_macaroons(std::vector *MS) { - for (size_t i = 0; i < MS->size(); ++i) - { - macaroon_destroy((*MS)[i]); - } + for (size_t i = 0; i < MS->size(); ++i) + { + macaroon_destroy((*MS)[i]); + } } bool -hyperdex :: auth_verify(const schema& sc, +hyperdex :: auth_verify(const schema &sc, bool has_value, - const std::vector* value, - auth_wallet* aw, - const char** exact, - general_caveat* general) + const std::vector *value, + auth_wallet *aw, + const char **exact, + general_caveat *general) { - if (!sc.authorization) - { - return true; - } - - if (!has_value || !aw) - { - return false; - } - - bool has_secret = false; - e::slice secret; - - for (size_t i = 1; i < sc.attrs_sz; ++i) - { - if (sc.attrs[i].type == HYPERDATATYPE_MACAROON_SECRET) - { - has_secret = true; - secret = (*value)[i - 1]; - } - } - - // build the verifier - struct macaroon_verifier* V = macaroon_verifier_create(); - - if (!V) - { - throw std::bad_alloc(); - } - - while (exact && *exact) - { - macaroon_returncode err; - - if (macaroon_verifier_satisfy_exact(V, reinterpret_cast(*exact), strlen(*exact), &err) < 0) - { - has_secret = false; - } - - ++exact; - } - - while (general && general->check) - { - macaroon_returncode err; - - if (macaroon_verifier_satisfy_general(V, general->check, general->ptr, &err) < 0) - { - has_secret = false; - } - - ++general; - } - - e::guard g1 = e::makeguard(macaroon_verifier_destroy, V); - std::vector MS; - e::guard g2 = e::makeguard(destroy_macaroons, &MS); - - if (!aw->get_macaroons(&MS) || MS.empty()) - { - return false; - } - - macaroon_returncode err; - int rc = macaroon_verify(V, MS[0], secret.data(), secret.size(), &MS[1], MS.size() - 1, &err); - return rc == 0 && has_secret; + if (!sc.authorization) + { + return true; + } + if (!has_value || !aw) + { + return false; + } + bool has_secret = false; + e::slice secret; + for (size_t i = 1; i < sc.attrs_sz; ++i) + { + if (sc.attrs[i].type == HYPERDATATYPE_MACAROON_SECRET) + { + has_secret = true; + secret = (*value)[i - 1]; + } + } + // build the verifier + struct macaroon_verifier *V = macaroon_verifier_create(); + if (!V) + { + throw std::bad_alloc(); + } + while (exact && *exact) + { + macaroon_returncode err; + if (macaroon_verifier_satisfy_exact(V, reinterpret_cast(*exact), strlen(*exact), &err) < 0) + { + has_secret = false; + } + ++exact; + } + while (general && general->check) + { + macaroon_returncode err; + if (macaroon_verifier_satisfy_general(V, general->check, general->ptr, &err) < 0) + { + has_secret = false; + } + ++general; + } + e::guard g1 = e::makeguard(macaroon_verifier_destroy, V); + std::vector MS; + e::guard g2 = e::makeguard(destroy_macaroons, &MS); + if (!aw->get_macaroons(&MS) || MS.empty()) + { + return false; + } + macaroon_returncode err; + int rc = macaroon_verify(V, MS[0], secret.data(), secret.size(), &MS[1], MS.size() - 1, &err); + return rc == 0 && has_secret; } #define TIME_PRED "time < " #define TIME_PRED_SZ (sizeof(TIME_PRED) - 1) static int -check_time(void* t, const unsigned char* pred, size_t pred_sz) +check_time(void *t, const unsigned char *pred, size_t pred_sz) { - if (pred_sz < TIME_PRED_SZ || - memcmp(pred, TIME_PRED, TIME_PRED_SZ) != 0) - { - return -1; - } - - std::string tmp(reinterpret_cast(pred) + TIME_PRED_SZ, pred_sz - TIME_PRED_SZ); - char* end = NULL; - unsigned long long expiry = strtoull(tmp.c_str(), &end, 10); - - if (end == NULL || *end != '\0') - { - return -1; - } - - return (*reinterpret_cast(t) < expiry) ? 0 : -1; + if (pred_sz < TIME_PRED_SZ || + memcmp(pred, TIME_PRED, TIME_PRED_SZ) != 0) + { + return -1; + } + std::string tmp(reinterpret_cast(pred) + TIME_PRED_SZ, pred_sz - TIME_PRED_SZ); + char *end = NULL; + unsigned long long expiry = strtoull(tmp.c_str(), &end, 10); + if (end == NULL || *end != '\0') + { + return -1; + } + return (*reinterpret_cast(t) < expiry) ? 0 : -1; } bool -hyperdex :: auth_verify_read(const schema& sc, +hyperdex :: auth_verify_read(const schema &sc, bool has_value, - const std::vector* value, - auth_wallet* aw) + const std::vector *value, + auth_wallet *aw) { - const char* exact[] = {"op = read", NULL}; - uint64_t time = po6::time() / 1000000000ULL; - general_caveat general[] = {general_caveat(check_time, &time), general_caveat()}; - return auth_verify(sc, has_value, value, aw, exact, general); + const char *exact[] = {"op = read", NULL}; + uint64_t time = po6::time() / 1000000000ULL; + general_caveat general[] = {general_caveat(check_time, &time), general_caveat()}; + return auth_verify(sc, has_value, value, aw, exact, general); } bool -hyperdex :: auth_verify_write(const schema& sc, +hyperdex :: auth_verify_write(const schema &sc, bool has_value, - const std::vector* value, - const key_change& kc) + const std::vector *value, + const key_change &kc) { - if (!sc.authorization) - { - return true; - } - - if (!has_value) - { - uint16_t attrnum = sc.lookup_attr(HYPERDEX_ATTRIBUTE_SECRET); - - if (attrnum == sc.attrs_sz) - { - return false; - } - - for (size_t i = 0; i < kc.funcs.size(); ++i) - { - if (kc.funcs[i].attr == attrnum && - kc.funcs[i].name == FUNC_SET && - kc.funcs[i].arg1_datatype == HYPERDATATYPE_MACAROON_SECRET) - { - return true; - } - } - - return false; - } - else - { - const char* exact[] = {"op = write", NULL}; - uint64_t time = po6::time() / 1000000000ULL; - general_caveat general[] = {general_caveat(check_time, &time), general_caveat()}; - return auth_verify(sc, has_value, value, kc.auth.get(), exact, general); - } + if (!sc.authorization) + { + return true; + } + if (!has_value) + { + uint16_t attrnum = sc.lookup_attr(HYPERDEX_ATTRIBUTE_SECRET); + if (attrnum == sc.attrs_sz) + { + return false; + } + for (size_t i = 0; i < kc.funcs.size(); ++i) + { + if (kc.funcs[i].attr == attrnum && + kc.funcs[i].name == FUNC_SET && + kc.funcs[i].arg1_datatype == HYPERDATATYPE_MACAROON_SECRET) + { + return true; + } + } + return false; + } + else + { + const char *exact[] = {"op = write", NULL}; + uint64_t time = po6::time() / 1000000000ULL; + general_caveat general[] = {general_caveat(check_time, &time), general_caveat()}; + return auth_verify(sc, has_value, value, kc.auth.get(), exact, general); + } } diff --git a/daemon/auth.h b/daemon/auth.h index fd9537edc..63861d25f 100644 --- a/daemon/auth.h +++ b/daemon/auth.h @@ -40,27 +40,27 @@ BEGIN_HYPERDEX_NAMESPACE void -sanitize_secrets(const schema& sc, std::vector* value); +sanitize_secrets(const schema &sc, std::vector *value); bool -auth_verify(const schema& sc, +auth_verify(const schema &sc, bool has_value, - const std::vector* value, - auth_wallet* aw, - const char** exact, - struct general_caveat* general); + const std::vector *value, + auth_wallet *aw, + const char **exact, + struct general_caveat *general); bool -auth_verify_read(const schema& sc, +auth_verify_read(const schema &sc, bool has_value, - const std::vector* value, - auth_wallet* aw); + const std::vector *value, + auth_wallet *aw); bool -auth_verify_write(const schema& sc, +auth_verify_write(const schema &sc, bool has_value, - const std::vector* value, - const key_change& kc); + const std::vector *value, + const key_change &kc); END_HYPERDEX_NAMESPACE diff --git a/daemon/background_thread.cc b/daemon/background_thread.cc index 09ed7a57b..b68c3e58b 100644 --- a/daemon/background_thread.cc +++ b/daemon/background_thread.cc @@ -43,169 +43,153 @@ using po6::threads::make_thread_wrapper; using hyperdex::background_thread; -background_thread :: background_thread(daemon* d) - : m_thread(make_thread_wrapper(&background_thread::run, this)) - , m_gc(&d->m_gc) - , m_protect() - , m_wakeup_thread(&m_protect) - , m_wakeup_pauser(&m_protect) - , m_shutdown(true) - , m_pause_count(0) - , m_paused(false) - , m_offline(false) +background_thread :: background_thread(daemon *d) + : m_thread(make_thread_wrapper(&background_thread::run, this)) + , m_gc(&d->m_gc) + , m_protect() + , m_wakeup_thread(&m_protect) + , m_wakeup_pauser(&m_protect) + , m_shutdown(true) + , m_pause_count(0) + , m_paused(false) + , m_offline(false) { - po6::threads::mutex::hold hold(&m_protect); + po6::threads::mutex::hold hold(&m_protect); } background_thread :: ~background_thread() throw () { - shutdown(); + shutdown(); } void background_thread :: start() { - po6::threads::mutex::hold hold(&m_protect); - m_thread.start(); - m_shutdown = false; + po6::threads::mutex::hold hold(&m_protect); + m_thread.start(); + m_shutdown = false; } void background_thread :: initiate_pause() { - po6::threads::mutex::hold hold(&m_protect); - ++m_pause_count; + po6::threads::mutex::hold hold(&m_protect); + ++m_pause_count; } void background_thread :: wait_until_paused() { - po6::threads::mutex::hold hold(&m_protect); - assert(m_pause_count > 0); - - while (!m_paused && !m_offline) - { - m_wakeup_pauser.wait(); - } + po6::threads::mutex::hold hold(&m_protect); + assert(m_pause_count > 0); + while (!m_paused && !m_offline) + { + m_wakeup_pauser.wait(); + } } void background_thread :: unpause() { - po6::threads::mutex::hold hold(&m_protect); - assert(m_pause_count > 0); - --m_pause_count; - m_wakeup_thread.broadcast(); + po6::threads::mutex::hold hold(&m_protect); + assert(m_pause_count > 0); + --m_pause_count; + m_wakeup_thread.broadcast(); } void background_thread :: shutdown() { - bool already_shutdown; - - { - po6::threads::mutex::hold hold(&m_protect); - m_wakeup_thread.broadcast(); - already_shutdown = m_shutdown; - m_shutdown = true; - } - - if (!already_shutdown) - { - m_thread.join(); - } + bool already_shutdown; + { + po6::threads::mutex::hold hold(&m_protect); + m_wakeup_thread.broadcast(); + already_shutdown = m_shutdown; + m_shutdown = true; + } + if (!already_shutdown) + { + m_thread.join(); + } } void background_thread :: offline() { - po6::threads::mutex::hold hold(&m_protect); - assert(!m_offline); - m_offline = true; - - if (m_pause_count > 0) - { - m_wakeup_pauser.broadcast(); - } + po6::threads::mutex::hold hold(&m_protect); + assert(!m_offline); + m_offline = true; + if (m_pause_count > 0) + { + m_wakeup_pauser.broadcast(); + } } void background_thread :: online() { - po6::threads::mutex::hold hold(&m_protect); - assert(m_offline); - m_offline = false; - - while (m_pause_count > 0 && !m_shutdown) - { - m_paused = true; - m_wakeup_thread.wait(); - m_paused = false; - } + po6::threads::mutex::hold hold(&m_protect); + assert(m_offline); + m_offline = false; + while (m_pause_count > 0 && !m_shutdown) + { + m_paused = true; + m_wakeup_thread.wait(); + m_paused = false; + } } void background_thread :: run() { - LOG(INFO) << this->thread_name() << " thread started"; - block_signals(); - e::garbage_collector::thread_state ts; - m_gc->register_thread(&ts); - - while (true) - { - { - m_gc->quiescent_state(&ts); - po6::threads::mutex::hold hold(&m_protect); - - while ((!this->have_work() && !m_shutdown) || m_pause_count > 0) - { - m_paused = true; - - if (m_pause_count > 0) - { - m_wakeup_pauser.signal(); - } - - m_gc->offline(&ts); - m_wakeup_thread.wait(); - m_gc->online(&ts); - m_paused = false; - } - - if (m_shutdown) - { - break; - } - - this->copy_work(); - } - - this->do_work(); - } - - m_gc->deregister_thread(&ts); - LOG(INFO) << this->thread_name() << " thread stopped"; + LOG(INFO) << this->thread_name() << " thread started"; + block_signals(); + e::garbage_collector::thread_state ts; + m_gc->register_thread(&ts); + while (true) + { + { + m_gc->quiescent_state(&ts); + po6::threads::mutex::hold hold(&m_protect); + while ((!this->have_work() && !m_shutdown) || m_pause_count > 0) + { + m_paused = true; + if (m_pause_count > 0) + { + m_wakeup_pauser.signal(); + } + m_gc->offline(&ts); + m_wakeup_thread.wait(); + m_gc->online(&ts); + m_paused = false; + } + if (m_shutdown) + { + break; + } + this->copy_work(); + } + this->do_work(); + } + m_gc->deregister_thread(&ts); + LOG(INFO) << this->thread_name() << " thread stopped"; } void background_thread :: block_signals() { - sigset_t ss; - - if (sigfillset(&ss) < 0) - { - PLOG(ERROR) << "sigfillset"; - LOG(ERROR) << "could not successfully block signals; this could result in undefined behavior"; - return; - } - - sigdelset(&ss, SIGPROF); - - if (pthread_sigmask(SIG_BLOCK, &ss, NULL) < 0) - { - PLOG(ERROR) << "could not block signals"; - LOG(ERROR) << "could not successfully block signals; this could result in undefined behavior"; - return; - } + sigset_t ss; + if (sigfillset(&ss) < 0) + { + PLOG(ERROR) << "sigfillset"; + LOG(ERROR) << "could not successfully block signals; this could result in undefined behavior"; + return; + } + sigdelset(&ss, SIGPROF); + if (pthread_sigmask(SIG_BLOCK, &ss, NULL) < 0) + { + PLOG(ERROR) << "could not block signals"; + LOG(ERROR) << "could not successfully block signals; this could result in undefined behavior"; + return; + } } diff --git a/daemon/background_thread.h b/daemon/background_thread.h index 574fe5f85..7fbf58f6d 100644 --- a/daemon/background_thread.h +++ b/daemon/background_thread.h @@ -44,52 +44,52 @@ class daemon; class background_thread { - public: - background_thread(daemon* d); - virtual ~background_thread() throw (); +public: + background_thread(daemon *d); + virtual ~background_thread() throw (); - public: - void start(); - void initiate_pause(); - void wait_until_paused(); - void unpause(); - void shutdown(); +public: + void start(); + void initiate_pause(); + void wait_until_paused(); + void unpause(); + void shutdown(); - protected: - virtual const char* thread_name() = 0; - virtual bool have_work() = 0; - virtual void copy_work() = 0; - virtual void do_work() = 0; +protected: + virtual const char *thread_name() = 0; + virtual bool have_work() = 0; + virtual void copy_work() = 0; + virtual void do_work() = 0; - protected: - // take the thread offline. pause will appear to work right away - void offline(); - // bring the thread back online. will block if paused - void online(); - bool is_paused() { return m_paused; } // call with lock() - bool is_shutdown() { return m_shutdown; } // call with lock() - void lock() { m_protect.lock(); } - void unlock() { m_protect.unlock(); } - void wakeup() { m_wakeup_thread.broadcast(); } +protected: + // take the thread offline. pause will appear to work right away + void offline(); + // bring the thread back online. will block if paused + void online(); + bool is_paused() { return m_paused; } // call with lock() + bool is_shutdown() { return m_shutdown; } // call with lock() + void lock() { m_protect.lock(); } + void unlock() { m_protect.unlock(); } + void wakeup() { m_wakeup_thread.broadcast(); } - private: - void run(); - void block_signals(); +private: + void run(); + void block_signals(); - private: - background_thread(const background_thread&); - background_thread& operator = (const background_thread&); +private: + background_thread(const background_thread &); + background_thread &operator = (const background_thread &); - private: - po6::threads::thread m_thread; - e::garbage_collector* m_gc; - po6::threads::mutex m_protect; - po6::threads::cond m_wakeup_thread; - po6::threads::cond m_wakeup_pauser; - bool m_shutdown; - int m_pause_count; - bool m_paused; - bool m_offline; +private: + po6::threads::thread m_thread; + e::garbage_collector *m_gc; + po6::threads::mutex m_protect; + po6::threads::cond m_wakeup_thread; + po6::threads::cond m_wakeup_pauser; + bool m_shutdown; + int m_pause_count; + bool m_paused; + bool m_offline; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/communication.cc b/daemon/communication.cc index a0166e787..e324e578a 100644 --- a/daemon/communication.cc +++ b/daemon/communication.cc @@ -45,31 +45,31 @@ using hyperdex::reconfigure_returncode; class communication::early_message { - public: - early_message(); - early_message(uint64_t version, uint64_t id, - std::auto_ptr m); - ~early_message() throw (); - - public: - uint64_t config_version; - uint64_t id; - std::auto_ptr msg; +public: + early_message(); + early_message(uint64_t version, uint64_t id, + std::auto_ptr m); + ~early_message() throw (); + +public: + uint64_t config_version; + uint64_t id; + std::auto_ptr msg; }; communication :: early_message :: early_message() - : config_version(0) - , id() - , msg() + : config_version(0) + , id() + , msg() { } communication :: early_message :: early_message(uint64_t v, uint64_t i, std::auto_ptr m) - : config_version(v) - , id(i) - , msg(m) + : config_version(v) + , id(i) + , msg(m) { } @@ -79,11 +79,11 @@ communication :: early_message :: ~early_message() throw () ///////////////////////////////// Public Class ///////////////////////////////// -communication :: communication(daemon* d) - : m_daemon(d) - , m_busybee_mapper(&m_daemon->m_config) - , m_busybee() - , m_early_messages() +communication :: communication(daemon *d) + : m_daemon(d) + , m_busybee_mapper(&m_daemon->m_config) + , m_busybee() + , m_early_messages() { } @@ -92,12 +92,12 @@ communication :: ~communication() throw () } bool -communication :: setup(const po6::net::location& bind_to, +communication :: setup(const po6::net::location &bind_to, unsigned threads) { - m_busybee.reset(new busybee_mta(&m_daemon->m_gc, &m_busybee_mapper, bind_to, m_daemon->m_us.get(), threads)); - m_busybee->set_ignore_signals(); - return true; + m_busybee.reset(new busybee_mta(&m_daemon->m_gc, &m_busybee_mapper, bind_to, m_daemon->m_us.get(), threads)); + m_busybee->set_ignore_signals(); + return true; } void @@ -106,417 +106,372 @@ communication :: teardown() } void -communication :: reconfigure(const configuration&, - const configuration& new_config, - const server_id&) +communication :: reconfigure(const configuration &, + const configuration &new_config, + const server_id &) { - e::lockfree_fifo ems; - early_message em; - - while (m_early_messages.pop(&em)) - { - if (em.config_version <= new_config.version()) - { - m_busybee->deliver(em.id, em.msg); - } - else - { - ems.push(em); - } - } - - while (ems.pop(&em)) - { - m_early_messages.push(em); - } + e::lockfree_fifo ems; + early_message em; + while (m_early_messages.pop(&em)) + { + if (em.config_version <= new_config.version()) + { + m_busybee->deliver(em.id, em.msg); + } + else + { + ems.push(em); + } + } + while (ems.pop(&em)) + { + m_early_messages.push(em); + } } bool -communication :: send_client(const virtual_server_id& from, - const server_id& to, +communication :: send_client(const virtual_server_id &from, + const server_id &to, network_msgtype msg_type, std::auto_ptr msg) { - assert(msg->size() >= HYPERDEX_HEADER_SIZE_VC); - - if (m_daemon->m_us != m_daemon->m_config.get_server_id(from) && - from != virtual_server_id(UINT64_MAX)) - { - return false; - } - - uint8_t mt = static_cast(msg_type); - msg->pack_at(BUSYBEE_HEADER_SIZE) << mt << from.get(); - + assert(msg->size() >= HYPERDEX_HEADER_SIZE_VC); + if (m_daemon->m_us != m_daemon->m_config.get_server_id(from) && + from != virtual_server_id(UINT64_MAX)) + { + return false; + } + uint8_t mt = static_cast(msg_type); + msg->pack_at(BUSYBEE_HEADER_SIZE) << mt << from.get(); #ifdef HD_LOG_ALL_MESSAGES - LOG(INFO) << "SEND " << from << "->" << to << " " << msg_type << " " << msg->hex(); + LOG(INFO) << "SEND " << from << "->" << to << " " << msg_type << " " << msg->hex(); #endif - - if (to == m_daemon->m_us) - { - m_busybee->deliver(to.get(), msg); - } - else - { - busybee_returncode rc = m_busybee->send(to.get(), msg); - - switch (rc) - { - case BUSYBEE_SUCCESS: - break; - case BUSYBEE_DISRUPTED: - handle_disruption(to.get()); - return false; - case BUSYBEE_SHUTDOWN: - case BUSYBEE_POLLFAILED: - case BUSYBEE_ADDFDFAIL: - case BUSYBEE_TIMEOUT: - case BUSYBEE_EXTERNAL: - case BUSYBEE_INTERRUPTED: - default: - LOG(ERROR) << "BusyBee unexpectedly returned " << rc; - return false; - } - } - - return true; + if (to == m_daemon->m_us) + { + m_busybee->deliver(to.get(), msg); + } + else + { + busybee_returncode rc = m_busybee->send(to.get(), msg); + switch (rc) + { + case BUSYBEE_SUCCESS: + break; + case BUSYBEE_DISRUPTED: + handle_disruption(to.get()); + return false; + case BUSYBEE_SHUTDOWN: + case BUSYBEE_POLLFAILED: + case BUSYBEE_ADDFDFAIL: + case BUSYBEE_TIMEOUT: + case BUSYBEE_EXTERNAL: + case BUSYBEE_INTERRUPTED: + default: + LOG(ERROR) << "BusyBee unexpectedly returned " << rc; + return false; + } + } + return true; } bool -communication :: send(const virtual_server_id& from, - const server_id& to, +communication :: send(const virtual_server_id &from, + const server_id &to, network_msgtype msg_type, std::auto_ptr msg) { - assert(msg->size() >= HYPERDEX_HEADER_SIZE_VV); - - if (m_daemon->m_us != m_daemon->m_config.get_server_id(from)) - { - return false; - } - - uint8_t mt = static_cast(msg_type); - uint8_t flags = 1; - virtual_server_id vto(UINT64_MAX); - msg->pack_at(BUSYBEE_HEADER_SIZE) << mt << flags << m_daemon->m_config.version() << vto.get() << from.get(); - - if (to == server_id()) - { - return false; - } - + assert(msg->size() >= HYPERDEX_HEADER_SIZE_VV); + if (m_daemon->m_us != m_daemon->m_config.get_server_id(from)) + { + return false; + } + uint8_t mt = static_cast(msg_type); + uint8_t flags = 1; + virtual_server_id vto(UINT64_MAX); + msg->pack_at(BUSYBEE_HEADER_SIZE) << mt << flags << m_daemon->m_config.version() << vto.get() << from.get(); + if (to == server_id()) + { + return false; + } #ifdef HD_LOG_ALL_MESSAGES - LOG(INFO) << "SEND " << from << "->" << to << " " << msg_type << " " << msg->hex(); + LOG(INFO) << "SEND " << from << "->" << to << " " << msg_type << " " << msg->hex(); #endif - - if (to == m_daemon->m_us) - { - m_busybee->deliver(to.get(), msg); - } - else - { - busybee_returncode rc = m_busybee->send(to.get(), msg); - - switch (rc) - { - case BUSYBEE_SUCCESS: - break; - case BUSYBEE_DISRUPTED: - handle_disruption(to.get()); - return false; - case BUSYBEE_SHUTDOWN: - case BUSYBEE_POLLFAILED: - case BUSYBEE_ADDFDFAIL: - case BUSYBEE_TIMEOUT: - case BUSYBEE_EXTERNAL: - case BUSYBEE_INTERRUPTED: - default: - LOG(ERROR) << "BusyBee unexpectedly returned " << rc; - return false; - } - } - - return true; + if (to == m_daemon->m_us) + { + m_busybee->deliver(to.get(), msg); + } + else + { + busybee_returncode rc = m_busybee->send(to.get(), msg); + switch (rc) + { + case BUSYBEE_SUCCESS: + break; + case BUSYBEE_DISRUPTED: + handle_disruption(to.get()); + return false; + case BUSYBEE_SHUTDOWN: + case BUSYBEE_POLLFAILED: + case BUSYBEE_ADDFDFAIL: + case BUSYBEE_TIMEOUT: + case BUSYBEE_EXTERNAL: + case BUSYBEE_INTERRUPTED: + default: + LOG(ERROR) << "BusyBee unexpectedly returned " << rc; + return false; + } + } + return true; } bool -communication :: send(const virtual_server_id& from, - const virtual_server_id& vto, +communication :: send(const virtual_server_id &from, + const virtual_server_id &vto, network_msgtype msg_type, std::auto_ptr msg) { - assert(msg->size() >= HYPERDEX_HEADER_SIZE_VV); - - if (m_daemon->m_us != m_daemon->m_config.get_server_id(from)) - { - return false; - } - - uint8_t mt = static_cast(msg_type); - uint8_t flags = 1; - msg->pack_at(BUSYBEE_HEADER_SIZE) << mt << flags << m_daemon->m_config.version() << vto.get() << from.get(); - server_id to = m_daemon->m_config.get_server_id(vto); - - if (to == server_id()) - { - return false; - } - + assert(msg->size() >= HYPERDEX_HEADER_SIZE_VV); + if (m_daemon->m_us != m_daemon->m_config.get_server_id(from)) + { + return false; + } + uint8_t mt = static_cast(msg_type); + uint8_t flags = 1; + msg->pack_at(BUSYBEE_HEADER_SIZE) << mt << flags << m_daemon->m_config.version() << vto.get() << from.get(); + server_id to = m_daemon->m_config.get_server_id(vto); + if (to == server_id()) + { + return false; + } #ifdef HD_LOG_ALL_MESSAGES - LOG(INFO) << "SEND " << from << "->" << vto << " " << msg_type << " " << msg->hex(); + LOG(INFO) << "SEND " << from << "->" << vto << " " << msg_type << " " << msg->hex(); #endif - - if (to == m_daemon->m_us) - { - m_busybee->deliver(to.get(), msg); - } - else - { - busybee_returncode rc = m_busybee->send(to.get(), msg); - - switch (rc) - { - case BUSYBEE_SUCCESS: - break; - case BUSYBEE_DISRUPTED: - handle_disruption(to.get()); - return false; - case BUSYBEE_SHUTDOWN: - case BUSYBEE_POLLFAILED: - case BUSYBEE_ADDFDFAIL: - case BUSYBEE_TIMEOUT: - case BUSYBEE_EXTERNAL: - case BUSYBEE_INTERRUPTED: - default: - LOG(ERROR) << "BusyBee unexpectedly returned " << rc; - return false; - } - } - - return true; + if (to == m_daemon->m_us) + { + m_busybee->deliver(to.get(), msg); + } + else + { + busybee_returncode rc = m_busybee->send(to.get(), msg); + switch (rc) + { + case BUSYBEE_SUCCESS: + break; + case BUSYBEE_DISRUPTED: + handle_disruption(to.get()); + return false; + case BUSYBEE_SHUTDOWN: + case BUSYBEE_POLLFAILED: + case BUSYBEE_ADDFDFAIL: + case BUSYBEE_TIMEOUT: + case BUSYBEE_EXTERNAL: + case BUSYBEE_INTERRUPTED: + default: + LOG(ERROR) << "BusyBee unexpectedly returned " << rc; + return false; + } + } + return true; } bool -communication :: send(const virtual_server_id& vto, +communication :: send(const virtual_server_id &vto, network_msgtype msg_type, std::auto_ptr msg) { - assert(msg->size() >= HYPERDEX_HEADER_SIZE_SV); - - uint8_t mt = static_cast(msg_type); - uint8_t flags = 0; - msg->pack_at(BUSYBEE_HEADER_SIZE) << mt << flags << m_daemon->m_config.version() << vto.get(); - server_id to = m_daemon->m_config.get_server_id(vto); - - if (to == server_id()) - { - return false; - } - + assert(msg->size() >= HYPERDEX_HEADER_SIZE_SV); + uint8_t mt = static_cast(msg_type); + uint8_t flags = 0; + msg->pack_at(BUSYBEE_HEADER_SIZE) << mt << flags << m_daemon->m_config.version() << vto.get(); + server_id to = m_daemon->m_config.get_server_id(vto); + if (to == server_id()) + { + return false; + } #ifdef HD_LOG_ALL_MESSAGES - LOG(INFO) << "SEND ->" << vto << " " << msg_type << " " << msg->hex(); + LOG(INFO) << "SEND ->" << vto << " " << msg_type << " " << msg->hex(); #endif - - if (to == m_daemon->m_us) - { - m_busybee->deliver(to.get(), msg); - } - else - { - busybee_returncode rc = m_busybee->send(to.get(), msg); - - switch (rc) - { - case BUSYBEE_SUCCESS: - break; - case BUSYBEE_DISRUPTED: - handle_disruption(to.get()); - return false; - case BUSYBEE_SHUTDOWN: - case BUSYBEE_POLLFAILED: - case BUSYBEE_ADDFDFAIL: - case BUSYBEE_TIMEOUT: - case BUSYBEE_EXTERNAL: - case BUSYBEE_INTERRUPTED: - default: - LOG(ERROR) << "BusyBee unexpectedly returned " << rc; - return false; - } - } - - return true; + if (to == m_daemon->m_us) + { + m_busybee->deliver(to.get(), msg); + } + else + { + busybee_returncode rc = m_busybee->send(to.get(), msg); + switch (rc) + { + case BUSYBEE_SUCCESS: + break; + case BUSYBEE_DISRUPTED: + handle_disruption(to.get()); + return false; + case BUSYBEE_SHUTDOWN: + case BUSYBEE_POLLFAILED: + case BUSYBEE_ADDFDFAIL: + case BUSYBEE_TIMEOUT: + case BUSYBEE_EXTERNAL: + case BUSYBEE_INTERRUPTED: + default: + LOG(ERROR) << "BusyBee unexpectedly returned " << rc; + return false; + } + } + return true; } bool -communication :: send_exact(const virtual_server_id& from, - const virtual_server_id& vto, +communication :: send_exact(const virtual_server_id &from, + const virtual_server_id &vto, network_msgtype msg_type, std::auto_ptr msg) { - assert(msg->size() >= HYPERDEX_HEADER_SIZE_VV); - - if (m_daemon->m_us != m_daemon->m_config.get_server_id(from)) - { - return false; - } - - uint8_t mt = static_cast(msg_type); - uint8_t flags = 1 | 2; - msg->pack_at(BUSYBEE_HEADER_SIZE) << mt << flags << m_daemon->m_config.version() << vto.get() << from.get(); - server_id to = m_daemon->m_config.get_server_id(vto); - - if (to == server_id()) - { - return false; - } - + assert(msg->size() >= HYPERDEX_HEADER_SIZE_VV); + if (m_daemon->m_us != m_daemon->m_config.get_server_id(from)) + { + return false; + } + uint8_t mt = static_cast(msg_type); + uint8_t flags = 1 | 2; + msg->pack_at(BUSYBEE_HEADER_SIZE) << mt << flags << m_daemon->m_config.version() << vto.get() << from.get(); + server_id to = m_daemon->m_config.get_server_id(vto); + if (to == server_id()) + { + return false; + } #ifdef HD_LOG_ALL_MESSAGES - LOG(INFO) << "SEND " << from << "->" << vto << " " << msg_type << " " << msg->hex(); + LOG(INFO) << "SEND " << from << "->" << vto << " " << msg_type << " " << msg->hex(); #endif - - if (to == m_daemon->m_us) - { - m_busybee->deliver(to.get(), msg); - } - else - { - busybee_returncode rc = m_busybee->send(to.get(), msg); - - switch (rc) - { - case BUSYBEE_SUCCESS: - break; - case BUSYBEE_DISRUPTED: - handle_disruption(to.get()); - return false; - case BUSYBEE_SHUTDOWN: - case BUSYBEE_POLLFAILED: - case BUSYBEE_ADDFDFAIL: - case BUSYBEE_TIMEOUT: - case BUSYBEE_EXTERNAL: - case BUSYBEE_INTERRUPTED: - default: - LOG(ERROR) << "BusyBee unexpectedly returned " << rc; - return false; - } - } - - return true; + if (to == m_daemon->m_us) + { + m_busybee->deliver(to.get(), msg); + } + else + { + busybee_returncode rc = m_busybee->send(to.get(), msg); + switch (rc) + { + case BUSYBEE_SUCCESS: + break; + case BUSYBEE_DISRUPTED: + handle_disruption(to.get()); + return false; + case BUSYBEE_SHUTDOWN: + case BUSYBEE_POLLFAILED: + case BUSYBEE_ADDFDFAIL: + case BUSYBEE_TIMEOUT: + case BUSYBEE_EXTERNAL: + case BUSYBEE_INTERRUPTED: + default: + LOG(ERROR) << "BusyBee unexpectedly returned " << rc; + return false; + } + } + return true; } bool -communication :: recv(e::garbage_collector::thread_state* ts, - server_id* from, - virtual_server_id* vfrom, - virtual_server_id* vto, - network_msgtype* msg_type, - std::auto_ptr* msg, - e::unpacker* up) +communication :: recv(e::garbage_collector::thread_state *ts, + server_id *from, + virtual_server_id *vfrom, + virtual_server_id *vto, + network_msgtype *msg_type, + std::auto_ptr *msg, + e::unpacker *up) { - // Read messages from the network until we get one that meets the following - // constraints: - // - It is addressed to a virtual_server_id - // - The virtual_server_id destination maps to us - // - If it comes from a virtual_server_id, that id maps to the sender - // - The message version is less than or equal to our current config - while (true) - { - uint64_t id; - busybee_returncode rc = m_busybee->recv(ts, &id, msg); - - switch (rc) - { - case BUSYBEE_SUCCESS: - break; - case BUSYBEE_SHUTDOWN: - return false; - case BUSYBEE_DISRUPTED: - handle_disruption(id); - continue; - case BUSYBEE_INTERRUPTED: - continue; - case BUSYBEE_POLLFAILED: - case BUSYBEE_ADDFDFAIL: - case BUSYBEE_TIMEOUT: - case BUSYBEE_EXTERNAL: - default: - LOG(ERROR) << "busybee unexpectedly returned " << rc; - continue; - } - - uint8_t mt; - uint8_t flags; - uint64_t version; - uint64_t vidf; - uint64_t vidt; - *up = (*msg)->unpack_from(BUSYBEE_HEADER_SIZE); - *up = *up >> mt >> flags >> version >> vidt; - *msg_type = static_cast(mt); - *from = server_id(id); - *vto = virtual_server_id(vidt); - - if ((flags & 0x1)) - { - *up = *up >> vidf; - *vfrom = virtual_server_id(vidf); - } - else - { - *vfrom = virtual_server_id(); - } - - if (up->error()) - { - LOG(WARNING) << "dropping message that has a malformed header; here's some hex: " << (*msg)->hex(); - continue; - } - - bool from_valid = true; - bool to_valid = m_daemon->m_us == m_daemon->m_config.get_server_id(*vto) || - *vto == virtual_server_id(UINT64_MAX); - - // If this is a virtual-virtual message - if ((flags & 0x1)) - { - from_valid = *from == m_daemon->m_config.get_server_id(virtual_server_id(vidf)); - } - - // No matter what, wait for the config the sender saw - if (version > m_daemon->m_config.version()) - { - early_message em(version, id, *msg); - m_early_messages.push(em); - continue; - } - - if ((flags & 0x2) && version < m_daemon->m_config.version()) - { - continue; - } - - if (from_valid && to_valid) - { + // Read messages from the network until we get one that meets the following + // constraints: + // - It is addressed to a virtual_server_id + // - The virtual_server_id destination maps to us + // - If it comes from a virtual_server_id, that id maps to the sender + // - The message version is less than or equal to our current config + while (true) + { + uint64_t id; + busybee_returncode rc = m_busybee->recv(ts, &id, msg); + switch (rc) + { + case BUSYBEE_SUCCESS: + break; + case BUSYBEE_SHUTDOWN: + return false; + case BUSYBEE_DISRUPTED: + handle_disruption(id); + continue; + case BUSYBEE_INTERRUPTED: + continue; + case BUSYBEE_POLLFAILED: + case BUSYBEE_ADDFDFAIL: + case BUSYBEE_TIMEOUT: + case BUSYBEE_EXTERNAL: + default: + LOG(ERROR) << "busybee unexpectedly returned " << rc; + continue; + } + uint8_t mt; + uint8_t flags; + uint64_t version; + uint64_t vidf; + uint64_t vidt; + *up = (*msg)->unpack_from(BUSYBEE_HEADER_SIZE); + *up = *up >> mt >> flags >> version >> vidt; + *msg_type = static_cast(mt); + *from = server_id(id); + *vto = virtual_server_id(vidt); + if ((flags & 0x1)) + { + *up = *up >> vidf; + *vfrom = virtual_server_id(vidf); + } + else + { + *vfrom = virtual_server_id(); + } + if (up->error()) + { + LOG(WARNING) << "dropping message that has a malformed header; here's some hex: " << (*msg)->hex(); + continue; + } + bool from_valid = true; + bool to_valid = m_daemon->m_us == m_daemon->m_config.get_server_id(*vto) || + *vto == virtual_server_id(UINT64_MAX); + // If this is a virtual-virtual message + if ((flags & 0x1)) + { + from_valid = *from == m_daemon->m_config.get_server_id(virtual_server_id(vidf)); + } + // No matter what, wait for the config the sender saw + if (version > m_daemon->m_config.version()) + { + early_message em(version, id, *msg); + m_early_messages.push(em); + continue; + } + if ((flags & 0x2) && version < m_daemon->m_config.version()) + { + continue; + } + if (from_valid && to_valid) + { #ifdef HD_LOG_ALL_MESSAGES - LOG(INFO) << "RECV " << *from << "/" << *vfrom << "->" << *vto << " " << *msg_type << " " << (*msg)->hex(); + LOG(INFO) << "RECV " << *from << "/" << *vfrom << "->" << *vto << " " << *msg_type << " " << (*msg)->hex(); #endif - return true; - } - - // Shove the message back at the client so it fails with a reconfigure. - if (!(flags & 0x1)) - { - mt = static_cast(CONFIGMISMATCH); - (*msg)->pack_at(BUSYBEE_HEADER_SIZE) << mt; - m_busybee->send(id, *msg); - } - } + return true; + } + // Shove the message back at the client so it fails with a reconfigure. + if (!(flags & 0x1)) + { + mt = static_cast(CONFIGMISMATCH); + (*msg)->pack_at(BUSYBEE_HEADER_SIZE) << mt; + m_busybee->send(id, *msg); + } + } } void communication :: handle_disruption(uint64_t id) { - if (m_daemon->m_config.get_address(server_id(id)) != po6::net::location()) - { - m_daemon->m_coord->report_tcp_disconnect(m_daemon->m_config.version(), server_id(id)); - } + if (m_daemon->m_config.get_address(server_id(id)) != po6::net::location()) + { + m_daemon->m_coord->report_tcp_disconnect(m_daemon->m_config.version(), server_id(id)); + } } diff --git a/daemon/communication.h b/daemon/communication.h index 0a8b88c57..47fffed25 100644 --- a/daemon/communication.h +++ b/daemon/communication.h @@ -67,68 +67,68 @@ class daemon; class communication { - public: - communication(daemon* d); - ~communication() throw (); - - public: - void pause() { m_busybee->pause(); } - void unpause() { m_busybee->unpause(); } - void shutdown() { m_busybee->shutdown(); } - void wake_one() { m_busybee->wake_one(); } - - public: - bool setup(const po6::net::location& bind_to, - unsigned threads); - void teardown(); - void reconfigure(const configuration& old_config, - const configuration& new_config, - const server_id& us); - - public: - // Send data to another server (pretending to be a client) - bool send_client(const virtual_server_id& from, - const server_id& to, - network_msgtype msg_type, - std::auto_ptr msg); - bool send(const virtual_server_id& from, - const server_id& to, - network_msgtype msg_type, - std::auto_ptr msg); - bool send(const virtual_server_id& from, - const virtual_server_id& to, - network_msgtype msg_type, - std::auto_ptr msg); - bool send(const virtual_server_id& to, - network_msgtype msg_type, - std::auto_ptr msg); - bool send_exact(const virtual_server_id& from, - const virtual_server_id& to, - network_msgtype msg_type, - std::auto_ptr msg); - bool recv(e::garbage_collector::thread_state* ts, - server_id* from, - virtual_server_id* vfrom, - virtual_server_id* vto, - network_msgtype* msg_type, - std::auto_ptr* msg, - e::unpacker* up); - - private: - class early_message; - - private: - void handle_disruption(uint64_t id); - - private: - communication(const communication&); - communication& operator = (const communication&); - - private: - daemon* m_daemon; - mapper m_busybee_mapper; - std::auto_ptr m_busybee; - e::lockfree_fifo m_early_messages; +public: + communication(daemon *d); + ~communication() throw (); + +public: + void pause() { m_busybee->pause(); } + void unpause() { m_busybee->unpause(); } + void shutdown() { m_busybee->shutdown(); } + void wake_one() { m_busybee->wake_one(); } + +public: + bool setup(const po6::net::location &bind_to, + unsigned threads); + void teardown(); + void reconfigure(const configuration &old_config, + const configuration &new_config, + const server_id &us); + +public: + // Send data to another server (pretending to be a client) + bool send_client(const virtual_server_id &from, + const server_id &to, + network_msgtype msg_type, + std::auto_ptr msg); + bool send(const virtual_server_id &from, + const server_id &to, + network_msgtype msg_type, + std::auto_ptr msg); + bool send(const virtual_server_id &from, + const virtual_server_id &to, + network_msgtype msg_type, + std::auto_ptr msg); + bool send(const virtual_server_id &to, + network_msgtype msg_type, + std::auto_ptr msg); + bool send_exact(const virtual_server_id &from, + const virtual_server_id &to, + network_msgtype msg_type, + std::auto_ptr msg); + bool recv(e::garbage_collector::thread_state *ts, + server_id *from, + virtual_server_id *vfrom, + virtual_server_id *vto, + network_msgtype *msg_type, + std::auto_ptr *msg, + e::unpacker *up); + +private: + class early_message; + +private: + void handle_disruption(uint64_t id); + +private: + communication(const communication &); + communication &operator = (const communication &); + +private: + daemon *m_daemon; + mapper m_busybee_mapper; + std::auto_ptr m_busybee; + e::lockfree_fifo m_early_messages; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/coordinator_link.cc b/daemon/coordinator_link.cc index 48d4931b7..05c1fa4d3 100644 --- a/daemon/coordinator_link.cc +++ b/daemon/coordinator_link.cc @@ -48,28 +48,28 @@ using hyperdex::coordinator_link; struct coordinator_link::rpc { - rpc(); - ~rpc() throw (); - - std::string func; - std::string input; - unsigned flags; - replicant_returncode status; - char* output; - size_t output_sz; - - private: - rpc(const rpc&); - rpc& operator = (const rpc&); + rpc(); + ~rpc() throw (); + + std::string func; + std::string input; + unsigned flags; + replicant_returncode status; + char *output; + size_t output_sz; + +private: + rpc(const rpc &); + rpc &operator = (const rpc &); }; coordinator_link :: rpc :: rpc() - : func() - , input() - , flags(0) - , status(REPLICANT_GARBAGE) - , output(NULL) - , output_sz(0) + : func() + , input() + , flags(0) + , status(REPLICANT_GARBAGE) + , output(NULL) + , output_sz(0) { } @@ -77,33 +77,33 @@ coordinator_link :: rpc :: ~rpc() throw () { } -coordinator_link :: coordinator_link(daemon* d, const char* host, uint16_t port) - : m_daemon(d) - , m_sleep_ms(0) - , m_config() - , m_config_id(-1) - , m_config_status() - , m_config_state(0) - , m_config_data(NULL) - , m_config_data_sz(0) - , m_checkpoint_id(-1) - , m_checkpoint_status() - , m_checkpoint_state(0) - , m_checkpoint_data(NULL) - , m_checkpoint_data_sz(0) - , m_value_checkpoint_config_version(0) - , m_value_checkpoint(0) - , m_value_checkpoint_stable(0) - , m_value_checkpoint_gc(0) - , m_throwaway_status() - , m_mtx() - , m_repl(replicant_client_create(host, port)) - , m_rpcs() +coordinator_link :: coordinator_link(daemon *d, const char *host, uint16_t port) + : m_daemon(d) + , m_sleep_ms(0) + , m_config() + , m_config_id(-1) + , m_config_status() + , m_config_state(0) + , m_config_data(NULL) + , m_config_data_sz(0) + , m_checkpoint_id(-1) + , m_checkpoint_status() + , m_checkpoint_state(0) + , m_checkpoint_data(NULL) + , m_checkpoint_data_sz(0) + , m_value_checkpoint_config_version(0) + , m_value_checkpoint(0) + , m_value_checkpoint_stable(0) + , m_value_checkpoint_gc(0) + , m_throwaway_status() + , m_mtx() + , m_repl(replicant_client_create(host, port)) + , m_rpcs() { - if (!m_repl) - { - throw std::bad_alloc(); - } + if (!m_repl) + { + throw std::bad_alloc(); + } } coordinator_link :: ~coordinator_link() throw () @@ -111,444 +111,404 @@ coordinator_link :: ~coordinator_link() throw () } bool -coordinator_link :: register_server(server_id us, const po6::net::location& bind_to) +coordinator_link :: register_server(server_id us, const po6::net::location &bind_to) { - std::string register_msg; - e::packer(®ister_msg) << us << bind_to; - char* output = NULL; - size_t output_sz = 0; - std::ostringstream ostr; - ostr << "register as " << us; - - if (!synchronous_call(ostr.str().c_str(), "server_register", - register_msg.data(), register_msg.size(), - &output, &output_sz)) - { - return false; - } - - assert(output); - e::guard g_output = e::makeguard(free, output); - - if (output_sz >= 2) - { - uint16_t x; - e::unpack16be(output, &x); - coordinator_returncode rc = static_cast(x); - - switch (rc) - { - case COORD_SUCCESS: - return true; - case COORD_DUPLICATE: - LOG(ERROR) << "could not register as " << us << ": another server has this ID"; - return false; - case COORD_UNINITIALIZED: - LOG(ERROR) << "could not register as " << us << ": coordinator not initialized"; - return false; - case COORD_MALFORMED: - case COORD_NOT_FOUND: - case COORD_NO_CAN_DO: - default: - LOG(ERROR) << "could not register as " << us << ": coordinator returned " << rc; - return false; - } - } - else - { - LOG(ERROR) << "could not register as " << us << ": coordinator returned invalid message"; - return false; - } + std::string register_msg; + e::packer(®ister_msg) << us << bind_to; + char *output = NULL; + size_t output_sz = 0; + std::ostringstream ostr; + ostr << "register as " << us; + if (!synchronous_call(ostr.str().c_str(), "server_register", + register_msg.data(), register_msg.size(), + &output, &output_sz)) + { + return false; + } + assert(output); + e::guard g_output = e::makeguard(free, output); + if (output_sz >= 2) + { + uint16_t x; + e::unpack16be(output, &x); + coordinator_returncode rc = static_cast(x); + switch (rc) + { + case COORD_SUCCESS: + return true; + case COORD_DUPLICATE: + LOG(ERROR) << "could not register as " << us << ": another server has this ID"; + return false; + case COORD_UNINITIALIZED: + LOG(ERROR) << "could not register as " << us << ": coordinator not initialized"; + return false; + case COORD_MALFORMED: + case COORD_NOT_FOUND: + case COORD_NO_CAN_DO: + default: + LOG(ERROR) << "could not register as " << us << ": coordinator returned " << rc; + return false; + } + } + else + { + LOG(ERROR) << "could not register as " << us << ": coordinator returned invalid message"; + return false; + } } bool coordinator_link :: initialize() { - char* output = NULL; - size_t output_sz = 0; - - if (!synchronous_call("get current configuration", "config_get", NULL, 0, &output, &output_sz)) - { - return false; - } - - assert(output); - e::guard g_output = e::makeguard(free, output); - - if (!process_configuration(output, output_sz)) - { - LOG(ERROR) << "could not get initial configuration; it appears to be invalid"; - return false; - } - - if (!bring_online()) - { - return false; - } - - return true; + char *output = NULL; + size_t output_sz = 0; + if (!synchronous_call("get current configuration", "config_get", NULL, 0, &output, &output_sz)) + { + return false; + } + assert(output); + e::guard g_output = e::makeguard(free, output); + if (!process_configuration(output, output_sz)) + { + LOG(ERROR) << "could not get initial configuration; it appears to be invalid"; + return false; + } + if (!bring_online()) + { + return false; + } + return true; } void -increment_sleep(unsigned* x) +increment_sleep(unsigned *x) { - if (*x == 0) - { - *x = 100; - } - else - { - *x = std::min(*x * 2, 20000U); - } + if (*x == 0) + { + *x = 100; + } + else + { + *x = std::min(*x * 2, 20000U); + } } static bool atomically_allow_pending_blocked_signals() { - sigset_t ss; - sigemptyset(&ss); - - if (sigpending(&ss) == 0 && - (sigismember(&ss, SIGHUP) == 1 || - sigismember(&ss, SIGINT) == 1 || - sigismember(&ss, SIGTERM) == 1 || - sigismember(&ss, SIGQUIT) == 1 || - sigismember(&ss, SIGALRM) == 1)) - { - sigemptyset(&ss); - sigsuspend(&ss); - return true; - } - - return false; + sigset_t ss; + sigemptyset(&ss); + if (sigpending(&ss) == 0 && + (sigismember(&ss, SIGHUP) == 1 || + sigismember(&ss, SIGINT) == 1 || + sigismember(&ss, SIGTERM) == 1 || + sigismember(&ss, SIGQUIT) == 1 || + sigismember(&ss, SIGALRM) == 1)) + { + sigemptyset(&ss); + sigsuspend(&ss); + return true; + } + return false; } bool coordinator_link :: maintain() { - while (true) - { - if (m_sleep_ms > 0) - { - timespec ts; - ts.tv_sec = m_sleep_ms / 1000; - ts.tv_nsec = (m_sleep_ms % 1000) * 1000ULL * 1000ULL; - nanosleep(&ts, NULL); - - if (atomically_allow_pending_blocked_signals()) - { - return false; - } - } - - { - po6::threads::mutex::hold hold(&m_mtx); - - if (m_config_status != REPLICANT_SUCCESS) - { - replicant_client_kill(m_repl, m_config_id); - m_config_id = -1; - } - - if (m_config_id < 0) - { - m_config_status = REPLICANT_SUCCESS; - m_config_id = replicant_client_cond_follow(m_repl, "hyperdex", "config", - &m_config_status, &m_config_state, - &m_config_data, &m_config_data_sz); - } - - if (m_checkpoint_status != REPLICANT_SUCCESS) - { - replicant_client_kill(m_repl, m_checkpoint_id); - m_checkpoint_id = -1; - } - - if (m_checkpoint_id < 0) - { - m_checkpoint_status = REPLICANT_SUCCESS; - m_checkpoint_id = replicant_client_cond_follow(m_repl, "hyperdex", "checkpoint", - &m_checkpoint_status, &m_checkpoint_state, - &m_checkpoint_data, &m_checkpoint_data_sz); - } - } - - if (replicant_client_block(m_repl, 50) < 0) - { - return false; - } - - int64_t id; - replicant_returncode rc; - po6::threads::mutex::hold hold(&m_mtx); - id = replicant_client_loop(m_repl, 0, &rc); - - if (id < 0) - { - if (rc == REPLICANT_INTERRUPTED) - { - return false; - } - else if (rc != REPLICANT_NONE_PENDING && rc != REPLICANT_TIMEOUT) - { - LOG(ERROR) << "coordinator failure: " << replicant_client_error_message(m_repl); - LOG(INFO) << "error [" << replicant_returncode_to_string(rc) - << "] at " << replicant_client_error_location(m_repl); - increment_sleep(&m_sleep_ms); - return false; - } - } - - m_sleep_ms = 0; - - if (id == m_config_id && m_config_status == REPLICANT_SUCCESS) - { - if (!process_configuration(m_config_data, m_config_data_sz)) - { - increment_sleep(&m_sleep_ms); - LOG(ERROR) << "received an invalid configuration from the coordinator"; - return false; - } - - if (m_config.get_state(m_daemon->m_us) == server::NOT_AVAILABLE) - { - if (!bring_online()) - { - return false; - } - } - - return true; - } - else if (id == m_checkpoint_id && m_checkpoint_status == REPLICANT_SUCCESS) - { - uint64_t value_checkpoint_config_version; - uint64_t value_checkpoint; - uint64_t value_checkpoint_stable; - uint64_t value_checkpoint_gc; - e::unpacker up(m_checkpoint_data, m_checkpoint_data_sz); - up = up >> value_checkpoint_config_version - >> value_checkpoint - >> value_checkpoint_stable - >> value_checkpoint_gc; - - if (!up.error()) - { - // set the values and force the main thread out of here to act - // on new checkpoints - m_value_checkpoint_config_version = value_checkpoint_config_version; - m_value_checkpoint = value_checkpoint; - m_value_checkpoint_stable = value_checkpoint_stable; - m_value_checkpoint_gc = value_checkpoint_gc; - return false; - } - } - else - { - std::map >::iterator rit; - rit = m_rpcs.find(id); - - if (rit == m_rpcs.end()) - { - continue; - } - - e::compat::shared_ptr r = rit->second; - m_rpcs.erase(rit); - - if (r->status != REPLICANT_SUCCESS) - { - increment_sleep(&m_sleep_ms); - LOG(ERROR) << "call to coordinator method \"" << r->func - << "\" failed: " << replicant_client_error_message(m_repl); - - if ((r->flags & REPLICANT_CALL_IDEMPOTENT)) - { - LOG(ERROR) << "retrying call to coordinator method \"" << r->func << "\""; - make_rpc_no_synchro(r); - } - } - } - } + while (true) + { + if (m_sleep_ms > 0) + { + timespec ts; + ts.tv_sec = m_sleep_ms / 1000; + ts.tv_nsec = (m_sleep_ms % 1000) * 1000ULL * 1000ULL; + nanosleep(&ts, NULL); + if (atomically_allow_pending_blocked_signals()) + { + return false; + } + } + { + po6::threads::mutex::hold hold(&m_mtx); + if (m_config_status != REPLICANT_SUCCESS) + { + replicant_client_kill(m_repl, m_config_id); + m_config_id = -1; + } + if (m_config_id < 0) + { + m_config_status = REPLICANT_SUCCESS; + m_config_id = replicant_client_cond_follow(m_repl, "hyperdex", "config", + &m_config_status, &m_config_state, + &m_config_data, &m_config_data_sz); + } + if (m_checkpoint_status != REPLICANT_SUCCESS) + { + replicant_client_kill(m_repl, m_checkpoint_id); + m_checkpoint_id = -1; + } + if (m_checkpoint_id < 0) + { + m_checkpoint_status = REPLICANT_SUCCESS; + m_checkpoint_id = replicant_client_cond_follow(m_repl, "hyperdex", "checkpoint", + &m_checkpoint_status, &m_checkpoint_state, + &m_checkpoint_data, &m_checkpoint_data_sz); + } + } + if (replicant_client_block(m_repl, 50) < 0) + { + return false; + } + int64_t id; + replicant_returncode rc; + po6::threads::mutex::hold hold(&m_mtx); + id = replicant_client_loop(m_repl, 0, &rc); + if (id < 0) + { + if (rc == REPLICANT_INTERRUPTED) + { + return false; + } + else if (rc != REPLICANT_NONE_PENDING && rc != REPLICANT_TIMEOUT) + { + LOG(ERROR) << "coordinator failure: " << replicant_client_error_message(m_repl); + LOG(INFO) << "error [" << replicant_returncode_to_string(rc) + << "] at " << replicant_client_error_location(m_repl); + increment_sleep(&m_sleep_ms); + return false; + } + } + m_sleep_ms = 0; + if (id == m_config_id && m_config_status == REPLICANT_SUCCESS) + { + if (!process_configuration(m_config_data, m_config_data_sz)) + { + increment_sleep(&m_sleep_ms); + LOG(ERROR) << "received an invalid configuration from the coordinator"; + return false; + } + if (m_config.get_state(m_daemon->m_us) == server::NOT_AVAILABLE) + { + if (!bring_online()) + { + return false; + } + } + return true; + } + else if (id == m_checkpoint_id && m_checkpoint_status == REPLICANT_SUCCESS) + { + uint64_t value_checkpoint_config_version; + uint64_t value_checkpoint; + uint64_t value_checkpoint_stable; + uint64_t value_checkpoint_gc; + e::unpacker up(m_checkpoint_data, m_checkpoint_data_sz); + up = up >> value_checkpoint_config_version + >> value_checkpoint + >> value_checkpoint_stable + >> value_checkpoint_gc; + if (!up.error()) + { + // set the values and force the main thread out of here to act + // on new checkpoints + m_value_checkpoint_config_version = value_checkpoint_config_version; + m_value_checkpoint = value_checkpoint; + m_value_checkpoint_stable = value_checkpoint_stable; + m_value_checkpoint_gc = value_checkpoint_gc; + return false; + } + } + else + { + std::map >::iterator rit; + rit = m_rpcs.find(id); + if (rit == m_rpcs.end()) + { + continue; + } + e::compat::shared_ptr r = rit->second; + m_rpcs.erase(rit); + if (r->status != REPLICANT_SUCCESS) + { + increment_sleep(&m_sleep_ms); + LOG(ERROR) << "call to coordinator method \"" << r->func + << "\" failed: " << replicant_client_error_message(m_repl); + if ((r->flags & REPLICANT_CALL_IDEMPOTENT)) + { + LOG(ERROR) << "retrying call to coordinator method \"" << r->func << "\""; + make_rpc_no_synchro(r); + } + } + } + } } void coordinator_link :: shutdown() { - e::compat::shared_ptr r(new rpc()); - r->func = "server_shutdown"; - r->flags = REPLICANT_CALL_IDEMPOTENT; - e::packer(&r->input) << m_daemon->m_us; - make_rpc(r); + e::compat::shared_ptr r(new rpc()); + r->func = "server_shutdown"; + r->flags = REPLICANT_CALL_IDEMPOTENT; + e::packer(&r->input) << m_daemon->m_us; + make_rpc(r); } void coordinator_link :: config_ack(uint64_t config_version) { - e::compat::shared_ptr r(new rpc()); - r->func = "config_ack"; - r->flags = REPLICANT_CALL_IDEMPOTENT; - e::packer(&r->input) << m_daemon->m_us << config_version; - make_rpc(r); + e::compat::shared_ptr r(new rpc()); + r->func = "config_ack"; + r->flags = REPLICANT_CALL_IDEMPOTENT; + e::packer(&r->input) << m_daemon->m_us << config_version; + make_rpc(r); } void coordinator_link :: config_stable(uint64_t config_version) { - e::compat::shared_ptr r(new rpc()); - r->func = "config_stable"; - r->flags = REPLICANT_CALL_IDEMPOTENT; - e::packer(&r->input) << m_daemon->m_us << config_version; - make_rpc(r); + e::compat::shared_ptr r(new rpc()); + r->func = "config_stable"; + r->flags = REPLICANT_CALL_IDEMPOTENT; + e::packer(&r->input) << m_daemon->m_us << config_version; + make_rpc(r); } void coordinator_link :: checkpoint_report_stable(uint64_t config_version) { - e::compat::shared_ptr r(new rpc()); - r->func = "checkpoint_stable"; - r->flags = REPLICANT_CALL_IDEMPOTENT; - e::packer(&r->input) << m_daemon->m_us - << m_value_checkpoint_config_version - << config_version; - make_rpc(r); + e::compat::shared_ptr r(new rpc()); + r->func = "checkpoint_stable"; + r->flags = REPLICANT_CALL_IDEMPOTENT; + e::packer(&r->input) << m_daemon->m_us + << m_value_checkpoint_config_version + << config_version; + make_rpc(r); } void -coordinator_link :: transfer_go_live(const transfer_id& id) +coordinator_link :: transfer_go_live(const transfer_id &id) { - e::compat::shared_ptr r(new rpc()); - r->func = "transfer_go_live"; - r->flags = REPLICANT_CALL_IDEMPOTENT; - e::packer(&r->input) << id; - make_rpc(r); + e::compat::shared_ptr r(new rpc()); + r->func = "transfer_go_live"; + r->flags = REPLICANT_CALL_IDEMPOTENT; + e::packer(&r->input) << id; + make_rpc(r); } void -coordinator_link :: transfer_complete(const transfer_id& id) +coordinator_link :: transfer_complete(const transfer_id &id) { - e::compat::shared_ptr r(new rpc()); - r->func = "transfer_complete"; - r->flags = REPLICANT_CALL_IDEMPOTENT; - e::packer(&r->input) << id; - make_rpc(r); + e::compat::shared_ptr r(new rpc()); + r->func = "transfer_complete"; + r->flags = REPLICANT_CALL_IDEMPOTENT; + e::packer(&r->input) << id; + make_rpc(r); } void -coordinator_link :: report_tcp_disconnect(uint64_t config_version, const server_id& id) +coordinator_link :: report_tcp_disconnect(uint64_t config_version, const server_id &id) { - e::compat::shared_ptr r(new rpc()); - r->func = "report_disconnect"; - r->flags = REPLICANT_CALL_IDEMPOTENT; - e::packer(&r->input) << config_version << id; - make_rpc(r); + e::compat::shared_ptr r(new rpc()); + r->func = "report_disconnect"; + r->flags = REPLICANT_CALL_IDEMPOTENT; + e::packer(&r->input) << config_version << id; + make_rpc(r); } void coordinator_link :: make_rpc(e::compat::shared_ptr r) { - po6::threads::mutex::hold hold(&m_mtx); - make_rpc_no_synchro(r); + po6::threads::mutex::hold hold(&m_mtx); + make_rpc_no_synchro(r); } void coordinator_link :: make_rpc_no_synchro(e::compat::shared_ptr r) { - int64_t id = replicant_client_call(m_repl, "hyperdex", r->func.c_str(), - r->input.data(), r->input.size(), r->flags, - &r->status, &r->output, &r->output_sz); - - if (id < 0) - { - LOG(ERROR) << "call to coordinator method \"" << r->func - << "\" failed: " << replicant_client_error_message(m_repl); - } - else - { - m_rpcs.insert(std::make_pair(id, r)); - } + int64_t id = replicant_client_call(m_repl, "hyperdex", r->func.c_str(), + r->input.data(), r->input.size(), r->flags, + &r->status, &r->output, &r->output_sz); + if (id < 0) + { + LOG(ERROR) << "call to coordinator method \"" << r->func + << "\" failed: " << replicant_client_error_message(m_repl); + } + else + { + m_rpcs.insert(std::make_pair(id, r)); + } } bool -coordinator_link :: synchronous_call(const char* log_action, const char* func, - const char* input, size_t input_sz, - char** output, size_t* output_sz) +coordinator_link :: synchronous_call(const char *log_action, const char *func, + const char *input, size_t input_sz, + char **output, size_t *output_sz) { - po6::threads::mutex::hold hold(&m_mtx); - replicant_returncode status; - int64_t rid = replicant_client_call(m_repl, "hyperdex", func, input, input_sz, - REPLICANT_CALL_ROBUST, &status, output, output_sz); - - if (rid < 0) - { - LOG(ERROR) << "could not " << log_action << ": " - << replicant_client_error_message(m_repl); - LOG(INFO) << "error [" << replicant_returncode_to_string(status) - << "] at " << replicant_client_error_location(m_repl); - return false; - } - - replicant_returncode lstatus = REPLICANT_GARBAGE; - int64_t lid = replicant_client_wait(m_repl, rid, -1, &lstatus); - - if (lid < 0) - { - LOG(ERROR) << "could not " << log_action << ": " - << replicant_client_error_message(m_repl); - LOG(INFO) << "error [" << replicant_returncode_to_string(status) - << "] at " << replicant_client_error_location(m_repl); - return false; - } - - assert(lid == rid); - - if (status != REPLICANT_SUCCESS) - { - LOG(ERROR) << "could not " << log_action << ": " - << replicant_client_error_message(m_repl); - LOG(INFO) << "error [" << replicant_returncode_to_string(status) - << "] at " << replicant_client_error_location(m_repl); - return false; - } - - return true; + po6::threads::mutex::hold hold(&m_mtx); + replicant_returncode status; + int64_t rid = replicant_client_call(m_repl, "hyperdex", func, input, input_sz, + REPLICANT_CALL_ROBUST, &status, output, output_sz); + if (rid < 0) + { + LOG(ERROR) << "could not " << log_action << ": " + << replicant_client_error_message(m_repl); + LOG(INFO) << "error [" << replicant_returncode_to_string(status) + << "] at " << replicant_client_error_location(m_repl); + return false; + } + replicant_returncode lstatus = REPLICANT_GARBAGE; + int64_t lid = replicant_client_wait(m_repl, rid, -1, &lstatus); + if (lid < 0) + { + LOG(ERROR) << "could not " << log_action << ": " + << replicant_client_error_message(m_repl); + LOG(INFO) << "error [" << replicant_returncode_to_string(status) + << "] at " << replicant_client_error_location(m_repl); + return false; + } + assert(lid == rid); + if (status != REPLICANT_SUCCESS) + { + LOG(ERROR) << "could not " << log_action << ": " + << replicant_client_error_message(m_repl); + LOG(INFO) << "error [" << replicant_returncode_to_string(status) + << "] at " << replicant_client_error_location(m_repl); + return false; + } + return true; } bool -coordinator_link :: process_configuration(const char* str, size_t str_sz) +coordinator_link :: process_configuration(const char *str, size_t str_sz) { - e::unpacker up(str, str_sz); - configuration config; - up = up >> config; - - if (up.error()) - { - return false; - } - - m_config = config; - return true; + e::unpacker up(str, str_sz); + configuration config; + up = up >> config; + if (up.error()) + { + return false; + } + m_config = config; + return true; } bool coordinator_link :: bring_online() { - std::string enter_input; - e::packer(&enter_input) << m_daemon->m_us << m_daemon->m_bind_to; - std::string exit_input; - e::packer(&exit_input) << m_daemon->m_us; - - if (replicant_client_defended_call(m_repl, "hyperdex", - "server_online", enter_input.data(), enter_input.size(), - "server_suspect", exit_input.data(), exit_input.size(), - &m_throwaway_status) < 0) - { - LOG(ERROR) << "error bringing server online: " << replicant_client_error_message(m_repl); - LOG(INFO) << "error [" << replicant_returncode_to_string(m_throwaway_status) - << "] at " << replicant_client_error_location(m_repl); - increment_sleep(&m_sleep_ms); - return false; - } - - return true; + std::string enter_input; + e::packer(&enter_input) << m_daemon->m_us << m_daemon->m_bind_to; + std::string exit_input; + e::packer(&exit_input) << m_daemon->m_us; + if (replicant_client_defended_call(m_repl, "hyperdex", + "server_online", enter_input.data(), enter_input.size(), + "server_suspect", exit_input.data(), exit_input.size(), + &m_throwaway_status) < 0) + { + LOG(ERROR) << "error bringing server online: " << replicant_client_error_message(m_repl); + LOG(INFO) << "error [" << replicant_returncode_to_string(m_throwaway_status) + << "] at " << replicant_client_error_location(m_repl); + increment_sleep(&m_sleep_ms); + return false; + } + return true; } diff --git a/daemon/coordinator_link.h b/daemon/coordinator_link.h index 0b74e88ab..f4c9111b9 100644 --- a/daemon/coordinator_link.h +++ b/daemon/coordinator_link.h @@ -50,71 +50,71 @@ class daemon; class coordinator_link { - public: - coordinator_link(daemon* d, const char* host, uint16_t port); - coordinator_link(daemon* d, const char* conn_str); - ~coordinator_link() throw (); +public: + coordinator_link(daemon *d, const char *host, uint16_t port); + coordinator_link(daemon *d, const char *conn_str); + ~coordinator_link() throw (); - // external synchro required - public: - bool register_server(server_id us, const po6::net::location& bind_to); - bool initialize(); - bool maintain(); - void shutdown(); - const configuration& config() { return m_config; } - uint64_t checkpoint_config_version() { return m_value_checkpoint_config_version; } - uint64_t checkpoint() { return m_value_checkpoint; } - uint64_t checkpoint_stable() { return m_value_checkpoint_stable; } - uint64_t checkpoint_gc() { return m_value_checkpoint_gc; } + // external synchro required +public: + bool register_server(server_id us, const po6::net::location &bind_to); + bool initialize(); + bool maintain(); + void shutdown(); + const configuration &config() { return m_config; } + uint64_t checkpoint_config_version() { return m_value_checkpoint_config_version; } + uint64_t checkpoint() { return m_value_checkpoint; } + uint64_t checkpoint_stable() { return m_value_checkpoint_stable; } + uint64_t checkpoint_gc() { return m_value_checkpoint_gc; } - // internally synchronized - public: - void config_ack(uint64_t config_version); - void config_stable(uint64_t config_version); - void checkpoint_report_stable(uint64_t config_version); - void transfer_go_live(const transfer_id& id); - void transfer_complete(const transfer_id& id); - void report_tcp_disconnect(uint64_t config_version, const server_id& id); + // internally synchronized +public: + void config_ack(uint64_t config_version); + void config_stable(uint64_t config_version); + void checkpoint_report_stable(uint64_t config_version); + void transfer_go_live(const transfer_id &id); + void transfer_complete(const transfer_id &id); + void report_tcp_disconnect(uint64_t config_version, const server_id &id); - private: - struct rpc; - void make_rpc(e::compat::shared_ptr r); - void make_rpc_no_synchro(e::compat::shared_ptr r); - bool synchronous_call(const char* log_action, const char* func, - const char* input, size_t input_sz, - char** output, size_t* output_sz); - bool process_configuration(const char* config, size_t config_sz); - bool bring_online(); +private: + struct rpc; + void make_rpc(e::compat::shared_ptr r); + void make_rpc_no_synchro(e::compat::shared_ptr r); + bool synchronous_call(const char *log_action, const char *func, + const char *input, size_t input_sz, + char **output, size_t *output_sz); + bool process_configuration(const char *config, size_t config_sz); + bool bring_online(); - private: - daemon* m_daemon; - unsigned m_sleep_ms; - // configuration - configuration m_config; - int64_t m_config_id; - replicant_returncode m_config_status; - uint64_t m_config_state; - char* m_config_data; - size_t m_config_data_sz; - // checkpoints - int64_t m_checkpoint_id; - replicant_returncode m_checkpoint_status; - uint64_t m_checkpoint_state; - char* m_checkpoint_data; - size_t m_checkpoint_data_sz; - uint64_t m_value_checkpoint_config_version; - uint64_t m_value_checkpoint; - uint64_t m_value_checkpoint_stable; - uint64_t m_value_checkpoint_gc; - // other RPCs - replicant_returncode m_throwaway_status; - po6::threads::mutex m_mtx; - replicant_client* m_repl; - std::map > m_rpcs; +private: + daemon *m_daemon; + unsigned m_sleep_ms; + // configuration + configuration m_config; + int64_t m_config_id; + replicant_returncode m_config_status; + uint64_t m_config_state; + char *m_config_data; + size_t m_config_data_sz; + // checkpoints + int64_t m_checkpoint_id; + replicant_returncode m_checkpoint_status; + uint64_t m_checkpoint_state; + char *m_checkpoint_data; + size_t m_checkpoint_data_sz; + uint64_t m_value_checkpoint_config_version; + uint64_t m_value_checkpoint; + uint64_t m_value_checkpoint_stable; + uint64_t m_value_checkpoint_gc; + // other RPCs + replicant_returncode m_throwaway_status; + po6::threads::mutex m_mtx; + replicant_client *m_repl; + std::map > m_rpcs; - private: - coordinator_link(const coordinator_link&); - coordinator_link& operator = (const coordinator_link&); +private: + coordinator_link(const coordinator_link &); + coordinator_link &operator = (const coordinator_link &); }; END_HYPERDEX_NAMESPACE diff --git a/daemon/daemon.cc b/daemon/daemon.cc index ad81afb78..b2f768e63 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -70,107 +70,104 @@ bool s_debug = false; static void exit_on_signal(int /*signum*/) { - if (__sync_fetch_and_add(&s_interrupts, 1) == 0) - { - RAW_LOG(ERROR, "interrupted: initiating shutdown; we'll try for up to 10 seconds (interrupt again to exit immediately)"); - } - else - { - RAW_LOG(ERROR, "interrupted again: exiting immediately"); - } + if (__sync_fetch_and_add(&s_interrupts, 1) == 0) + { + RAW_LOG(ERROR, "interrupted: initiating shutdown; we'll try for up to 10 seconds (interrupt again to exit immediately)"); + } + else + { + RAW_LOG(ERROR, "interrupted again: exiting immediately"); + } } static void exit_after_timeout(int /*signum*/) { - __sync_fetch_and_add(&s_interrupts, 1); - RAW_LOG(ERROR, "took too long to shutdown; just exiting"); + __sync_fetch_and_add(&s_interrupts, 1); + RAW_LOG(ERROR, "took too long to shutdown; just exiting"); } static void handle_debug(int /*signum*/) { - s_debug = true; + s_debug = true; } daemon :: daemon() - : m_us() - , m_bind_to() - , m_threads() - , m_gc() - , m_gc_ts() - , m_coord() - , m_data_dir() - , m_data(this) - , m_comm(this) - , m_repl(this) - , m_stm(this) - , m_sm(this) - , m_config() - , m_protect_pause() - , m_can_pause(&m_protect_pause) - , m_paused(false) - , m_perf_req_get() - , m_perf_req_get_partial() - , m_perf_req_atomic() - , m_perf_req_search_start() - , m_perf_req_search_next() - , m_perf_req_search_stop() - , m_perf_req_sorted_search() - , m_perf_req_count() - , m_perf_req_search_describe() - , m_perf_req_group_atomic() - , m_perf_chain_op() - , m_perf_chain_subspace() - , m_perf_chain_ack() - , m_perf_xfer_handshake_syn() - , m_perf_xfer_handshake_synack() - , m_perf_xfer_handshake_ack() - , m_perf_xfer_handshake_wiped() - , m_perf_xfer_op() - , m_perf_xfer_ack() - , m_perf_backup() - , m_perf_perf_counters() - , m_block_stat_path() - , m_stat_collector(make_thread_wrapper(&daemon::collect_stats, this)) - , m_protect_stats() - , m_stats_start(0) - , m_stats() + : m_us() + , m_bind_to() + , m_threads() + , m_gc() + , m_gc_ts() + , m_coord() + , m_data_dir() + , m_data(this) + , m_comm(this) + , m_repl(this) + , m_stm(this) + , m_sm(this) + , m_config() + , m_protect_pause() + , m_can_pause(&m_protect_pause) + , m_paused(false) + , m_perf_req_get() + , m_perf_req_get_partial() + , m_perf_req_atomic() + , m_perf_req_search_start() + , m_perf_req_search_next() + , m_perf_req_search_stop() + , m_perf_req_sorted_search() + , m_perf_req_count() + , m_perf_req_search_describe() + , m_perf_req_group_atomic() + , m_perf_chain_op() + , m_perf_chain_subspace() + , m_perf_chain_ack() + , m_perf_xfer_handshake_syn() + , m_perf_xfer_handshake_synack() + , m_perf_xfer_handshake_ack() + , m_perf_xfer_handshake_wiped() + , m_perf_xfer_op() + , m_perf_xfer_ack() + , m_perf_backup() + , m_perf_perf_counters() + , m_block_stat_path() + , m_stat_collector(make_thread_wrapper(&daemon::collect_stats, this)) + , m_protect_stats() + , m_stats_start(0) + , m_stats() { - m_gc.register_thread(&m_gc_ts); + m_gc.register_thread(&m_gc_ts); } daemon :: ~daemon() throw () { - m_gc.deregister_thread(&m_gc_ts); + m_gc.deregister_thread(&m_gc_ts); } static bool install_signal_handler(int signum, void (*f)(int)) { - struct sigaction handle; - handle.sa_handler = f; - sigfillset(&handle.sa_mask); - handle.sa_flags = SA_RESTART; - return sigaction(signum, &handle, NULL) >= 0; + struct sigaction handle; + handle.sa_handler = f; + sigfillset(&handle.sa_mask); + handle.sa_flags = SA_RESTART; + return sigaction(signum, &handle, NULL) >= 0; } static bool -generate_token(uint64_t* token) +generate_token(uint64_t *token) { - po6::io::fd sysrand(open("/dev/urandom", O_RDONLY)); - - if (sysrand.get() < 0) - { - return false; - } - - if (sysrand.read(token, sizeof(*token)) != sizeof(*token)) - { - return false; - } - - return true; + po6::io::fd sysrand(open("/dev/urandom", O_RDONLY)); + if (sysrand.get() < 0) + { + return false; + } + if (sysrand.read(token, sizeof(*token)) != sizeof(*token)) + { + return false; + } + return true; } int @@ -185,512 +182,453 @@ daemon :: run(bool daemonize, po6::net::hostname coordinator, unsigned threads) { - if (!install_signal_handler(SIGHUP, exit_on_signal) || - !install_signal_handler(SIGINT, exit_on_signal) || - !install_signal_handler(SIGTERM, exit_on_signal) || - !install_signal_handler(SIGUSR2, handle_debug)) - { - std::cerr << "could not install signal handlers: " << po6::strerror(errno) << std::endl; - return EXIT_FAILURE; - } - - sigset_t ss; - - if (sigfillset(&ss) < 0 || - pthread_sigmask(SIG_SETMASK, &ss, NULL) < 0) - { - std::cerr << "could not block signals: " << po6::strerror(errno) << std::endl; - return EXIT_FAILURE; - } - - google::LogToStderr(); - - if (daemonize) - { - struct stat x; - - if (lstat(log.c_str(), &x) < 0 || !S_ISDIR(x.st_mode)) - { - LOG(ERROR) << "cannot fork off to the background because " - << log.c_str() << " does not exist or is not writable"; - return EXIT_FAILURE; - } - - if (!has_pidfile) - { - LOG(INFO) << "forking off to the background"; - LOG(INFO) << "you can find the log at " << log.c_str() << "/hyperdex-daemon-YYYYMMDD-HHMMSS.sssss"; - LOG(INFO) << "provide \"--foreground\" on the command-line if you want to run in the foreground"; - } - - google::SetLogSymlink(google::INFO, ""); - google::SetLogSymlink(google::WARNING, ""); - google::SetLogSymlink(google::ERROR, ""); - google::SetLogSymlink(google::FATAL, ""); - log = po6::path::join(log, "hyperdex-daemon-"); - google::SetLogDestination(google::INFO, log.c_str()); - - if (::daemon(1, 0) < 0) - { - PLOG(ERROR) << "could not daemonize"; - return EXIT_FAILURE; - } - - if (has_pidfile) - { - char buf[21]; - ssize_t buf_sz = sprintf(buf, "%d\n", getpid()); - assert(buf_sz < static_cast(sizeof(buf))); - po6::io::fd pid(open(pidfile.c_str(), O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)); - - if (pid.get() < 0 || pid.xwrite(buf, buf_sz) != buf_sz) - { - PLOG(ERROR) << "could not create pidfile " << pidfile.c_str(); - return EXIT_FAILURE; - } - } - } - else - { - LOG(INFO) << "running in the foreground"; - LOG(INFO) << "no log will be generated; instead, the log messages will print to the terminal"; - LOG(INFO) << "provide \"--daemon\" on the command-line if you want to run in the background"; - } - - bool saved = false; - server_id saved_us; - po6::net::location saved_bind_to; - po6::net::hostname saved_coordinator; - LOG(INFO) << "initializing local storage"; - m_data_dir = data; - - if (!m_data.initialize(data, &saved, &saved_us, &saved_bind_to, &saved_coordinator)) - { - return EXIT_FAILURE; - } - - if (po6::path::dirname(data).size()) - { - if (chdir(po6::path::dirname(data).c_str()) < 0) - { - PLOG(ERROR) << "could not change cwd to data directory"; - return EXIT_FAILURE; - } - } - - if (saved) - { - if (set_bind_to && bind_to != saved_bind_to) - { - LOG(INFO) << "changing bind address from " - << saved_bind_to << " to " << bind_to; - } - else - { - bind_to = saved_bind_to; - } - - if (set_coordinator && coordinator != saved_coordinator) - { - LOG(INFO) << "changing coordinator address from " - << saved_coordinator << " to " << coordinator; - } - else - { - coordinator = saved_coordinator; - } - - m_us = saved_us; - } - - m_bind_to = bind_to; - m_coord.reset(new coordinator_link(this, coordinator.address.c_str(), coordinator.port)); - - if (!saved) - { - uint64_t sid; - - if (!generate_token(&sid)) - { - PLOG(ERROR) << "could not read random token from /dev/urandom"; - return EXIT_FAILURE; - } - - LOG(INFO) << "generated new random token: " << sid; - - if (!m_coord->register_server(server_id(sid), bind_to)) - { - return EXIT_FAILURE; - } - - m_us = server_id(sid); - } - - if (!m_data.save_state(m_us, bind_to, coordinator)) - { - return EXIT_FAILURE; - } - - if (!m_coord->initialize()) - { - return EXIT_FAILURE; - } - - determine_block_stat_path(data); - m_comm.setup(bind_to, threads); - m_repl.setup(); - m_stm.setup(); - m_sm.setup(); - - for (size_t i = 0; i < threads; ++i) - { - using namespace po6::threads; - e::compat::shared_ptr t(new thread(make_thread_wrapper(&daemon::loop, this, i))); - m_threads.push_back(t); - t->start(); - } - - m_stat_collector.start(); - uint64_t checkpoint = 0; - uint64_t checkpoint_stable = 0; - uint64_t checkpoint_gc = 0; - - while (__sync_fetch_and_add(&s_interrupts, 0) < 2) - { - if (s_debug) - { - s_debug = false; - LOG(INFO) << "recieved SIGUSR2; dumping internal tables"; - m_data.debug_dump(); - m_repl.debug_dump(); - m_stm.debug_dump(); - LOG(INFO) << "end debug dump"; - } - - if (__sync_fetch_and_add(&s_interrupts, 0) == 1) - { - if (!install_signal_handler(SIGALRM, exit_after_timeout)) - { - __sync_fetch_and_add(&s_interrupts, 2); - break; - } - - alarm(10); - m_coord->shutdown(); - } - - if (m_config.version() > 0 && - m_config.version() == m_coord->checkpoint_config_version() && - checkpoint < m_coord->checkpoint()) - { - checkpoint = m_coord->checkpoint(); - m_repl.begin_checkpoint(checkpoint); - } - - if (m_config.version() > 0 && - m_config.version() == m_coord->checkpoint_config_version() && - checkpoint_stable < m_coord->checkpoint_stable()) - { - checkpoint_stable = m_coord->checkpoint_stable(); - m_repl.end_checkpoint(checkpoint_stable); - } - - if (m_config.version() > 0 && - m_config.version() == m_coord->checkpoint_config_version() && - checkpoint_gc < m_coord->checkpoint_gc()) - { - checkpoint_gc = m_coord->checkpoint_gc(); - m_data.set_checkpoint_gc(checkpoint_gc); - } - - - m_gc.offline(&m_gc_ts); - bool have_config = m_coord->maintain(); - m_gc.online(&m_gc_ts); - - if (!have_config) - { - continue; - } - - const configuration& old_config(m_config); - const configuration& new_config(m_coord->config()); - - if (old_config.cluster() != 0 && - old_config.cluster() != new_config.cluster()) - { - LOG(ERROR) << "================================================================================"; - LOG(ERROR) << "Exiting because the coordinator changed on us."; - LOG(ERROR) << "This is most likely the result of deploying a new cluster in place of an"; - LOG(ERROR) << "existing cluster, and then switching daemons from the old cluster to the new"; - LOG(ERROR) << "cluster. To protect data on this node, it will exit."; - LOG(ERROR) << "To fix this issue, use the --coordinator flag to specify the coordinator"; - LOG(ERROR) << "that this HyperDex data node was originally connected to."; - LOG(ERROR) << "================================================================================"; - break; - } - - if (__sync_fetch_and_add(&s_interrupts, 0) > 0 && - m_coord->config().get_state(m_us) == server::SHUTDOWN) - { - break; - } - - if (!new_config.exists(m_us)) - { - LOG(ERROR) << "================================================================================"; - LOG(ERROR) << "Exiting because the coordinator does not know about this node."; - LOG(ERROR) << "This is most likely the result of running the command"; - LOG(ERROR) << "\t\"hyperdex server-forget " << m_us.get() << "\""; - LOG(ERROR) << "If you can verify that the cluster is otherwise operational,"; - LOG(ERROR) << "you should be able to delete the data directory of this node"; - LOG(ERROR) << "and re-connect it to the cluster under a different identity."; - LOG(ERROR) << "================================================================================"; - break; - } - - if (old_config.version() > new_config.version()) - { - LOG(ERROR) << "received new configuration version=" << new_config.version() - << " that's older than our current configuration version=" - << old_config.version(); - continue; - } - else if (old_config.version() >= new_config.version()) - { - continue; - } - - LOG(INFO) << "moving to configuration version=" << new_config.version() - << "; pausing all activity while we reconfigure"; - this->pause(); - m_comm.reconfigure(old_config, new_config, m_us); - m_data.reconfigure(old_config, new_config, m_us); - m_repl.reconfigure(old_config, new_config, m_us); - m_stm.reconfigure(old_config, new_config, m_us); - m_sm.reconfigure(old_config, new_config, m_us); - m_config = new_config; - this->unpause(); - LOG(INFO) << "reconfiguration complete; resuming normal operation"; - - // let the coordinator know we've moved to this config - m_coord->config_ack(new_config.version()); - } - - __sync_fetch_and_add(&s_interrupts, 2); - m_stat_collector.join(); - m_comm.shutdown(); - - for (size_t i = 0; i < m_threads.size(); ++i) - { - m_threads[i]->join(); - } - - m_sm.teardown(); - m_stm.teardown(); - m_repl.teardown(); - m_comm.teardown(); - m_data.teardown(); - LOG(INFO) << "hyperdex-daemon will now terminate"; - return EXIT_SUCCESS; + if (!install_signal_handler(SIGHUP, exit_on_signal) || + !install_signal_handler(SIGINT, exit_on_signal) || + !install_signal_handler(SIGTERM, exit_on_signal) || + !install_signal_handler(SIGUSR2, handle_debug)) + { + std::cerr << "could not install signal handlers: " << po6::strerror(errno) << std::endl; + return EXIT_FAILURE; + } + sigset_t ss; + if (sigfillset(&ss) < 0 || + pthread_sigmask(SIG_SETMASK, &ss, NULL) < 0) + { + std::cerr << "could not block signals: " << po6::strerror(errno) << std::endl; + return EXIT_FAILURE; + } + google::LogToStderr(); + if (daemonize) + { + struct stat x; + if (lstat(log.c_str(), &x) < 0 || !S_ISDIR(x.st_mode)) + { + LOG(ERROR) << "cannot fork off to the background because " + << log.c_str() << " does not exist or is not writable"; + return EXIT_FAILURE; + } + if (!has_pidfile) + { + LOG(INFO) << "forking off to the background"; + LOG(INFO) << "you can find the log at " << log.c_str() << "/hyperdex-daemon-YYYYMMDD-HHMMSS.sssss"; + LOG(INFO) << "provide \"--foreground\" on the command-line if you want to run in the foreground"; + } + google::SetLogSymlink(google::INFO, ""); + google::SetLogSymlink(google::WARNING, ""); + google::SetLogSymlink(google::ERROR, ""); + google::SetLogSymlink(google::FATAL, ""); + log = po6::path::join(log, "hyperdex-daemon-"); + google::SetLogDestination(google::INFO, log.c_str()); + if (::daemon(1, 0) < 0) + { + PLOG(ERROR) << "could not daemonize"; + return EXIT_FAILURE; + } + if (has_pidfile) + { + char buf[21]; + ssize_t buf_sz = sprintf(buf, "%d\n", getpid()); + assert(buf_sz < static_cast(sizeof(buf))); + po6::io::fd pid(open(pidfile.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); + if (pid.get() < 0 || pid.xwrite(buf, buf_sz) != buf_sz) + { + PLOG(ERROR) << "could not create pidfile " << pidfile.c_str(); + return EXIT_FAILURE; + } + } + } + else + { + LOG(INFO) << "running in the foreground"; + LOG(INFO) << "no log will be generated; instead, the log messages will print to the terminal"; + LOG(INFO) << "provide \"--daemon\" on the command-line if you want to run in the background"; + } + bool saved = false; + server_id saved_us; + po6::net::location saved_bind_to; + po6::net::hostname saved_coordinator; + LOG(INFO) << "initializing local storage"; + m_data_dir = data; + if (!m_data.initialize(data, &saved, &saved_us, &saved_bind_to, &saved_coordinator)) + { + return EXIT_FAILURE; + } + if (po6::path::dirname(data).size()) + { + if (chdir(po6::path::dirname(data).c_str()) < 0) + { + PLOG(ERROR) << "could not change cwd to data directory"; + return EXIT_FAILURE; + } + } + if (saved) + { + if (set_bind_to && bind_to != saved_bind_to) + { + LOG(INFO) << "changing bind address from " + << saved_bind_to << " to " << bind_to; + } + else + { + bind_to = saved_bind_to; + } + if (set_coordinator && coordinator != saved_coordinator) + { + LOG(INFO) << "changing coordinator address from " + << saved_coordinator << " to " << coordinator; + } + else + { + coordinator = saved_coordinator; + } + m_us = saved_us; + } + m_bind_to = bind_to; + m_coord.reset(new coordinator_link(this, coordinator.address.c_str(), coordinator.port)); + if (!saved) + { + uint64_t sid; + if (!generate_token(&sid)) + { + PLOG(ERROR) << "could not read random token from /dev/urandom"; + return EXIT_FAILURE; + } + LOG(INFO) << "generated new random token: " << sid; + if (!m_coord->register_server(server_id(sid), bind_to)) + { + return EXIT_FAILURE; + } + m_us = server_id(sid); + } + if (!m_data.save_state(m_us, bind_to, coordinator)) + { + return EXIT_FAILURE; + } + if (!m_coord->initialize()) + { + return EXIT_FAILURE; + } + determine_block_stat_path(data); + m_comm.setup(bind_to, threads); + m_repl.setup(); + m_stm.setup(); + m_sm.setup(); + for (size_t i = 0; i < threads; ++i) + { + using namespace po6::threads; + e::compat::shared_ptr t(new thread(make_thread_wrapper(&daemon::loop, this, i))); + m_threads.push_back(t); + t->start(); + } + m_stat_collector.start(); + uint64_t checkpoint = 0; + uint64_t checkpoint_stable = 0; + uint64_t checkpoint_gc = 0; + while (__sync_fetch_and_add(&s_interrupts, 0) < 2) + { + if (s_debug) + { + s_debug = false; + LOG(INFO) << "recieved SIGUSR2; dumping internal tables"; + m_data.debug_dump(); + m_repl.debug_dump(); + m_stm.debug_dump(); + LOG(INFO) << "end debug dump"; + } + if (__sync_fetch_and_add(&s_interrupts, 0) == 1) + { + if (!install_signal_handler(SIGALRM, exit_after_timeout)) + { + __sync_fetch_and_add(&s_interrupts, 2); + break; + } + alarm(10); + m_coord->shutdown(); + } + if (m_config.version() > 0 && + m_config.version() == m_coord->checkpoint_config_version() && + checkpoint < m_coord->checkpoint()) + { + checkpoint = m_coord->checkpoint(); + m_repl.begin_checkpoint(checkpoint); + } + if (m_config.version() > 0 && + m_config.version() == m_coord->checkpoint_config_version() && + checkpoint_stable < m_coord->checkpoint_stable()) + { + checkpoint_stable = m_coord->checkpoint_stable(); + m_repl.end_checkpoint(checkpoint_stable); + } + if (m_config.version() > 0 && + m_config.version() == m_coord->checkpoint_config_version() && + checkpoint_gc < m_coord->checkpoint_gc()) + { + checkpoint_gc = m_coord->checkpoint_gc(); + m_data.set_checkpoint_gc(checkpoint_gc); + } + m_gc.offline(&m_gc_ts); + bool have_config = m_coord->maintain(); + m_gc.online(&m_gc_ts); + if (!have_config) + { + continue; + } + const configuration &old_config(m_config); + const configuration &new_config(m_coord->config()); + if (old_config.cluster() != 0 && + old_config.cluster() != new_config.cluster()) + { + LOG(ERROR) << "================================================================================"; + LOG(ERROR) << "Exiting because the coordinator changed on us."; + LOG(ERROR) << "This is most likely the result of deploying a new cluster in place of an"; + LOG(ERROR) << "existing cluster, and then switching daemons from the old cluster to the new"; + LOG(ERROR) << "cluster. To protect data on this node, it will exit."; + LOG(ERROR) << "To fix this issue, use the --coordinator flag to specify the coordinator"; + LOG(ERROR) << "that this HyperDex data node was originally connected to."; + LOG(ERROR) << "================================================================================"; + break; + } + if (__sync_fetch_and_add(&s_interrupts, 0) > 0 && + m_coord->config().get_state(m_us) == server::SHUTDOWN) + { + break; + } + if (!new_config.exists(m_us)) + { + LOG(ERROR) << "================================================================================"; + LOG(ERROR) << "Exiting because the coordinator does not know about this node."; + LOG(ERROR) << "This is most likely the result of running the command"; + LOG(ERROR) << "\t\"hyperdex server-forget " << m_us.get() << "\""; + LOG(ERROR) << "If you can verify that the cluster is otherwise operational,"; + LOG(ERROR) << "you should be able to delete the data directory of this node"; + LOG(ERROR) << "and re-connect it to the cluster under a different identity."; + LOG(ERROR) << "================================================================================"; + break; + } + if (old_config.version() > new_config.version()) + { + LOG(ERROR) << "received new configuration version=" << new_config.version() + << " that's older than our current configuration version=" + << old_config.version(); + continue; + } + else if (old_config.version() >= new_config.version()) + { + continue; + } + LOG(INFO) << "moving to configuration version=" << new_config.version() + << "; pausing all activity while we reconfigure"; + this->pause(); + m_comm.reconfigure(old_config, new_config, m_us); + m_data.reconfigure(old_config, new_config, m_us); + m_repl.reconfigure(old_config, new_config, m_us); + m_stm.reconfigure(old_config, new_config, m_us); + m_sm.reconfigure(old_config, new_config, m_us); + m_config = new_config; + this->unpause(); + LOG(INFO) << "reconfiguration complete; resuming normal operation"; + // let the coordinator know we've moved to this config + m_coord->config_ack(new_config.version()); + } + __sync_fetch_and_add(&s_interrupts, 2); + m_stat_collector.join(); + m_comm.shutdown(); + for (size_t i = 0; i < m_threads.size(); ++i) + { + m_threads[i]->join(); + } + m_sm.teardown(); + m_stm.teardown(); + m_repl.teardown(); + m_comm.teardown(); + m_data.teardown(); + LOG(INFO) << "hyperdex-daemon will now terminate"; + return EXIT_SUCCESS; } void daemon :: pause() { - po6::threads::mutex::hold hold(&m_protect_pause); - - while (m_paused) - { - m_can_pause.wait(); - } - - m_paused = true; - m_sm.pause(); - m_stm.pause(); - m_repl.pause(); - m_data.pause(); - m_comm.pause(); + po6::threads::mutex::hold hold(&m_protect_pause); + while (m_paused) + { + m_can_pause.wait(); + } + m_paused = true; + m_sm.pause(); + m_stm.pause(); + m_repl.pause(); + m_data.pause(); + m_comm.pause(); } void daemon :: unpause() { - po6::threads::mutex::hold hold(&m_protect_pause); - m_comm.unpause(); - m_data.unpause(); - m_repl.unpause(); - m_stm.unpause(); - m_sm.unpause(); - assert(m_paused); - m_paused = false; - m_can_pause.signal(); + po6::threads::mutex::hold hold(&m_protect_pause); + m_comm.unpause(); + m_data.unpause(); + m_repl.unpause(); + m_stm.unpause(); + m_sm.unpause(); + assert(m_paused); + m_paused = false; + m_can_pause.signal(); } void daemon :: loop(size_t thread) { - sigset_t ss; - - size_t core = thread % sysconf(_SC_NPROCESSORS_ONLN); + sigset_t ss; + size_t core = thread % sysconf(_SC_NPROCESSORS_ONLN); #ifdef __LINUX__ - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET(core, &cpuset); - pthread_t cur = pthread_self(); - int x = pthread_setaffinity_np(cur, sizeof(cpu_set_t), &cpuset); - assert(x == 0); + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(core, &cpuset); + pthread_t cur = pthread_self(); + int x = pthread_setaffinity_np(cur, sizeof(cpu_set_t), &cpuset); + assert(x == 0); #elif defined(__APPLE__) - thread_affinity_policy_data_t policy; - policy.affinity_tag = 0; - thread_policy_set(mach_thread_self(), - THREAD_AFFINITY_POLICY, - (thread_policy_t)&policy, - THREAD_AFFINITY_POLICY_COUNT); + thread_affinity_policy_data_t policy; + policy.affinity_tag = 0; + thread_policy_set(mach_thread_self(), + THREAD_AFFINITY_POLICY, + (thread_policy_t)&policy, + THREAD_AFFINITY_POLICY_COUNT); #endif - - LOG(INFO) << "network thread " << thread << " started on core " << core; - - if (sigfillset(&ss) < 0) - { - PLOG(ERROR) << "sigfillset"; - return; - } - - sigdelset(&ss, SIGPROF); - - if (pthread_sigmask(SIG_SETMASK, &ss, NULL) < 0) - { - PLOG(ERROR) << "could not block signals"; - return; - } - - e::garbage_collector::thread_state ts; - m_gc.register_thread(&ts); - - server_id from; - virtual_server_id vfrom; - virtual_server_id vto; - network_msgtype type; - std::auto_ptr msg; - e::unpacker up; - - while (m_comm.recv(&ts, &from, &vfrom, &vto, &type, &msg, &up)) - { - assert(from != server_id()); - assert(vto != virtual_server_id()); - - switch (type) - { - case REQ_GET: - process_req_get(from, vfrom, vto, msg, up); - m_perf_req_get.tap(); - break; - case REQ_GET_PARTIAL: - process_req_get_partial(from, vfrom, vto, msg, up); - m_perf_req_get_partial.tap(); - break; - case REQ_ATOMIC: - process_req_atomic(from, vfrom, vto, msg, up); - m_perf_req_atomic.tap(); - break; - case REQ_SEARCH_START: - process_req_search_start(from, vfrom, vto, msg, up); - m_perf_req_search_start.tap(); - break; - case REQ_SEARCH_NEXT: - process_req_search_next(from, vfrom, vto, msg, up); - m_perf_req_search_next.tap(); - break; - case REQ_SEARCH_STOP: - process_req_search_stop(from, vfrom, vto, msg, up); - m_perf_req_search_stop.tap(); - break; - case REQ_SORTED_SEARCH: - process_req_sorted_search(from, vfrom, vto, msg, up); - m_perf_req_sorted_search.tap(); - break; - case REQ_COUNT: - process_req_count(from, vfrom, vto, msg, up); - m_perf_req_count.tap(); - break; - case REQ_SUM: - process_req_sum(from, vfrom, vto, msg, up); - m_perf_req_sum.tap(); - break; - case REQ_SEARCH_DESCRIBE: - process_req_search_describe(from, vfrom, vto, msg, up); - m_perf_req_search_describe.tap(); - break; - case REQ_GROUP_ATOMIC: - process_req_group_atomic(from, vfrom, vto, msg, up); - m_perf_req_group_atomic.tap(); - break; - case CHAIN_OP: - process_chain_op(from, vfrom, vto, msg, up); - m_perf_chain_op.tap(); - break; - case CHAIN_SUBSPACE: - process_chain_subspace(from, vfrom, vto, msg, up); - m_perf_chain_subspace.tap(); - break; - case CHAIN_ACK: - process_chain_ack(from, vfrom, vto, msg, up); - m_perf_chain_ack.tap(); - break; - case XFER_HS: - process_xfer_handshake_syn(from, vfrom, vto, msg, up); - m_perf_xfer_handshake_syn.tap(); - break; - case XFER_HSA: - process_xfer_handshake_synack(from, vfrom, vto, msg, up); - m_perf_xfer_handshake_synack.tap(); - break; - case XFER_HA: - process_xfer_handshake_ack(from, vfrom, vto, msg, up); - m_perf_xfer_handshake_ack.tap(); - break; - case XFER_HW: - process_xfer_handshake_wiped(from, vfrom, vto, msg, up); - m_perf_xfer_handshake_wiped.tap(); - break; - case XFER_OP: - process_xfer_op(from, vfrom, vto, msg, up); - m_perf_xfer_op.tap(); - break; - case XFER_ACK: - process_xfer_ack(from, vfrom, vto, msg, up); - m_perf_xfer_ack.tap(); - break; - case BACKUP: - process_backup(from, vfrom, vto, msg, up); - m_perf_backup.tap(); - case PERF_COUNTERS: - process_perf_counters(from, vfrom, vto, msg, up); - m_perf_perf_counters.tap(); - break; - case RESP_GET: - case RESP_GET_PARTIAL: - case RESP_ATOMIC: - case RESP_GROUP_ATOMIC: - case RESP_SEARCH_ITEM: - case RESP_SEARCH_DONE: - case RESP_SORTED_SEARCH: - case RESP_COUNT: - case RESP_SUM: - case RESP_SEARCH_DESCRIBE: - case CONFIGMISMATCH: - case PACKET_NOP: - default: - LOG(INFO) << "received " << type << " message which servers do not process"; - break; - } - - m_gc.quiescent_state(&ts); - } - - m_gc.deregister_thread(&ts); - LOG(INFO) << "network thread shutting down"; + LOG(INFO) << "network thread " << thread << " started on core " << core; + if (sigfillset(&ss) < 0) + { + PLOG(ERROR) << "sigfillset"; + return; + } + sigdelset(&ss, SIGPROF); + if (pthread_sigmask(SIG_SETMASK, &ss, NULL) < 0) + { + PLOG(ERROR) << "could not block signals"; + return; + } + e::garbage_collector::thread_state ts; + m_gc.register_thread(&ts); + server_id from; + virtual_server_id vfrom; + virtual_server_id vto; + network_msgtype type; + std::auto_ptr msg; + e::unpacker up; + while (m_comm.recv(&ts, &from, &vfrom, &vto, &type, &msg, &up)) + { + assert(from != server_id()); + assert(vto != virtual_server_id()); + switch (type) + { + case REQ_GET: + process_req_get(from, vfrom, vto, msg, up); + m_perf_req_get.tap(); + break; + case REQ_GET_PARTIAL: + process_req_get_partial(from, vfrom, vto, msg, up); + m_perf_req_get_partial.tap(); + break; + case REQ_ATOMIC: + process_req_atomic(from, vfrom, vto, msg, up); + m_perf_req_atomic.tap(); + break; + case REQ_SEARCH_START: + process_req_search_start(from, vfrom, vto, msg, up); + m_perf_req_search_start.tap(); + break; + case REQ_SEARCH_NEXT: + process_req_search_next(from, vfrom, vto, msg, up); + m_perf_req_search_next.tap(); + break; + case REQ_SEARCH_STOP: + process_req_search_stop(from, vfrom, vto, msg, up); + m_perf_req_search_stop.tap(); + break; + case REQ_SORTED_SEARCH: + process_req_sorted_search(from, vfrom, vto, msg, up); + m_perf_req_sorted_search.tap(); + break; + case REQ_COUNT: + process_req_count(from, vfrom, vto, msg, up); + m_perf_req_count.tap(); + break; + case REQ_SUM: + process_req_sum(from, vfrom, vto, msg, up); + m_perf_req_sum.tap(); + break; + case REQ_SEARCH_DESCRIBE: + process_req_search_describe(from, vfrom, vto, msg, up); + m_perf_req_search_describe.tap(); + break; + case REQ_GROUP_ATOMIC: + process_req_group_atomic(from, vfrom, vto, msg, up); + m_perf_req_group_atomic.tap(); + break; + case CHAIN_OP: + process_chain_op(from, vfrom, vto, msg, up); + m_perf_chain_op.tap(); + break; + case CHAIN_SUBSPACE: + process_chain_subspace(from, vfrom, vto, msg, up); + m_perf_chain_subspace.tap(); + break; + case CHAIN_ACK: + process_chain_ack(from, vfrom, vto, msg, up); + m_perf_chain_ack.tap(); + break; + case XFER_HS: + process_xfer_handshake_syn(from, vfrom, vto, msg, up); + m_perf_xfer_handshake_syn.tap(); + break; + case XFER_HSA: + process_xfer_handshake_synack(from, vfrom, vto, msg, up); + m_perf_xfer_handshake_synack.tap(); + break; + case XFER_HA: + process_xfer_handshake_ack(from, vfrom, vto, msg, up); + m_perf_xfer_handshake_ack.tap(); + break; + case XFER_HW: + process_xfer_handshake_wiped(from, vfrom, vto, msg, up); + m_perf_xfer_handshake_wiped.tap(); + break; + case XFER_OP: + process_xfer_op(from, vfrom, vto, msg, up); + m_perf_xfer_op.tap(); + break; + case XFER_ACK: + process_xfer_ack(from, vfrom, vto, msg, up); + m_perf_xfer_ack.tap(); + break; + case BACKUP: + process_backup(from, vfrom, vto, msg, up); + m_perf_backup.tap(); + case PERF_COUNTERS: + process_perf_counters(from, vfrom, vto, msg, up); + m_perf_perf_counters.tap(); + break; + case RESP_GET: + case RESP_GET_PARTIAL: + case RESP_ATOMIC: + case RESP_GROUP_ATOMIC: + case RESP_SEARCH_ITEM: + case RESP_SEARCH_DONE: + case RESP_SORTED_SEARCH: + case RESP_COUNT: + case RESP_SUM: + case RESP_SEARCH_DESCRIBE: + case CONFIGMISMATCH: + case PACKET_NOP: + default: + LOG(INFO) << "received " << type << " message which servers do not process"; + break; + } + m_gc.quiescent_state(&ts); + } + m_gc.deregister_thread(&ts); + LOG(INFO) << "network thread shutting down"; } void @@ -700,78 +638,70 @@ daemon :: process_req_get(server_id from, std::auto_ptr msg, e::unpacker up) { - uint64_t nonce; - e::slice key; - bool has_auth = false; - auth_wallet aw; - up = up >> nonce >> key; - - if (up.remain()) - { - has_auth = true; - up = up >> aw; - } - - if (up.error()) - { - LOG(WARNING) << "unpack of REQ_GET failed; here's some hex: " << msg->hex(); - return; - } - - region_id ri = m_config.get_region_id(vto); - bool has_value = false; - std::vector value; - uint64_t version; - datalayer::reference ref; - network_returncode result; - - switch (m_data.get(ri, key, &value, &version, &ref)) - { - case datalayer::SUCCESS: - has_value = true; - result = NET_SUCCESS; - break; - case datalayer::NOT_FOUND: - result = NET_NOTFOUND; - break; - case datalayer::BAD_ENCODING: - case datalayer::CORRUPTION: - case datalayer::IO_ERROR: - case datalayer::LEVELDB_ERROR: - default: - LOG(ERROR) << "GET returned unacceptable error code."; - result = NET_SERVERERROR; - break; - } - - const schema* sc = m_config.get_schema(ri); - - if (!auth_verify_read(*sc, has_value, &value, (has_auth ? &aw : NULL))) - { - size_t sz = HYPERDEX_HEADER_SIZE_VC - + sizeof(uint64_t) - + sizeof(uint16_t); - msg.reset(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << static_cast(NET_UNAUTHORIZED); - } - else - { - sanitize_secrets(*sc, &value); - size_t sz = HYPERDEX_HEADER_SIZE_VC - + sizeof(uint64_t) - + sizeof(uint16_t) - + pack_size(value); - msg.reset(e::buffer::create(sz)); - e::packer pa = msg->pack_at(HYPERDEX_HEADER_SIZE_VC); - pa = pa << nonce << static_cast(result); - - if (result == NET_SUCCESS) - { - pa = pa << value; - } - } - - m_comm.send_client(vto, from, RESP_GET, msg); + uint64_t nonce; + e::slice key; + bool has_auth = false; + auth_wallet aw; + up = up >> nonce >> key; + if (up.remain()) + { + has_auth = true; + up = up >> aw; + } + if (up.error()) + { + LOG(WARNING) << "unpack of REQ_GET failed; here's some hex: " << msg->hex(); + return; + } + region_id ri = m_config.get_region_id(vto); + bool has_value = false; + std::vector value; + uint64_t version; + datalayer::reference ref; + network_returncode result; + switch (m_data.get(ri, key, &value, &version, &ref)) + { + case datalayer::SUCCESS: + has_value = true; + result = NET_SUCCESS; + break; + case datalayer::NOT_FOUND: + result = NET_NOTFOUND; + break; + case datalayer::BAD_ENCODING: + case datalayer::CORRUPTION: + case datalayer::IO_ERROR: + case datalayer::LEVELDB_ERROR: + default: + LOG(ERROR) << "GET returned unacceptable error code."; + result = NET_SERVERERROR; + break; + } + const schema *sc = m_config.get_schema(ri); + if (!auth_verify_read(*sc, has_value, &value, (has_auth ? &aw : NULL))) + { + size_t sz = HYPERDEX_HEADER_SIZE_VC + + sizeof(uint64_t) + + sizeof(uint16_t); + msg.reset(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << static_cast(NET_UNAUTHORIZED); + } + else + { + sanitize_secrets(*sc, &value); + size_t sz = HYPERDEX_HEADER_SIZE_VC + + sizeof(uint64_t) + + sizeof(uint16_t) + + pack_size(value); + msg.reset(e::buffer::create(sz)); + e::packer pa = msg->pack_at(HYPERDEX_HEADER_SIZE_VC); + pa = pa << nonce << static_cast(result); + if (result == NET_SUCCESS) + { + pa = pa << value; + } + } + m_comm.send_client(vto, from, RESP_GET, msg); } void @@ -781,89 +711,80 @@ daemon :: process_req_get_partial(server_id from, std::auto_ptr msg, e::unpacker up) { - uint64_t nonce; - e::slice key; - std::vector attrs; - bool has_auth = false; - auth_wallet aw; - up = up >> nonce >> key >> attrs; - - if (up.remain()) - { - has_auth = true; - up = up >> aw; - } - - if (up.error()) - { - LOG(WARNING) << "unpack of REQ_GET_PARTIAL failed; here's some hex: " << msg->hex(); - return; - } - - region_id ri = m_config.get_region_id(vto); - std::sort(attrs.begin(), attrs.end()); - bool has_value = false; - std::vector value; - uint64_t version; - datalayer::reference ref; - network_returncode result; - - switch (m_data.get(ri, key, &value, &version, &ref)) - { - case datalayer::SUCCESS: - has_value = true; - result = NET_SUCCESS; - break; - case datalayer::NOT_FOUND: - result = NET_NOTFOUND; - break; - case datalayer::BAD_ENCODING: - case datalayer::CORRUPTION: - case datalayer::IO_ERROR: - case datalayer::LEVELDB_ERROR: - default: - LOG(ERROR) << "GET returned unacceptable error code."; - result = NET_SERVERERROR; - break; - } - - const schema* sc = m_config.get_schema(ri); - - if (!auth_verify_read(*sc, has_value, &value, (has_auth ? &aw : NULL))) - { - size_t sz = HYPERDEX_HEADER_SIZE_VC - + sizeof(uint64_t) - + sizeof(uint16_t); - msg.reset(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << static_cast(NET_UNAUTHORIZED); - } - else - { - sanitize_secrets(*sc, &value); - size_t sz = HYPERDEX_HEADER_SIZE_VC - + sizeof(uint64_t) - + sizeof(uint16_t) - + pack_size(value) - + value.size() * sizeof(uint16_t); - msg.reset(e::buffer::create(sz)); - e::packer pa = msg->pack_at(HYPERDEX_HEADER_SIZE_VC); - pa = pa << nonce << static_cast(result); - - if (result == NET_SUCCESS) - { - for (size_t i = 0; i < value.size(); ++i) - { - uint16_t attr = i + 1; - - if (std::binary_search(attrs.begin(), attrs.end(), attr)) - { - pa = pa << attr << value[i]; - } - } - } - } - - m_comm.send_client(vto, from, RESP_GET_PARTIAL, msg); + uint64_t nonce; + e::slice key; + std::vector attrs; + bool has_auth = false; + auth_wallet aw; + up = up >> nonce >> key >> attrs; + if (up.remain()) + { + has_auth = true; + up = up >> aw; + } + if (up.error()) + { + LOG(WARNING) << "unpack of REQ_GET_PARTIAL failed; here's some hex: " << msg->hex(); + return; + } + region_id ri = m_config.get_region_id(vto); + std::sort(attrs.begin(), attrs.end()); + bool has_value = false; + std::vector value; + uint64_t version; + datalayer::reference ref; + network_returncode result; + switch (m_data.get(ri, key, &value, &version, &ref)) + { + case datalayer::SUCCESS: + has_value = true; + result = NET_SUCCESS; + break; + case datalayer::NOT_FOUND: + result = NET_NOTFOUND; + break; + case datalayer::BAD_ENCODING: + case datalayer::CORRUPTION: + case datalayer::IO_ERROR: + case datalayer::LEVELDB_ERROR: + default: + LOG(ERROR) << "GET returned unacceptable error code."; + result = NET_SERVERERROR; + break; + } + const schema *sc = m_config.get_schema(ri); + if (!auth_verify_read(*sc, has_value, &value, (has_auth ? &aw : NULL))) + { + size_t sz = HYPERDEX_HEADER_SIZE_VC + + sizeof(uint64_t) + + sizeof(uint16_t); + msg.reset(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << static_cast(NET_UNAUTHORIZED); + } + else + { + sanitize_secrets(*sc, &value); + size_t sz = HYPERDEX_HEADER_SIZE_VC + + sizeof(uint64_t) + + sizeof(uint16_t) + + pack_size(value) + + value.size() * sizeof(uint16_t); + msg.reset(e::buffer::create(sz)); + e::packer pa = msg->pack_at(HYPERDEX_HEADER_SIZE_VC); + pa = pa << nonce << static_cast(result); + if (result == NET_SUCCESS) + { + for (size_t i = 0; i < value.size(); ++i) + { + uint16_t attr = i + 1; + if (std::binary_search(attrs.begin(), attrs.end(), attr)) + { + pa = pa << attr << value[i]; + } + } + } + } + m_comm.send_client(vto, from, RESP_GET_PARTIAL, msg); } void @@ -873,19 +794,16 @@ daemon :: process_req_atomic(server_id from, std::auto_ptr msg, e::unpacker up) { - // initialize nonce from pseudo-random memory - uint64_t nonce; - - std::auto_ptr kc(new key_change()); - up = up >> nonce >> *kc; - - if (up.error()) - { - LOG(WARNING) << "unpack of REQ_ATOMIC failed; here's some hex: " << msg->hex(); - return; - } - - m_repl.client_atomic(from, vto, nonce, kc, msg); + // initialize nonce from pseudo-random memory + uint64_t nonce; + std::auto_ptr kc(new key_change()); + up = up >> nonce >> *kc; + if (up.error()) + { + LOG(WARNING) << "unpack of REQ_ATOMIC failed; here's some hex: " << msg->hex(); + return; + } + m_repl.client_atomic(from, vto, nonce, kc, msg); } void @@ -895,17 +813,15 @@ daemon :: process_req_search_start(server_id from, std::auto_ptr msg, e::unpacker up) { - uint64_t nonce; - uint64_t search_id; - std::vector checks; - - if ((up >> nonce >> search_id >> checks).error()) - { - LOG(WARNING) << "unpack of REQ_SEARCH_START failed; here's some hex: " << msg->hex(); - return; - } - - m_sm.start(from, vto, msg, nonce, search_id, &checks); + uint64_t nonce; + uint64_t search_id; + std::vector checks; + if ((up >> nonce >> search_id >> checks).error()) + { + LOG(WARNING) << "unpack of REQ_SEARCH_START failed; here's some hex: " << msg->hex(); + return; + } + m_sm.start(from, vto, msg, nonce, search_id, &checks); } void @@ -915,16 +831,14 @@ daemon :: process_req_search_next(server_id from, std::auto_ptr msg, e::unpacker up) { - uint64_t nonce; - uint64_t search_id; - - if ((up >> nonce >> search_id).error()) - { - LOG(WARNING) << "unpack of REQ_SEARCH_NEXT failed; here's some hex: " << msg->hex(); - return; - } - - m_sm.next(from, vto, nonce, search_id); + uint64_t nonce; + uint64_t search_id; + if ((up >> nonce >> search_id).error()) + { + LOG(WARNING) << "unpack of REQ_SEARCH_NEXT failed; here's some hex: " << msg->hex(); + return; + } + m_sm.next(from, vto, nonce, search_id); } void @@ -934,16 +848,14 @@ daemon :: process_req_search_stop(server_id from, std::auto_ptr msg, e::unpacker up) { - uint64_t nonce; - uint64_t search_id; - - if ((up >> nonce >> search_id).error()) - { - LOG(WARNING) << "unpack of REQ_SEARCH_STOP failed; here's some hex: " << msg->hex(); - return; - } - - m_sm.stop(from, vto, search_id); + uint64_t nonce; + uint64_t search_id; + if ((up >> nonce >> search_id).error()) + { + LOG(WARNING) << "unpack of REQ_SEARCH_STOP failed; here's some hex: " << msg->hex(); + return; + } + m_sm.stop(from, vto, search_id); } void @@ -953,19 +865,17 @@ daemon :: process_req_sorted_search(server_id from, std::auto_ptr msg, e::unpacker up) { - uint64_t nonce; - std::vector checks; - uint64_t limit; - uint16_t sort_by; - uint8_t flags; - - if ((up >> nonce >> checks >> limit >> sort_by >> flags).error()) - { - LOG(WARNING) << "unpack of REQ_SORTED_SEARCH failed; here's some hex: " << msg->hex(); - return; - } - - m_sm.sorted_search(from, vto, nonce, &checks, limit, sort_by, flags & 0x1); + uint64_t nonce; + std::vector checks; + uint64_t limit; + uint16_t sort_by; + uint8_t flags; + if ((up >> nonce >> checks >> limit >> sort_by >> flags).error()) + { + LOG(WARNING) << "unpack of REQ_SORTED_SEARCH failed; here's some hex: " << msg->hex(); + return; + } + m_sm.sorted_search(from, vto, nonce, &checks, limit, sort_by, flags & 0x1); } void @@ -975,36 +885,32 @@ daemon :: process_req_count(server_id from, std::auto_ptr msg, e::unpacker up) { - uint64_t nonce; - std::vector checks; - - if ((up >> nonce >> checks).error()) - { - LOG(WARNING) << "unpack of REQ_COUNT failed; here's some hex: " << msg->hex(); - return; - } - - m_sm.count(from, vto, nonce, &checks); + uint64_t nonce; + std::vector checks; + if ((up >> nonce >> checks).error()) + { + LOG(WARNING) << "unpack of REQ_COUNT failed; here's some hex: " << msg->hex(); + return; + } + m_sm.count(from, vto, nonce, &checks); } void daemon :: process_req_sum(server_id from, - virtual_server_id, - virtual_server_id vto, - std::auto_ptr msg, - e::unpacker up) + virtual_server_id, + virtual_server_id vto, + std::auto_ptr msg, + e::unpacker up) { - uint64_t nonce; - std::vector checks; - uint16_t sum_idx; - - if ((up >> nonce >> checks >> sum_idx).error()) - { - LOG(WARNING) << "unpack of REQ_SUM failed; here's some hex: " << msg->hex(); - return; - } - - m_sm.sum(from, vto, nonce, &checks, sum_idx); + uint64_t nonce; + std::vector checks; + uint16_t sum_idx; + if ((up >> nonce >> checks >> sum_idx).error()) + { + LOG(WARNING) << "unpack of REQ_SUM failed; here's some hex: " << msg->hex(); + return; + } + m_sm.sum(from, vto, nonce, &checks, sum_idx); } void @@ -1014,16 +920,14 @@ daemon :: process_req_search_describe(server_id from, std::auto_ptr msg, e::unpacker up) { - uint64_t nonce; - std::vector checks; - - if ((up >> nonce >> checks).error()) - { - LOG(WARNING) << "unpack of REQ_SEARCH_DESCRIBE failed; here's some hex: " << msg->hex(); - return; - } - - m_sm.search_describe(from, vto, nonce, &checks); + uint64_t nonce; + std::vector checks; + if ((up >> nonce >> checks).error()) + { + LOG(WARNING) << "unpack of REQ_SEARCH_DESCRIBE failed; here's some hex: " << msg->hex(); + return; + } + m_sm.search_describe(from, vto, nonce, &checks); } void @@ -1033,19 +937,17 @@ daemon :: process_req_group_atomic(server_id from, std::auto_ptr msg, e::unpacker up) { - uint64_t nonce; - std::vector checks; - up = up >> nonce >> checks; - - if (up.error()) - { - LOG(WARNING) << "unpack of REQ_GROUP_ATOMIC failed; here's some hex: " << msg->hex(); - return; - } - - // Only forward the actual atomic operation - e::slice sl = up.remainder(); - m_sm.group_keyop(from, vto, nonce, &checks, REQ_ATOMIC, sl, RESP_GROUP_ATOMIC); + uint64_t nonce; + std::vector checks; + up = up >> nonce >> checks; + if (up.error()) + { + LOG(WARNING) << "unpack of REQ_GROUP_ATOMIC failed; here's some hex: " << msg->hex(); + return; + } + // Only forward the actual atomic operation + e::slice sl = up.remainder(); + m_sm.group_keyop(from, vto, nonce, &checks, REQ_ATOMIC, sl, RESP_GROUP_ATOMIC); } void @@ -1055,21 +957,19 @@ daemon :: process_chain_op(server_id, std::auto_ptr msg, e::unpacker up) { - uint8_t flags; - uint64_t old_version; - uint64_t new_version; - e::slice key; - std::vector value; - - if ((up >> flags >> old_version >> new_version >> key >> value).error()) - { - LOG(WARNING) << "unpack of CHAIN_OP failed; here's some hex: " << msg->hex(); - return; - } - - bool fresh = flags & 1; - bool has_value = flags & 2; - m_repl.chain_op(vfrom, vto, old_version, new_version, fresh, has_value, key, value, msg); + uint8_t flags; + uint64_t old_version; + uint64_t new_version; + e::slice key; + std::vector value; + if ((up >> flags >> old_version >> new_version >> key >> value).error()) + { + LOG(WARNING) << "unpack of CHAIN_OP failed; here's some hex: " << msg->hex(); + return; + } + bool fresh = flags & 1; + bool has_value = flags & 2; + m_repl.chain_op(vfrom, vto, old_version, new_version, fresh, has_value, key, value, msg); } void @@ -1079,24 +979,22 @@ daemon :: process_chain_subspace(server_id, std::auto_ptr msg, e::unpacker up) { - uint64_t old_version; - uint64_t new_version; - e::slice key; - std::vector value; - region_id prev_region; - region_id this_old_region; - region_id this_new_region; - region_id next_region; - - if ((up >> old_version >> new_version >> key >> value >> - prev_region >> this_old_region >> this_new_region >> next_region).error()) - { - LOG(WARNING) << "unpack of CHAIN_SUBSPACE failed; here's some hex: " << msg->hex(); - return; - } - - m_repl.chain_subspace(vfrom, vto, old_version, new_version, key, value, msg, - prev_region, this_old_region, this_new_region, next_region); + uint64_t old_version; + uint64_t new_version; + e::slice key; + std::vector value; + region_id prev_region; + region_id this_old_region; + region_id this_new_region; + region_id next_region; + if ((up >> old_version >> new_version >> key >> value >> + prev_region >> this_old_region >> this_new_region >> next_region).error()) + { + LOG(WARNING) << "unpack of CHAIN_SUBSPACE failed; here's some hex: " << msg->hex(); + return; + } + m_repl.chain_subspace(vfrom, vto, old_version, new_version, key, value, msg, + prev_region, this_old_region, this_new_region, next_region); } void @@ -1106,16 +1004,14 @@ daemon :: process_chain_ack(server_id, std::auto_ptr msg, e::unpacker up) { - uint64_t version; - e::slice key; - - if ((up >> version >> key).error()) - { - LOG(WARNING) << "unpack of CHAIN_ACK failed; here's some hex: " << msg->hex(); - return; - } - - m_repl.chain_ack(vfrom, vto, version, key); + uint64_t version; + e::slice key; + if ((up >> version >> key).error()) + { + LOG(WARNING) << "unpack of CHAIN_ACK failed; here's some hex: " << msg->hex(); + return; + } + m_repl.chain_ack(vfrom, vto, version, key); } void @@ -1125,15 +1021,13 @@ daemon :: process_xfer_handshake_syn(server_id, std::auto_ptr msg, e::unpacker up) { - transfer_id xid; - - if ((up >> xid).error()) - { - LOG(WARNING) << "unpack of XFER_HS failed; here's some hex: " << msg->hex(); - return; - } - - m_stm.handshake_syn(vfrom, xid); + transfer_id xid; + if ((up >> xid).error()) + { + LOG(WARNING) << "unpack of XFER_HS failed; here's some hex: " << msg->hex(); + return; + } + m_stm.handshake_syn(vfrom, xid); } void @@ -1143,16 +1037,14 @@ daemon :: process_xfer_handshake_synack(server_id from, std::auto_ptr msg, e::unpacker up) { - transfer_id xid; - uint64_t timestamp; - - if ((up >> xid >> timestamp).error()) - { - LOG(WARNING) << "unpack of XFER_HSA failed; here's some hex: " << msg->hex(); - return; - } - - m_stm.handshake_synack(from, to, xid, timestamp); + transfer_id xid; + uint64_t timestamp; + if ((up >> xid >> timestamp).error()) + { + LOG(WARNING) << "unpack of XFER_HSA failed; here's some hex: " << msg->hex(); + return; + } + m_stm.handshake_synack(from, to, xid, timestamp); } void @@ -1162,17 +1054,15 @@ daemon :: process_xfer_handshake_ack(server_id, std::auto_ptr msg, e::unpacker up) { - transfer_id xid; - uint8_t flags; - - if ((up >> xid >> flags).error()) - { - LOG(WARNING) << "unpack of XFER_HA failed; here's some hex: " << msg->hex(); - return; - } - - bool wipe = flags & 0x1; - m_stm.handshake_ack(vfrom, xid, wipe); + transfer_id xid; + uint8_t flags; + if ((up >> xid >> flags).error()) + { + LOG(WARNING) << "unpack of XFER_HA failed; here's some hex: " << msg->hex(); + return; + } + bool wipe = flags & 0x1; + m_stm.handshake_ack(vfrom, xid, wipe); } void @@ -1182,15 +1072,13 @@ daemon :: process_xfer_handshake_wiped(server_id from, std::auto_ptr msg, e::unpacker up) { - transfer_id xid; - - if ((up >> xid).error()) - { - LOG(WARNING) << "unpack of XFER_HW failed; here's some hex: " << msg->hex(); - return; - } - - m_stm.handshake_wiped(from, to, xid); + transfer_id xid; + if ((up >> xid).error()) + { + LOG(WARNING) << "unpack of XFER_HW failed; here's some hex: " << msg->hex(); + return; + } + m_stm.handshake_wiped(from, to, xid); } void @@ -1200,21 +1088,19 @@ daemon :: process_xfer_op(server_id, std::auto_ptr msg, e::unpacker up) { - uint8_t flags; - uint64_t xid; - uint64_t seq_no; - uint64_t version; - e::slice key; - std::vector value; - - if ((up >> flags >> xid >> seq_no >> version >> key >> value).error()) - { - LOG(WARNING) << "unpack of XFER_OP failed; here's some hex: " << msg->hex(); - return; - } - - bool has_value = flags & 1; - m_stm.xfer_op(vfrom, transfer_id(xid), seq_no, has_value, version, msg, key, value); + uint8_t flags; + uint64_t xid; + uint64_t seq_no; + uint64_t version; + e::slice key; + std::vector value; + if ((up >> flags >> xid >> seq_no >> version >> key >> value).error()) + { + LOG(WARNING) << "unpack of XFER_OP failed; here's some hex: " << msg->hex(); + return; + } + bool has_value = flags & 1; + m_stm.xfer_op(vfrom, transfer_id(xid), seq_no, has_value, version, msg, key, value); } void @@ -1224,17 +1110,15 @@ daemon :: process_xfer_ack(server_id from, std::auto_ptr msg, e::unpacker up) { - uint8_t flags; - uint64_t xid; - uint64_t seq_no; - - if ((up >> flags >> xid >> seq_no).error()) - { - LOG(WARNING) << "unpack of XFER_ACK failed; here's some hex: " << msg->hex(); - return; - } - - m_stm.xfer_ack(from, vto, transfer_id(xid), seq_no); + uint8_t flags; + uint64_t xid; + uint64_t seq_no; + if ((up >> flags >> xid >> seq_no).error()) + { + LOG(WARNING) << "unpack of XFER_ACK failed; here's some hex: " << msg->hex(); + return; + } + m_stm.xfer_ack(from, vto, transfer_id(xid), seq_no); } void @@ -1244,48 +1128,41 @@ daemon :: process_backup(server_id from, std::auto_ptr msg, e::unpacker up) { - uint64_t nonce; - e::slice _name; - - if ((up >> nonce >> _name).error() || - strnlen(reinterpret_cast(_name.data()), _name.size()) == _name.size()) - { - LOG(WARNING) << "unpack of BACKUP failed; here's some hex: " << msg->hex(); - return; - } - - std::string name(reinterpret_cast(_name.data())); - network_returncode result = NET_SUCCESS; - - if (!m_data.backup(e::slice(name))) - { - result = NET_SERVERERROR; - } - else - { - LOG(INFO) << "Backup succeeded and is available in the directory \"backup-" - << e::strescape(name) << "\" within the data directory." - << " Copy the complete directory to elsewhere so your backup is safe."; - } - - using po6::path::join; - std::string _path(join(m_data_dir, "backup-" + name)); - - if (!po6::path::realpath(_path, &_path)) - { - // XXX - } - - e::slice path(_path.c_str()); - - size_t sz = HYPERDEX_HEADER_SIZE_VC - + sizeof(uint64_t) - + sizeof(uint16_t) - + pack_size(path); - msg.reset(e::buffer::create(sz)); - e::packer pa = msg->pack_at(HYPERDEX_HEADER_SIZE_VC); - pa = pa << nonce << static_cast(result) << path; - m_comm.send_client(vto, from, BACKUP, msg); + uint64_t nonce; + e::slice _name; + if ((up >> nonce >> _name).error() || + strnlen(reinterpret_cast(_name.data()), _name.size()) == _name.size()) + { + LOG(WARNING) << "unpack of BACKUP failed; here's some hex: " << msg->hex(); + return; + } + std::string name(reinterpret_cast(_name.data())); + network_returncode result = NET_SUCCESS; + if (!m_data.backup(e::slice(name))) + { + result = NET_SERVERERROR; + } + else + { + LOG(INFO) << "Backup succeeded and is available in the directory \"backup-" + << e::strescape(name) << "\" within the data directory." + << " Copy the complete directory to elsewhere so your backup is safe."; + } + using po6::path::join; + std::string _path(join(m_data_dir, "backup-" + name)); + if (!po6::path::realpath(_path, &_path)) + { + // XXX + } + e::slice path(_path.c_str()); + size_t sz = HYPERDEX_HEADER_SIZE_VC + + sizeof(uint64_t) + + sizeof(uint16_t) + + pack_size(path); + msg.reset(e::buffer::create(sz)); + e::packer pa = msg->pack_at(HYPERDEX_HEADER_SIZE_VC); + pa = pa << nonce << static_cast(result) << path; + m_comm.send_client(vto, from, BACKUP, msg); } void @@ -1295,49 +1172,42 @@ daemon :: process_perf_counters(server_id from, std::auto_ptr msg, e::unpacker up) { - uint64_t nonce; - uint64_t when; - up = up >> nonce >> when; - - if (up.error()) - { - LOG(WARNING) << "unpack of PERF_COUNTERS failed; here's some hex: " << msg->hex(); - return; - } - - std::string out; - - { - po6::threads::mutex::hold hold(&m_protect_stats); - std::list >::iterator it; - it = m_stats.begin(); - - while (it != m_stats.end() && it->first <= when) - { - ++it; - } - - if (it == m_stats.begin()) - { - std::ostringstream ret; - ret << m_stats_start << " reset=" << m_stats_start << "\n"; - out += ret.str(); - } - - while (it != m_stats.end()) - { - out += it->second; - ++it; - } - } - - size_t sz = HYPERDEX_HEADER_SIZE_VC - + sizeof(uint64_t) - + out.size() + 1; - msg.reset(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VC) - << nonce << e::pack_memmove(out.c_str(), out.size() + 1); - m_comm.send_client(vto, from, PERF_COUNTERS, msg); + uint64_t nonce; + uint64_t when; + up = up >> nonce >> when; + if (up.error()) + { + LOG(WARNING) << "unpack of PERF_COUNTERS failed; here's some hex: " << msg->hex(); + return; + } + std::string out; + { + po6::threads::mutex::hold hold(&m_protect_stats); + std::list >::iterator it; + it = m_stats.begin(); + while (it != m_stats.end() && it->first <= when) + { + ++it; + } + if (it == m_stats.begin()) + { + std::ostringstream ret; + ret << m_stats_start << " reset=" << m_stats_start << "\n"; + out += ret.str(); + } + while (it != m_stats.end()) + { + out += it->second; + ++it; + } + } + size_t sz = HYPERDEX_HEADER_SIZE_VC + + sizeof(uint64_t) + + out.size() + 1; + msg.reset(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VC) + << nonce << e::pack_memmove(out.c_str(), out.size() + 1); + m_comm.send_client(vto, from, PERF_COUNTERS, msg); } #define INTERVAL 100000000ULL @@ -1345,69 +1215,62 @@ daemon :: process_perf_counters(server_id from, void daemon :: collect_stats() { - uint64_t target = po6::monotonic_time(); - target = target - (target % INTERVAL) + INTERVAL; - - { - po6::threads::mutex::hold hold(&m_protect_stats); - m_stats_start = target; - } - - while (__sync_fetch_and_add(&s_interrupts, 0) == 0) - { - // every INTERVAL nanoseconds collect stats - uint64_t now = po6::monotonic_time(); - - if (now < target) - { - struct timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = std::min(target - now, (uint64_t)50000000UL); - nanosleep(&ts, NULL); - continue; - } - - // collect the stats - std::ostringstream ret; - ret << target; - collect_stats_msgs(&ret); - collect_stats_leveldb(&ret); - collect_stats_io(&ret); - ret << "\n"; - std::string out = ret.str(); - - po6::threads::mutex::hold hold(&m_protect_stats); - m_stats.push_back(std::make_pair(target, out)); - - if (m_stats.size() > 600) - { - m_stats.pop_front(); - } - - // next interval - target += INTERVAL; - } + uint64_t target = po6::monotonic_time(); + target = target - (target % INTERVAL) + INTERVAL; + { + po6::threads::mutex::hold hold(&m_protect_stats); + m_stats_start = target; + } + while (__sync_fetch_and_add(&s_interrupts, 0) == 0) + { + // every INTERVAL nanoseconds collect stats + uint64_t now = po6::monotonic_time(); + if (now < target) + { + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = std::min(target - now, (uint64_t)50000000UL); + nanosleep(&ts, NULL); + continue; + } + // collect the stats + std::ostringstream ret; + ret << target; + collect_stats_msgs(&ret); + collect_stats_leveldb(&ret); + collect_stats_io(&ret); + ret << "\n"; + std::string out = ret.str(); + po6::threads::mutex::hold hold(&m_protect_stats); + m_stats.push_back(std::make_pair(target, out)); + if (m_stats.size() > 600) + { + m_stats.pop_front(); + } + // next interval + target += INTERVAL; + } } void -daemon :: collect_stats_msgs(std::ostringstream* ret) +daemon :: collect_stats_msgs(std::ostringstream *ret) { - *ret << " msgs.req_get=" << m_perf_req_get.read(); - *ret << " msgs.req_get_partial=" << m_perf_req_get_partial.read(); - *ret << " msgs.req_atomic=" << m_perf_req_atomic.read(); - *ret << " msgs.req_search_start=" << m_perf_req_search_start.read(); - *ret << " msgs.req_search_next=" << m_perf_req_search_next.read(); - *ret << " msgs.req_search_stop=" << m_perf_req_search_stop.read(); - *ret << " msgs.req_sorted_search=" << m_perf_req_sorted_search.read(); - *ret << " msgs.req_count=" << m_perf_req_count.read(); - *ret << " msgs.req_search_describe=" << m_perf_req_search_describe.read(); - *ret << " msgs.req_group_atomic=" << m_perf_req_group_atomic.read(); - *ret << " msgs.chain_op=" << m_perf_chain_op.read(); - *ret << " msgs.chain_subspace=" << m_perf_chain_subspace.read(); - *ret << " msgs.chain_ack=" << m_perf_chain_ack.read(); - *ret << " msgs.xfer_op=" << m_perf_xfer_op.read(); - *ret << " msgs.xfer_ack=" << m_perf_xfer_ack.read(); - *ret << " msgs.perf_counters=" << m_perf_perf_counters.read(); + *ret << " msgs.req_get=" << m_perf_req_get.read(); + *ret << " msgs.req_get_partial=" << m_perf_req_get_partial.read(); + *ret << " msgs.req_atomic=" << m_perf_req_atomic.read(); + *ret << " msgs.req_search_start=" << m_perf_req_search_start.read(); + *ret << " msgs.req_search_next=" << m_perf_req_search_next.read(); + *ret << " msgs.req_search_stop=" << m_perf_req_search_stop.read(); + *ret << " msgs.req_sorted_search=" << m_perf_req_sorted_search.read(); + *ret << " msgs.req_count=" << m_perf_req_count.read(); + *ret << " msgs.req_search_describe=" << m_perf_req_search_describe.read(); + *ret << " msgs.req_group_atomic=" << m_perf_req_group_atomic.read(); + *ret << " msgs.chain_op=" << m_perf_chain_op.read(); + *ret << " msgs.chain_subspace=" << m_perf_chain_subspace.read(); + *ret << " msgs.chain_ack=" << m_perf_chain_ack.read(); + *ret << " msgs.xfer_op=" << m_perf_xfer_op.read(); + *ret << " msgs.xfer_ack=" << m_perf_xfer_ack.read(); + *ret << " msgs.perf_counters=" << m_perf_perf_counters.read(); } namespace @@ -1415,243 +1278,210 @@ namespace struct leveldb_stat { - leveldb_stat() : files(0), size(0), time(0), read(0), write(0) {} - uint64_t files; - uint64_t size; - uint64_t time; - uint64_t read; - uint64_t write; + leveldb_stat() : files(0), size(0), time(0), read(0), write(0) {} + uint64_t files; + uint64_t size; + uint64_t time; + uint64_t read; + uint64_t write; }; } // namespace void -daemon :: collect_stats_leveldb(std::ostringstream* ret) +daemon :: collect_stats_leveldb(std::ostringstream *ret) { - *ret << " leveldb.size=" << m_data.approximate_size(); - std::string tmp; - - if (m_data.get_property(e::slice("leveldb.stats"), &tmp)) - { - std::vector lines(tmp.c_str(), tmp.c_str() + tmp.size() + 1); - char* ptr = &lines.front(); - char* end = ptr + lines.size() - 1; - leveldb_stat stats[7]; - - while (ptr < end) - { - char* eol = strchr(ptr, '\n'); - eol = eol ? eol : end; - *eol = 0; - int level; - int files; - double size; - double time; - double read; - double write; - - if (sscanf(ptr, "%d %d %lf %lf %lf %lf", - &level, &files, &size, &time, &read, &write) == 6 && - level < 7) - { - stats[level].files = files; - stats[level].size = size * 1048576ULL; - stats[level].time = time; - stats[level].read = read * 1048576ULL; - stats[level].write = write * 1048576ULL; - } - - ptr = eol + 1; - } - - for (size_t i = 0; i < 7; ++i) - { - *ret << " leveldb.files" << i << "=" << stats[i].files; - *ret << " leveldb.size" << i << "=" << stats[i].size; - *ret << " leveldb.time" << i << "=" << stats[i].time; - *ret << " leveldb.read" << i << "=" << stats[i].read; - *ret << " leveldb.write" << i << "=" << stats[i].write; - } - } + *ret << " leveldb.size=" << m_data.approximate_size(); + std::string tmp; + if (m_data.get_property(e::slice("leveldb.stats"), &tmp)) + { + std::vector lines(tmp.c_str(), tmp.c_str() + tmp.size() + 1); + char *ptr = &lines.front(); + char *end = ptr + lines.size() - 1; + leveldb_stat stats[7]; + while (ptr < end) + { + char *eol = strchr(ptr, '\n'); + eol = eol ? eol : end; + *eol = 0; + int level; + int files; + double size; + double time; + double read; + double write; + if (sscanf(ptr, "%d %d %lf %lf %lf %lf", + &level, &files, &size, &time, &read, &write) == 6 && + level < 7) + { + stats[level].files = files; + stats[level].size = size * 1048576ULL; + stats[level].time = time; + stats[level].read = read * 1048576ULL; + stats[level].write = write * 1048576ULL; + } + ptr = eol + 1; + } + for (size_t i = 0; i < 7; ++i) + { + *ret << " leveldb.files" << i << "=" << stats[i].files; + *ret << " leveldb.size" << i << "=" << stats[i].size; + *ret << " leveldb.time" << i << "=" << stats[i].time; + *ret << " leveldb.read" << i << "=" << stats[i].read; + *ret << " leveldb.write" << i << "=" << stats[i].write; + } + } } namespace { bool -read_sys_block_star(std::vector* blocks) +read_sys_block_star(std::vector *blocks) { - DIR* dir = opendir("/sys/block"); - struct dirent* ent = NULL; - - if (dir == NULL) - { - return false; - } - - errno = 0; - - while ((ent = readdir(dir)) != NULL) - { - blocks->push_back(ent->d_name); - } - - closedir(dir); - return errno == 0; + DIR *dir = opendir("/sys/block"); + struct dirent *ent = NULL; + if (dir == NULL) + { + return false; + } + errno = 0; + while ((ent = readdir(dir)) != NULL) + { + blocks->push_back(ent->d_name); + } + closedir(dir); + return errno == 0; } } // namespace void -daemon :: determine_block_stat_path(const std::string& data) +daemon :: determine_block_stat_path(const std::string &data) { - std::string dir; - - if (!po6::path::realpath(data, &dir)) - { - LOG(ERROR) << "could not resolve true path for data: " << po6::strerror(errno); - LOG(ERROR) << "iostat-like statistics will not be reported"; - return; - } - - std::vector block_devs; - - if (!read_sys_block_star(&block_devs)) - { - LOG(ERROR) << "could not ls /sys/block"; - LOG(ERROR) << "iostat-like statistics will not be reported"; - return; - } - - FILE* mounts = fopen("/proc/mounts", "r"); - - if (!mounts) - { - LOG(ERROR) << "could not open /proc/mounts: " << po6::strerror(errno); - LOG(ERROR) << "iostat-like statistics will not be reported"; - return; - } - - char* line = NULL; - size_t line_sz = 0; - size_t max_mnt_sz = 0; - - while (true) - { - ssize_t amt = getline(&line, &line_sz, mounts); - - if (amt < 0) - { - if (ferror(mounts) != 0) - { - LOG(WARNING) << "could not read from /proc/mounts: " << po6::strerror(errno); - break; - } - - if (feof(mounts) != 0) - { - break; - } - - LOG(WARNING) << "unknown error when reading from /proc/mounts\n"; - break; - } - - char dev[4096]; - char mnt[4096]; - int pts = sscanf(line, "%4095s %4095s", dev, mnt); - - if (pts != 2) - { - continue; - } - - size_t msz = strlen(mnt); - - if (strncmp(mnt, dir.c_str(), msz) != 0 || - msz < max_mnt_sz) - { - continue; - } - - std::string stat_path = po6::path::basename(dev); - - for (size_t i = 0; i < block_devs.size(); ++i) - { - size_t dsz = std::min(stat_path.size(), block_devs[i].size()); - - if (strncmp(block_devs[i].c_str(), stat_path.c_str(), dsz) == 0) - { - max_mnt_sz = msz; - m_block_stat_path = std::string("/sys/block/") + block_devs[i] + "/stat"; - } - } - } - - if (!m_block_stat_path.empty()) - { - LOG(INFO) << "using " << m_block_stat_path << " for reporting io.* stats"; - } - else - { - LOG(WARNING) << "cannot determine device name for reporting io.* stats"; - LOG(WARNING) << "iostat-like statistics will not be reported"; - } - - if (line) - { - free(line); - } - - fclose(mounts); + std::string dir; + if (!po6::path::realpath(data, &dir)) + { + LOG(ERROR) << "could not resolve true path for data: " << po6::strerror(errno); + LOG(ERROR) << "iostat-like statistics will not be reported"; + return; + } + std::vector block_devs; + if (!read_sys_block_star(&block_devs)) + { + LOG(ERROR) << "could not ls /sys/block"; + LOG(ERROR) << "iostat-like statistics will not be reported"; + return; + } + FILE *mounts = fopen("/proc/mounts", "r"); + if (!mounts) + { + LOG(ERROR) << "could not open /proc/mounts: " << po6::strerror(errno); + LOG(ERROR) << "iostat-like statistics will not be reported"; + return; + } + char *line = NULL; + size_t line_sz = 0; + size_t max_mnt_sz = 0; + while (true) + { + ssize_t amt = getline(&line, &line_sz, mounts); + if (amt < 0) + { + if (ferror(mounts) != 0) + { + LOG(WARNING) << "could not read from /proc/mounts: " << po6::strerror(errno); + break; + } + if (feof(mounts) != 0) + { + break; + } + LOG(WARNING) << "unknown error when reading from /proc/mounts\n"; + break; + } + char dev[4096]; + char mnt[4096]; + int pts = sscanf(line, "%4095s %4095s", dev, mnt); + if (pts != 2) + { + continue; + } + size_t msz = strlen(mnt); + if (strncmp(mnt, dir.c_str(), msz) != 0 || + msz < max_mnt_sz) + { + continue; + } + std::string stat_path = po6::path::basename(dev); + for (size_t i = 0; i < block_devs.size(); ++i) + { + size_t dsz = std::min(stat_path.size(), block_devs[i].size()); + if (strncmp(block_devs[i].c_str(), stat_path.c_str(), dsz) == 0) + { + max_mnt_sz = msz; + m_block_stat_path = std::string("/sys/block/") + block_devs[i] + "/stat"; + } + } + } + if (!m_block_stat_path.empty()) + { + LOG(INFO) << "using " << m_block_stat_path << " for reporting io.* stats"; + } + else + { + LOG(WARNING) << "cannot determine device name for reporting io.* stats"; + LOG(WARNING) << "iostat-like statistics will not be reported"; + } + if (line) + { + free(line); + } + fclose(mounts); } void -daemon :: collect_stats_io(std::ostringstream* ret) +daemon :: collect_stats_io(std::ostringstream *ret) { - if (m_block_stat_path.empty()) - { - return; - } - - FILE* fin = fopen(m_block_stat_path.c_str(), "r"); - - if (!fin) - { - LOG(ERROR) << "could not open " << m_block_stat_path << " for reading block-device stats; io.* stats will not be reported"; - m_block_stat_path = ""; - return; - } - - uint64_t read_ios; - uint64_t read_merges; - uint64_t read_sectors; - uint64_t read_ticks; - uint64_t write_ios; - uint64_t write_merges; - uint64_t write_sectors; - uint64_t write_ticks; - uint64_t in_flight; - uint64_t io_ticks; - uint64_t time_in_queue; - int x = fscanf(fin, "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", - &read_ios, &read_merges, &read_sectors, &read_ticks, - &write_ios, &write_merges, &write_sectors, &write_ticks, - &in_flight, &io_ticks, &time_in_queue); - fclose(fin); - - if (x == 11) - { - *ret << " io.read_ios=" << read_ios; - *ret << " io.read_merges=" << read_merges; - *ret << " io.read_bytes=" << read_sectors * 512; - *ret << " io.read_ticks=" << read_ticks; - *ret << " io.write_ios=" << write_ios; - *ret << " io.write_merges=" << write_merges; - *ret << " io.write_bytes=" << write_sectors * 512; - *ret << " io.write_ticks=" << write_ticks; - *ret << " io.in_flight=" << in_flight; - *ret << " io.io_ticks=" << io_ticks; - *ret << " io.time_in_queue=" << time_in_queue; - } + if (m_block_stat_path.empty()) + { + return; + } + FILE *fin = fopen(m_block_stat_path.c_str(), "r"); + if (!fin) + { + LOG(ERROR) << "could not open " << m_block_stat_path << " for reading block-device stats; io.* stats will not be reported"; + m_block_stat_path = ""; + return; + } + uint64_t read_ios; + uint64_t read_merges; + uint64_t read_sectors; + uint64_t read_ticks; + uint64_t write_ios; + uint64_t write_merges; + uint64_t write_sectors; + uint64_t write_ticks; + uint64_t in_flight; + uint64_t io_ticks; + uint64_t time_in_queue; + int x = fscanf(fin, "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", + &read_ios, &read_merges, &read_sectors, &read_ticks, + &write_ios, &write_merges, &write_sectors, &write_ticks, + &in_flight, &io_ticks, &time_in_queue); + fclose(fin); + if (x == 11) + { + *ret << " io.read_ios=" << read_ios; + *ret << " io.read_merges=" << read_merges; + *ret << " io.read_bytes=" << read_sectors * 512; + *ret << " io.read_ticks=" << read_ticks; + *ret << " io.write_ios=" << write_ios; + *ret << " io.write_merges=" << write_merges; + *ret << " io.write_bytes=" << write_sectors * 512; + *ret << " io.write_ticks=" << write_ticks; + *ret << " io.in_flight=" << in_flight; + *ret << " io.io_ticks=" << io_ticks; + *ret << " io.time_in_queue=" << time_in_queue; + } } diff --git a/daemon/daemon.h b/daemon/daemon.h index 4c5b02aaa..380bd5d9e 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -56,118 +56,118 @@ BEGIN_HYPERDEX_NAMESPACE class daemon { - public: - daemon(); - ~daemon() throw (); +public: + daemon(); + ~daemon() throw (); - public: - int run(bool daemonize, - std::string data, - std::string log, - std::string pidfile, - bool has_pidfile, - bool set_bind_to, - po6::net::location bind_to, - bool set_coordinator, - po6::net::hostname coordinator, - unsigned threads); +public: + int run(bool daemonize, + std::string data, + std::string log, + std::string pidfile, + bool has_pidfile, + bool set_bind_to, + po6::net::location bind_to, + bool set_coordinator, + po6::net::hostname coordinator, + unsigned threads); - private: - // Pause and unpause all activity, e.g. for reconfiguration or - // installing new indices. If called from a background thread, the - // thread must remain offline for entire time between pause/unpause. - void pause(); - void unpause(); - // process messages from the network threads - void loop(size_t thread); - void process_req_get(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_req_get_partial(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_req_atomic(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_req_search_start(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_req_search_next(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_req_search_stop(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_req_sorted_search(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_req_count(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_req_sum(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_req_search_describe(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_req_group_atomic(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_chain_op(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_chain_subspace(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_chain_ack(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_xfer_handshake_syn(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_xfer_handshake_synack(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_xfer_handshake_ack(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_xfer_handshake_wiped(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_xfer_op(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_xfer_ack(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_backup(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_perf_counters(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); +private: + // Pause and unpause all activity, e.g. for reconfiguration or + // installing new indices. If called from a background thread, the + // thread must remain offline for entire time between pause/unpause. + void pause(); + void unpause(); + // process messages from the network threads + void loop(size_t thread); + void process_req_get(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_req_get_partial(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_req_atomic(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_req_search_start(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_req_search_next(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_req_search_stop(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_req_sorted_search(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_req_count(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_req_sum(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_req_search_describe(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_req_group_atomic(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_chain_op(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_chain_subspace(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_chain_ack(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_xfer_handshake_syn(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_xfer_handshake_synack(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_xfer_handshake_ack(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_xfer_handshake_wiped(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_xfer_op(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_xfer_ack(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_backup(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_perf_counters(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - private: - void collect_stats(); - void collect_stats_msgs(std::ostringstream* ret); - void collect_stats_leveldb(std::ostringstream* ret); - void determine_block_stat_path(const std::string& data); - void collect_stats_io(std::ostringstream* ret); +private: + void collect_stats(); + void collect_stats_msgs(std::ostringstream *ret); + void collect_stats_leveldb(std::ostringstream *ret); + void determine_block_stat_path(const std::string &data); + void collect_stats_io(std::ostringstream *ret); - private: - friend class background_thread; - friend class communication; - friend class coordinator_link; - friend class datalayer; - friend class key_state; - friend class replication_manager; - friend class search_manager; - friend class state_transfer_manager; +private: + friend class background_thread; + friend class communication; + friend class coordinator_link; + friend class datalayer; + friend class key_state; + friend class replication_manager; + friend class search_manager; + friend class state_transfer_manager; - private: - server_id m_us; - po6::net::location m_bind_to; - std::vector > m_threads; - e::garbage_collector m_gc; - e::garbage_collector::thread_state m_gc_ts; - std::auto_ptr m_coord; - std::string m_data_dir; - datalayer m_data; - communication m_comm; - replication_manager m_repl; - state_transfer_manager m_stm; - search_manager m_sm; - configuration m_config; - // pause management - po6::threads::mutex m_protect_pause; - po6::threads::cond m_can_pause; - bool m_paused; - // counters - performance_counter m_perf_req_get; - performance_counter m_perf_req_get_partial; - performance_counter m_perf_req_atomic; - performance_counter m_perf_req_search_start; - performance_counter m_perf_req_search_next; - performance_counter m_perf_req_search_stop; - performance_counter m_perf_req_sorted_search; - performance_counter m_perf_req_count; - performance_counter m_perf_req_sum; - performance_counter m_perf_req_search_describe; - performance_counter m_perf_req_group_atomic; - performance_counter m_perf_chain_op; - performance_counter m_perf_chain_subspace; - performance_counter m_perf_chain_ack; - performance_counter m_perf_xfer_handshake_syn; - performance_counter m_perf_xfer_handshake_synack; - performance_counter m_perf_xfer_handshake_ack; - performance_counter m_perf_xfer_handshake_wiped; - performance_counter m_perf_xfer_op; - performance_counter m_perf_xfer_ack; - performance_counter m_perf_backup; - performance_counter m_perf_perf_counters; - // iostat-like stats - std::string m_block_stat_path; - // historical data - po6::threads::thread m_stat_collector; - po6::threads::mutex m_protect_stats; - uint64_t m_stats_start; - std::list > m_stats; +private: + server_id m_us; + po6::net::location m_bind_to; + std::vector > m_threads; + e::garbage_collector m_gc; + e::garbage_collector::thread_state m_gc_ts; + std::auto_ptr m_coord; + std::string m_data_dir; + datalayer m_data; + communication m_comm; + replication_manager m_repl; + state_transfer_manager m_stm; + search_manager m_sm; + configuration m_config; + // pause management + po6::threads::mutex m_protect_pause; + po6::threads::cond m_can_pause; + bool m_paused; + // counters + performance_counter m_perf_req_get; + performance_counter m_perf_req_get_partial; + performance_counter m_perf_req_atomic; + performance_counter m_perf_req_search_start; + performance_counter m_perf_req_search_next; + performance_counter m_perf_req_search_stop; + performance_counter m_perf_req_sorted_search; + performance_counter m_perf_req_count; + performance_counter m_perf_req_sum; + performance_counter m_perf_req_search_describe; + performance_counter m_perf_req_group_atomic; + performance_counter m_perf_chain_op; + performance_counter m_perf_chain_subspace; + performance_counter m_perf_chain_ack; + performance_counter m_perf_xfer_handshake_syn; + performance_counter m_perf_xfer_handshake_synack; + performance_counter m_perf_xfer_handshake_ack; + performance_counter m_perf_xfer_handshake_wiped; + performance_counter m_perf_xfer_op; + performance_counter m_perf_xfer_ack; + performance_counter m_perf_backup; + performance_counter m_perf_perf_counters; + // iostat-like stats + std::string m_block_stat_path; + // historical data + po6::threads::thread m_stat_collector; + po6::threads::mutex m_protect_stats; + uint64_t m_stats_start; + std::list > m_stats; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/datalayer.cc b/daemon/datalayer.cc index 67cfd126f..d3c3edb2b 100644 --- a/daemon/datalayer.cc +++ b/daemon/datalayer.cc @@ -78,818 +78,730 @@ using hyperdex::reconfigure_returncode; const hyperdex::region_id datalayer::defaultri; -datalayer :: datalayer(daemon* d) - : m_daemon(d) - , m_db() - , m_indices() - , m_versions() - , m_checkpointer(new checkpointer_thread(d)) - , m_mediator(new wiper_indexer_mediator()) - , m_indexer(new indexer_thread(d, m_mediator.get())) - , m_wiper(new wiper_thread(d, m_mediator.get())) +datalayer :: datalayer(daemon *d) + : m_daemon(d) + , m_db() + , m_indices() + , m_versions() + , m_checkpointer(new checkpointer_thread(d)) + , m_mediator(new wiper_indexer_mediator()) + , m_indexer(new indexer_thread(d, m_mediator.get())) + , m_wiper(new wiper_thread(d, m_mediator.get())) { } datalayer :: ~datalayer() throw () { - m_checkpointer->shutdown(); - m_indexer->shutdown(); - m_wiper->shutdown(); + m_checkpointer->shutdown(); + m_indexer->shutdown(); + m_wiper->shutdown(); } #define FORMAT_1_6 "v1.6.0 format" bool -datalayer :: initialize(const std::string& path, - bool* saved, - server_id* saved_us, - po6::net::location* saved_bind_to, - po6::net::hostname* saved_coordinator) +datalayer :: initialize(const std::string &path, + bool *saved, + server_id *saved_us, + po6::net::location *saved_bind_to, + po6::net::hostname *saved_coordinator) { - leveldb::Options opts; - opts.write_buffer_size = 16ULL * 1024ULL * 1024ULL; - opts.create_if_missing = true; - opts.filter_policy = leveldb::NewBloomFilterPolicy(10); - opts.manual_garbage_collection = true; - opts.max_open_files = std::max(sysconf(_SC_OPEN_MAX) >> 1, 1024L); - std::string name(path); - leveldb::DB* tmp_db; - leveldb::Status st = leveldb::DB::Open(opts, name, &tmp_db); - - if (!st.ok()) - { - LOG(ERROR) << "could not open LevelDB: " << st.ToString(); - return false; - } - - m_db.reset(tmp_db); - leveldb::ReadOptions ropts; - ropts.fill_cache = true; - ropts.verify_checksums = true; - leveldb::WriteOptions wopts; - wopts.sync = true; - - // read the "hyperdex" key and check the version - std::string rbacking; - st = m_db->Get(ropts, leveldb::Slice("hyperdex", 8), &rbacking); - bool first_time = false; - - if (st.ok()) - { - first_time = false; - - if (rbacking != FORMAT_1_6) - { - LOG(ERROR) << "could not restore daemon " - << "the existing data was created with" - << "HyperDex " << rbacking << " but " - << "this is requires the v1.6.0-compatible format"; - return false; - } - } - else if (st.IsNotFound()) - { - first_time = true; - leveldb::Slice k("hyperdex", 8); - leveldb::Slice v(FORMAT_1_6, STRLENOF(FORMAT_1_6)); - st = m_db->Put(wopts, k, v); - - if (!st.ok()) - { - LOG(ERROR) << "could not save \"hyperdex\" key to disk: " << st.ToString(); - return false; - } - } - else - { - LOG(ERROR) << "could not read \"hyperdex\" key from LevelDB: " << st.ToString(); - return false; - } - - // read the "state" key and parse it - std::string sbacking; - st = m_db->Get(ropts, leveldb::Slice("state", 5), &sbacking); - - if (st.ok()) - { - if (first_time) - { - LOG(ERROR) << "could not restore from LevelDB because a previous " - << "execution crashed and the database was tampered with; " - << "you'll need to manually erase this DB and create a new one"; - return false; - } - - e::unpacker up(sbacking.data(), sbacking.size()); - uint64_t us; - up = up >> us >> *saved_bind_to >> *saved_coordinator; - *saved_us = server_id(us); - - if (up.error()) - { - LOG(ERROR) << "could not restore from LevelDB because a previous " - << "execution wrote an invalid state; " - << "you'll need to manually erase this DB and create a new one"; - return false; - } - } - else if (st.IsNotFound()) - { - if (!only_key_is_hyperdex_key()) - { - LOG(ERROR) << "could not restore from LevelDB because a previous " - << "execution didn't save state and wrote other data; " - << "you'll need to manually erase this DB and create a new one"; - return false; - } - } - else - { - LOG(ERROR) << "could not read \"hyperdex\" key from LevelDB: " << st.ToString(); - return false; - } - - m_checkpointer->start(); - m_indexer->start(); - m_wiper->start(); - *saved = !first_time; - return true; + leveldb::Options opts; + opts.write_buffer_size = 16ULL * 1024ULL * 1024ULL; + opts.create_if_missing = true; + opts.filter_policy = leveldb::NewBloomFilterPolicy(10); + opts.manual_garbage_collection = true; + opts.max_open_files = std::max(sysconf(_SC_OPEN_MAX) >> 1, 1024L); + std::string name(path); + leveldb::DB *tmp_db; + leveldb::Status st = leveldb::DB::Open(opts, name, &tmp_db); + if (!st.ok()) + { + LOG(ERROR) << "could not open LevelDB: " << st.ToString(); + return false; + } + m_db.reset(tmp_db); + leveldb::ReadOptions ropts; + ropts.fill_cache = true; + ropts.verify_checksums = true; + leveldb::WriteOptions wopts; + wopts.sync = true; + // read the "hyperdex" key and check the version + std::string rbacking; + st = m_db->Get(ropts, leveldb::Slice("hyperdex", 8), &rbacking); + bool first_time = false; + if (st.ok()) + { + first_time = false; + if (rbacking != FORMAT_1_6) + { + LOG(ERROR) << "could not restore daemon " + << "the existing data was created with" + << "HyperDex " << rbacking << " but " + << "this is requires the v1.6.0-compatible format"; + return false; + } + } + else if (st.IsNotFound()) + { + first_time = true; + leveldb::Slice k("hyperdex", 8); + leveldb::Slice v(FORMAT_1_6, STRLENOF(FORMAT_1_6)); + st = m_db->Put(wopts, k, v); + if (!st.ok()) + { + LOG(ERROR) << "could not save \"hyperdex\" key to disk: " << st.ToString(); + return false; + } + } + else + { + LOG(ERROR) << "could not read \"hyperdex\" key from LevelDB: " << st.ToString(); + return false; + } + // read the "state" key and parse it + std::string sbacking; + st = m_db->Get(ropts, leveldb::Slice("state", 5), &sbacking); + if (st.ok()) + { + if (first_time) + { + LOG(ERROR) << "could not restore from LevelDB because a previous " + << "execution crashed and the database was tampered with; " + << "you'll need to manually erase this DB and create a new one"; + return false; + } + e::unpacker up(sbacking.data(), sbacking.size()); + uint64_t us; + up = up >> us >> *saved_bind_to >> *saved_coordinator; + *saved_us = server_id(us); + if (up.error()) + { + LOG(ERROR) << "could not restore from LevelDB because a previous " + << "execution wrote an invalid state; " + << "you'll need to manually erase this DB and create a new one"; + return false; + } + } + else if (st.IsNotFound()) + { + if (!only_key_is_hyperdex_key()) + { + LOG(ERROR) << "could not restore from LevelDB because a previous " + << "execution didn't save state and wrote other data; " + << "you'll need to manually erase this DB and create a new one"; + return false; + } + } + else + { + LOG(ERROR) << "could not read \"hyperdex\" key from LevelDB: " << st.ToString(); + return false; + } + m_checkpointer->start(); + m_indexer->start(); + m_wiper->start(); + *saved = !first_time; + return true; } void datalayer :: teardown() { - m_checkpointer->shutdown(); - m_indexer->shutdown(); - m_wiper->shutdown(); + m_checkpointer->shutdown(); + m_indexer->shutdown(); + m_wiper->shutdown(); } bool -datalayer :: save_state(const server_id& us, - const po6::net::location& bind_to, - const po6::net::hostname& coordinator) +datalayer :: save_state(const server_id &us, + const po6::net::location &bind_to, + const po6::net::hostname &coordinator) { - leveldb::WriteOptions wopts; - wopts.sync = true; - size_t sz = sizeof(uint64_t) - + pack_size(bind_to) - + pack_size(coordinator); - std::auto_ptr state(e::buffer::create(sz)); - state->pack() << us << bind_to << coordinator; - leveldb::Status st = m_db->Put(wopts, leveldb::Slice("state", 5), - leveldb::Slice(reinterpret_cast(state->data()), state->size())); - - if (st.ok()) - { - return true; - } - else - { - LOG(ERROR) << "could not save state: " << st.ToString(); - return false; - } + leveldb::WriteOptions wopts; + wopts.sync = true; + size_t sz = sizeof(uint64_t) + + pack_size(bind_to) + + pack_size(coordinator); + std::auto_ptr state(e::buffer::create(sz)); + state->pack() << us << bind_to << coordinator; + leveldb::Status st = m_db->Put(wopts, leveldb::Slice("state", 5), + leveldb::Slice(reinterpret_cast(state->data()), state->size())); + if (st.ok()) + { + return true; + } + else + { + LOG(ERROR) << "could not save state: " << st.ToString(); + return false; + } } void datalayer :: pause() { - m_checkpointer->initiate_pause(); - m_indexer->initiate_pause(); - m_wiper->initiate_pause(); + m_checkpointer->initiate_pause(); + m_indexer->initiate_pause(); + m_wiper->initiate_pause(); } void datalayer :: unpause() { - m_checkpointer->unpause(); - m_indexer->unpause(); - m_wiper->unpause(); + m_checkpointer->unpause(); + m_indexer->unpause(); + m_wiper->unpause(); } void -datalayer :: reconfigure(const configuration&, - const configuration& config, - const server_id&) +datalayer :: reconfigure(const configuration &, + const configuration &config, + const server_id &) { - m_checkpointer->wait_until_paused(); - m_indexer->wait_until_paused(); - m_wiper->wait_until_paused(); - - // indices that must exist - std::vector > indices; - config.all_indices(m_daemon->m_us, &indices); - std::sort(indices.begin(), indices.end()); - std::vector >::iterator it; - it = std::unique(indices.begin(), indices.end()); - indices.resize(it - indices.begin()); - - // iterate and create indices where necessary - std::vector next_indices; - size_t old_idx = 0; - size_t new_idx = 0; - - while (new_idx < indices.size()) - { - int cmp = 1; - - if (old_idx < m_indices.size()) - { - cmp = e::tuple_compare(m_indices[old_idx].ri, m_indices[old_idx].ii, - indices[new_idx].first, indices[old_idx].second); - } - - if (cmp == 0) - { - // Case B - next_indices.push_back(m_indices[old_idx]); - ++old_idx; - ++new_idx; - } - else if (cmp < 0) - { - // Case A - ++old_idx; - } - else if (cmp > 0) - { - next_indices.push_back(index_state(indices[new_idx].first, - indices[new_idx].second)); - ++new_idx; - region_id ri(indices[new_idx].first); - index_id ii(indices[new_idx].second); - char buf[sizeof(uint8_t) + 2 * VARINT_64_MAX_SIZE]; - char* ptr = buf; - ptr = e::pack8be('I', ptr); - ptr = e::packvarint64(ri.get(), ptr); - ptr = e::packvarint64(ii.get(), ptr); - leveldb::ReadOptions ro; - leveldb::Slice key(buf, ptr - buf); - std::string val; - leveldb::Status st = m_db->Get(ro, key, &val); - - if (st.ok()) - { - next_indices.back().set_usable(); - } - else if (!st.IsNotFound()) - { - handle_error(st); - } - } - } - - m_indices.swap(next_indices); - - // update the versions - std::vector key_regions; - config.key_regions(m_daemon->m_us, &key_regions); - std::vector xfer_regions; - config.transfers_in_regions(m_daemon->m_us, &xfer_regions); - - for (size_t i = 0; i < xfer_regions.size(); ++i) - { - if (config.is_point_leader(config.head_of_region(xfer_regions[i]))) - { - key_regions.push_back(xfer_regions[i]); - } - } - - e::ao_hash_map new_versions; - - for (size_t i = 0; i < key_regions.size(); ++i) - { - uint64_t val = 0; - - if (!m_versions.get(key_regions[i], &val)) - { - val = disk_version(key_regions[i]); - } - - new_versions.put(key_regions[i], val); - } - - m_versions.swap(&new_versions); - m_indexer->kick(); - m_wiper->kick(); + m_checkpointer->wait_until_paused(); + m_indexer->wait_until_paused(); + m_wiper->wait_until_paused(); + // indices that must exist + std::vector > indices; + config.all_indices(m_daemon->m_us, &indices); + std::sort(indices.begin(), indices.end()); + std::vector >::iterator it; + it = std::unique(indices.begin(), indices.end()); + indices.resize(it - indices.begin()); + // iterate and create indices where necessary + std::vector next_indices; + size_t old_idx = 0; + size_t new_idx = 0; + while (new_idx < indices.size()) + { + int cmp = 1; + if (old_idx < m_indices.size()) + { + cmp = e::tuple_compare(m_indices[old_idx].ri, m_indices[old_idx].ii, + indices[new_idx].first, indices[old_idx].second); + } + if (cmp == 0) + { + // Case B + next_indices.push_back(m_indices[old_idx]); + ++old_idx; + ++new_idx; + } + else if (cmp < 0) + { + // Case A + ++old_idx; + } + else if (cmp > 0) + { + next_indices.push_back(index_state(indices[new_idx].first, + indices[new_idx].second)); + ++new_idx; + region_id ri(indices[new_idx].first); + index_id ii(indices[new_idx].second); + char buf[sizeof(uint8_t) + 2 * VARINT_64_MAX_SIZE]; + char *ptr = buf; + ptr = e::pack8be('I', ptr); + ptr = e::packvarint64(ri.get(), ptr); + ptr = e::packvarint64(ii.get(), ptr); + leveldb::ReadOptions ro; + leveldb::Slice key(buf, ptr - buf); + std::string val; + leveldb::Status st = m_db->Get(ro, key, &val); + if (st.ok()) + { + next_indices.back().set_usable(); + } + else if (!st.IsNotFound()) + { + handle_error(st); + } + } + } + m_indices.swap(next_indices); + // update the versions + std::vector key_regions; + config.key_regions(m_daemon->m_us, &key_regions); + std::vector xfer_regions; + config.transfers_in_regions(m_daemon->m_us, &xfer_regions); + for (size_t i = 0; i < xfer_regions.size(); ++i) + { + if (config.is_point_leader(config.head_of_region(xfer_regions[i]))) + { + key_regions.push_back(xfer_regions[i]); + } + } + e::ao_hash_map new_versions; + for (size_t i = 0; i < key_regions.size(); ++i) + { + uint64_t val = 0; + if (!m_versions.get(key_regions[i], &val)) + { + val = disk_version(key_regions[i]); + } + new_versions.put(key_regions[i], val); + } + m_versions.swap(&new_versions); + m_indexer->kick(); + m_wiper->kick(); } void datalayer :: debug_dump() { - LOG(INFO) << "index state ==================================================================="; - - for (size_t i = 0; i < m_indices.size(); ++i) - { - LOG(INFO) << "index id=" << m_indices[i].ii.get() - << " region=" << m_indices[i].ri.get() - << " usable=" << (m_indices[i].is_usable() ? "yes" : "no"); - } - - m_checkpointer->debug_dump(); - m_mediator->debug_dump(); - m_indexer->debug_dump(); - m_wiper->debug_dump(); + LOG(INFO) << "index state ==================================================================="; + for (size_t i = 0; i < m_indices.size(); ++i) + { + LOG(INFO) << "index id=" << m_indices[i].ii.get() + << " region=" << m_indices[i].ri.get() + << " usable=" << (m_indices[i].is_usable() ? "yes" : "no"); + } + m_checkpointer->debug_dump(); + m_mediator->debug_dump(); + m_indexer->debug_dump(); + m_wiper->debug_dump(); } bool -datalayer :: get_property(const e::slice& property, - std::string* value) +datalayer :: get_property(const e::slice &property, + std::string *value) { - leveldb::Slice prop(reinterpret_cast(property.data()), property.size()); - return m_db->GetProperty(prop, value); + leveldb::Slice prop(reinterpret_cast(property.data()), property.size()); + return m_db->GetProperty(prop, value); } std::string datalayer :: get_timestamp() { - std::string timestamp; - m_db->GetReplayTimestamp(×tamp); - return timestamp; + std::string timestamp; + m_db->GetReplayTimestamp(×tamp); + return timestamp; } uint64_t datalayer :: approximate_size() { - leveldb::Slice start("\x00", 1); - leveldb::Slice limit("\xff", 1); - leveldb::Range r(start, limit); - uint64_t ret = 0; - m_db->GetApproximateSizes(&r, 1, &ret); - return ret; + leveldb::Slice start("\x00", 1); + leveldb::Slice limit("\xff", 1); + leveldb::Range r(start, limit); + uint64_t ret = 0; + m_db->GetApproximateSizes(&r, 1, &ret); + return ret; } datalayer::returncode -datalayer :: get(const region_id& ri, - const e::slice& key, - std::vector* value, - uint64_t* version, - reference* ref) +datalayer :: get(const region_id &ri, + const e::slice &key, + std::vector *value, + uint64_t *version, + reference *ref) { - const schema& sc(*m_daemon->m_config.get_schema(ri)); - std::vector scratch; - - // create the encoded key - leveldb::Slice lkey; - encode_key(ri, sc.attrs[0].type, key, &scratch, &lkey); - - // perform the read - leveldb::ReadOptions opts; - opts.fill_cache = true; - opts.verify_checksums = true; - leveldb::Status st = m_db->Get(opts, lkey, &ref->m_backing); - - if (st.ok()) - { - e::slice v(ref->m_backing.data(), ref->m_backing.size()); - return decode_value(v, value, version); - } - else if (st.IsNotFound()) - { - return NOT_FOUND; - } - else - { - return handle_error(st); - } + const schema &sc(*m_daemon->m_config.get_schema(ri)); + std::vector scratch; + // create the encoded key + leveldb::Slice lkey; + encode_key(ri, sc.attrs[0].type, key, &scratch, &lkey); + // perform the read + leveldb::ReadOptions opts; + opts.fill_cache = true; + opts.verify_checksums = true; + leveldb::Status st = m_db->Get(opts, lkey, &ref->m_backing); + if (st.ok()) + { + e::slice v(ref->m_backing.data(), ref->m_backing.size()); + return decode_value(v, value, version); + } + else if (st.IsNotFound()) + { + return NOT_FOUND; + } + else + { + return handle_error(st); + } } datalayer::returncode -datalayer :: del(const region_id& ri, - const e::slice& key, - const std::vector& old_value) +datalayer :: del(const region_id &ri, + const e::slice &key, + const std::vector &old_value) { - leveldb::WriteBatch updates; - const schema& sc(*m_daemon->m_config.get_schema(ri)); - std::vector scratch; - - // create the encoded key - leveldb::Slice lkey; - encode_key(ri, sc.attrs[0].type, key, &scratch, &lkey); - - // delete the actual object - updates.Delete(lkey); - - // delete the index entries - std::vector indices; - find_indices(ri, &indices); - create_index_changes(sc, ri, indices, key, &old_value, NULL, &updates); - - // Perform the write - leveldb::WriteOptions opts; - opts.sync = false; - leveldb::Status st = m_db->Write(opts, &updates); - - if (st.ok()) - { - return SUCCESS; - } - else if (st.IsNotFound()) - { - return NOT_FOUND; - } - else - { - return handle_error(st); - } + leveldb::WriteBatch updates; + const schema &sc(*m_daemon->m_config.get_schema(ri)); + std::vector scratch; + // create the encoded key + leveldb::Slice lkey; + encode_key(ri, sc.attrs[0].type, key, &scratch, &lkey); + // delete the actual object + updates.Delete(lkey); + // delete the index entries + std::vector indices; + find_indices(ri, &indices); + create_index_changes(sc, ri, indices, key, &old_value, NULL, &updates); + // Perform the write + leveldb::WriteOptions opts; + opts.sync = false; + leveldb::Status st = m_db->Write(opts, &updates); + if (st.ok()) + { + return SUCCESS; + } + else if (st.IsNotFound()) + { + return NOT_FOUND; + } + else + { + return handle_error(st); + } } datalayer::returncode -datalayer :: put(const region_id& ri, - const e::slice& key, - const std::vector& new_value, +datalayer :: put(const region_id &ri, + const e::slice &key, + const std::vector &new_value, uint64_t version) { - leveldb::WriteBatch updates; - const schema& sc(*m_daemon->m_config.get_schema(ri)); - std::vector scratch1; - std::vector scratch2; - - // create the encoded key - leveldb::Slice lkey; - encode_key(ri, sc.attrs[0].type, key, &scratch1, &lkey); - - // create the encoded value - leveldb::Slice lval; - encode_value(new_value, version, &scratch2, &lval); - - // put the actual object - updates.Put(lkey, lval); - - // put the index entries - std::vector indices; - find_indices(ri, &indices); - create_index_changes(sc, ri, indices, key, NULL, &new_value, &updates); - - // ensure we've recorded a version at least as high as this key - write_version(ri, version, &updates); - - // Perform the write - leveldb::WriteOptions opts; - opts.sync = false; - leveldb::Status st = m_db->Write(opts, &updates); - - if (st.ok()) - { - update_memory_version(ri, version); - return SUCCESS; - } - else - { - return handle_error(st); - } + leveldb::WriteBatch updates; + const schema &sc(*m_daemon->m_config.get_schema(ri)); + std::vector scratch1; + std::vector scratch2; + // create the encoded key + leveldb::Slice lkey; + encode_key(ri, sc.attrs[0].type, key, &scratch1, &lkey); + // create the encoded value + leveldb::Slice lval; + encode_value(new_value, version, &scratch2, &lval); + // put the actual object + updates.Put(lkey, lval); + // put the index entries + std::vector indices; + find_indices(ri, &indices); + create_index_changes(sc, ri, indices, key, NULL, &new_value, &updates); + // ensure we've recorded a version at least as high as this key + write_version(ri, version, &updates); + // Perform the write + leveldb::WriteOptions opts; + opts.sync = false; + leveldb::Status st = m_db->Write(opts, &updates); + if (st.ok()) + { + update_memory_version(ri, version); + return SUCCESS; + } + else + { + return handle_error(st); + } } datalayer::returncode -datalayer :: overput(const region_id& ri, - const e::slice& key, - const std::vector& old_value, - const std::vector& new_value, +datalayer :: overput(const region_id &ri, + const e::slice &key, + const std::vector &old_value, + const std::vector &new_value, uint64_t version) { - leveldb::WriteBatch updates; - const schema& sc(*m_daemon->m_config.get_schema(ri)); - std::vector scratch1; - std::vector scratch2; - - // create the encoded key - leveldb::Slice lkey; - encode_key(ri, sc.attrs[0].type, key, &scratch1, &lkey); - - // create the encoded value - leveldb::Slice lval; - encode_value(new_value, version, &scratch2, &lval); - - // put the actual object - updates.Put(lkey, lval); - - // put the index entries - std::vector indices; - find_indices(ri, &indices); - create_index_changes(sc, ri, indices, key, &old_value, &new_value, &updates); - - // ensure we've recorded a version at least as high as this key - write_version(ri, version, &updates); - - // Perform the write - leveldb::WriteOptions opts; - opts.sync = false; - leveldb::Status st = m_db->Write(opts, &updates); - - if (st.ok()) - { - update_memory_version(ri, version); - return SUCCESS; - } - else - { - return handle_error(st); - } + leveldb::WriteBatch updates; + const schema &sc(*m_daemon->m_config.get_schema(ri)); + std::vector scratch1; + std::vector scratch2; + // create the encoded key + leveldb::Slice lkey; + encode_key(ri, sc.attrs[0].type, key, &scratch1, &lkey); + // create the encoded value + leveldb::Slice lval; + encode_value(new_value, version, &scratch2, &lval); + // put the actual object + updates.Put(lkey, lval); + // put the index entries + std::vector indices; + find_indices(ri, &indices); + create_index_changes(sc, ri, indices, key, &old_value, &new_value, &updates); + // ensure we've recorded a version at least as high as this key + write_version(ri, version, &updates); + // Perform the write + leveldb::WriteOptions opts; + opts.sync = false; + leveldb::Status st = m_db->Write(opts, &updates); + if (st.ok()) + { + update_memory_version(ri, version); + return SUCCESS; + } + else + { + return handle_error(st); + } } datalayer::returncode -datalayer :: uncertain_del(const region_id& ri, - const e::slice& key) +datalayer :: uncertain_del(const region_id &ri, + const e::slice &key) { - const schema& sc(*m_daemon->m_config.get_schema(ri)); - std::vector scratch; - - // create the encoded key - leveldb::Slice lkey; - encode_key(ri, sc.attrs[0].type, key, &scratch, &lkey); - - // perform the read - std::string ref; - leveldb::ReadOptions opts; - opts.fill_cache = true; - opts.verify_checksums = true; - leveldb::Status st = m_db->Get(opts, lkey, &ref); - - if (st.ok()) - { - std::vector old_value; - uint64_t old_version; - returncode rc = decode_value(e::slice(ref.data(), ref.size()), - &old_value, &old_version); - - if (rc != SUCCESS) - { - return rc; - } - - if (old_value.size() + 1 != sc.attrs_sz) - { - return BAD_ENCODING; - } - - return del(ri, key, old_value); - } - else if (st.IsNotFound()) - { - return SUCCESS; - } - else - { - return handle_error(st); - } + const schema &sc(*m_daemon->m_config.get_schema(ri)); + std::vector scratch; + // create the encoded key + leveldb::Slice lkey; + encode_key(ri, sc.attrs[0].type, key, &scratch, &lkey); + // perform the read + std::string ref; + leveldb::ReadOptions opts; + opts.fill_cache = true; + opts.verify_checksums = true; + leveldb::Status st = m_db->Get(opts, lkey, &ref); + if (st.ok()) + { + std::vector old_value; + uint64_t old_version; + returncode rc = decode_value(e::slice(ref.data(), ref.size()), + &old_value, &old_version); + if (rc != SUCCESS) + { + return rc; + } + if (old_value.size() + 1 != sc.attrs_sz) + { + return BAD_ENCODING; + } + return del(ri, key, old_value); + } + else if (st.IsNotFound()) + { + return SUCCESS; + } + else + { + return handle_error(st); + } } datalayer::returncode -datalayer :: uncertain_put(const region_id& ri, - const e::slice& key, - const std::vector& new_value, +datalayer :: uncertain_put(const region_id &ri, + const e::slice &key, + const std::vector &new_value, uint64_t version) { - const schema& sc(*m_daemon->m_config.get_schema(ri)); - std::vector scratch; - - // create the encoded key - leveldb::Slice lkey; - encode_key(ri, sc.attrs[0].type, key, &scratch, &lkey); - - // perform the read - std::string ref; - leveldb::ReadOptions opts; - opts.fill_cache = true; - opts.verify_checksums = true; - leveldb::Status st = m_db->Get(opts, lkey, &ref); - - if (st.ok()) - { - std::vector old_value; - uint64_t old_version; - returncode rc = decode_value(e::slice(ref.data(), ref.size()), - &old_value, &old_version); - - if (rc != SUCCESS) - { - return rc; - } - - if (old_value.size() + 1 != sc.attrs_sz) - { - return BAD_ENCODING; - } - - return overput(ri, key, old_value, new_value, version); - } - else if (st.IsNotFound()) - { - return put(ri, key, new_value, version); - } - else - { - return handle_error(st); - } + const schema &sc(*m_daemon->m_config.get_schema(ri)); + std::vector scratch; + // create the encoded key + leveldb::Slice lkey; + encode_key(ri, sc.attrs[0].type, key, &scratch, &lkey); + // perform the read + std::string ref; + leveldb::ReadOptions opts; + opts.fill_cache = true; + opts.verify_checksums = true; + leveldb::Status st = m_db->Get(opts, lkey, &ref); + if (st.ok()) + { + std::vector old_value; + uint64_t old_version; + returncode rc = decode_value(e::slice(ref.data(), ref.size()), + &old_value, &old_version); + if (rc != SUCCESS) + { + return rc; + } + if (old_value.size() + 1 != sc.attrs_sz) + { + return BAD_ENCODING; + } + return overput(ri, key, old_value, new_value, version); + } + else if (st.IsNotFound()) + { + return put(ri, key, new_value, version); + } + else + { + return handle_error(st); + } } datalayer::snapshot datalayer :: make_snapshot() { - return leveldb_snapshot_ptr(m_db, m_db->GetSnapshot()); + return leveldb_snapshot_ptr(m_db, m_db->GetSnapshot()); } -datalayer::iterator* +datalayer::iterator * datalayer :: make_search_iterator(snapshot snap, - const region_id& ri, - const std::vector& checks, - std::ostringstream* ostr) + const region_id &ri, + const std::vector &checks, + std::ostringstream *ostr) { - const schema& sc(*m_daemon->m_config.get_schema(ri)); - std::vector > iterators; - - // pull a set of range queries from checks - std::vector ranges; - range_searches(sc, checks, &ranges); - const index_encoding* key_ie = index_encoding::lookup(sc.attrs[0].type); - const index_info* key_ii = index_info::lookup(sc.attrs[0].type); - - // for each range query, construct an iterator - for (size_t i = 0; i < ranges.size(); ++i) - { - if (ranges[i].invalid) - { - if (ostr) *ostr << "encountered invalid range; returning no results\n"; - return new dummy_iterator(); - } - - assert(ranges[i].attr < sc.attrs_sz); - assert(ranges[i].type == sc.attrs[ranges[i].attr].type); - std::vector indices; - find_indices(ri, ranges[i].attr, &indices); - - for (size_t j = 0; j < indices.size(); ++j) - { - assert(indices[j]->attr == ranges[i].attr); - const index* idx = indices[j]; - const index_info* ii = index_info::lookup(ranges[i].type); - - if (!ii) - { - continue; - } - - e::intrusive_ptr it = ii->iterator_from_range(snap, ri, idx->id, ranges[i], key_ie); - - if (it) - { - iterators.push_back(it); - - if (ostr) *ostr << " considering attr " << ranges[i].attr << " Range(" - << ranges[i].start.hex() << ", " << ranges[i].end.hex() << ") " << ranges[i].type << " " - << (ranges[i].has_start ? "[" : "<") << "-" << (ranges[i].has_end ? "]" : ">") - << " " << (ranges[i].invalid ? "invalid" : "valid") << "\n"; - } - } - } - - // For each index - for (size_t i = 0; i < checks.size(); ++i) - { - std::vector indices; - find_indices(ri, checks[i].attr, &indices); - - for (size_t j = 0; j < indices.size(); ++j) - { - const index* idx = indices[j]; - const index_info* ii = index_info::lookup(sc.attrs[checks[i].attr].type); - - if (!ii) - { - continue; - } - - e::intrusive_ptr it = ii->iterator_from_check(snap, ri, idx->id, checks[i], key_ie); - - if (it) - { - iterators.push_back(it); - } - } - } - - // figure out the cost of accessing all objects - e::intrusive_ptr full_scan; - full_scan = key_ii->iterator_for_keys(snap, ri); - if (ostr) *ostr << " accessing all objects has cost " << full_scan->cost(m_db.get()) << "\n"; - - // figure out the cost of each iterator - // we do this here and not below so that iterators can cache the size and we - // don't ping-pong between HyperDex and LevelDB. - for (size_t i = 0; i < iterators.size(); ++i) - { - uint64_t iterator_cost = iterators[i]->cost(m_db.get()); - if (ostr) *ostr << " iterator " << *iterators[i] << " has cost " << iterator_cost << "\n"; - } - - std::vector > sorted; - std::vector > unsorted; - - for (size_t i = 0; i < iterators.size(); ++i) - { - if (iterators[i]->sorted()) - { - sorted.push_back(iterators[i]); - } - else - { - unsorted.push_back(iterators[i]); - } - } - - e::intrusive_ptr best; - - if (!best && !sorted.empty()) - { - best = new intersect_iterator(snap, sorted); - } - else if (!best && !unsorted.empty()) - { - best = unsorted[0]; - } - else - { - best = full_scan; - } - - assert(best); - uint64_t cost = best->cost(m_db.get()); - - if (cost > 0 && cost * 4 > full_scan->cost(m_db.get())) - { - best = full_scan; - } - - if (ostr) *ostr << " choosing to use " << *best << "\n"; - return new search_iterator(this, ri, best, ostr, &checks); + const schema &sc(*m_daemon->m_config.get_schema(ri)); + std::vector > iterators; + // pull a set of range queries from checks + std::vector ranges; + range_searches(sc, checks, &ranges); + const index_encoding *key_ie = index_encoding::lookup(sc.attrs[0].type); + const index_info *key_ii = index_info::lookup(sc.attrs[0].type); + // for each range query, construct an iterator + for (size_t i = 0; i < ranges.size(); ++i) + { + if (ranges[i].invalid) + { + if (ostr) *ostr << "encountered invalid range; returning no results\n"; + return new dummy_iterator(); + } + assert(ranges[i].attr < sc.attrs_sz); + assert(ranges[i].type == sc.attrs[ranges[i].attr].type); + std::vector indices; + find_indices(ri, ranges[i].attr, &indices); + for (size_t j = 0; j < indices.size(); ++j) + { + assert(indices[j]->attr == ranges[i].attr); + const index *idx = indices[j]; + const index_info *ii = index_info::lookup(ranges[i].type); + if (!ii) + { + continue; + } + e::intrusive_ptr it = ii->iterator_from_range(snap, ri, idx->id, ranges[i], key_ie); + if (it) + { + iterators.push_back(it); + if (ostr) *ostr << " considering attr " << ranges[i].attr << " Range(" + << ranges[i].start.hex() << ", " << ranges[i].end.hex() << ") " << ranges[i].type << " " + << (ranges[i].has_start ? "[" : "<") << "-" << (ranges[i].has_end ? "]" : ">") + << " " << (ranges[i].invalid ? "invalid" : "valid") << "\n"; + } + } + } + // For each index + for (size_t i = 0; i < checks.size(); ++i) + { + std::vector indices; + find_indices(ri, checks[i].attr, &indices); + for (size_t j = 0; j < indices.size(); ++j) + { + const index *idx = indices[j]; + const index_info *ii = index_info::lookup(sc.attrs[checks[i].attr].type); + if (!ii) + { + continue; + } + e::intrusive_ptr it = ii->iterator_from_check(snap, ri, idx->id, checks[i], key_ie); + if (it) + { + iterators.push_back(it); + } + } + } + // figure out the cost of accessing all objects + e::intrusive_ptr full_scan; + full_scan = key_ii->iterator_for_keys(snap, ri); + if (ostr) *ostr << " accessing all objects has cost " << full_scan->cost(m_db.get()) << "\n"; + // figure out the cost of each iterator + // we do this here and not below so that iterators can cache the size and we + // don't ping-pong between HyperDex and LevelDB. + for (size_t i = 0; i < iterators.size(); ++i) + { + uint64_t iterator_cost = iterators[i]->cost(m_db.get()); + if (ostr) *ostr << " iterator " << *iterators[i] << " has cost " << iterator_cost << "\n"; + } + std::vector > sorted; + std::vector > unsorted; + for (size_t i = 0; i < iterators.size(); ++i) + { + if (iterators[i]->sorted()) + { + sorted.push_back(iterators[i]); + } + else + { + unsorted.push_back(iterators[i]); + } + } + e::intrusive_ptr best; + if (!best && !sorted.empty()) + { + best = new intersect_iterator(snap, sorted); + } + else if (!best && !unsorted.empty()) + { + best = unsorted[0]; + } + else + { + best = full_scan; + } + assert(best); + uint64_t cost = best->cost(m_db.get()); + if (cost > 0 && cost * 4 > full_scan->cost(m_db.get())) + { + best = full_scan; + } + if (ostr) *ostr << " choosing to use " << *best << "\n"; + return new search_iterator(this, ri, best, ostr, &checks); } bool -datalayer :: backup(const e::slice& _name) +datalayer :: backup(const e::slice &_name) { - leveldb::Slice name(reinterpret_cast(_name.data()), _name.size()); - leveldb::Status st = m_db->LiveBackup(name); - - if (st.ok()) - { - return true; - } - else if (st.IsCorruption()) - { - LOG(ERROR) << "corruption while taking a backup: " << st.ToString(); - return false; - } - else if (st.IsIOError()) - { - LOG(ERROR) << "IO error while taking a backup: " << st.ToString(); - return false; - } - else - { - LOG(ERROR) << "LevelDB returned an unknown error that we don't know how to handle: " << st.ToString(); - return false; - } + leveldb::Slice name(reinterpret_cast(_name.data()), _name.size()); + leveldb::Status st = m_db->LiveBackup(name); + if (st.ok()) + { + return true; + } + else if (st.IsCorruption()) + { + LOG(ERROR) << "corruption while taking a backup: " << st.ToString(); + return false; + } + else if (st.IsIOError()) + { + LOG(ERROR) << "IO error while taking a backup: " << st.ToString(); + return false; + } + else + { + LOG(ERROR) << "LevelDB returned an unknown error that we don't know how to handle: " << st.ToString(); + return false; + } } datalayer::returncode -datalayer :: get_from_iterator(const region_id& ri, - const schema& sc, - iterator* iter, - e::slice* key, - std::vector* value, - uint64_t* version, - reference* ref) +datalayer :: get_from_iterator(const region_id &ri, + const schema &sc, + iterator *iter, + e::slice *key, + std::vector *value, + uint64_t *version, + reference *ref) { - std::vector scratch; - - // create the encoded key - leveldb::Slice lkey; - encode_key(ri, sc.attrs[0].type, iter->key(), &scratch, &lkey); - - // perform the read - leveldb::ReadOptions opts; - opts.fill_cache = true; - opts.verify_checksums = true; - opts.snapshot = iter->snap().get(); - leveldb::Status st = m_db->Get(opts, lkey, &ref->m_backing); - - if (st.ok()) - { - ref->m_backing += std::string(reinterpret_cast(iter->key().data()), iter->key().size()); - *key = e::slice(ref->m_backing.data() - + ref->m_backing.size() - - iter->key().size(), - iter->key().size()); - e::slice v(ref->m_backing.data(), ref->m_backing.size() - iter->key().size()); - return decode_value(v, value, version); - } - else if (st.IsNotFound()) - { - return NOT_FOUND; - } - else - { - return handle_error(st); - } + std::vector scratch; + // create the encoded key + leveldb::Slice lkey; + encode_key(ri, sc.attrs[0].type, iter->key(), &scratch, &lkey); + // perform the read + leveldb::ReadOptions opts; + opts.fill_cache = true; + opts.verify_checksums = true; + opts.snapshot = iter->snap().get(); + leveldb::Status st = m_db->Get(opts, lkey, &ref->m_backing); + if (st.ok()) + { + ref->m_backing += std::string(reinterpret_cast(iter->key().data()), iter->key().size()); + *key = e::slice(ref->m_backing.data() + + ref->m_backing.size() + - iter->key().size(), + iter->key().size()); + e::slice v(ref->m_backing.data(), ref->m_backing.size() - iter->key().size()); + return decode_value(v, value, version); + } + else if (st.IsNotFound()) + { + return NOT_FOUND; + } + else + { + return handle_error(st); + } } namespace @@ -898,524 +810,462 @@ namespace uint64_t roundup_version(uint64_t v) { - const static uint64_t REGION_PERIODIC = hyperdex::datalayer::REGION_PERIODIC; - v += REGION_PERIODIC; - v = v & ~(REGION_PERIODIC - 1); - return v; + const static uint64_t REGION_PERIODIC = hyperdex::datalayer::REGION_PERIODIC; + v += REGION_PERIODIC; + v = v & ~(REGION_PERIODIC - 1); + return v; } } bool -datalayer :: write_version(const region_id& ri, +datalayer :: write_version(const region_id &ri, uint64_t version, - leveldb::WriteBatch* updates) + leveldb::WriteBatch *updates) { - version = roundup_version(version); - uint64_t* current = NULL; - - if (!m_versions.mod(ri, ¤t) || - e::atomic::load_64_nobarrier(current) >= version) - { - return false; - } - - char vbacking[VERSION_BUF_SIZE]; - encode_version(ri, version, vbacking); - updates->Put(leveldb::Slice(vbacking, VERSION_BUF_SIZE), leveldb::Slice()); - return true; + version = roundup_version(version); + uint64_t *current = NULL; + if (!m_versions.mod(ri, ¤t) || + e::atomic::load_64_nobarrier(current) >= version) + { + return false; + } + char vbacking[VERSION_BUF_SIZE]; + encode_version(ri, version, vbacking); + updates->Put(leveldb::Slice(vbacking, VERSION_BUF_SIZE), leveldb::Slice()); + return true; } void -datalayer :: update_memory_version(const region_id& ri, uint64_t version) +datalayer :: update_memory_version(const region_id &ri, uint64_t version) { - version = roundup_version(version); - uint64_t* current = NULL; - m_versions.mod(ri, ¤t); - - if (current == NULL) - { - return; - } - - uint64_t expected = e::atomic::load_64_nobarrier(current); - uint64_t witness = 0; - - while ((witness = e::atomic::compare_and_swap_64_nobarrier(current, expected, version)) < version) - { - expected = witness; - } + version = roundup_version(version); + uint64_t *current = NULL; + m_versions.mod(ri, ¤t); + if (current == NULL) + { + return; + } + uint64_t expected = e::atomic::load_64_nobarrier(current); + uint64_t witness = 0; + while ((witness = e::atomic::compare_and_swap_64_nobarrier(current, expected, version)) < version) + { + expected = witness; + } } void -datalayer :: bump_version(const region_id& ri, uint64_t version) +datalayer :: bump_version(const region_id &ri, uint64_t version) { - leveldb::WriteBatch updates; - - if (!write_version(ri, version, &updates)) - { - return; - } - - // Perform the write - leveldb::WriteOptions opts; - opts.sync = false; - leveldb::Status st = m_db->Write(opts, &updates); - - if (!st.ok()) - { - handle_error(st); - } - - update_memory_version(ri, version); + leveldb::WriteBatch updates; + if (!write_version(ri, version, &updates)) + { + return; + } + // Perform the write + leveldb::WriteOptions opts; + opts.sync = false; + leveldb::Status st = m_db->Write(opts, &updates); + if (!st.ok()) + { + handle_error(st); + } + update_memory_version(ri, version); } uint64_t -datalayer :: max_version(const region_id& ri) +datalayer :: max_version(const region_id &ri) { - uint64_t val; - - if (!m_versions.get(ri, &val)) - { - val = disk_version(ri); - } - - return val; + uint64_t val; + if (!m_versions.get(ri, &val)) + { + val = disk_version(ri); + } + return val; } uint64_t -datalayer :: disk_version(const region_id& ri) +datalayer :: disk_version(const region_id &ri) { - leveldb::ReadOptions opts; - opts.fill_cache = false; - opts.verify_checksums = true; - opts.snapshot = NULL; - std::auto_ptr it(m_db->NewIterator(opts)); - char vbacking[VERSION_BUF_SIZE]; - encode_version(ri, UINT64_MAX, vbacking); - leveldb::Slice key(vbacking, VERSION_BUF_SIZE); - it->Seek(key); - - if (!it->Valid()) - { - // XXX err - return 0; - } - - key = it->key(); - region_id tmp_ri; - uint64_t tmp_version; - datalayer::returncode rc = decode_version(e::slice(key.data(), key.size()), - &tmp_ri, &tmp_version); - - if (rc != SUCCESS) - { - // XXX err - return 0; - } - - if (tmp_ri != ri) - { - return 0; - } - - return tmp_version; + leveldb::ReadOptions opts; + opts.fill_cache = false; + opts.verify_checksums = true; + opts.snapshot = NULL; + std::auto_ptr it(m_db->NewIterator(opts)); + char vbacking[VERSION_BUF_SIZE]; + encode_version(ri, UINT64_MAX, vbacking); + leveldb::Slice key(vbacking, VERSION_BUF_SIZE); + it->Seek(key); + if (!it->Valid()) + { + // XXX err + return 0; + } + key = it->key(); + region_id tmp_ri; + uint64_t tmp_version; + datalayer::returncode rc = decode_version(e::slice(key.data(), key.size()), + &tmp_ri, &tmp_version); + if (rc != SUCCESS) + { + // XXX err + return 0; + } + if (tmp_ri != ri) + { + return 0; + } + return tmp_version; } datalayer::returncode -datalayer :: create_checkpoint(const region_timestamp& rt) +datalayer :: create_checkpoint(const region_timestamp &rt) { - m_wiper->inhibit_wiping(); - e::guard g = e::makeobjguard(*m_wiper, &wiper_thread::permit_wiping); - g.use_variable(); - - if (m_wiper->region_will_be_wiped(rt.rid)) - { - return SUCCESS; - } - - char cbacking[CHECKPOINT_BUF_SIZE]; - encode_checkpoint(rt.rid, rt.checkpoint, cbacking); - leveldb::WriteOptions opts; - opts.sync = false; - leveldb::Slice ckey(cbacking, CHECKPOINT_BUF_SIZE); - leveldb::Slice val(rt.local_timestamp); - leveldb::Status st = m_db->Put(opts, ckey, val); - - if (!st.ok()) - { - return handle_error(st); - } - - return SUCCESS; + m_wiper->inhibit_wiping(); + e::guard g = e::makeobjguard(*m_wiper, &wiper_thread::permit_wiping); + g.use_variable(); + if (m_wiper->region_will_be_wiped(rt.rid)) + { + return SUCCESS; + } + char cbacking[CHECKPOINT_BUF_SIZE]; + encode_checkpoint(rt.rid, rt.checkpoint, cbacking); + leveldb::WriteOptions opts; + opts.sync = false; + leveldb::Slice ckey(cbacking, CHECKPOINT_BUF_SIZE); + leveldb::Slice val(rt.local_timestamp); + leveldb::Status st = m_db->Put(opts, ckey, val); + if (!st.ok()) + { + return handle_error(st); + } + return SUCCESS; } void datalayer :: set_checkpoint_gc(uint64_t checkpoint_gc) { - m_checkpointer->set_checkpoint_gc(checkpoint_gc); + m_checkpointer->set_checkpoint_gc(checkpoint_gc); } void -datalayer :: largest_checkpoint_for(const region_id& ri, uint64_t* checkpoint) +datalayer :: largest_checkpoint_for(const region_id &ri, uint64_t *checkpoint) { - m_wiper->inhibit_wiping(); - e::guard g = e::makeobjguard(*m_wiper, &wiper_thread::permit_wiping); - g.use_variable(); - - if (m_wiper->region_will_be_wiped(ri)) - { - *checkpoint = 0; - return; - } - - leveldb::ReadOptions opts; - opts.verify_checksums = true; - std::auto_ptr it; - it.reset(m_db->NewIterator(opts)); - char cbacking[CHECKPOINT_BUF_SIZE]; - encode_checkpoint(ri, 0, cbacking); - it->Seek(leveldb::Slice(cbacking, CHECKPOINT_BUF_SIZE)); - *checkpoint = 0; - - while (it->Valid()) - { - region_timestamp rt; - e::slice key(it->key().data(), it->key().size()); - returncode rc = decode_checkpoint(key, &rt.rid, &rt.checkpoint); - - if (rc != datalayer::SUCCESS) - { - break; - } - - if (rt.rid != ri) - { - break; - } - - *checkpoint = std::max(*checkpoint, rt.checkpoint); - it->Next(); - } + m_wiper->inhibit_wiping(); + e::guard g = e::makeobjguard(*m_wiper, &wiper_thread::permit_wiping); + g.use_variable(); + if (m_wiper->region_will_be_wiped(ri)) + { + *checkpoint = 0; + return; + } + leveldb::ReadOptions opts; + opts.verify_checksums = true; + std::auto_ptr it; + it.reset(m_db->NewIterator(opts)); + char cbacking[CHECKPOINT_BUF_SIZE]; + encode_checkpoint(ri, 0, cbacking); + it->Seek(leveldb::Slice(cbacking, CHECKPOINT_BUF_SIZE)); + *checkpoint = 0; + while (it->Valid()) + { + region_timestamp rt; + e::slice key(it->key().data(), it->key().size()); + returncode rc = decode_checkpoint(key, &rt.rid, &rt.checkpoint); + if (rc != datalayer::SUCCESS) + { + break; + } + if (rt.rid != ri) + { + break; + } + *checkpoint = std::max(*checkpoint, rt.checkpoint); + it->Next(); + } } bool datalayer :: region_will_be_wiped(region_id rid) { - return m_wiper->region_will_be_wiped(rid); + return m_wiper->region_will_be_wiped(rid); } void -datalayer :: request_wipe(const transfer_id& xid, - const region_id& ri) +datalayer :: request_wipe(const transfer_id &xid, + const region_id &ri) { - m_wiper->request_wipe(xid, ri); + m_wiper->request_wipe(xid, ri); } void datalayer :: inhibit_wiping() { - m_wiper->inhibit_wiping(); + m_wiper->inhibit_wiping(); } void datalayer :: permit_wiping() { - m_wiper->permit_wiping(); + m_wiper->permit_wiping(); } -datalayer::replay_iterator* -datalayer :: replay_region_from_checkpoint(const region_id& ri, +datalayer::replay_iterator * +datalayer :: replay_region_from_checkpoint(const region_id &ri, uint64_t checkpoint, - bool* wipe) + bool *wipe) { - m_wiper->inhibit_wiping(); - e::guard g1 = e::makeobjguard(*m_wiper, &wiper_thread::permit_wiping); - g1.use_variable(); - m_checkpointer->inhibit_gc(); - e::guard g2 = e::makeobjguard(*m_checkpointer, &checkpointer_thread::permit_gc); - g2.use_variable(); - - leveldb::ReadOptions opts; - opts.verify_checksums = true; - std::auto_ptr it; - it.reset(m_db->NewIterator(opts)); - char cbacking[CHECKPOINT_BUF_SIZE]; - encode_checkpoint(ri, 0, cbacking); - it->Seek(leveldb::Slice(cbacking, CHECKPOINT_BUF_SIZE)); - std::string local_timestamp("all"); - - while (it->Valid()) - { - region_timestamp rt; - e::slice key(it->key().data(), it->key().size()); - returncode rc = decode_checkpoint(key, &rt.rid, &rt.checkpoint); - - if (rc != datalayer::SUCCESS) - { - break; - } - - if (rt.rid != ri || rt.checkpoint > checkpoint) - { - break; - } - - local_timestamp.assign(it->value().data(), it->value().size()); - it->Next(); - } - - assert(!m_wiper->region_will_be_wiped(ri)); - *wipe = local_timestamp == "all"; - leveldb::ReplayIterator* iter; - leveldb::Status st = m_db->GetReplayIterator(local_timestamp, &iter); - - if (!st.ok()) - { - LOG(ERROR) << "LevelDB corruption: invalid timestamp"; - abort(); - } - - leveldb_replay_iterator_ptr ptr(m_db, iter); - const schema& sc(*m_daemon->m_config.get_schema(ri)); - return new replay_iterator(ri, ptr, index_encoding::lookup(sc.attrs[0].type)); + m_wiper->inhibit_wiping(); + e::guard g1 = e::makeobjguard(*m_wiper, &wiper_thread::permit_wiping); + g1.use_variable(); + m_checkpointer->inhibit_gc(); + e::guard g2 = e::makeobjguard(*m_checkpointer, &checkpointer_thread::permit_gc); + g2.use_variable(); + leveldb::ReadOptions opts; + opts.verify_checksums = true; + std::auto_ptr it; + it.reset(m_db->NewIterator(opts)); + char cbacking[CHECKPOINT_BUF_SIZE]; + encode_checkpoint(ri, 0, cbacking); + it->Seek(leveldb::Slice(cbacking, CHECKPOINT_BUF_SIZE)); + std::string local_timestamp("all"); + while (it->Valid()) + { + region_timestamp rt; + e::slice key(it->key().data(), it->key().size()); + returncode rc = decode_checkpoint(key, &rt.rid, &rt.checkpoint); + if (rc != datalayer::SUCCESS) + { + break; + } + if (rt.rid != ri || rt.checkpoint > checkpoint) + { + break; + } + local_timestamp.assign(it->value().data(), it->value().size()); + it->Next(); + } + assert(!m_wiper->region_will_be_wiped(ri)); + *wipe = local_timestamp == "all"; + leveldb::ReplayIterator *iter; + leveldb::Status st = m_db->GetReplayIterator(local_timestamp, &iter); + if (!st.ok()) + { + LOG(ERROR) << "LevelDB corruption: invalid timestamp"; + abort(); + } + leveldb_replay_iterator_ptr ptr(m_db, iter); + const schema &sc(*m_daemon->m_config.get_schema(ri)); + return new replay_iterator(ri, ptr, index_encoding::lookup(sc.attrs[0].type)); } void -datalayer :: create_index_marker(const region_id& ri, const index_id& ii) +datalayer :: create_index_marker(const region_id &ri, const index_id &ii) { - char buf[sizeof(uint8_t) + 2 * VARINT_64_MAX_SIZE]; - char* ptr = buf; - ptr = e::pack8be('I', ptr); - ptr = e::packvarint64(ri.get(), ptr); - ptr = e::packvarint64(ii.get(), ptr); - leveldb::Slice key(buf, ptr - buf); - leveldb::Slice val; - leveldb::Status st = m_db->Put(leveldb::WriteOptions(), key, val); - - if (!st.ok()) - { - LOG(ERROR) << "LevelDB corruption: could not put"; - abort(); - } + char buf[sizeof(uint8_t) + 2 * VARINT_64_MAX_SIZE]; + char *ptr = buf; + ptr = e::pack8be('I', ptr); + ptr = e::packvarint64(ri.get(), ptr); + ptr = e::packvarint64(ii.get(), ptr); + leveldb::Slice key(buf, ptr - buf); + leveldb::Slice val; + leveldb::Status st = m_db->Put(leveldb::WriteOptions(), key, val); + if (!st.ok()) + { + LOG(ERROR) << "LevelDB corruption: could not put"; + abort(); + } } bool -datalayer :: has_index_marker(const region_id& ri, const index_id& ii) +datalayer :: has_index_marker(const region_id &ri, const index_id &ii) { - char buf[sizeof(uint8_t) + 2 * VARINT_64_MAX_SIZE]; - char* ptr = buf; - ptr = e::pack8be('I', ptr); - ptr = e::packvarint64(ri.get(), ptr); - ptr = e::packvarint64(ii.get(), ptr); - leveldb::Slice key(buf, ptr - buf); - std::string val; - leveldb::Status st = m_db->Get(leveldb::ReadOptions(), key, &val); - - if (!st.ok() && !st.IsNotFound()) - { - LOG(ERROR) << "LevelDB corruption: could not get"; - abort(); - } - - return st.ok(); + char buf[sizeof(uint8_t) + 2 * VARINT_64_MAX_SIZE]; + char *ptr = buf; + ptr = e::pack8be('I', ptr); + ptr = e::packvarint64(ri.get(), ptr); + ptr = e::packvarint64(ii.get(), ptr); + leveldb::Slice key(buf, ptr - buf); + std::string val; + leveldb::Status st = m_db->Get(leveldb::ReadOptions(), key, &val); + if (!st.ok() && !st.IsNotFound()) + { + LOG(ERROR) << "LevelDB corruption: could not get"; + abort(); + } + return st.ok(); } bool datalayer :: only_key_is_hyperdex_key() { - leveldb::ReadOptions opts; - opts.fill_cache = false; - opts.verify_checksums = true; - opts.snapshot = NULL; - std::auto_ptr it(m_db->NewIterator(opts)); - it->SeekToFirst(); - bool seen = false; - - while (it->Valid()) - { - if (it->key().compare(leveldb::Slice("hyperdex", 8)) != 0) - { - return false; - } - - it->Next(); - seen = true; - } - - return seen; + leveldb::ReadOptions opts; + opts.fill_cache = false; + opts.verify_checksums = true; + opts.snapshot = NULL; + std::auto_ptr it(m_db->NewIterator(opts)); + it->SeekToFirst(); + bool seen = false; + while (it->Valid()) + { + if (it->key().compare(leveldb::Slice("hyperdex", 8)) != 0) + { + return false; + } + it->Next(); + seen = true; + } + return seen; } bool datalayer :: upgrade_13x_to_14() { - leveldb::WriteOptions wopts; - wopts.sync = true; - - // first scan every key that starts with "a", making a map from region id to max seqid. - std::map seq_ids; - leveldb::ReadOptions ropts; - ropts.fill_cache = false; - ropts.verify_checksums = true; - ropts.snapshot = NULL; - std::auto_ptr it(m_db->NewIterator(ropts)); - it->Seek(leveldb::Slice("a", 1)); - - while (it->Valid()) - { - if (it->key().size() != sizeof(uint64_t) * 3 + 1 || - it->key().data()[0] != 'a') - { - break; - } - - const char* ptr = it->key().data(); - uint64_t reg_id; - uint64_t seq_id; - uint64_t ri; - e::unpack64be(ptr + 1, ®_id); - e::unpack64be(ptr + 9, &seq_id); - e::unpack64be(ptr + 17, &ri); - - if (reg_id == ri) - { - seq_id = std::max(seq_ids[region_id(ri)], UINT64_MAX - seq_id); - seq_ids[region_id(ri)] = seq_id; - } - - it->Next(); - } - - if (!it->status().ok()) - { - LOG(ERROR) << "could not upgrade to 1.4: " << it->status().ToString(); - return false; - } - - // now write out versions for the regions that we saw - for (std::map::iterator s = seq_ids.begin(); - s != seq_ids.end(); ++s) - { - char vbacking[VERSION_BUF_SIZE]; - uint64_t v = std::max(s->second, disk_version(s->first)); - encode_version(s->first, roundup_version(v), vbacking); - leveldb::Status st = m_db->Put(wopts, leveldb::Slice(vbacking, VERSION_BUF_SIZE), leveldb::Slice()); - - if (!st.ok()) - { - LOG(ERROR) << "could not upgrade to 1.4: " << st.ToString(); - return false; - } - } - - // only after those are on disk should we delete the original keys - it->Seek(leveldb::Slice("a", 1)); - - while (it->Valid()) - { - if (it->key().size() == sizeof(uint64_t) * 3 + 1 || - it->key().data()[0] != 'a') - { - break; - } - - leveldb::Status st = m_db->Delete(wopts, it->key()); - - if (!st.ok()) - { - LOG(ERROR) << "could not upgrade to 1.4: " << it->status().ToString(); - return false; - } - - it->Next(); - } - - if (!it->status().ok()) - { - LOG(ERROR) << "could not upgrade to 1.4: " << it->status().ToString(); - return false; - } - - // finally mark the new version - leveldb::Slice k("hyperdex", 8); - leveldb::Slice v(PACKAGE_VERSION, STRLENOF(PACKAGE_VERSION)); - leveldb::Status st = m_db->Put(wopts, k, v); - - if (!st.ok()) - { - LOG(ERROR) << "could not upgrade to 1.4: " << st.ToString(); - return false; - } - - return true; + leveldb::WriteOptions wopts; + wopts.sync = true; + // first scan every key that starts with "a", making a map from region id to max seqid. + std::map seq_ids; + leveldb::ReadOptions ropts; + ropts.fill_cache = false; + ropts.verify_checksums = true; + ropts.snapshot = NULL; + std::auto_ptr it(m_db->NewIterator(ropts)); + it->Seek(leveldb::Slice("a", 1)); + while (it->Valid()) + { + if (it->key().size() != sizeof(uint64_t) * 3 + 1 || + it->key().data()[0] != 'a') + { + break; + } + const char *ptr = it->key().data(); + uint64_t reg_id; + uint64_t seq_id; + uint64_t ri; + e::unpack64be(ptr + 1, ®_id); + e::unpack64be(ptr + 9, &seq_id); + e::unpack64be(ptr + 17, &ri); + if (reg_id == ri) + { + seq_id = std::max(seq_ids[region_id(ri)], UINT64_MAX - seq_id); + seq_ids[region_id(ri)] = seq_id; + } + it->Next(); + } + if (!it->status().ok()) + { + LOG(ERROR) << "could not upgrade to 1.4: " << it->status().ToString(); + return false; + } + // now write out versions for the regions that we saw + for (std::map::iterator s = seq_ids.begin(); + s != seq_ids.end(); ++s) + { + char vbacking[VERSION_BUF_SIZE]; + uint64_t v = std::max(s->second, disk_version(s->first)); + encode_version(s->first, roundup_version(v), vbacking); + leveldb::Status st = m_db->Put(wopts, leveldb::Slice(vbacking, VERSION_BUF_SIZE), leveldb::Slice()); + if (!st.ok()) + { + LOG(ERROR) << "could not upgrade to 1.4: " << st.ToString(); + return false; + } + } + // only after those are on disk should we delete the original keys + it->Seek(leveldb::Slice("a", 1)); + while (it->Valid()) + { + if (it->key().size() == sizeof(uint64_t) * 3 + 1 || + it->key().data()[0] != 'a') + { + break; + } + leveldb::Status st = m_db->Delete(wopts, it->key()); + if (!st.ok()) + { + LOG(ERROR) << "could not upgrade to 1.4: " << it->status().ToString(); + return false; + } + it->Next(); + } + if (!it->status().ok()) + { + LOG(ERROR) << "could not upgrade to 1.4: " << it->status().ToString(); + return false; + } + // finally mark the new version + leveldb::Slice k("hyperdex", 8); + leveldb::Slice v(PACKAGE_VERSION, STRLENOF(PACKAGE_VERSION)); + leveldb::Status st = m_db->Put(wopts, k, v); + if (!st.ok()) + { + LOG(ERROR) << "could not upgrade to 1.4: " << st.ToString(); + return false; + } + return true; } void -datalayer :: find_indices(const region_id& rid, std::vector* indices) +datalayer :: find_indices(const region_id &rid, std::vector *indices) { - std::vector::iterator it; - it = std::lower_bound(m_indices.begin(), m_indices.end(), rid); - - for (; it < m_indices.end() && it->ri == rid; ++it) - { - if (!it->is_usable()) - { - continue; - } - - const index* idx = m_daemon->m_config.get_index(it->ii); - assert(idx); - indices->push_back(idx); - } + std::vector::iterator it; + it = std::lower_bound(m_indices.begin(), m_indices.end(), rid); + for (; it < m_indices.end() && it->ri == rid; ++it) + { + if (!it->is_usable()) + { + continue; + } + const index *idx = m_daemon->m_config.get_index(it->ii); + assert(idx); + indices->push_back(idx); + } } void -datalayer :: find_indices(const region_id& rid, uint16_t attr, - std::vector* indices) +datalayer :: find_indices(const region_id &rid, uint16_t attr, + std::vector *indices) { - std::vector::iterator it; - it = std::lower_bound(m_indices.begin(), m_indices.end(), rid); - - for (; it < m_indices.end() && it->ri == rid; ++it) - { - if (!it->is_usable()) - { - continue; - } - - const index* idx = m_daemon->m_config.get_index(it->ii); - assert(idx); - - if (idx->attr == attr) - { - indices->push_back(idx); - } - } + std::vector::iterator it; + it = std::lower_bound(m_indices.begin(), m_indices.end(), rid); + for (; it < m_indices.end() && it->ri == rid; ++it) + { + if (!it->is_usable()) + { + continue; + } + const index *idx = m_daemon->m_config.get_index(it->ii); + assert(idx); + if (idx->attr == attr) + { + indices->push_back(idx); + } + } } datalayer::returncode datalayer :: handle_error(leveldb::Status st) { - if (st.IsCorruption()) - { - LOG(ERROR) << "corruption at the disk layer: " << st.ToString(); - return CORRUPTION; - } - else if (st.IsIOError()) - { - LOG(ERROR) << "IO error at the disk layer: " << st.ToString(); - return IO_ERROR; - } - else - { - LOG(ERROR) << "LevelDB returned an unknown error that we don't know how to handle:"; - LOG(ERROR) << st.ToString(); - return LEVELDB_ERROR; - } + if (st.IsCorruption()) + { + LOG(ERROR) << "corruption at the disk layer: " << st.ToString(); + return CORRUPTION; + } + else if (st.IsIOError()) + { + LOG(ERROR) << "IO error at the disk layer: " << st.ToString(); + return IO_ERROR; + } + else + { + LOG(ERROR) << "LevelDB returned an unknown error that we don't know how to handle:"; + LOG(ERROR) << st.ToString(); + return LEVELDB_ERROR; + } } datalayer :: reference :: reference() - : m_backing() + : m_backing() { } @@ -1424,25 +1274,24 @@ datalayer :: reference :: ~reference() throw () } void -datalayer :: reference :: swap(reference* ref) +datalayer :: reference :: swap(reference *ref) { - m_backing.swap(ref->m_backing); + m_backing.swap(ref->m_backing); } -std::ostream& -hyperdex :: operator << (std::ostream& lhs, datalayer::returncode rhs) +std::ostream & +hyperdex :: operator << (std::ostream &lhs, datalayer::returncode rhs) { - switch (rhs) - { - STRINGIFY(datalayer::SUCCESS); - STRINGIFY(datalayer::NOT_FOUND); - STRINGIFY(datalayer::BAD_ENCODING); - STRINGIFY(datalayer::CORRUPTION); - STRINGIFY(datalayer::IO_ERROR); - STRINGIFY(datalayer::LEVELDB_ERROR); - default: - lhs << "unknown returncode"; - } - - return lhs; + switch (rhs) + { + STRINGIFY(datalayer::SUCCESS); + STRINGIFY(datalayer::NOT_FOUND); + STRINGIFY(datalayer::BAD_ENCODING); + STRINGIFY(datalayer::CORRUPTION); + STRINGIFY(datalayer::IO_ERROR); + STRINGIFY(datalayer::LEVELDB_ERROR); + default: + lhs << "unknown returncode"; + } + return lhs; } diff --git a/daemon/datalayer.h b/daemon/datalayer.h index a84f7632c..6d1a8bbef 100644 --- a/daemon/datalayer.h +++ b/daemon/datalayer.h @@ -65,176 +65,176 @@ class daemon; class datalayer { - public: - enum returncode - { - SUCCESS, - NOT_FOUND, - BAD_ENCODING, - CORRUPTION, - IO_ERROR, - LEVELDB_ERROR - }; - class reference; - class iterator; - class replay_iterator; - class dummy_iterator; - class region_iterator; - class search_iterator; - class index_iterator; - class range_index_iterator; - class intersect_iterator; - typedef leveldb_snapshot_ptr snapshot; - // must be pow2 - const static uint64_t REGION_PERIODIC = 65536; - - public: - datalayer(daemon*); - ~datalayer() throw (); - - public: - bool initialize(const std::string& path, - bool* saved, - server_id* saved_us, - po6::net::location* saved_bind_to, - po6::net::hostname* saved_coordinator); - bool save_state(const server_id& m_us, - const po6::net::location& bind_to, - const po6::net::hostname& coordinator); - void teardown(); - // reconfiguration - void pause(); - void unpause(); - void reconfigure(const configuration& old_config, - const configuration& new_config, - const server_id& us); - void debug_dump(); - // stats - bool get_property(const e::slice& property, - std::string* value); - std::string get_timestamp(); - uint64_t approximate_size(); - - public: - // retrieve the current value of a key - returncode get(const region_id& ri, - const e::slice& key, - std::vector* value, - uint64_t* version, - reference* ref); - // put, overput, or delete a key where the existing value is known - returncode del(const region_id& ri, - const e::slice& key, - const std::vector& old_value); - returncode put(const region_id& ri, - const e::slice& key, - const std::vector& new_value, - uint64_t version); - returncode overput(const region_id& ri, - const e::slice& key, - const std::vector& old_value, - const std::vector& new_value, - uint64_t version); - // put or delete where the previous value is unknown - returncode uncertain_del(const region_id& ri, - const e::slice& key); - returncode uncertain_put(const region_id& ri, - const e::slice& key, - const std::vector& new_value, - uint64_t version); - // leveldb provides no failure mechanism for this, neither do we - snapshot make_snapshot(); - // create iterators from snapshots - iterator* make_search_iterator(snapshot snap, - const region_id& ri, - const std::vector& checks, - std::ostringstream* ostr); - // backups - bool backup(const e::slice& name); - // get the object pointed to by the iterator - returncode get_from_iterator(const region_id& ri, - const schema& sc, - iterator* iter, - e::slice* key, - std::vector* value, - uint64_t* version, - reference* ref); - // track version counters - void bump_version(const region_id& ri, uint64_t version); - uint64_t max_version(const region_id& ri); - // checkpointing - returncode create_checkpoint(const region_timestamp& rt); - void set_checkpoint_gc(uint64_t checkpoint_gc); - void largest_checkpoint_for(const region_id& ri, uint64_t* checkpoint); - bool region_will_be_wiped(region_id rid); - void request_wipe(const transfer_id& xid, - const region_id& ri); - void inhibit_wiping(); - void permit_wiping(); - replay_iterator* replay_region_from_checkpoint(const region_id& ri, - uint64_t checkpoint, bool* wipe); - // indexing - void create_index_marker(const region_id& ri, const index_id& ii); - bool has_index_marker(const region_id& ri, const index_id& ii); - // used on startup - bool only_key_is_hyperdex_key(); - bool upgrade_13x_to_14(); - - private: - class index_state; - class checkpointer_thread; - class indexer_thread; - class wiper_thread; - class wiper_indexer_mediator; - datalayer(const datalayer&); - datalayer& operator = (const datalayer&); - - private: - bool write_version(const region_id& ri, - uint64_t version, - leveldb::WriteBatch* updates); - void update_memory_version(const region_id& ri, uint64_t version); - uint64_t disk_version(const region_id& ri); - void find_indices(const region_id& rid, - std::vector* indices); - void find_indices(const region_id& rid, uint16_t attr, - std::vector* indices); - - returncode handle_error(leveldb::Status st); - void collect_lower_checkpoints(uint64_t checkpoint_gc); - - const static region_id defaultri; - static uint64_t id(region_id ri) { return ri.get(); } - - private: - daemon* m_daemon; - leveldb_db_ptr m_db; - std::vector m_indices; - e::ao_hash_map m_versions; - const std::auto_ptr m_checkpointer; - const std::auto_ptr m_mediator; - const std::auto_ptr m_indexer; - const std::auto_ptr m_wiper; +public: + enum returncode + { + SUCCESS, + NOT_FOUND, + BAD_ENCODING, + CORRUPTION, + IO_ERROR, + LEVELDB_ERROR + }; + class reference; + class iterator; + class replay_iterator; + class dummy_iterator; + class region_iterator; + class search_iterator; + class index_iterator; + class range_index_iterator; + class intersect_iterator; + typedef leveldb_snapshot_ptr snapshot; + // must be pow2 + const static uint64_t REGION_PERIODIC = 65536; + +public: + datalayer(daemon *); + ~datalayer() throw (); + +public: + bool initialize(const std::string &path, + bool *saved, + server_id *saved_us, + po6::net::location *saved_bind_to, + po6::net::hostname *saved_coordinator); + bool save_state(const server_id &m_us, + const po6::net::location &bind_to, + const po6::net::hostname &coordinator); + void teardown(); + // reconfiguration + void pause(); + void unpause(); + void reconfigure(const configuration &old_config, + const configuration &new_config, + const server_id &us); + void debug_dump(); + // stats + bool get_property(const e::slice &property, + std::string *value); + std::string get_timestamp(); + uint64_t approximate_size(); + +public: + // retrieve the current value of a key + returncode get(const region_id &ri, + const e::slice &key, + std::vector *value, + uint64_t *version, + reference *ref); + // put, overput, or delete a key where the existing value is known + returncode del(const region_id &ri, + const e::slice &key, + const std::vector &old_value); + returncode put(const region_id &ri, + const e::slice &key, + const std::vector &new_value, + uint64_t version); + returncode overput(const region_id &ri, + const e::slice &key, + const std::vector &old_value, + const std::vector &new_value, + uint64_t version); + // put or delete where the previous value is unknown + returncode uncertain_del(const region_id &ri, + const e::slice &key); + returncode uncertain_put(const region_id &ri, + const e::slice &key, + const std::vector &new_value, + uint64_t version); + // leveldb provides no failure mechanism for this, neither do we + snapshot make_snapshot(); + // create iterators from snapshots + iterator *make_search_iterator(snapshot snap, + const region_id &ri, + const std::vector &checks, + std::ostringstream *ostr); + // backups + bool backup(const e::slice &name); + // get the object pointed to by the iterator + returncode get_from_iterator(const region_id &ri, + const schema &sc, + iterator *iter, + e::slice *key, + std::vector *value, + uint64_t *version, + reference *ref); + // track version counters + void bump_version(const region_id &ri, uint64_t version); + uint64_t max_version(const region_id &ri); + // checkpointing + returncode create_checkpoint(const region_timestamp &rt); + void set_checkpoint_gc(uint64_t checkpoint_gc); + void largest_checkpoint_for(const region_id &ri, uint64_t *checkpoint); + bool region_will_be_wiped(region_id rid); + void request_wipe(const transfer_id &xid, + const region_id &ri); + void inhibit_wiping(); + void permit_wiping(); + replay_iterator *replay_region_from_checkpoint(const region_id &ri, + uint64_t checkpoint, bool *wipe); + // indexing + void create_index_marker(const region_id &ri, const index_id &ii); + bool has_index_marker(const region_id &ri, const index_id &ii); + // used on startup + bool only_key_is_hyperdex_key(); + bool upgrade_13x_to_14(); + +private: + class index_state; + class checkpointer_thread; + class indexer_thread; + class wiper_thread; + class wiper_indexer_mediator; + datalayer(const datalayer &); + datalayer &operator = (const datalayer &); + +private: + bool write_version(const region_id &ri, + uint64_t version, + leveldb::WriteBatch *updates); + void update_memory_version(const region_id &ri, uint64_t version); + uint64_t disk_version(const region_id &ri); + void find_indices(const region_id &rid, + std::vector *indices); + void find_indices(const region_id &rid, uint16_t attr, + std::vector *indices); + + returncode handle_error(leveldb::Status st); + void collect_lower_checkpoints(uint64_t checkpoint_gc); + + const static region_id defaultri; + static uint64_t id(region_id ri) { return ri.get(); } + +private: + daemon *m_daemon; + leveldb_db_ptr m_db; + std::vector m_indices; + e::ao_hash_map m_versions; + const std::auto_ptr m_checkpointer; + const std::auto_ptr m_mediator; + const std::auto_ptr m_indexer; + const std::auto_ptr m_wiper; }; class datalayer::reference { - public: - reference(); - ~reference() throw (); +public: + reference(); + ~reference() throw (); - public: - void swap(reference* ref); +public: + void swap(reference *ref); - private: - friend class datalayer; +private: + friend class datalayer; - private: - std::string m_backing; +private: + std::string m_backing; }; -std::ostream& -operator << (std::ostream& lhs, datalayer::returncode rhs); +std::ostream & +operator << (std::ostream &lhs, datalayer::returncode rhs); END_HYPERDEX_NAMESPACE diff --git a/daemon/datalayer_checkpointer_thread.cc b/daemon/datalayer_checkpointer_thread.cc index 646bf0305..6c5f1eb65 100644 --- a/daemon/datalayer_checkpointer_thread.cc +++ b/daemon/datalayer_checkpointer_thread.cc @@ -38,13 +38,13 @@ using hyperdex::datalayer; -datalayer :: checkpointer_thread :: checkpointer_thread(daemon* d) - : background_thread(d) - , m_daemon(d) - , m_checkpoint_gc(0) - , m_checkpoint_gced(0) - , m_checkpoint_target(0) - , m_gc_inhibit_permit_diff(0) +datalayer :: checkpointer_thread :: checkpointer_thread(daemon *d) + : background_thread(d) + , m_daemon(d) + , m_checkpoint_gc(0) + , m_checkpoint_gced(0) + , m_checkpoint_target(0) + , m_gc_inhibit_permit_diff(0) { } @@ -52,129 +52,116 @@ datalayer :: checkpointer_thread :: ~checkpointer_thread() throw () { } -const char* +const char * datalayer :: checkpointer_thread :: thread_name() { - return "checkpointer"; + return "checkpointer"; } bool datalayer :: checkpointer_thread :: have_work() { - return m_checkpoint_gced < m_checkpoint_gc && - m_gc_inhibit_permit_diff == 0; + return m_checkpoint_gced < m_checkpoint_gc && + m_gc_inhibit_permit_diff == 0; } void datalayer :: checkpointer_thread :: copy_work() { - m_checkpoint_target = m_checkpoint_gc; + m_checkpoint_target = m_checkpoint_gc; } void datalayer :: checkpointer_thread :: do_work() { - collect_lower_checkpoints(m_checkpoint_target); + collect_lower_checkpoints(m_checkpoint_target); } void datalayer :: checkpointer_thread :: debug_dump() { - this->lock(); - LOG(INFO) << "checkpointer thread ==========================================================="; - LOG(INFO) << "checkpoint_gc=" << m_checkpoint_gc; - LOG(INFO) << "checkpoint_gced=" << m_checkpoint_gced; - LOG(INFO) << "checkpoint_target=" << m_checkpoint_target; - LOG(INFO) << "gc_inhibit_permit_diff=" << m_gc_inhibit_permit_diff; - this->unlock(); + this->lock(); + LOG(INFO) << "checkpointer thread ==========================================================="; + LOG(INFO) << "checkpoint_gc=" << m_checkpoint_gc; + LOG(INFO) << "checkpoint_gced=" << m_checkpoint_gced; + LOG(INFO) << "checkpoint_target=" << m_checkpoint_target; + LOG(INFO) << "gc_inhibit_permit_diff=" << m_gc_inhibit_permit_diff; + this->unlock(); } void datalayer :: checkpointer_thread :: inhibit_gc() { - this->lock(); - ++m_gc_inhibit_permit_diff; - this->unlock(); + this->lock(); + ++m_gc_inhibit_permit_diff; + this->unlock(); } void datalayer :: checkpointer_thread :: permit_gc() { - this->lock(); - assert(m_gc_inhibit_permit_diff > 0); - --m_gc_inhibit_permit_diff; - - if (m_gc_inhibit_permit_diff == 0) - { - this->wakeup(); - } - - this->unlock(); + this->lock(); + assert(m_gc_inhibit_permit_diff > 0); + --m_gc_inhibit_permit_diff; + if (m_gc_inhibit_permit_diff == 0) + { + this->wakeup(); + } + this->unlock(); } void datalayer :: checkpointer_thread :: set_checkpoint_gc(uint64_t checkpoint_gc) { - this->lock(); - m_checkpoint_gc = std::max(checkpoint_gc, m_checkpoint_gc); - this->wakeup(); - this->unlock(); + this->lock(); + m_checkpoint_gc = std::max(checkpoint_gc, m_checkpoint_gc); + this->wakeup(); + this->unlock(); } void datalayer :: checkpointer_thread :: collect_lower_checkpoints(uint64_t checkpoint_gc) { - leveldb::ReadOptions opts; - opts.verify_checksums = true; - std::auto_ptr it; - it.reset(m_daemon->m_data.m_db->NewIterator(opts)); - it->Seek(leveldb::Slice("c", 1)); - std::string lower_bound_timestamp("now"); - - while (it->Valid()) - { - region_timestamp rt; - e::slice key(it->key().data(), it->key().size()); - returncode rc = decode_checkpoint(key, &rt.rid, &rt.checkpoint); - - if (rc != datalayer::SUCCESS) - { - break; - } - - rt.local_timestamp = std::string(it->value().data(), it->value().size()); - - if (rt.checkpoint >= checkpoint_gc && - m_daemon->m_data.m_db->ValidateTimestamp(rt.local_timestamp)) - { - if (m_daemon->m_data.m_db->CompareTimestamps(rt.local_timestamp, lower_bound_timestamp) < 0) - { - lower_bound_timestamp = rt.local_timestamp; - } - - it->Next(); - continue; - } - - leveldb::WriteOptions wopts; - wopts.sync = false; - leveldb::Status st = m_daemon->m_data.m_db->Delete(wopts, it->key()); - - if (!st.ok()) - { - break; - } - - it->Next(); - } - - this->lock(); - - if (m_gc_inhibit_permit_diff == 0) - { - m_daemon->m_data.m_db->AllowGarbageCollectBeforeTimestamp(lower_bound_timestamp); - m_checkpoint_gced = m_checkpoint_target; - } - - this->unlock(); + leveldb::ReadOptions opts; + opts.verify_checksums = true; + std::auto_ptr it; + it.reset(m_daemon->m_data.m_db->NewIterator(opts)); + it->Seek(leveldb::Slice("c", 1)); + std::string lower_bound_timestamp("now"); + while (it->Valid()) + { + region_timestamp rt; + e::slice key(it->key().data(), it->key().size()); + returncode rc = decode_checkpoint(key, &rt.rid, &rt.checkpoint); + if (rc != datalayer::SUCCESS) + { + break; + } + rt.local_timestamp = std::string(it->value().data(), it->value().size()); + if (rt.checkpoint >= checkpoint_gc && + m_daemon->m_data.m_db->ValidateTimestamp(rt.local_timestamp)) + { + if (m_daemon->m_data.m_db->CompareTimestamps(rt.local_timestamp, lower_bound_timestamp) < 0) + { + lower_bound_timestamp = rt.local_timestamp; + } + it->Next(); + continue; + } + leveldb::WriteOptions wopts; + wopts.sync = false; + leveldb::Status st = m_daemon->m_data.m_db->Delete(wopts, it->key()); + if (!st.ok()) + { + break; + } + it->Next(); + } + this->lock(); + if (m_gc_inhibit_permit_diff == 0) + { + m_daemon->m_data.m_db->AllowGarbageCollectBeforeTimestamp(lower_bound_timestamp); + m_checkpoint_gced = m_checkpoint_target; + } + this->unlock(); } diff --git a/daemon/datalayer_checkpointer_thread.h b/daemon/datalayer_checkpointer_thread.h index 563fb3020..dd5d60a5d 100644 --- a/daemon/datalayer_checkpointer_thread.h +++ b/daemon/datalayer_checkpointer_thread.h @@ -35,37 +35,37 @@ class hyperdex::datalayer::checkpointer_thread : public hyperdex::background_thread { - public: - checkpointer_thread(daemon* d); - ~checkpointer_thread() throw (); +public: + checkpointer_thread(daemon *d); + ~checkpointer_thread() throw (); - public: - virtual const char* thread_name(); - virtual bool have_work(); - virtual void copy_work(); - virtual void do_work(); +public: + virtual const char *thread_name(); + virtual bool have_work(); + virtual void copy_work(); + virtual void do_work(); - public: - void debug_dump(); - // these are different than pause/unpause, which should only ever be - // called by the main thread. - void inhibit_gc(); - void permit_gc(); - void set_checkpoint_gc(uint64_t checkpoint_gc); +public: + void debug_dump(); + // these are different than pause/unpause, which should only ever be + // called by the main thread. + void inhibit_gc(); + void permit_gc(); + void set_checkpoint_gc(uint64_t checkpoint_gc); - private: - void collect_lower_checkpoints(uint64_t checkpoint_gc); +private: + void collect_lower_checkpoints(uint64_t checkpoint_gc); - private: - daemon* m_daemon; - uint64_t m_checkpoint_gc; // under lock - uint64_t m_checkpoint_gced; - uint64_t m_checkpoint_target; // do_work; no lock; copy of _gc - uint64_t m_gc_inhibit_permit_diff; +private: + daemon *m_daemon; + uint64_t m_checkpoint_gc; // under lock + uint64_t m_checkpoint_gced; + uint64_t m_checkpoint_target; // do_work; no lock; copy of _gc + uint64_t m_gc_inhibit_permit_diff; - private: - checkpointer_thread(const checkpointer_thread&); - checkpointer_thread& operator = (const checkpointer_thread&); +private: + checkpointer_thread(const checkpointer_thread &); + checkpointer_thread &operator = (const checkpointer_thread &); }; #endif // hyperdex_daemon_datalayer_checkpointer_h_ diff --git a/daemon/datalayer_encodings.cc b/daemon/datalayer_encodings.cc index ff3cf43c5..6450897f3 100644 --- a/daemon/datalayer_encodings.cc +++ b/daemon/datalayer_encodings.cc @@ -43,300 +43,269 @@ using hyperdex::datalayer; size_t hyperdex :: object_prefix_sz(region_id ri) { - return e::varint_length(ri.get()) + 1; + return e::varint_length(ri.get()) + 1; } -char* -hyperdex :: encode_object_prefix(region_id ri, char* ptr) +char * +hyperdex :: encode_object_prefix(region_id ri, char *ptr) { - ptr = e::pack8be('o', ptr); - ptr = e::packvarint64(ri.get(), ptr); - return ptr; + ptr = e::pack8be('o', ptr); + ptr = e::packvarint64(ri.get(), ptr); + return ptr; } void -hyperdex :: encode_object_region(const region_id& ri, - std::vector* scratch, - leveldb::Slice* out) +hyperdex :: encode_object_region(const region_id &ri, + std::vector *scratch, + leveldb::Slice *out) { - size_t sz = object_prefix_sz(ri); - - if (scratch->size() < sz) - { - scratch->resize(sz); - } - - char* ptr = &scratch->front(); - *out = leveldb::Slice(ptr, sz); - ptr = encode_object_prefix(ri, ptr); + size_t sz = object_prefix_sz(ri); + if (scratch->size() < sz) + { + scratch->resize(sz); + } + char *ptr = &scratch->front(); + *out = leveldb::Slice(ptr, sz); + ptr = encode_object_prefix(ri, ptr); } void -hyperdex :: encode_key(const region_id& ri, - const e::slice& internal_key, - std::vector* scratch, - leveldb::Slice* out) +hyperdex :: encode_key(const region_id &ri, + const e::slice &internal_key, + std::vector *scratch, + leveldb::Slice *out) { - size_t sz = object_prefix_sz(ri) + internal_key.size(); - - if (scratch->size() < sz) - { - scratch->resize(sz); - } - - char* ptr = &scratch->front(); - *out = leveldb::Slice(ptr, sz); - ptr = encode_object_prefix(ri, ptr); - memmove(ptr, internal_key.data(), internal_key.size()); + size_t sz = object_prefix_sz(ri) + internal_key.size(); + if (scratch->size() < sz) + { + scratch->resize(sz); + } + char *ptr = &scratch->front(); + *out = leveldb::Slice(ptr, sz); + ptr = encode_object_prefix(ri, ptr); + memmove(ptr, internal_key.data(), internal_key.size()); } void -hyperdex :: encode_key(const region_id& ri, +hyperdex :: encode_key(const region_id &ri, hyperdatatype key_type, - const e::slice& key, - std::vector* scratch, - leveldb::Slice* out) + const e::slice &key, + std::vector *scratch, + leveldb::Slice *out) { - const index_encoding* ie(index_encoding::lookup(key_type)); - size_t sz = object_prefix_sz(ri) + ie->encoded_size(key); - - if (scratch->size() < sz) - { - scratch->resize(sz); - } - - char* ptr = &scratch->front(); - *out = leveldb::Slice(ptr, sz); - ptr = encode_object_prefix(ri, ptr); - ie->encode(key, ptr); + const index_encoding *ie(index_encoding::lookup(key_type)); + size_t sz = object_prefix_sz(ri) + ie->encoded_size(key); + if (scratch->size() < sz) + { + scratch->resize(sz); + } + char *ptr = &scratch->front(); + *out = leveldb::Slice(ptr, sz); + ptr = encode_object_prefix(ri, ptr); + ie->encode(key, ptr); } bool -hyperdex :: decode_key(const leveldb::Slice& in, - region_id* ri, - e::slice* internal_key) +hyperdex :: decode_key(const leveldb::Slice &in, + region_id *ri, + e::slice *internal_key) { - if (in.size() < 2 || in.data()[0] != 'o') - { - return false; - } - - uint64_t r; - const char* const end = in.data() + in.size(); - const char* ptr = in.data() + sizeof(uint8_t); - ptr = e::varint64_decode(ptr, end, &r); - - if (!ptr) - { - return false; - } - - *ri = region_id(r); - *internal_key = e::slice(ptr, end - ptr); - return true; + if (in.size() < 2 || in.data()[0] != 'o') + { + return false; + } + uint64_t r; + const char *const end = in.data() + in.size(); + const char *ptr = in.data() + sizeof(uint8_t); + ptr = e::varint64_decode(ptr, end, &r); + if (!ptr) + { + return false; + } + *ri = region_id(r); + *internal_key = e::slice(ptr, end - ptr); + return true; } void -hyperdex :: encode_value(const std::vector& attrs, +hyperdex :: encode_value(const std::vector &attrs, uint64_t version, - std::vector* backing, - leveldb::Slice* out) + std::vector *backing, + leveldb::Slice *out) { - assert(attrs.size() < 65536); - size_t sz = sizeof(uint64_t) + sizeof(uint16_t); - - for (size_t i = 0; i < attrs.size(); ++i) - { - sz += sizeof(uint32_t) + attrs[i].size(); - } - - backing->resize(sz); - char* ptr = &backing->front(); - ptr = e::pack64be(version, ptr); - ptr = e::pack16be(attrs.size(), ptr); - - for (size_t i = 0; i < attrs.size(); ++i) - { - ptr = e::pack32be(attrs[i].size(), ptr); - memmove(ptr, attrs[i].data(), attrs[i].size()); - ptr += attrs[i].size(); - } - - *out = leveldb::Slice(&backing->front(), sz); + assert(attrs.size() < 65536); + size_t sz = sizeof(uint64_t) + sizeof(uint16_t); + for (size_t i = 0; i < attrs.size(); ++i) + { + sz += sizeof(uint32_t) + attrs[i].size(); + } + backing->resize(sz); + char *ptr = &backing->front(); + ptr = e::pack64be(version, ptr); + ptr = e::pack16be(attrs.size(), ptr); + for (size_t i = 0; i < attrs.size(); ++i) + { + ptr = e::pack32be(attrs[i].size(), ptr); + memmove(ptr, attrs[i].data(), attrs[i].size()); + ptr += attrs[i].size(); + } + *out = leveldb::Slice(&backing->front(), sz); } datalayer::returncode -hyperdex :: decode_value(const e::slice& in, - std::vector* attrs, - uint64_t* version) +hyperdex :: decode_value(const e::slice &in, + std::vector *attrs, + uint64_t *version) { - const uint8_t* ptr = in.data(); - const uint8_t* end = ptr + in.size(); - - if (ptr + sizeof(uint64_t) <= end) - { - ptr = e::unpack64be(ptr, version); - } - else - { - return datalayer::BAD_ENCODING; - } - - uint16_t num_attrs; - - if (ptr + sizeof(uint16_t) <= end) - { - ptr = e::unpack16be(ptr, &num_attrs); - } - else - { - return datalayer::BAD_ENCODING; - } - - attrs->clear(); - - for (size_t i = 0; i < num_attrs; ++i) - { - uint32_t sz = 0; - - if (ptr + sizeof(uint32_t) <= end) - { - ptr = e::unpack32be(ptr, &sz); - } - else - { - return datalayer::BAD_ENCODING; - } - - e::slice s(reinterpret_cast(ptr), sz); - ptr += sz; - attrs->push_back(s); - } - - return datalayer::SUCCESS; + const uint8_t *ptr = in.data(); + const uint8_t *end = ptr + in.size(); + if (ptr + sizeof(uint64_t) <= end) + { + ptr = e::unpack64be(ptr, version); + } + else + { + return datalayer::BAD_ENCODING; + } + uint16_t num_attrs; + if (ptr + sizeof(uint16_t) <= end) + { + ptr = e::unpack16be(ptr, &num_attrs); + } + else + { + return datalayer::BAD_ENCODING; + } + attrs->clear(); + for (size_t i = 0; i < num_attrs; ++i) + { + uint32_t sz = 0; + if (ptr + sizeof(uint32_t) <= end) + { + ptr = e::unpack32be(ptr, &sz); + } + else + { + return datalayer::BAD_ENCODING; + } + e::slice s(reinterpret_cast(ptr), sz); + ptr += sz; + attrs->push_back(s); + } + return datalayer::SUCCESS; } void -hyperdex :: encode_version(const region_id& ri, /*region we wrote*/ +hyperdex :: encode_version(const region_id &ri, /*region we wrote*/ uint64_t version, - char* out) + char *out) { - char* ptr = out; - ptr = e::pack8be('v', ptr); - ptr = e::pack64be(ri.get(), ptr); - ptr = e::pack64be(UINT64_MAX - version, ptr); + char *ptr = out; + ptr = e::pack8be('v', ptr); + ptr = e::pack64be(ri.get(), ptr); + ptr = e::pack64be(UINT64_MAX - version, ptr); } datalayer::returncode -hyperdex :: decode_version(const e::slice& in, - region_id* ri, /*region we saw an ack for*/ - uint64_t* version) +hyperdex :: decode_version(const e::slice &in, + region_id *ri, /*region we saw an ack for*/ + uint64_t *version) { - if (in.size() != VERSION_BUF_SIZE) - { - return datalayer::BAD_ENCODING; - } - - uint8_t _p; - uint64_t _ri; - const uint8_t* ptr = in.data(); - ptr = e::unpack8be(ptr, &_p); - ptr = e::unpack64be(ptr, &_ri); - ptr = e::unpack64be(ptr, version); - *ri = region_id(_ri); - *version = UINT64_MAX - *version; - return _p == 'v' ? datalayer::SUCCESS : datalayer::BAD_ENCODING; + if (in.size() != VERSION_BUF_SIZE) + { + return datalayer::BAD_ENCODING; + } + uint8_t _p; + uint64_t _ri; + const uint8_t *ptr = in.data(); + ptr = e::unpack8be(ptr, &_p); + ptr = e::unpack64be(ptr, &_ri); + ptr = e::unpack64be(ptr, version); + *ri = region_id(_ri); + *version = UINT64_MAX - *version; + return _p == 'v' ? datalayer::SUCCESS : datalayer::BAD_ENCODING; } void -hyperdex :: encode_checkpoint(const region_id& ri, +hyperdex :: encode_checkpoint(const region_id &ri, uint64_t checkpoint, - char* out) + char *out) { - char* ptr = out; - ptr = e::pack8be('c', ptr); - ptr = e::pack64be(ri.get(), ptr); - ptr = e::pack64be(checkpoint, ptr); + char *ptr = out; + ptr = e::pack8be('c', ptr); + ptr = e::pack64be(ri.get(), ptr); + ptr = e::pack64be(checkpoint, ptr); } datalayer::returncode -hyperdex :: decode_checkpoint(const e::slice& in, - region_id* ri, - uint64_t* checkpoint) +hyperdex :: decode_checkpoint(const e::slice &in, + region_id *ri, + uint64_t *checkpoint) { - if (in.size() != CHECKPOINT_BUF_SIZE) - { - return datalayer::BAD_ENCODING; - } - - const uint8_t* ptr = in.data(); - uint8_t t; - uint64_t _ri; - ptr = e::unpack8be(ptr, &t); - ptr = e::unpack64be(ptr, &_ri); - ptr = e::unpack64be(ptr, checkpoint); - *ri = region_id(_ri); - return t == 'c' ? datalayer::SUCCESS : datalayer::BAD_ENCODING; + if (in.size() != CHECKPOINT_BUF_SIZE) + { + return datalayer::BAD_ENCODING; + } + const uint8_t *ptr = in.data(); + uint8_t t; + uint64_t _ri; + ptr = e::unpack8be(ptr, &t); + ptr = e::unpack64be(ptr, &_ri); + ptr = e::unpack64be(ptr, checkpoint); + *ri = region_id(_ri); + return t == 'c' ? datalayer::SUCCESS : datalayer::BAD_ENCODING; } void -hyperdex :: create_index_changes(const schema& sc, - const region_id& ri, - const std::vector& indices, - const e::slice& key, - const std::vector* old_value, - const std::vector* new_value, - leveldb::WriteBatch* updates) +hyperdex :: create_index_changes(const schema &sc, + const region_id &ri, + const std::vector &indices, + const e::slice &key, + const std::vector *old_value, + const std::vector *new_value, + leveldb::WriteBatch *updates) { - assert(!old_value || !new_value || old_value->size() == new_value->size()); - assert(!old_value || old_value->size() + 1 == sc.attrs_sz); - assert(!new_value || new_value->size() + 1 == sc.attrs_sz); - const index_encoding* key_ie = index_encoding::lookup(sc.attrs[0].type); - - for (size_t i = 0; i < indices.size(); ++i) - { - const index* idx = indices[i]; - - assert(idx->attr > 0); - assert(idx->attr < sc.attrs_sz); - - const index_info* ai = index_info::lookup(sc.attrs[idx->attr].type); - assert(ai); - - const e::slice* old_attr = NULL; - const e::slice* new_attr = NULL; - old_attr = old_value ? &(*old_value)[idx->attr - 1] : NULL; - new_attr = new_value ? &(*new_value)[idx->attr - 1] : NULL; - - if (!old_attr && !new_attr) - { - continue; - } - - ai->index_changes(idx, ri, key_ie, key, old_attr, new_attr, updates); - } + assert(!old_value || !new_value || old_value->size() == new_value->size()); + assert(!old_value || old_value->size() + 1 == sc.attrs_sz); + assert(!new_value || new_value->size() + 1 == sc.attrs_sz); + const index_encoding *key_ie = index_encoding::lookup(sc.attrs[0].type); + for (size_t i = 0; i < indices.size(); ++i) + { + const index *idx = indices[i]; + assert(idx->attr > 0); + assert(idx->attr < sc.attrs_sz); + const index_info *ai = index_info::lookup(sc.attrs[idx->attr].type); + assert(ai); + const e::slice *old_attr = NULL; + const e::slice *new_attr = NULL; + old_attr = old_value ? &(*old_value)[idx->attr - 1] : NULL; + new_attr = new_value ? &(*new_value)[idx->attr - 1] : NULL; + if (!old_attr && !new_attr) + { + continue; + } + ai->index_changes(idx, ri, key_ie, key, old_attr, new_attr, updates); + } } void -hyperdex :: encode_bump(char* _ptr, char* _end) +hyperdex :: encode_bump(char *_ptr, char *_end) { - assert(_ptr); - assert(_ptr < _end); - uint8_t* ptr = reinterpret_cast(_end) - 1; - uint8_t* end = reinterpret_cast(_ptr); - - for (; ptr >= end; --ptr) - { - if (*ptr < 255) - { - ++(*ptr); - return; - } - else - { - *ptr = 0; - } - } - - abort(); + assert(_ptr); + assert(_ptr < _end); + uint8_t *ptr = reinterpret_cast(_end) - 1; + uint8_t *end = reinterpret_cast(_ptr); + for (; ptr >= end; --ptr) + { + if (*ptr < 255) + { + ++(*ptr); + return; + } + else + { + *ptr = 0; + } + } + abort(); } diff --git a/daemon/datalayer_encodings.h b/daemon/datalayer_encodings.h index 50a69cb6f..e6405f71c 100644 --- a/daemon/datalayer_encodings.h +++ b/daemon/datalayer_encodings.h @@ -41,75 +41,75 @@ BEGIN_HYPERDEX_NAMESPACE size_t object_prefix_sz(region_id ri); -char* -encode_object_prefix(region_id ri, char* ptr); +char * +encode_object_prefix(region_id ri, char *ptr); void -encode_object_region(const region_id& ri, - std::vector* scratch, - leveldb::Slice* out); +encode_object_region(const region_id &ri, + std::vector *scratch, + leveldb::Slice *out); void -encode_key(const region_id& ri, - const e::slice& internal_key, - std::vector* scratch, - leveldb::Slice* out); +encode_key(const region_id &ri, + const e::slice &internal_key, + std::vector *scratch, + leveldb::Slice *out); void -encode_key(const region_id& ri, +encode_key(const region_id &ri, hyperdatatype key_type, - const e::slice& key, - std::vector* scratch, - leveldb::Slice* out); + const e::slice &key, + std::vector *scratch, + leveldb::Slice *out); bool -decode_key(const leveldb::Slice& in, - region_id* ri, - e::slice* internal_key); +decode_key(const leveldb::Slice &in, + region_id *ri, + e::slice *internal_key); void -encode_value(const std::vector& attrs, +encode_value(const std::vector &attrs, uint64_t version, - std::vector* backing, - leveldb::Slice* out); + std::vector *backing, + leveldb::Slice *out); datalayer::returncode -decode_value(const e::slice& in, - std::vector* attrs, - uint64_t* version); +decode_value(const e::slice &in, + std::vector *attrs, + uint64_t *version); // Encode the record of an operation for which we have sent an ACK #define VERSION_BUF_SIZE (sizeof(uint8_t) + 2 * sizeof(uint64_t)) void -encode_version(const region_id& ri, /*region we wrote*/ +encode_version(const region_id &ri, /*region we wrote*/ uint64_t version, - char* out); + char *out); datalayer::returncode -decode_version(const e::slice& in, - region_id* ri, /*region we saw an ack for*/ - uint64_t* version); +decode_version(const e::slice &in, + region_id *ri, /*region we saw an ack for*/ + uint64_t *version); // checkpoints #define CHECKPOINT_BUF_SIZE (sizeof(uint8_t) + 2 * sizeof(uint64_t)) void -encode_checkpoint(const region_id& ri, +encode_checkpoint(const region_id &ri, uint64_t checkpoint, - char* out); + char *out); datalayer::returncode -decode_checkpoint(const e::slice& in, - region_id* ri, - uint64_t* checkpoint); +decode_checkpoint(const e::slice &in, + region_id *ri, + uint64_t *checkpoint); void -create_index_changes(const schema& sc, - const region_id& ri, - const std::vector& indices, - const e::slice& key, - const std::vector* old_value, - const std::vector* new_value, - leveldb::WriteBatch* updates); +create_index_changes(const schema &sc, + const region_id &ri, + const std::vector &indices, + const e::slice &key, + const std::vector *old_value, + const std::vector *new_value, + leveldb::WriteBatch *updates); void -encode_bump(char* start, char* end); +encode_bump(char *start, char *end); END_HYPERDEX_NAMESPACE diff --git a/daemon/datalayer_index_state.h b/daemon/datalayer_index_state.h index 639b2cff1..9c3cc5b9b 100644 --- a/daemon/datalayer_index_state.h +++ b/daemon/datalayer_index_state.h @@ -35,32 +35,31 @@ using hyperdex::datalayer; struct datalayer::index_state { - index_state() : ri(), ii(), m_usable(0) {} - index_state(region_id _ri, index_id _ii) - : ri(_ri), ii(_ii), m_usable(0) {} - index_state(const index_state& other) - : ri(other.ri), ii(other.ii) - , m_usable(other.m_usable) {} - bool is_usable() { e::atomic::memory_barrier(); return e::atomic::load_64_acquire(&m_usable) == 1; } - void set_usable() { e::atomic::store_64_release(&m_usable, 1); e::atomic::memory_barrier(); } - index_state& operator = (const index_state& rhs) - { - if (this != &rhs) - { - ri = rhs.ri; - ii = rhs.ii; - m_usable = rhs.m_usable; - } + index_state() : ri(), ii(), m_usable(0) {} + index_state(region_id _ri, index_id _ii) + : ri(_ri), ii(_ii), m_usable(0) {} + index_state(const index_state &other) + : ri(other.ri), ii(other.ii) + , m_usable(other.m_usable) {} + bool is_usable() { e::atomic::memory_barrier(); return e::atomic::load_64_acquire(&m_usable) == 1; } + void set_usable() { e::atomic::store_64_release(&m_usable, 1); e::atomic::memory_barrier(); } + index_state &operator = (const index_state &rhs) + { + if (this != &rhs) + { + ri = rhs.ri; + ii = rhs.ii; + m_usable = rhs.m_usable; + } + return *this; + } + bool operator < (const region_id &x) const { return ri < x; } - return *this; - } - bool operator < (const region_id& x) const { return ri < x; } + region_id ri; + index_id ii; - region_id ri; - index_id ii; - - private: - uint64_t m_usable; +private: + uint64_t m_usable; }; #endif // hyperdex_daemon_datalayer_index_state_h_ diff --git a/daemon/datalayer_indexer_thread.cc b/daemon/datalayer_indexer_thread.cc index 90d49a7b0..4a5a5fb91 100644 --- a/daemon/datalayer_indexer_thread.cc +++ b/daemon/datalayer_indexer_thread.cc @@ -44,16 +44,16 @@ using hyperdex::datalayer; -datalayer :: indexer_thread :: indexer_thread(daemon* d, wiper_indexer_mediator* m) - : background_thread(d) - , m_daemon(d) - , m_mediator(m) - , m_config() - , m_have_current(false) - , m_current_region() - , m_current_index() - , m_interrupted_count(0) - , m_interrupted(false) +datalayer :: indexer_thread :: indexer_thread(daemon *d, wiper_indexer_mediator *m) + : background_thread(d) + , m_daemon(d) + , m_mediator(m) + , m_config() + , m_have_current(false) + , m_current_region() + , m_current_index() + , m_interrupted_count(0) + , m_interrupted(false) { } @@ -61,434 +61,382 @@ datalayer :: indexer_thread :: ~indexer_thread() throw () { } -const char* +const char * datalayer :: indexer_thread :: thread_name() { - return "indexing"; + return "indexing"; } bool datalayer :: indexer_thread :: have_work() { - m_interrupted = false; - m_mediator->clear_indexer_region(); - m_have_current = false; - m_current_region = region_id(); - m_current_index = index_id(); - - for (size_t i = 0; i < m_daemon->m_data.m_indices.size(); ++i) - { - index_state* is = &m_daemon->m_data.m_indices[i]; - - // if it's not usable (we have to index it first), and it's not - // currently being wiped, and it's something that we've been mapped to, - // then we have work to do - if (!is->is_usable() && - !m_mediator->region_conflicts_with_wiper(is->ri) && - m_daemon->m_config.get_virtual(is->ri, m_daemon->m_us) != virtual_server_id()) - { - return true; - } - } - - return false; + m_interrupted = false; + m_mediator->clear_indexer_region(); + m_have_current = false; + m_current_region = region_id(); + m_current_index = index_id(); + for (size_t i = 0; i < m_daemon->m_data.m_indices.size(); ++i) + { + index_state *is = &m_daemon->m_data.m_indices[i]; + // if it's not usable (we have to index it first), and it's not + // currently being wiped, and it's something that we've been mapped to, + // then we have work to do + if (!is->is_usable() && + !m_mediator->region_conflicts_with_wiper(is->ri) && + m_daemon->m_config.get_virtual(is->ri, m_daemon->m_us) != virtual_server_id()) + { + return true; + } + } + return false; } void datalayer :: indexer_thread :: copy_work() { - for (size_t i = 0; i < m_daemon->m_data.m_indices.size(); ++i) - { - index_state* is = &m_daemon->m_data.m_indices[i]; - - // if it's not usable (we have to index it first), and it's not - // currently being wiped, and it's something that we've been mapped to, - // then we have work to do - if (!is->is_usable() && - m_daemon->m_config.get_virtual(is->ri, m_daemon->m_us) != virtual_server_id() && - m_mediator->set_indexer_region(is->ri)) - { - m_config = m_daemon->m_config; - m_have_current = true; - m_current_region = is->ri; - m_current_index = is->ii; - return; - } - } + for (size_t i = 0; i < m_daemon->m_data.m_indices.size(); ++i) + { + index_state *is = &m_daemon->m_data.m_indices[i]; + // if it's not usable (we have to index it first), and it's not + // currently being wiped, and it's something that we've been mapped to, + // then we have work to do + if (!is->is_usable() && + m_daemon->m_config.get_virtual(is->ri, m_daemon->m_us) != virtual_server_id() && + m_mediator->set_indexer_region(is->ri)) + { + m_config = m_daemon->m_config; + m_have_current = true; + m_current_region = is->ri; + m_current_index = is->ii; + return; + } + } } void datalayer :: indexer_thread :: do_work() { - if (!m_have_current) - { - return; - } - - if (!wipe(m_current_region, m_current_index)) - { - return; - } - - configuration config = m_config; - leveldb_db_ptr db = m_daemon->m_data.m_db; - const schema* sc = config.get_schema(m_current_region); - const index* idx = config.get_index(m_current_index); - assert(idx); - std::vector idxs(1, idx); - - // prohibit garbage collection during this section. - // this ensures that the timestamp we take will remain valid until the end - m_daemon->m_data.m_checkpointer->inhibit_gc(); - e::guard g1 = e::makeobjguard(*m_daemon->m_data.m_checkpointer, - &checkpointer_thread::permit_gc); - g1.use_variable(); - - // Take a timestamp from the data layer. We could just use a replay - // iterator for "all", but we wouldn't know which objects we indexed twice. - // By taking an iterator and then a replay iterator from the timestamp, we - // ensure that the majority of data gets indexed using "put" ops instead of - // the "get/put" pattern necessary to remove existing indices before adding. - std::string timestamp; - db->GetReplayTimestamp(×tamp); - - // Take this offline - this->offline(); - e::guard g2 = e::makeobjguard(*this, &indexer_thread::online); - g2.use_variable(); - - // Now iterate over the data once. - std::auto_ptr it(play(m_current_region, sc)); - - if (!it.get()) - { - return; - } - - while (it->valid()) - { - if (!index_from_iterator(it.get(), sc, m_current_region, idxs)) - { - return; - } - - it->next(); - } - - // Now do it again from the checkpoint we took. - std::auto_ptr rit(replay(m_current_region, timestamp)); - - if (!rit.get()) - { - return; - } - - while (rit->valid()) - { - if (!index_from_replay_iterator(rit.get(), sc, m_current_region, idxs)) - { - return; - } - - rit->next(); - } - - // Pause writes so we can hit the end of the iterator. - m_daemon->pause(); - e::guard g3 = e::makeobjguard(*m_daemon, &daemon::unpause); - g3.use_variable(); - - // Keep iterating on the replay iterator - while (rit->valid()) - { - if (!index_from_replay_iterator(rit.get(), sc, m_current_region, idxs)) - { - return; - } - - rit->next(); - } - - // make the index usable to all - if (!mark_usable(m_current_region, m_current_index)) - { - return; - } - - // Unpause writes - g3.dismiss(); - m_daemon->unpause(); - - // Let the index possibly do its thing - m_daemon->m_data.m_wiper->kick(); + if (!m_have_current) + { + return; + } + if (!wipe(m_current_region, m_current_index)) + { + return; + } + configuration config = m_config; + leveldb_db_ptr db = m_daemon->m_data.m_db; + const schema *sc = config.get_schema(m_current_region); + const index *idx = config.get_index(m_current_index); + assert(idx); + std::vector idxs(1, idx); + // prohibit garbage collection during this section. + // this ensures that the timestamp we take will remain valid until the end + m_daemon->m_data.m_checkpointer->inhibit_gc(); + e::guard g1 = e::makeobjguard(*m_daemon->m_data.m_checkpointer, + &checkpointer_thread::permit_gc); + g1.use_variable(); + // Take a timestamp from the data layer. We could just use a replay + // iterator for "all", but we wouldn't know which objects we indexed twice. + // By taking an iterator and then a replay iterator from the timestamp, we + // ensure that the majority of data gets indexed using "put" ops instead of + // the "get/put" pattern necessary to remove existing indices before adding. + std::string timestamp; + db->GetReplayTimestamp(×tamp); + // Take this offline + this->offline(); + e::guard g2 = e::makeobjguard(*this, &indexer_thread::online); + g2.use_variable(); + // Now iterate over the data once. + std::auto_ptr it(play(m_current_region, sc)); + if (!it.get()) + { + return; + } + while (it->valid()) + { + if (!index_from_iterator(it.get(), sc, m_current_region, idxs)) + { + return; + } + it->next(); + } + // Now do it again from the checkpoint we took. + std::auto_ptr rit(replay(m_current_region, timestamp)); + if (!rit.get()) + { + return; + } + while (rit->valid()) + { + if (!index_from_replay_iterator(rit.get(), sc, m_current_region, idxs)) + { + return; + } + rit->next(); + } + // Pause writes so we can hit the end of the iterator. + m_daemon->pause(); + e::guard g3 = e::makeobjguard(*m_daemon, &daemon::unpause); + g3.use_variable(); + // Keep iterating on the replay iterator + while (rit->valid()) + { + if (!index_from_replay_iterator(rit.get(), sc, m_current_region, idxs)) + { + return; + } + rit->next(); + } + // make the index usable to all + if (!mark_usable(m_current_region, m_current_index)) + { + return; + } + // Unpause writes + g3.dismiss(); + m_daemon->unpause(); + // Let the index possibly do its thing + m_daemon->m_data.m_wiper->kick(); } void datalayer :: indexer_thread :: debug_dump() { - this->lock(); - LOG(INFO) << "indexer thread ================================================================"; - LOG(INFO) << "have_current=" << (m_have_current ? "yes" : "no"); - LOG(INFO) << "current_region=" << m_current_region; - LOG(INFO) << "current_index=" << m_current_index; - LOG(INFO) << "interrupted_count=" << m_interrupted_count; - this->unlock(); + this->lock(); + LOG(INFO) << "indexer thread ================================================================"; + LOG(INFO) << "have_current=" << (m_have_current ? "yes" : "no"); + LOG(INFO) << "current_region=" << m_current_region; + LOG(INFO) << "current_index=" << m_current_index; + LOG(INFO) << "interrupted_count=" << m_interrupted_count; + this->unlock(); } void datalayer :: indexer_thread :: kick() { - this->lock(); - this->wakeup(); - this->unlock(); + this->lock(); + this->wakeup(); + this->unlock(); } bool -datalayer :: indexer_thread :: mark_usable(const region_id& ri, const index_id& ii) +datalayer :: indexer_thread :: mark_usable(const region_id &ri, const index_id &ii) { - // Publish the index - char buf[sizeof(uint8_t) + 2 * VARINT_64_MAX_SIZE]; - char* ptr = buf; - ptr = e::pack8be('I', ptr); - ptr = e::packvarint64(ri.get(), ptr); - ptr = e::packvarint64(ii.get(), ptr); - leveldb::WriteOptions wo; - leveldb::Slice key(buf, ptr - buf); - leveldb::Slice val; - leveldb::Status st = m_daemon->m_data.m_db->Put(wo, key, val); - - if (!st.ok()) - { - LOG(ERROR) << "error indexing: write failed: " << st.ToString(); - return false; - } - - // Set the index to be usable - for (size_t i = 0; i < m_daemon->m_data.m_indices.size(); ++i) - { - index_state* is = &m_daemon->m_data.m_indices[i]; - - if (is->ri == ri && - is->ii == ii) - { - is->set_usable(); - } - } - - return true; + // Publish the index + char buf[sizeof(uint8_t) + 2 * VARINT_64_MAX_SIZE]; + char *ptr = buf; + ptr = e::pack8be('I', ptr); + ptr = e::packvarint64(ri.get(), ptr); + ptr = e::packvarint64(ii.get(), ptr); + leveldb::WriteOptions wo; + leveldb::Slice key(buf, ptr - buf); + leveldb::Slice val; + leveldb::Status st = m_daemon->m_data.m_db->Put(wo, key, val); + if (!st.ok()) + { + LOG(ERROR) << "error indexing: write failed: " << st.ToString(); + return false; + } + // Set the index to be usable + for (size_t i = 0; i < m_daemon->m_data.m_indices.size(); ++i) + { + index_state *is = &m_daemon->m_data.m_indices[i]; + if (is->ri == ri && + is->ii == ii) + { + is->set_usable(); + } + } + return true; } bool datalayer :: indexer_thread :: interrupted() { - ++m_interrupted_count; - bool ret = m_interrupted; - - if (m_interrupted_count % 1000 == 0) - { - this->lock(); - ret = this->is_shutdown(); - m_interrupted = ret; - this->unlock(); - } - - return ret; + ++m_interrupted_count; + bool ret = m_interrupted; + if (m_interrupted_count % 1000 == 0) + { + this->lock(); + ret = this->is_shutdown(); + m_interrupted = ret; + this->unlock(); + } + return ret; } -datalayer::region_iterator* -datalayer :: indexer_thread :: play(const region_id& ri, const schema* sc) +datalayer::region_iterator * +datalayer :: indexer_thread :: play(const region_id &ri, const schema *sc) { - leveldb_db_ptr db = m_daemon->m_data.m_db; - leveldb_iterator_ptr iip; - leveldb::ReadOptions ro; - ro.fill_cache = false; - iip.reset(leveldb_snapshot_ptr(db, NULL), db->NewIterator(ro)); - const index_encoding* ie = index_encoding::lookup(sc->attrs[0].type); - return new region_iterator(iip, ri, ie); + leveldb_db_ptr db = m_daemon->m_data.m_db; + leveldb_iterator_ptr iip; + leveldb::ReadOptions ro; + ro.fill_cache = false; + iip.reset(leveldb_snapshot_ptr(db, NULL), db->NewIterator(ro)); + const index_encoding *ie = index_encoding::lookup(sc->attrs[0].type); + return new region_iterator(iip, ri, ie); } -datalayer::replay_iterator* -datalayer :: indexer_thread :: replay(const region_id& ri, const std::string& timestamp) +datalayer::replay_iterator * +datalayer :: indexer_thread :: replay(const region_id &ri, const std::string ×tamp) { - leveldb::ReplayIterator* riip; - leveldb::Status st = m_daemon->m_data.m_db->GetReplayIterator(timestamp, &riip); - - if (!st.ok()) - { - LOG(ERROR) << "error indexing: LevelDB corruption: invalid timestamp"; - return NULL; - } - - leveldb_replay_iterator_ptr ptr(m_daemon->m_data.m_db, riip); - const schema& sc(*m_daemon->m_config.get_schema(ri)); - return new replay_iterator(ri, ptr, index_encoding::lookup(sc.attrs[0].type)); + leveldb::ReplayIterator *riip; + leveldb::Status st = m_daemon->m_data.m_db->GetReplayIterator(timestamp, &riip); + if (!st.ok()) + { + LOG(ERROR) << "error indexing: LevelDB corruption: invalid timestamp"; + return NULL; + } + leveldb_replay_iterator_ptr ptr(m_daemon->m_data.m_db, riip); + const schema &sc(*m_daemon->m_config.get_schema(ri)); + return new replay_iterator(ri, ptr, index_encoding::lookup(sc.attrs[0].type)); } bool -datalayer :: indexer_thread :: wipe(const region_id& ri, const index_id& ii) +datalayer :: indexer_thread :: wipe(const region_id &ri, const index_id &ii) { - return wipe_common('I', ri, ii) && wipe_common('i', ri, ii); + return wipe_common('I', ri, ii) && wipe_common('i', ri, ii); } bool -datalayer :: indexer_thread :: wipe_common(uint8_t c, const region_id& ri, const index_id& ii) +datalayer :: indexer_thread :: wipe_common(uint8_t c, const region_id &ri, const index_id &ii) { - std::auto_ptr it; - it.reset(m_daemon->m_data.m_db->NewIterator(leveldb::ReadOptions())); - char backing[sizeof(uint8_t) + 2 * VARINT_64_MAX_SIZE]; - char* ptr = backing; - ptr = e::pack8be(c, ptr); - ptr = e::packvarint64(ri.get(), ptr); - ptr = e::packvarint64(ii.get(), ptr); - leveldb::Slice prefix(backing, ptr - backing); - it->Seek(prefix); - - while (it->key().starts_with(prefix)) - { - if (interrupted()) - { - return false; - } - - m_daemon->m_data.m_db->Delete(leveldb::WriteOptions(), it->key()); - it->Next(); - } - - return true; + std::auto_ptr it; + it.reset(m_daemon->m_data.m_db->NewIterator(leveldb::ReadOptions())); + char backing[sizeof(uint8_t) + 2 * VARINT_64_MAX_SIZE]; + char *ptr = backing; + ptr = e::pack8be(c, ptr); + ptr = e::packvarint64(ri.get(), ptr); + ptr = e::packvarint64(ii.get(), ptr); + leveldb::Slice prefix(backing, ptr - backing); + it->Seek(prefix); + while (it->key().starts_with(prefix)) + { + if (interrupted()) + { + return false; + } + m_daemon->m_data.m_db->Delete(leveldb::WriteOptions(), it->key()); + it->Next(); + } + return true; } bool -datalayer :: indexer_thread :: index_from_iterator(region_iterator* it, - const schema* sc, - const region_id& ri, - const std::vector& idxs) +datalayer :: indexer_thread :: index_from_iterator(region_iterator *it, + const schema *sc, + const region_id &ri, + const std::vector &idxs) { - if (interrupted()) - { - return false; - } - - e::slice key; - std::vector value; - uint64_t version; - datalayer::reference ref; - datalayer::returncode rc; - rc = m_daemon->m_data.get_from_iterator(ri, *sc, it, - &key, &value, &version, &ref); - - if (rc != SUCCESS) - { - LOG(ERROR) << "error indexing: " << rc; - return false; - } - - leveldb::WriteBatch batch; - create_index_changes(*sc, ri, idxs, key, NULL, &value, &batch); - - leveldb::WriteOptions opts; - opts.sync = false; - leveldb::Status st = m_daemon->m_data.m_db->Write(opts, &batch); - - if (!st.ok()) - { - rc = m_daemon->m_data.handle_error(st); - LOG(ERROR) << "error indexing: " << rc; - return false; - } - - return true; + if (interrupted()) + { + return false; + } + e::slice key; + std::vector value; + uint64_t version; + datalayer::reference ref; + datalayer::returncode rc; + rc = m_daemon->m_data.get_from_iterator(ri, *sc, it, + &key, &value, &version, &ref); + if (rc != SUCCESS) + { + LOG(ERROR) << "error indexing: " << rc; + return false; + } + leveldb::WriteBatch batch; + create_index_changes(*sc, ri, idxs, key, NULL, &value, &batch); + leveldb::WriteOptions opts; + opts.sync = false; + leveldb::Status st = m_daemon->m_data.m_db->Write(opts, &batch); + if (!st.ok()) + { + rc = m_daemon->m_data.handle_error(st); + LOG(ERROR) << "error indexing: " << rc; + return false; + } + return true; } bool -datalayer :: indexer_thread :: index_from_replay_iterator(replay_iterator* rit, - const schema* sc, - const region_id& ri, - const std::vector& idxs) +datalayer :: indexer_thread :: index_from_replay_iterator(replay_iterator *rit, + const schema *sc, + const region_id &ri, + const std::vector &idxs) { - if (interrupted()) - { - return false; - } - - e::slice key = rit->key(); - std::vector _value; - uint64_t version; - datalayer::reference ref1; - datalayer::returncode rc; - std::vector* old_value = NULL; - std::vector* new_value = NULL; - - if (rit->has_value()) - { - rc = rit->unpack_value(&_value, &version, &ref1); - - if (rc != SUCCESS) - { - LOG(ERROR) << "error indexing: " << rc; - return false; - } - - new_value = &_value; - } - else - { - new_value = NULL; - } - - // perform the read - std::vector scratch; - leveldb::Slice lkey; - encode_key(ri, sc->attrs[0].type, key, &scratch, &lkey); - std::string ref2; - leveldb::ReadOptions opts; - opts.verify_checksums = true; - leveldb::Status st = m_daemon->m_data.m_db->Get(opts, lkey, &ref2); - std::vector _old_value; - - if (st.ok()) - { - uint64_t old_version; - rc = decode_value(e::slice(ref2.data(), ref2.size()), - &_old_value, &old_version); - - if (rc != SUCCESS) - { - rc = m_daemon->m_data.handle_error(st); - LOG(ERROR) << "error indexing: " << rc; - return false; - } - - if (_old_value.size() + 1 != sc->attrs_sz) - { - LOG(ERROR) << "error indexing: " << BAD_ENCODING; - return false; - } - - old_value = &_old_value; - } - else if (st.IsNotFound()) - { - old_value = NULL; - } - else - { - rc = m_daemon->m_data.handle_error(st); - LOG(ERROR) << "error indexing: " << rc; - return false; - } - - leveldb::WriteBatch batch; - create_index_changes(*sc, ri, idxs, key, old_value, new_value, &batch); - leveldb::WriteOptions wopts; - wopts.sync = false; - st = m_daemon->m_data.m_db->Write(wopts, &batch); - - if (!st.ok()) - { - rc = m_daemon->m_data.handle_error(st); - LOG(ERROR) << "error indexing: " << rc; - return false; - } - - return true; + if (interrupted()) + { + return false; + } + e::slice key = rit->key(); + std::vector _value; + uint64_t version; + datalayer::reference ref1; + datalayer::returncode rc; + std::vector *old_value = NULL; + std::vector *new_value = NULL; + if (rit->has_value()) + { + rc = rit->unpack_value(&_value, &version, &ref1); + if (rc != SUCCESS) + { + LOG(ERROR) << "error indexing: " << rc; + return false; + } + new_value = &_value; + } + else + { + new_value = NULL; + } + // perform the read + std::vector scratch; + leveldb::Slice lkey; + encode_key(ri, sc->attrs[0].type, key, &scratch, &lkey); + std::string ref2; + leveldb::ReadOptions opts; + opts.verify_checksums = true; + leveldb::Status st = m_daemon->m_data.m_db->Get(opts, lkey, &ref2); + std::vector _old_value; + if (st.ok()) + { + uint64_t old_version; + rc = decode_value(e::slice(ref2.data(), ref2.size()), + &_old_value, &old_version); + if (rc != SUCCESS) + { + rc = m_daemon->m_data.handle_error(st); + LOG(ERROR) << "error indexing: " << rc; + return false; + } + if (_old_value.size() + 1 != sc->attrs_sz) + { + LOG(ERROR) << "error indexing: " << BAD_ENCODING; + return false; + } + old_value = &_old_value; + } + else if (st.IsNotFound()) + { + old_value = NULL; + } + else + { + rc = m_daemon->m_data.handle_error(st); + LOG(ERROR) << "error indexing: " << rc; + return false; + } + leveldb::WriteBatch batch; + create_index_changes(*sc, ri, idxs, key, old_value, new_value, &batch); + leveldb::WriteOptions wopts; + wopts.sync = false; + st = m_daemon->m_data.m_db->Write(wopts, &batch); + if (!st.ok()) + { + rc = m_daemon->m_data.handle_error(st); + LOG(ERROR) << "error indexing: " << rc; + return false; + } + return true; } diff --git a/daemon/datalayer_indexer_thread.h b/daemon/datalayer_indexer_thread.h index 3e79f47ac..8e054801a 100644 --- a/daemon/datalayer_indexer_thread.h +++ b/daemon/datalayer_indexer_thread.h @@ -39,50 +39,50 @@ class hyperdex::datalayer::indexer_thread : public hyperdex::background_thread { - public: - indexer_thread(daemon* d, wiper_indexer_mediator* m); - ~indexer_thread() throw (); +public: + indexer_thread(daemon *d, wiper_indexer_mediator *m); + ~indexer_thread() throw (); - public: - virtual const char* thread_name(); - virtual bool have_work(); - virtual void copy_work(); - virtual void do_work(); +public: + virtual const char *thread_name(); + virtual bool have_work(); + virtual void copy_work(); + virtual void do_work(); - public: - void debug_dump(); - void kick(); - bool mark_usable(const region_id& ri, const index_id& ii); +public: + void debug_dump(); + void kick(); + bool mark_usable(const region_id &ri, const index_id &ii); - private: - bool interrupted(); - region_iterator* play(const region_id& ri, const schema* sc); - replay_iterator* replay(const region_id& ri, - const std::string& timestamp); - bool wipe(const region_id& ri, const index_id& ii); - bool wipe_common(uint8_t c, const region_id& ri, const index_id& ii); - bool index_from_iterator(region_iterator* it, - const schema* sc, - const region_id& ri, - const std::vector& idxs); - bool index_from_replay_iterator(replay_iterator* rit, - const schema* sc, - const region_id& ri, - const std::vector& idxs); +private: + bool interrupted(); + region_iterator *play(const region_id &ri, const schema *sc); + replay_iterator *replay(const region_id &ri, + const std::string ×tamp); + bool wipe(const region_id &ri, const index_id &ii); + bool wipe_common(uint8_t c, const region_id &ri, const index_id &ii); + bool index_from_iterator(region_iterator *it, + const schema *sc, + const region_id &ri, + const std::vector &idxs); + bool index_from_replay_iterator(replay_iterator *rit, + const schema *sc, + const region_id &ri, + const std::vector &idxs); - private: - daemon* m_daemon; - wiper_indexer_mediator* m_mediator; - configuration m_config; - bool m_have_current; - region_id m_current_region; - index_id m_current_index; - uint64_t m_interrupted_count; - bool m_interrupted; +private: + daemon *m_daemon; + wiper_indexer_mediator *m_mediator; + configuration m_config; + bool m_have_current; + region_id m_current_region; + index_id m_current_index; + uint64_t m_interrupted_count; + bool m_interrupted; - private: - indexer_thread(const indexer_thread&); - indexer_thread& operator = (const indexer_thread&); +private: + indexer_thread(const indexer_thread &); + indexer_thread &operator = (const indexer_thread &); }; #endif // hyperdex_daemon_datalayer_indexer_h_ diff --git a/daemon/datalayer_iterator.cc b/daemon/datalayer_iterator.cc index 95ec0a3e4..e6867abc8 100644 --- a/daemon/datalayer_iterator.cc +++ b/daemon/datalayer_iterator.cc @@ -39,33 +39,29 @@ using hyperdex::datalayer; using hyperdex::leveldb_snapshot_ptr; -inline leveldb::Slice e2level(const e::slice& s) { return leveldb::Slice(reinterpret_cast(s.data()), s.size()); } -inline e::slice level2e(const leveldb::Slice& s) { return e::slice(s.data(), s.size()); } +inline leveldb::Slice e2level(const e::slice &s) { return leveldb::Slice(reinterpret_cast(s.data()), s.size()); } +inline e::slice level2e(const leveldb::Slice &s) { return e::slice(s.data(), s.size()); } namespace { int -internal_key_compare(const e::slice& lhs, const e::slice& rhs) -{ - int cmp = memcmp(lhs.data(), rhs.data(), std::min(lhs.size(), rhs.size())); - - if (cmp == 0) - { - if (lhs.size() < rhs.size()) - { - return -1; - } - - if (lhs.size() > rhs.size()) - { - return 1; - } - - return 0; - } - - return cmp; +internal_key_compare(const e::slice &lhs, const e::slice &rhs) +{ + int cmp = memcmp(lhs.data(), rhs.data(), std::min(lhs.size(), rhs.size())); + if (cmp == 0) + { + if (lhs.size() < rhs.size()) + { + return -1; + } + if (lhs.size() > rhs.size()) + { + return 1; + } + return 0; + } + return cmp; } } // namespace @@ -73,15 +69,15 @@ internal_key_compare(const e::slice& lhs, const e::slice& rhs) //////////////////////////////// class iterator //////////////////////////////// datalayer :: iterator :: iterator(leveldb_snapshot_ptr s) - : m_ref(0) - , m_snap(s) + : m_ref(0) + , m_snap(s) { } leveldb_snapshot_ptr datalayer :: iterator :: snap() { - return m_snap; + return m_snap; } datalayer :: iterator :: ~iterator() throw () @@ -90,101 +86,97 @@ datalayer :: iterator :: ~iterator() throw () ///////////////////////////// class replay_iterator //////////////////////////// -datalayer :: replay_iterator :: replay_iterator(const region_id& ri, +datalayer :: replay_iterator :: replay_iterator(const region_id &ri, leveldb_replay_iterator_ptr ptr, - const index_encoding* ie) - : m_ri(ri) - , m_iter(ptr.get()) - , m_ptr(ptr) - , m_decoded() - , m_ie(ie) + const index_encoding *ie) + : m_ri(ri) + , m_iter(ptr.get()) + , m_ptr(ptr) + , m_decoded() + , m_ie(ie) { } bool datalayer :: replay_iterator :: valid() { - char buf[sizeof(uint8_t) + VARINT_64_MAX_SIZE]; - char* ptr = buf; - ptr = e::pack8be('o', ptr); - ptr = e::packvarint64(m_ri.get(), ptr); - leveldb::Slice prefix(buf, ptr - buf); - - while (m_iter->Valid()) - { - if (m_iter->key().starts_with(prefix)) - { - return true; - } - else if (m_iter->key().compare(prefix) < 0) - { - m_iter->SkipTo(prefix); - } - else - { - m_iter->SkipToLast(); - } - } - - return false; + char buf[sizeof(uint8_t) + VARINT_64_MAX_SIZE]; + char *ptr = buf; + ptr = e::pack8be('o', ptr); + ptr = e::packvarint64(m_ri.get(), ptr); + leveldb::Slice prefix(buf, ptr - buf); + while (m_iter->Valid()) + { + if (m_iter->key().starts_with(prefix)) + { + return true; + } + else if (m_iter->key().compare(prefix) < 0) + { + m_iter->SkipTo(prefix); + } + else + { + m_iter->SkipToLast(); + } + } + return false; } void datalayer :: replay_iterator :: next() { - m_iter->Next(); + m_iter->Next(); } bool datalayer :: replay_iterator :: has_value() { - return m_iter->HasValue(); + return m_iter->HasValue(); } e::slice datalayer :: replay_iterator :: key() { - const size_t sz = object_prefix_sz(m_ri); - leveldb::Slice _k = m_iter->key(); - e::slice k = e::slice(_k.data() + sz, _k.size() - sz); - size_t decoded_sz = m_ie->decoded_size(k); - - if (m_decoded.size() < decoded_sz) - { - m_decoded.resize(decoded_sz); - } - - m_ie->decode(k, &m_decoded.front()); - return e::slice(&m_decoded.front(), decoded_sz); + const size_t sz = object_prefix_sz(m_ri); + leveldb::Slice _k = m_iter->key(); + e::slice k = e::slice(_k.data() + sz, _k.size() - sz); + size_t decoded_sz = m_ie->decoded_size(k); + if (m_decoded.size() < decoded_sz) + { + m_decoded.resize(decoded_sz); + } + m_ie->decode(k, &m_decoded.front()); + return e::slice(&m_decoded.front(), decoded_sz); } datalayer::returncode -datalayer :: replay_iterator :: unpack_value(std::vector* value, - uint64_t* version, - reference* ref) +datalayer :: replay_iterator :: unpack_value(std::vector *value, + uint64_t *version, + reference *ref) { - ref->m_backing.assign(m_iter->value().data(), m_iter->value().size()); - e::slice v(ref->m_backing.data(), ref->m_backing.size()); - return decode_value(v, value, version); + ref->m_backing.assign(m_iter->value().data(), m_iter->value().size()); + e::slice v(ref->m_backing.data(), ref->m_backing.size()); + return decode_value(v, value, version); } leveldb::Status datalayer :: replay_iterator :: status() { - return m_iter->status(); + return m_iter->status(); } ///////////////////////////// class dummy_iterator ///////////////////////////// datalayer :: dummy_iterator :: dummy_iterator() - : iterator(leveldb_snapshot_ptr()) + : iterator(leveldb_snapshot_ptr()) { } bool datalayer :: dummy_iterator :: valid() { - return false; + return false; } void @@ -193,21 +185,21 @@ datalayer :: dummy_iterator :: next() } uint64_t -datalayer :: dummy_iterator :: cost(leveldb::DB*) +datalayer :: dummy_iterator :: cost(leveldb::DB *) { - return 0; + return 0; } e::slice datalayer :: dummy_iterator :: key() { - return e::slice(); + return e::slice(); } -std::ostream& -datalayer :: dummy_iterator :: describe(std::ostream& out) const +std::ostream & +datalayer :: dummy_iterator :: describe(std::ostream &out) const { - return out << "dummy_iterator()"; + return out << "dummy_iterator()"; } datalayer :: dummy_iterator :: ~dummy_iterator() throw () @@ -217,111 +209,103 @@ datalayer :: dummy_iterator :: ~dummy_iterator() throw () ///////////////////////////// class region_iterator //////////////////////////// datalayer :: region_iterator :: region_iterator(leveldb_iterator_ptr iter, - const region_id& ri, - const index_encoding* ie) - : iterator(iter.snap()) - , m_iter(iter) - , m_ri(ri) - , m_decoded() - , m_ie(ie) + const region_id &ri, + const index_encoding *ie) + : iterator(iter.snap()) + , m_iter(iter) + , m_ri(ri) + , m_decoded() + , m_ie(ie) { - char buf[sizeof(uint8_t) + VARINT_64_MAX_SIZE]; - char* ptr = buf; - ptr = e::pack8be('o', ptr); - ptr = e::packvarint64(ri.get(), ptr); - m_iter->Seek(leveldb::Slice(buf, ptr - buf)); + char buf[sizeof(uint8_t) + VARINT_64_MAX_SIZE]; + char *ptr = buf; + ptr = e::pack8be('o', ptr); + ptr = e::packvarint64(ri.get(), ptr); + m_iter->Seek(leveldb::Slice(buf, ptr - buf)); } datalayer :: region_iterator :: ~region_iterator() throw () { } -std::ostream& -datalayer :: region_iterator :: describe(std::ostream& out) const +std::ostream & +datalayer :: region_iterator :: describe(std::ostream &out) const { - return out << "region_iterator(" << m_ri << ")"; + return out << "region_iterator(" << m_ri << ")"; } bool datalayer :: region_iterator :: valid() { - if (!m_iter->Valid()) - { - return false; - } - - leveldb::Slice k = m_iter->key(); - - if (k.size() < 2 || k.data()[0] != 'o') - { - return false; - } - - uint64_t ri; - - if (!e::varint64_decode(k.data() + sizeof(uint8_t), k.data() + k.size(), &ri)) - { - return false; - } - - return region_id(ri) == m_ri; + if (!m_iter->Valid()) + { + return false; + } + leveldb::Slice k = m_iter->key(); + if (k.size() < 2 || k.data()[0] != 'o') + { + return false; + } + uint64_t ri; + if (!e::varint64_decode(k.data() + sizeof(uint8_t), k.data() + k.size(), &ri)) + { + return false; + } + return region_id(ri) == m_ri; } void datalayer :: region_iterator :: next() { - m_iter->Next(); + m_iter->Next(); } uint64_t -datalayer :: region_iterator :: cost(leveldb::DB* db) -{ - const size_t sz = object_prefix_sz(m_ri); - char buf[2 * (sizeof(uint8_t) + VARINT_64_MAX_SIZE)]; - char* ptr = buf; - ptr = encode_object_prefix(m_ri, ptr); - assert(ptr == buf + sz); - ptr = encode_object_prefix(m_ri, ptr); - assert(ptr == buf + sz + sz); - encode_bump(buf + sz, buf + 2 * sz); - // create the range - leveldb::Range r; - r.start = leveldb::Slice(buf, sz); - r.limit = leveldb::Slice(buf + sz, sz); - // ask leveldb for the size of the range - uint64_t ret; - db->GetApproximateSizes(&r, 1, &ret); - return ret; +datalayer :: region_iterator :: cost(leveldb::DB *db) +{ + const size_t sz = object_prefix_sz(m_ri); + char buf[2 * (sizeof(uint8_t) + VARINT_64_MAX_SIZE)]; + char *ptr = buf; + ptr = encode_object_prefix(m_ri, ptr); + assert(ptr == buf + sz); + ptr = encode_object_prefix(m_ri, ptr); + assert(ptr == buf + sz + sz); + encode_bump(buf + sz, buf + 2 * sz); + // create the range + leveldb::Range r; + r.start = leveldb::Slice(buf, sz); + r.limit = leveldb::Slice(buf + sz, sz); + // ask leveldb for the size of the range + uint64_t ret; + db->GetApproximateSizes(&r, 1, &ret); + return ret; } e::slice datalayer :: region_iterator :: key() { - // first pull out the internal key - leveldb::Slice _k = m_iter->key(); - const char* end = _k.data() + _k.size(); - const char* ptr = _k.data() + sizeof(uint8_t); - uint64_t region; - ptr = e::varint64_decode(ptr, end, ®ion); - assert(ptr); - - // now convert that into its decoded form - e::slice k = e::slice(ptr, end - ptr); - size_t decoded_sz = m_ie->decoded_size(k); - - if (m_decoded.size() < decoded_sz) - { - m_decoded.resize(decoded_sz); - } - - m_ie->decode(k, &m_decoded.front()); - return e::slice(&m_decoded.front(), decoded_sz); + // first pull out the internal key + leveldb::Slice _k = m_iter->key(); + const char *end = _k.data() + _k.size(); + const char *ptr = _k.data() + sizeof(uint8_t); + uint64_t region; + ptr = e::varint64_decode(ptr, end, ®ion); + assert(ptr); + // now convert that into its decoded form + e::slice k = e::slice(ptr, end - ptr); + size_t decoded_sz = m_ie->decoded_size(k); + if (m_decoded.size() < decoded_sz) + { + m_decoded.resize(decoded_sz); + } + m_ie->decode(k, &m_decoded.front()); + return e::slice(&m_decoded.front(), decoded_sz); } ///////////////////////////// class index_iterator ///////////////////////////// datalayer :: index_iterator :: index_iterator(leveldb_snapshot_ptr s) - : iterator(s) + : iterator(s) { } @@ -332,58 +316,54 @@ datalayer :: index_iterator :: ~index_iterator() throw () ////////////////////////// class range_index_iterator ////////////////////////// datalayer :: range_index_iterator :: range_index_iterator(leveldb_snapshot_ptr s, - size_t prefix_sz, - const e::slice& range_lower, - const e::slice& range_upper, - bool has_lower, - bool has_upper, - const index_encoding* val_ie, - const index_encoding* key_ie) - : index_iterator(s) - , m_iter() - , m_val_ie(val_ie) - , m_key_ie(key_ie) - , m_prefix() - , m_range_lower() - , m_range_upper() - , m_value_lower() - , m_value_upper() - , m_range_buf(range_lower.size() + range_upper.size()) - , m_scratch() - , m_has_lower(has_lower) - , m_has_upper(has_upper) - , m_invalid(false) -{ - // setup the iterator - leveldb::ReadOptions opts; - opts.fill_cache = true; - opts.verify_checksums = true; - opts.snapshot = s.get(); - m_iter.reset(s, s.db()->NewIterator(opts)); - - // copy the lower/upper into our buffer - memmove(&m_range_buf[0], range_lower.data(), range_lower.size()); - memmove(&m_range_buf[0] + range_lower.size(), range_upper.data(), range_upper.size()); - m_range_lower = e::slice(&m_range_buf[0], range_lower.size()); - m_range_upper = e::slice(&m_range_buf[0] + range_lower.size(), range_upper.size()); - assert(m_range_lower.size() >= prefix_sz); - assert(m_range_upper.size() >= prefix_sz); - assert(memcmp(m_range_lower.data(), m_range_upper.data(), prefix_sz) == 0); - m_prefix = e::slice(m_range_lower.data(), prefix_sz); - - // pull the value lower/upper - if (m_has_lower) - { - m_invalid = !decode_entry_keyless(m_range_lower, &m_value_lower) || m_invalid; - } - - // pull the value lower/upper - if (m_has_upper) - { - m_invalid = !decode_entry_keyless(m_range_upper, &m_value_upper) || m_invalid; - } - - m_iter->Seek(e2level(m_range_lower)); + size_t prefix_sz, + const e::slice &range_lower, + const e::slice &range_upper, + bool has_lower, + bool has_upper, + const index_encoding *val_ie, + const index_encoding *key_ie) + : index_iterator(s) + , m_iter() + , m_val_ie(val_ie) + , m_key_ie(key_ie) + , m_prefix() + , m_range_lower() + , m_range_upper() + , m_value_lower() + , m_value_upper() + , m_range_buf(range_lower.size() + range_upper.size()) + , m_scratch() + , m_has_lower(has_lower) + , m_has_upper(has_upper) + , m_invalid(false) +{ + // setup the iterator + leveldb::ReadOptions opts; + opts.fill_cache = true; + opts.verify_checksums = true; + opts.snapshot = s.get(); + m_iter.reset(s, s.db()->NewIterator(opts)); + // copy the lower/upper into our buffer + memmove(&m_range_buf[0], range_lower.data(), range_lower.size()); + memmove(&m_range_buf[0] + range_lower.size(), range_upper.data(), range_upper.size()); + m_range_lower = e::slice(&m_range_buf[0], range_lower.size()); + m_range_upper = e::slice(&m_range_buf[0] + range_lower.size(), range_upper.size()); + assert(m_range_lower.size() >= prefix_sz); + assert(m_range_upper.size() >= prefix_sz); + assert(memcmp(m_range_lower.data(), m_range_upper.data(), prefix_sz) == 0); + m_prefix = e::slice(m_range_lower.data(), prefix_sz); + // pull the value lower/upper + if (m_has_lower) + { + m_invalid = !decode_entry_keyless(m_range_lower, &m_value_lower) || m_invalid; + } + // pull the value lower/upper + if (m_has_upper) + { + m_invalid = !decode_entry_keyless(m_range_upper, &m_value_upper) || m_invalid; + } + m_iter->Seek(e2level(m_range_lower)); } datalayer :: range_index_iterator :: ~range_index_iterator() throw () @@ -393,274 +373,244 @@ datalayer :: range_index_iterator :: ~range_index_iterator() throw () bool datalayer :: range_index_iterator :: valid() { - while (!m_invalid && m_iter->Valid()) - { - if (!m_iter->key().starts_with(e2level(m_prefix))) - { - m_invalid = true; - return false; - } - - e::slice current = level2e(m_iter->key()); - e::slice iv; - e::slice ik; - - if (!decode_entry(current, &iv, &ik)) - { - m_invalid = true; - return false; - } - - size_t sz = std::min(m_range_upper.size(), current.size()); - - if (m_has_upper && memcmp(m_range_upper.data(), current.data(), sz) < 0) - { - m_invalid = true; - return false; - } - - if (m_has_lower && internal_key_compare(m_value_lower, iv) > 0) - { - m_iter->Next(); - continue; - } - - if (m_has_upper && internal_key_compare(m_value_upper, iv) < 0) - { - m_iter->Next(); - continue; - } - - return true; - } - - return false; + while (!m_invalid && m_iter->Valid()) + { + if (!m_iter->key().starts_with(e2level(m_prefix))) + { + m_invalid = true; + return false; + } + e::slice current = level2e(m_iter->key()); + e::slice iv; + e::slice ik; + if (!decode_entry(current, &iv, &ik)) + { + m_invalid = true; + return false; + } + size_t sz = std::min(m_range_upper.size(), current.size()); + if (m_has_upper && memcmp(m_range_upper.data(), current.data(), sz) < 0) + { + m_invalid = true; + return false; + } + if (m_has_lower && internal_key_compare(m_value_lower, iv) > 0) + { + m_iter->Next(); + continue; + } + if (m_has_upper && internal_key_compare(m_value_upper, iv) < 0) + { + m_iter->Next(); + continue; + } + return true; + } + return false; } void datalayer :: range_index_iterator :: next() { - m_iter->Next(); + m_iter->Next(); } uint64_t -datalayer :: range_index_iterator :: cost(leveldb::DB* db) -{ - if (m_scratch.size() < m_range_upper.size()) - { - m_scratch.resize(m_range_upper.size()); - } - - memmove(&m_scratch[0], m_range_upper.data(), m_range_upper.size()); - hyperdex::encode_bump(&m_scratch[0], &m_scratch[0] + m_range_upper.size()); - // create the range - leveldb::Range r; - r.start = m_iter->key(); - r.limit = leveldb::Slice(&m_scratch[0], m_range_upper.size()); - // ask leveldb for the size of the range - uint64_t ret; - db->GetApproximateSizes(&r, 1, &ret); - return ret; +datalayer :: range_index_iterator :: cost(leveldb::DB *db) +{ + if (m_scratch.size() < m_range_upper.size()) + { + m_scratch.resize(m_range_upper.size()); + } + memmove(&m_scratch[0], m_range_upper.data(), m_range_upper.size()); + hyperdex::encode_bump(&m_scratch[0], &m_scratch[0] + m_range_upper.size()); + // create the range + leveldb::Range r; + r.start = m_iter->key(); + r.limit = leveldb::Slice(&m_scratch[0], m_range_upper.size()); + // ask leveldb for the size of the range + uint64_t ret; + db->GetApproximateSizes(&r, 1, &ret); + return ret; } e::slice datalayer :: range_index_iterator :: key() { - e::slice ik = this->internal_key(); - size_t decoded_sz = m_key_ie->decoded_size(ik); - - if (m_scratch.size() < decoded_sz) - { - m_scratch.resize(decoded_sz); - } - - m_key_ie->decode(ik, &m_scratch.front()); - return e::slice(&m_scratch.front(), decoded_sz); + e::slice ik = this->internal_key(); + size_t decoded_sz = m_key_ie->decoded_size(ik); + if (m_scratch.size() < decoded_sz) + { + m_scratch.resize(decoded_sz); + } + m_key_ie->decode(ik, &m_scratch.front()); + return e::slice(&m_scratch.front(), decoded_sz); } -std::ostream& -datalayer :: range_index_iterator :: describe(std::ostream& out) const +std::ostream & +datalayer :: range_index_iterator :: describe(std::ostream &out) const { - return out << "range_iterator()"; + return out << "range_iterator()"; } e::slice datalayer :: range_index_iterator :: internal_key() { - leveldb::Slice in = m_iter->key(); - e::slice v; - e::slice k; - decode_entry(level2e(in), &v, &k); - return k; + leveldb::Slice in = m_iter->key(); + e::slice v; + e::slice k; + decode_entry(level2e(in), &v, &k); + return k; } bool datalayer :: range_index_iterator :: sorted() { - return m_has_lower && m_has_upper && m_value_lower == m_value_upper; + return m_has_lower && m_has_upper && m_value_lower == m_value_upper; } void -datalayer :: range_index_iterator :: seek(const e::slice& ik) +datalayer :: range_index_iterator :: seek(const e::slice &ik) { - leveldb::Slice in = m_iter->key(); - e::slice v; - e::slice k; - decode_entry(level2e(in), &v, &k); - encode_entry(v, ik, &m_scratch, &k); - m_iter->Seek(e2level(k)); + leveldb::Slice in = m_iter->key(); + e::slice v; + e::slice k; + decode_entry(level2e(in), &v, &k); + encode_entry(v, ik, &m_scratch, &k); + m_iter->Seek(e2level(k)); } bool -datalayer :: range_index_iterator :: decode_entry(const e::slice& in, e::slice* v, e::slice* k) -{ - assert(in.starts_with(m_prefix)); - const char* ptr = reinterpret_cast(in.data()); - const char* const end = ptr + in.size(); - ptr += m_prefix.size(); - size_t rem = end - ptr; - - if (!m_val_ie) - { - *k = e::slice(ptr, rem); - *v = *k; - } - else if (m_val_ie->encoding_fixed()) - { - size_t sz = m_val_ie->encoded_size(e::slice()); - - if (sz > rem) - { - return false; - } - - *v = e::slice(ptr, sz); - *k = e::slice(ptr + sz, rem - sz); - } - else if (m_key_ie->encoding_fixed()) - { - size_t sz = m_key_ie->encoded_size(e::slice()); - - if (sz > rem) - { - return false; - } - - *v = e::slice(ptr, rem - sz); - *k = e::slice(ptr + rem - sz, sz); - } - else - { - if (rem < sizeof(uint32_t)) - { - return false; - } - - uint32_t k_sz; - e::unpack32be(end - sizeof(uint32_t), &k_sz); - - if (k_sz + sizeof(uint32_t) > rem) - { - return false; - } - - *v = e::slice(ptr, rem - sizeof(uint32_t) - k_sz); - *k = e::slice(ptr + v->size(), k_sz); - } - - return true; +datalayer :: range_index_iterator :: decode_entry(const e::slice &in, e::slice *v, e::slice *k) +{ + assert(in.starts_with(m_prefix)); + const char *ptr = reinterpret_cast(in.data()); + const char *const end = ptr + in.size(); + ptr += m_prefix.size(); + size_t rem = end - ptr; + if (!m_val_ie) + { + *k = e::slice(ptr, rem); + *v = *k; + } + else if (m_val_ie->encoding_fixed()) + { + size_t sz = m_val_ie->encoded_size(e::slice()); + if (sz > rem) + { + return false; + } + *v = e::slice(ptr, sz); + *k = e::slice(ptr + sz, rem - sz); + } + else if (m_key_ie->encoding_fixed()) + { + size_t sz = m_key_ie->encoded_size(e::slice()); + if (sz > rem) + { + return false; + } + *v = e::slice(ptr, rem - sz); + *k = e::slice(ptr + rem - sz, sz); + } + else + { + if (rem < sizeof(uint32_t)) + { + return false; + } + uint32_t k_sz; + e::unpack32be(end - sizeof(uint32_t), &k_sz); + if (k_sz + sizeof(uint32_t) > rem) + { + return false; + } + *v = e::slice(ptr, rem - sizeof(uint32_t) - k_sz); + *k = e::slice(ptr + v->size(), k_sz); + } + return true; } bool -datalayer :: range_index_iterator :: decode_entry_keyless(const e::slice& in, e::slice* val) +datalayer :: range_index_iterator :: decode_entry_keyless(const e::slice &in, e::slice *val) { - assert(in.starts_with(m_prefix)); - *val = e::slice(in.data() + m_prefix.size(), in.size() - m_prefix.size()); - return true; + assert(in.starts_with(m_prefix)); + *val = e::slice(in.data() + m_prefix.size(), in.size() - m_prefix.size()); + return true; } void -datalayer :: range_index_iterator :: encode_entry(const e::slice& v, - const e::slice& k, - std::vector* scratch, - e::slice* slice) -{ - if (!m_val_ie) - { - size_t sz = m_prefix.size() + k.size(); - - if (scratch->size() < sz) - { - scratch->resize(sz); - } - - char* ptr = &(*scratch)[0]; - memmove(ptr, m_prefix.data(), m_prefix.size()); - ptr += m_prefix.size(); - memmove(ptr, k.data(), k.size()); - ptr += k.size(); - *slice = e::slice(&(*scratch)[0], ptr - &(*scratch)[0]); - } - else - { - size_t sz = m_prefix.size() + v.size() + k.size() + sizeof(uint32_t); - - if (scratch->size() < sz) - { - scratch->resize(sz); - } - - char* ptr = &(*scratch)[0]; - memmove(ptr, m_prefix.data(), m_prefix.size()); - ptr += m_prefix.size(); - memmove(ptr, v.data(), v.size()); - ptr += v.size(); - memmove(ptr, k.data(), k.size()); - ptr += k.size(); - - if (!m_val_ie->encoding_fixed() && !m_key_ie->encoding_fixed()) - { - ptr = e::pack32be(k.size(), ptr); - } - - *slice = e::slice(&(*scratch)[0], ptr - &(*scratch)[0]); - } +datalayer :: range_index_iterator :: encode_entry(const e::slice &v, + const e::slice &k, + std::vector *scratch, + e::slice *slice) +{ + if (!m_val_ie) + { + size_t sz = m_prefix.size() + k.size(); + if (scratch->size() < sz) + { + scratch->resize(sz); + } + char *ptr = &(*scratch)[0]; + memmove(ptr, m_prefix.data(), m_prefix.size()); + ptr += m_prefix.size(); + memmove(ptr, k.data(), k.size()); + ptr += k.size(); + *slice = e::slice(&(*scratch)[0], ptr - & (*scratch)[0]); + } + else + { + size_t sz = m_prefix.size() + v.size() + k.size() + sizeof(uint32_t); + if (scratch->size() < sz) + { + scratch->resize(sz); + } + char *ptr = &(*scratch)[0]; + memmove(ptr, m_prefix.data(), m_prefix.size()); + ptr += m_prefix.size(); + memmove(ptr, v.data(), v.size()); + ptr += v.size(); + memmove(ptr, k.data(), k.size()); + ptr += k.size(); + if (!m_val_ie->encoding_fixed() && !m_key_ie->encoding_fixed()) + { + ptr = e::pack32be(k.size(), ptr); + } + *slice = e::slice(&(*scratch)[0], ptr - & (*scratch)[0]); + } } //////////////////////////// class intersect_iterator //////////////////////////// datalayer :: intersect_iterator :: intersect_iterator(leveldb_snapshot_ptr s, - const std::vector >& iterators) - : index_iterator(s) - , m_iters() - , m_cost(0) - , m_invalid(false) -{ - assert(!iterators.empty()); - std::vector > > iters; - - for (size_t i = 0; i < iterators.size(); ++i) - { - assert(iterators[i]->sorted()); - iters.push_back(std::make_pair(iterators[i]->cost(s.db()), iterators[i])); - } - - std::sort(iters.begin(), iters.end()); - m_iters.resize(iters.size()); - - for (size_t i = 0; i < iters.size(); ++i) - { - m_cost += iters[i].first; - m_iters[i] = iters[i].second; - } - - for (size_t i = 0; i < m_iters.size(); ++i) - { - if (!m_iters[i]->valid()) - { - m_invalid = true; - } - } + const std::vector > &iterators) + : index_iterator(s) + , m_iters() + , m_cost(0) + , m_invalid(false) +{ + assert(!iterators.empty()); + std::vector > > iters; + for (size_t i = 0; i < iterators.size(); ++i) + { + assert(iterators[i]->sorted()); + iters.push_back(std::make_pair(iterators[i]->cost(s.db()), iterators[i])); + } + std::sort(iters.begin(), iters.end()); + m_iters.resize(iters.size()); + for (size_t i = 0; i < iters.size(); ++i) + { + m_cost += iters[i].first; + m_iters[i] = iters[i].second; + } + for (size_t i = 0; i < m_iters.size(); ++i) + { + if (!m_iters[i]->valid()) + { + m_invalid = true; + } + } } datalayer :: intersect_iterator :: ~intersect_iterator() throw () @@ -670,112 +620,102 @@ datalayer :: intersect_iterator :: ~intersect_iterator() throw () bool datalayer :: intersect_iterator :: valid() { - while (!m_invalid && m_iters[0]->valid()) - { - bool retry = false; - - for (size_t i = 1; i < m_iters.size(); ++i) - { - m_iters[i]->seek(m_iters[0]->internal_key()); - - if (!m_iters[i]->valid()) - { - m_invalid = true; - return false; - } - - int cmp = internal_key_compare(m_iters[0]->internal_key(), - m_iters[i]->internal_key()); - - if (cmp < 0) - { - m_iters[0]->seek(m_iters[i]->internal_key()); - retry = true; - break; - } - - assert(cmp == 0); - } - - if (!retry) - { - return true; - } - } - - m_invalid = true; - return false; + while (!m_invalid && m_iters[0]->valid()) + { + bool retry = false; + for (size_t i = 1; i < m_iters.size(); ++i) + { + m_iters[i]->seek(m_iters[0]->internal_key()); + if (!m_iters[i]->valid()) + { + m_invalid = true; + return false; + } + int cmp = internal_key_compare(m_iters[0]->internal_key(), + m_iters[i]->internal_key()); + if (cmp < 0) + { + m_iters[0]->seek(m_iters[i]->internal_key()); + retry = true; + break; + } + assert(cmp == 0); + } + if (!retry) + { + return true; + } + } + m_invalid = true; + return false; } void datalayer :: intersect_iterator :: next() { - m_iters[0]->next(); + m_iters[0]->next(); } uint64_t -datalayer :: intersect_iterator :: cost(leveldb::DB*) +datalayer :: intersect_iterator :: cost(leveldb::DB *) { - return m_cost; + return m_cost; } e::slice datalayer :: intersect_iterator :: key() { - return m_iters[0]->key(); + return m_iters[0]->key(); } -std::ostream& -datalayer :: intersect_iterator :: describe(std::ostream& out) const +std::ostream & +datalayer :: intersect_iterator :: describe(std::ostream &out) const { - out << "intersect_iterator("; - - for (size_t i = 0; i < m_iters.size(); ++i) - { - if (i > 0) - { - out << ", "; - } - - out << *m_iters[i]; - } - - return out << ")"; + out << "intersect_iterator("; + for (size_t i = 0; i < m_iters.size(); ++i) + { + if (i > 0) + { + out << ", "; + } + out << *m_iters[i]; + } + return out << ")"; } e::slice datalayer :: intersect_iterator :: internal_key() { - return m_iters[0]->internal_key(); + return m_iters[0]->internal_key(); } bool datalayer :: intersect_iterator :: sorted() { - return true; + return true; } void -datalayer :: intersect_iterator :: seek(const e::slice& k) +datalayer :: intersect_iterator :: seek(const e::slice &k) { - return m_iters[0]->seek(k); + return m_iters[0]->seek(k); } ///////////////////////////// class search_iterator //////////////////////////// -datalayer :: search_iterator :: search_iterator(datalayer* dl, - const region_id& ri, +datalayer :: search_iterator :: search_iterator(datalayer *dl, + const region_id &ri, e::intrusive_ptr iter, - std::ostringstream* ostr, - const std::vector* checks) - : iterator(iter->snap()) - , m_dl(dl) - , m_ri(ri) - , m_iter(iter) - , m_error(SUCCESS) - , m_ostr(ostr) - , m_num_gets(0) - , m_checks(checks) + std::ostringstream *ostr, + const std::vector *checks) + : iterator(iter->snap()) + , m_dl(dl) + , m_ri(ri) + , m_iter(iter) + , m_error(SUCCESS) + , m_ostr(ostr) + , m_num_gets(0) + , m_checks(checks) { } @@ -783,86 +723,78 @@ datalayer :: search_iterator :: ~search_iterator() throw () { } -std::ostream& -datalayer :: search_iterator :: describe(std::ostream& out) const +std::ostream & +datalayer :: search_iterator :: describe(std::ostream &out) const { - return out << "search_iterator(" << *m_iter << ")"; + return out << "search_iterator(" << *m_iter << ")"; } bool datalayer :: search_iterator :: valid() { - if (m_error != SUCCESS) - { - return false; - } - - // Don't try to optimize by replacing m_ri with a const schema* because it - // won't persist across reconfigurations - const schema& sc(*m_dl->m_daemon->m_config.get_schema(m_ri)); - - uint64_t version; - std::vector value; - reference ref; - - // while the most selective iterator is valid and not past the end - while (m_iter->valid()) - { - leveldb::ReadOptions opts; - opts.fill_cache = true; - opts.verify_checksums = true; - std::vector kbacking; - leveldb::Slice lkey; - encode_key(m_ri, sc.attrs[0].type, m_iter->key(), &kbacking, &lkey); - leveldb::Status st = m_dl->m_db->Get(opts, lkey, &ref.m_backing); - - if (st.ok()) - { - e::slice v(ref.m_backing.data(), ref.m_backing.size()); - datalayer::returncode rc = decode_value(v, &value, &version); - - if (rc != SUCCESS) - { - m_error = rc; - return false; - } - - ++m_num_gets; - } - else - { - m_error = m_dl->handle_error(st); - return false; - } - - if (passes_attribute_checks(sc, *m_checks, m_iter->key(), value) == m_checks->size()) - { - return true; - } - else - { - m_iter->next(); - } - } - - if (m_ostr) *m_ostr << " iterator retrieved " << m_num_gets << " objects from disk\n"; - return false; + if (m_error != SUCCESS) + { + return false; + } + // Don't try to optimize by replacing m_ri with a const schema* because it + // won't persist across reconfigurations + const schema &sc(*m_dl->m_daemon->m_config.get_schema(m_ri)); + uint64_t version; + std::vector value; + reference ref; + // while the most selective iterator is valid and not past the end + while (m_iter->valid()) + { + leveldb::ReadOptions opts; + opts.fill_cache = true; + opts.verify_checksums = true; + std::vector kbacking; + leveldb::Slice lkey; + encode_key(m_ri, sc.attrs[0].type, m_iter->key(), &kbacking, &lkey); + leveldb::Status st = m_dl->m_db->Get(opts, lkey, &ref.m_backing); + if (st.ok()) + { + e::slice v(ref.m_backing.data(), ref.m_backing.size()); + datalayer::returncode rc = decode_value(v, &value, &version); + if (rc != SUCCESS) + { + m_error = rc; + return false; + } + ++m_num_gets; + } + else + { + m_error = m_dl->handle_error(st); + return false; + } + if (passes_attribute_checks(sc, *m_checks, m_iter->key(), value) == m_checks->size()) + { + return true; + } + else + { + m_iter->next(); + } + } + if (m_ostr) *m_ostr << " iterator retrieved " << m_num_gets << " objects from disk\n"; + return false; } void datalayer :: search_iterator :: next() { - m_iter->next(); + m_iter->next(); } uint64_t -datalayer :: search_iterator :: cost(leveldb::DB* db) +datalayer :: search_iterator :: cost(leveldb::DB *db) { - return m_iter->cost(db); + return m_iter->cost(db); } e::slice datalayer :: search_iterator :: key() { - return m_iter->key(); + return m_iter->key(); } diff --git a/daemon/datalayer_iterator.h b/daemon/datalayer_iterator.h index 16a887004..22afa525d 100644 --- a/daemon/datalayer_iterator.h +++ b/daemon/datalayer_iterator.h @@ -40,225 +40,225 @@ BEGIN_HYPERDEX_NAMESPACE class datalayer::iterator { - public: - iterator(leveldb_snapshot_ptr snap); - - public: - virtual bool valid() = 0; - // REQUIRES: valid - virtual void next() = 0; - virtual uint64_t cost(leveldb::DB*) = 0; - // REQUIRES: valid - virtual e::slice key() = 0; - virtual std::ostream& describe(std::ostream&) const = 0; - - public: - leveldb_snapshot_ptr snap(); - - protected: - friend class e::intrusive_ptr; - virtual ~iterator() throw (); - void inc() { ++m_ref; } - void dec() { --m_ref; if (m_ref == 0) delete this; } - size_t m_ref; - - private: - leveldb_snapshot_ptr m_snap; +public: + iterator(leveldb_snapshot_ptr snap); + +public: + virtual bool valid() = 0; + // REQUIRES: valid + virtual void next() = 0; + virtual uint64_t cost(leveldb::DB *) = 0; + // REQUIRES: valid + virtual e::slice key() = 0; + virtual std::ostream &describe(std::ostream &) const = 0; + +public: + leveldb_snapshot_ptr snap(); + +protected: + friend class e::intrusive_ptr; + virtual ~iterator() throw (); + void inc() { ++m_ref; } + void dec() { --m_ref; if (m_ref == 0) delete this; } + size_t m_ref; + +private: + leveldb_snapshot_ptr m_snap; }; class datalayer::replay_iterator { - public: - replay_iterator(const region_id& ri, leveldb_replay_iterator_ptr ptr, const index_encoding* ie); - - public: - bool valid(); - void next(); - bool has_value(); - e::slice key(); - returncode unpack_value(std::vector* value, - uint64_t* version, - reference* ref); - leveldb::Status status(); - - private: - region_id m_ri; - leveldb::ReplayIterator* m_iter; - leveldb_replay_iterator_ptr m_ptr; - std::vector m_decoded; - const index_encoding *const m_ie; - - private: - replay_iterator(const replay_iterator&); - replay_iterator& operator = (const replay_iterator&); +public: + replay_iterator(const region_id &ri, leveldb_replay_iterator_ptr ptr, const index_encoding *ie); + +public: + bool valid(); + void next(); + bool has_value(); + e::slice key(); + returncode unpack_value(std::vector *value, + uint64_t *version, + reference *ref); + leveldb::Status status(); + +private: + region_id m_ri; + leveldb::ReplayIterator *m_iter; + leveldb_replay_iterator_ptr m_ptr; + std::vector m_decoded; + const index_encoding *const m_ie; + +private: + replay_iterator(const replay_iterator &); + replay_iterator &operator = (const replay_iterator &); }; class datalayer::dummy_iterator : public iterator { - public: - dummy_iterator(); - - public: - virtual bool valid(); - virtual void next(); - virtual uint64_t cost(leveldb::DB*); - virtual e::slice key(); - virtual std::ostream& describe(std::ostream&) const; - - protected: - virtual ~dummy_iterator() throw (); +public: + dummy_iterator(); + +public: + virtual bool valid(); + virtual void next(); + virtual uint64_t cost(leveldb::DB *); + virtual e::slice key(); + virtual std::ostream &describe(std::ostream &) const; + +protected: + virtual ~dummy_iterator() throw (); }; class datalayer::region_iterator : public iterator { - public: - region_iterator(leveldb_iterator_ptr iter, - const region_id& ri, - const index_encoding* ie); - virtual ~region_iterator() throw (); - - public: - virtual bool valid(); - virtual void next(); - virtual uint64_t cost(leveldb::DB*); - virtual e::slice key(); - virtual std::ostream& describe(std::ostream&) const; - - private: - region_iterator(const region_iterator&); - region_iterator& operator = (const region_iterator&); - - private: - leveldb_iterator_ptr m_iter; - region_id m_ri; - std::vector m_decoded; - const index_encoding *const m_ie; +public: + region_iterator(leveldb_iterator_ptr iter, + const region_id &ri, + const index_encoding *ie); + virtual ~region_iterator() throw (); + +public: + virtual bool valid(); + virtual void next(); + virtual uint64_t cost(leveldb::DB *); + virtual e::slice key(); + virtual std::ostream &describe(std::ostream &) const; + +private: + region_iterator(const region_iterator &); + region_iterator &operator = (const region_iterator &); + +private: + leveldb_iterator_ptr m_iter; + region_id m_ri; + std::vector m_decoded; + const index_encoding *const m_ie; }; class datalayer::index_iterator : public iterator { - public: - index_iterator(leveldb_snapshot_ptr snap); - virtual ~index_iterator() throw (); +public: + index_iterator(leveldb_snapshot_ptr snap); + virtual ~index_iterator() throw (); - public: - virtual e::slice internal_key() = 0; - virtual bool sorted() = 0; - virtual void seek(const e::slice& internal_key) = 0; +public: + virtual e::slice internal_key() = 0; + virtual bool sorted() = 0; + virtual void seek(const e::slice &internal_key) = 0; - protected: - friend class e::intrusive_ptr; +protected: + friend class e::intrusive_ptr; }; class datalayer::range_index_iterator : public index_iterator { - public: - range_index_iterator(leveldb_snapshot_ptr snap, - size_t range_prefix_sz, - const e::slice& range_lower, - const e::slice& range_upper, - bool has_value_lower, - bool has_value_upper, - const index_encoding* val_ie, - const index_encoding* key_ie); - virtual ~range_index_iterator() throw (); - - public: - virtual bool valid(); - virtual void next(); - virtual uint64_t cost(leveldb::DB*); - virtual e::slice key(); - virtual std::ostream& describe(std::ostream&) const; - virtual e::slice internal_key(); - virtual bool sorted(); - virtual void seek(const e::slice& internal_key); - - private: - bool decode_entry(const e::slice& in, e::slice* val, e::slice* key); - bool decode_entry_keyless(const e::slice& in, e::slice* val); - void encode_entry(const e::slice& val, - const e::slice& key, - std::vector* scratch, - e::slice* slice); - - private: - range_index_iterator(const range_index_iterator&); - range_index_iterator& operator = (const range_index_iterator&); - - private: - leveldb_iterator_ptr m_iter; - const index_encoding *const m_val_ie; - const index_encoding *const m_key_ie; - e::slice m_prefix; - e::slice m_range_lower; - e::slice m_range_upper; - e::slice m_value_lower; - e::slice m_value_upper; - std::vector m_range_buf; - std::vector m_scratch; - bool m_has_lower; - bool m_has_upper; - bool m_invalid; +public: + range_index_iterator(leveldb_snapshot_ptr snap, + size_t range_prefix_sz, + const e::slice &range_lower, + const e::slice &range_upper, + bool has_value_lower, + bool has_value_upper, + const index_encoding *val_ie, + const index_encoding *key_ie); + virtual ~range_index_iterator() throw (); + +public: + virtual bool valid(); + virtual void next(); + virtual uint64_t cost(leveldb::DB *); + virtual e::slice key(); + virtual std::ostream &describe(std::ostream &) const; + virtual e::slice internal_key(); + virtual bool sorted(); + virtual void seek(const e::slice &internal_key); + +private: + bool decode_entry(const e::slice &in, e::slice *val, e::slice *key); + bool decode_entry_keyless(const e::slice &in, e::slice *val); + void encode_entry(const e::slice &val, + const e::slice &key, + std::vector *scratch, + e::slice *slice); + +private: + range_index_iterator(const range_index_iterator &); + range_index_iterator &operator = (const range_index_iterator &); + +private: + leveldb_iterator_ptr m_iter; + const index_encoding *const m_val_ie; + const index_encoding *const m_key_ie; + e::slice m_prefix; + e::slice m_range_lower; + e::slice m_range_upper; + e::slice m_value_lower; + e::slice m_value_upper; + std::vector m_range_buf; + std::vector m_scratch; + bool m_has_lower; + bool m_has_upper; + bool m_invalid; }; class datalayer::intersect_iterator : public index_iterator { - public: - intersect_iterator(leveldb_snapshot_ptr snap, - const std::vector >& iterators); - virtual ~intersect_iterator() throw (); - - public: - virtual bool valid(); - virtual void next(); - virtual uint64_t cost(leveldb::DB*); - virtual e::slice key(); - virtual std::ostream& describe(std::ostream&) const; - virtual e::slice internal_key(); - virtual bool sorted(); - virtual void seek(const e::slice& internal_key); - - private: - std::vector > m_iters; - uint64_t m_cost; - bool m_invalid; +public: + intersect_iterator(leveldb_snapshot_ptr snap, + const std::vector > &iterators); + virtual ~intersect_iterator() throw (); + +public: + virtual bool valid(); + virtual void next(); + virtual uint64_t cost(leveldb::DB *); + virtual e::slice key(); + virtual std::ostream &describe(std::ostream &) const; + virtual e::slice internal_key(); + virtual bool sorted(); + virtual void seek(const e::slice &internal_key); + +private: + std::vector > m_iters; + uint64_t m_cost; + bool m_invalid; }; class datalayer::search_iterator : public iterator { - public: - search_iterator(datalayer* dl, - const region_id& ri, - e::intrusive_ptr iter, - std::ostringstream* ostr, - const std::vector* checks); - virtual ~search_iterator() throw (); - - public: - virtual bool valid(); - virtual void next(); - virtual uint64_t cost(leveldb::DB*); - virtual e::slice key(); - virtual std::ostream& describe(std::ostream&) const; - - private: - search_iterator(const search_iterator&); - search_iterator& operator = (const search_iterator&); - - private: - datalayer* m_dl; - region_id m_ri; - e::intrusive_ptr m_iter; - returncode m_error; - std::ostringstream* m_ostr; - uint64_t m_num_gets; - const std::vector* m_checks; +public: + search_iterator(datalayer *dl, + const region_id &ri, + e::intrusive_ptr iter, + std::ostringstream *ostr, + const std::vector *checks); + virtual ~search_iterator() throw (); + +public: + virtual bool valid(); + virtual void next(); + virtual uint64_t cost(leveldb::DB *); + virtual e::slice key(); + virtual std::ostream &describe(std::ostream &) const; + +private: + search_iterator(const search_iterator &); + search_iterator &operator = (const search_iterator &); + +private: + datalayer *m_dl; + region_id m_ri; + e::intrusive_ptr m_iter; + returncode m_error; + std::ostringstream *m_ostr; + uint64_t m_num_gets; + const std::vector *m_checks; }; -inline std::ostream& -operator << (std::ostream& lhs, const datalayer::iterator& rhs) +inline std::ostream & +operator << (std::ostream &lhs, const datalayer::iterator &rhs) { - return rhs.describe(lhs); + return rhs.describe(lhs); } END_HYPERDEX_NAMESPACE diff --git a/daemon/datalayer_wiper_indexer_mediator.h b/daemon/datalayer_wiper_indexer_mediator.h index 0a7e1bcb8..e0999789b 100644 --- a/daemon/datalayer_wiper_indexer_mediator.h +++ b/daemon/datalayer_wiper_indexer_mediator.h @@ -32,34 +32,34 @@ using hyperdex::datalayer; class datalayer::wiper_indexer_mediator { - public: - wiper_indexer_mediator(); - ~wiper_indexer_mediator() throw (); - - public: - void debug_dump(); - bool region_conflicts_with_wiper(const region_id& ri); - bool region_conflicts_with_indexer(const region_id& ri); - bool set_wiper_region(const region_id& ri); - bool set_indexer_region(const region_id& ri); - void clear_wiper_region(); - void clear_indexer_region(); - - private: - wiper_indexer_mediator(const wiper_indexer_mediator&); - wiper_indexer_mediator& operator = (const wiper_indexer_mediator&); - - private: - po6::threads::mutex m_protect; - region_id m_wiper; - region_id m_indexer; +public: + wiper_indexer_mediator(); + ~wiper_indexer_mediator() throw (); + +public: + void debug_dump(); + bool region_conflicts_with_wiper(const region_id &ri); + bool region_conflicts_with_indexer(const region_id &ri); + bool set_wiper_region(const region_id &ri); + bool set_indexer_region(const region_id &ri); + void clear_wiper_region(); + void clear_indexer_region(); + +private: + wiper_indexer_mediator(const wiper_indexer_mediator &); + wiper_indexer_mediator &operator = (const wiper_indexer_mediator &); + +private: + po6::threads::mutex m_protect; + region_id m_wiper; + region_id m_indexer; }; inline datalayer :: wiper_indexer_mediator :: wiper_indexer_mediator() - : m_protect() - , m_wiper() - , m_indexer() + : m_protect() + , m_wiper() + , m_indexer() { } @@ -71,66 +71,62 @@ datalayer :: wiper_indexer_mediator :: ~wiper_indexer_mediator() throw () inline void datalayer :: wiper_indexer_mediator :: debug_dump() { - po6::threads::mutex::hold hold(&m_protect); - LOG(INFO) << "wiper-indexer mediator ========================================================"; - LOG(INFO) << "wiper=" << m_wiper; - LOG(INFO) << "indexer=" << m_indexer; + po6::threads::mutex::hold hold(&m_protect); + LOG(INFO) << "wiper-indexer mediator ========================================================"; + LOG(INFO) << "wiper=" << m_wiper; + LOG(INFO) << "indexer=" << m_indexer; } inline bool -datalayer :: wiper_indexer_mediator :: region_conflicts_with_wiper(const region_id& ri) +datalayer :: wiper_indexer_mediator :: region_conflicts_with_wiper(const region_id &ri) { - po6::threads::mutex::hold hold(&m_protect); - return m_wiper == ri; + po6::threads::mutex::hold hold(&m_protect); + return m_wiper == ri; } inline bool -datalayer :: wiper_indexer_mediator :: region_conflicts_with_indexer(const region_id& ri) +datalayer :: wiper_indexer_mediator :: region_conflicts_with_indexer(const region_id &ri) { - po6::threads::mutex::hold hold(&m_protect); - return m_indexer == ri; + po6::threads::mutex::hold hold(&m_protect); + return m_indexer == ri; } inline bool -datalayer :: wiper_indexer_mediator :: set_wiper_region(const region_id& ri) +datalayer :: wiper_indexer_mediator :: set_wiper_region(const region_id &ri) { - po6::threads::mutex::hold hold(&m_protect); - - if (m_indexer != ri) - { - m_wiper = ri; - return true; - } - - return false; + po6::threads::mutex::hold hold(&m_protect); + if (m_indexer != ri) + { + m_wiper = ri; + return true; + } + return false; } inline bool -datalayer :: wiper_indexer_mediator :: set_indexer_region(const region_id& ri) +datalayer :: wiper_indexer_mediator :: set_indexer_region(const region_id &ri) { - po6::threads::mutex::hold hold(&m_protect); - - if (m_wiper != ri) - { - m_indexer = ri; - return true; - } - - return false; + po6::threads::mutex::hold hold(&m_protect); + if (m_wiper != ri) + { + m_indexer = ri; + return true; + } + return false; } inline void datalayer :: wiper_indexer_mediator :: clear_wiper_region() { - po6::threads::mutex::hold hold(&m_protect); - m_wiper = region_id(); + po6::threads::mutex::hold hold(&m_protect); + m_wiper = region_id(); } inline void datalayer :: wiper_indexer_mediator :: clear_indexer_region() { - po6::threads::mutex::hold hold(&m_protect); - m_indexer = region_id(); + po6::threads::mutex::hold hold(&m_protect); + m_indexer = region_id(); } #endif // hyperdex_daemon_datalayer_wiper_indexer_mediator_h_ diff --git a/daemon/datalayer_wiper_thread.cc b/daemon/datalayer_wiper_thread.cc index b7c0f7cb8..323b28f58 100644 --- a/daemon/datalayer_wiper_thread.cc +++ b/daemon/datalayer_wiper_thread.cc @@ -42,17 +42,17 @@ using hyperdex::datalayer; -datalayer :: wiper_thread :: wiper_thread(daemon* d, wiper_indexer_mediator* m) - : background_thread(d) - , m_daemon(d) - , m_mediator(m) - , m_wiping() - , m_have_current(false) - , m_wipe_current_xid() - , m_wipe_current_rid() - , m_wiping_inhibit_permit_diff(0) - , m_interrupted_count(0) - , m_interrupted(false) +datalayer :: wiper_thread :: wiper_thread(daemon *d, wiper_indexer_mediator *m) + : background_thread(d) + , m_daemon(d) + , m_mediator(m) + , m_wiping() + , m_have_current(false) + , m_wipe_current_xid() + , m_wipe_current_rid() + , m_wiping_inhibit_permit_diff(0) + , m_interrupted_count(0) + , m_interrupted(false) { } @@ -60,245 +60,223 @@ datalayer :: wiper_thread :: ~wiper_thread() throw () { } -const char* +const char * datalayer :: wiper_thread :: thread_name() { - return "wiping"; + return "wiping"; } bool datalayer :: wiper_thread :: have_work() { - m_interrupted = false; - m_mediator->clear_wiper_region(); - m_have_current = false; - m_wipe_current_xid = transfer_id(); - m_wipe_current_rid = region_id(); - return !m_wiping.empty() && m_wiping_inhibit_permit_diff == 0 && - !m_mediator->region_conflicts_with_indexer(m_wiping.front().second); + m_interrupted = false; + m_mediator->clear_wiper_region(); + m_have_current = false; + m_wipe_current_xid = transfer_id(); + m_wipe_current_rid = region_id(); + return !m_wiping.empty() && m_wiping_inhibit_permit_diff == 0 && + !m_mediator->region_conflicts_with_indexer(m_wiping.front().second); } void datalayer :: wiper_thread :: copy_work() { - m_wipe_current_xid = m_wiping.front().first; - m_wipe_current_rid = m_wiping.front().second; - m_have_current = m_mediator->set_wiper_region(m_wipe_current_rid); + m_wipe_current_xid = m_wiping.front().first; + m_wipe_current_rid = m_wiping.front().second; + m_have_current = m_mediator->set_wiper_region(m_wipe_current_rid); } void datalayer :: wiper_thread :: do_work() { - if (!m_have_current) - { - return; - } - - wipe(m_wipe_current_xid, m_wipe_current_rid); + if (!m_have_current) + { + return; + } + wipe(m_wipe_current_xid, m_wipe_current_rid); } void datalayer :: wiper_thread :: debug_dump() { - this->lock(); - LOG(INFO) << "wiper thread =================================================================="; - LOG(INFO) << "wiping:"; - - for (wipe_list_t::iterator it = m_wiping.begin(); it != m_wiping.end(); ++it) - { - LOG(INFO) << " " << it->first << " " << it->second; - } - - LOG(INFO) << "have_current=" << (m_have_current ? "yes" : "no"); - LOG(INFO) << "wipe_current_xid=" << m_wipe_current_xid; - LOG(INFO) << "wipe_current_rid=" << m_wipe_current_rid; - LOG(INFO) << "wiping_inhibit_permit_diff=" << m_wiping_inhibit_permit_diff; - LOG(INFO) << "interrupted_count=" << m_interrupted_count; - this->unlock(); + this->lock(); + LOG(INFO) << "wiper thread =================================================================="; + LOG(INFO) << "wiping:"; + for (wipe_list_t::iterator it = m_wiping.begin(); it != m_wiping.end(); ++it) + { + LOG(INFO) << " " << it->first << " " << it->second; + } + LOG(INFO) << "have_current=" << (m_have_current ? "yes" : "no"); + LOG(INFO) << "wipe_current_xid=" << m_wipe_current_xid; + LOG(INFO) << "wipe_current_rid=" << m_wipe_current_rid; + LOG(INFO) << "wiping_inhibit_permit_diff=" << m_wiping_inhibit_permit_diff; + LOG(INFO) << "interrupted_count=" << m_interrupted_count; + this->unlock(); } void datalayer :: wiper_thread :: inhibit_wiping() { - this->lock(); - ++m_wiping_inhibit_permit_diff; - this->unlock(); + this->lock(); + ++m_wiping_inhibit_permit_diff; + this->unlock(); } void datalayer :: wiper_thread :: permit_wiping() { - this->lock(); - assert(m_wiping_inhibit_permit_diff > 0); - --m_wiping_inhibit_permit_diff; - - if (m_wiping_inhibit_permit_diff == 0) - { - this->wakeup(); - } - - this->unlock(); + this->lock(); + assert(m_wiping_inhibit_permit_diff > 0); + --m_wiping_inhibit_permit_diff; + if (m_wiping_inhibit_permit_diff == 0) + { + this->wakeup(); + } + this->unlock(); } bool datalayer :: wiper_thread :: region_will_be_wiped(region_id rid) { - bool found = false; - this->lock(); - - for (wipe_list_t::iterator it = m_wiping.begin(); - !found && it != m_wiping.end(); ++it) - { - found = it->second == rid; - } - - this->unlock(); - return found; + bool found = false; + this->lock(); + for (wipe_list_t::iterator it = m_wiping.begin(); + !found && it != m_wiping.end(); ++it) + { + found = it->second == rid; + } + this->unlock(); + return found; } void datalayer :: wiper_thread :: request_wipe(transfer_id xid, - region_id ri) + region_id ri) { - this->lock(); - m_wiping.push_back(std::make_pair(xid, ri)); - this->wakeup(); - this->unlock(); + this->lock(); + m_wiping.push_back(std::make_pair(xid, ri)); + this->wakeup(); + this->unlock(); } void datalayer :: wiper_thread :: kick() { - this->lock(); - this->wakeup(); - this->unlock(); + this->lock(); + this->wakeup(); + this->unlock(); } bool datalayer :: wiper_thread :: interrupted() { - ++m_interrupted_count; - bool ret = m_interrupted; - - if (m_interrupted_count % 1000 == 0) - { - this->lock(); - ret = this->is_shutdown(); - m_interrupted = ret; - this->unlock(); - } - - return ret; + ++m_interrupted_count; + bool ret = m_interrupted; + if (m_interrupted_count % 1000 == 0) + { + this->lock(); + ret = this->is_shutdown(); + m_interrupted = ret; + this->unlock(); + } + return ret; } void datalayer :: wiper_thread :: wipe(transfer_id xid, region_id rid) { - this->offline(); - wipe_checkpoints(rid); - wipe_indices(rid); - wipe_objects(rid); - this->online(); - - if (interrupted()) - { - return; - } - - // now mark it as usable - for (size_t i = 0; i < m_daemon->m_data.m_indices.size(); ++i) - { - index_state* is = &m_daemon->m_data.m_indices[i]; - - if (is->ri == rid) - { - if (!m_daemon->m_data.m_indexer->mark_usable(is->ri, is->ii)) - { - return; - } - } - } - - this->lock(); - assert(!m_wiping.empty()); - assert(m_wiping.front().first == xid); - assert(m_wiping.front().second == rid); - - if (m_wiping_inhibit_permit_diff == 0) - { - m_wiping.pop_front(); - } - - this->unlock(); - m_daemon->m_data.m_indexer->kick(); - - // now report that it was wiped - m_daemon->m_stm.report_wiped(xid); + this->offline(); + wipe_checkpoints(rid); + wipe_indices(rid); + wipe_objects(rid); + this->online(); + if (interrupted()) + { + return; + } + // now mark it as usable + for (size_t i = 0; i < m_daemon->m_data.m_indices.size(); ++i) + { + index_state *is = &m_daemon->m_data.m_indices[i]; + if (is->ri == rid) + { + if (!m_daemon->m_data.m_indexer->mark_usable(is->ri, is->ii)) + { + return; + } + } + } + this->lock(); + assert(!m_wiping.empty()); + assert(m_wiping.front().first == xid); + assert(m_wiping.front().second == rid); + if (m_wiping_inhibit_permit_diff == 0) + { + m_wiping.pop_front(); + } + this->unlock(); + m_daemon->m_data.m_indexer->kick(); + // now report that it was wiped + m_daemon->m_stm.report_wiped(xid); } void datalayer :: wiper_thread :: wipe_checkpoints(region_id rid) { - std::auto_ptr it; - it.reset(m_daemon->m_data.m_db->NewIterator(leveldb::ReadOptions())); - char cbacking[CHECKPOINT_BUF_SIZE]; - encode_checkpoint(rid, 0, cbacking); - it->Seek(leveldb::Slice(cbacking, CHECKPOINT_BUF_SIZE)); - - while (it->Valid()) - { - if (interrupted()) - { - return; - } - - region_timestamp rt; - e::slice key(it->key().data(), it->key().size()); - returncode rc = decode_checkpoint(key, &rt.rid, &rt.checkpoint); - - if (rc != datalayer::SUCCESS || rt.rid != rid) - { - break; - } - - m_daemon->m_data.m_db->Delete(leveldb::WriteOptions(), it->key()); - it->Next(); - } + std::auto_ptr it; + it.reset(m_daemon->m_data.m_db->NewIterator(leveldb::ReadOptions())); + char cbacking[CHECKPOINT_BUF_SIZE]; + encode_checkpoint(rid, 0, cbacking); + it->Seek(leveldb::Slice(cbacking, CHECKPOINT_BUF_SIZE)); + while (it->Valid()) + { + if (interrupted()) + { + return; + } + region_timestamp rt; + e::slice key(it->key().data(), it->key().size()); + returncode rc = decode_checkpoint(key, &rt.rid, &rt.checkpoint); + if (rc != datalayer::SUCCESS || rt.rid != rid) + { + break; + } + m_daemon->m_data.m_db->Delete(leveldb::WriteOptions(), it->key()); + it->Next(); + } } void datalayer :: wiper_thread :: wipe_indices(region_id rid) { - wipe_common('I', rid); - wipe_common('i', rid); + wipe_common('I', rid); + wipe_common('i', rid); } void datalayer :: wiper_thread :: wipe_objects(region_id rid) { - wipe_common('o', rid); + wipe_common('o', rid); } void datalayer :: wiper_thread :: wipe_common(uint8_t c, region_id rid) { - std::auto_ptr it; - it.reset(m_daemon->m_data.m_db->NewIterator(leveldb::ReadOptions())); - char backing[sizeof(uint8_t) + VARINT_64_MAX_SIZE]; - char* ptr = backing; - ptr = e::pack8be(c, ptr); - ptr = e::packvarint64(rid.get(), ptr); - leveldb::Slice prefix(backing, ptr - backing); - it->Seek(prefix); - - while (it->key().starts_with(prefix)) - { - if (interrupted()) - { - return; - } - - m_daemon->m_data.m_db->Delete(leveldb::WriteOptions(), it->key()); - it->Next(); - } + std::auto_ptr it; + it.reset(m_daemon->m_data.m_db->NewIterator(leveldb::ReadOptions())); + char backing[sizeof(uint8_t) + VARINT_64_MAX_SIZE]; + char *ptr = backing; + ptr = e::pack8be(c, ptr); + ptr = e::packvarint64(rid.get(), ptr); + leveldb::Slice prefix(backing, ptr - backing); + it->Seek(prefix); + while (it->key().starts_with(prefix)) + { + if (interrupted()) + { + return; + } + m_daemon->m_data.m_db->Delete(leveldb::WriteOptions(), it->key()); + it->Next(); + } } diff --git a/daemon/datalayer_wiper_thread.h b/daemon/datalayer_wiper_thread.h index 4b16c8b4b..e441de380 100644 --- a/daemon/datalayer_wiper_thread.h +++ b/daemon/datalayer_wiper_thread.h @@ -35,53 +35,53 @@ class hyperdex::datalayer::wiper_thread : public hyperdex::background_thread { - public: - wiper_thread(daemon* d, wiper_indexer_mediator* m); - ~wiper_thread() throw (); +public: + wiper_thread(daemon *d, wiper_indexer_mediator *m); + ~wiper_thread() throw (); - public: - virtual const char* thread_name(); - virtual bool have_work(); - virtual void copy_work(); - virtual void do_work(); +public: + virtual const char *thread_name(); + virtual bool have_work(); + virtual void copy_work(); + virtual void do_work(); - public: - void debug_dump(); - // These are different than pause/unpause, which should only ever be - // called by the main thread. They guarantee that after the wiper is - // done with the current region, it will not make progress to the next - // region. Thus, between pairs of inhibit/permit, - // "region_will_be_wiped" is guaranteed not to go from true->false. - void inhibit_wiping(); - void permit_wiping(); - bool region_will_be_wiped(region_id rid); - void request_wipe(transfer_id xid, - region_id ri); - void kick(); +public: + void debug_dump(); + // These are different than pause/unpause, which should only ever be + // called by the main thread. They guarantee that after the wiper is + // done with the current region, it will not make progress to the next + // region. Thus, between pairs of inhibit/permit, + // "region_will_be_wiped" is guaranteed not to go from true->false. + void inhibit_wiping(); + void permit_wiping(); + bool region_will_be_wiped(region_id rid); + void request_wipe(transfer_id xid, + region_id ri); + void kick(); - private: - bool interrupted(); - void wipe(transfer_id xid, region_id rid); - void wipe_checkpoints(region_id rid); - void wipe_indices(region_id rid); - void wipe_objects(region_id rid); - void wipe_common(uint8_t c, region_id rid); +private: + bool interrupted(); + void wipe(transfer_id xid, region_id rid); + void wipe_checkpoints(region_id rid); + void wipe_indices(region_id rid); + void wipe_objects(region_id rid); + void wipe_common(uint8_t c, region_id rid); - private: - daemon* m_daemon; - wiper_indexer_mediator* m_mediator; - typedef std::list > wipe_list_t; - wipe_list_t m_wiping; - bool m_have_current; - transfer_id m_wipe_current_xid; - region_id m_wipe_current_rid; - uint64_t m_wiping_inhibit_permit_diff; - uint64_t m_interrupted_count; - bool m_interrupted; +private: + daemon *m_daemon; + wiper_indexer_mediator *m_mediator; + typedef std::list > wipe_list_t; + wipe_list_t m_wiping; + bool m_have_current; + transfer_id m_wipe_current_xid; + region_id m_wipe_current_rid; + uint64_t m_wiping_inhibit_permit_diff; + uint64_t m_interrupted_count; + bool m_interrupted; - private: - wiper_thread(const wiper_thread&); - wiper_thread& operator = (const wiper_thread&); +private: + wiper_thread(const wiper_thread &); + wiper_thread &operator = (const wiper_thread &); }; #endif // hyperdex_daemon_datalayer_wiper_thread_h_ diff --git a/daemon/identifier_collector.cc b/daemon/identifier_collector.cc index 477305ef7..55c8fe21b 100644 --- a/daemon/identifier_collector.cc +++ b/daemon/identifier_collector.cc @@ -39,9 +39,9 @@ using hyperdex::region_id; const region_id identifier_collector::defaultri; -identifier_collector :: identifier_collector(e::garbage_collector* gc) - : m_gc(gc) - , m_collectors() +identifier_collector :: identifier_collector(e::garbage_collector *gc) + : m_gc(gc) + , m_collectors() { } @@ -50,64 +50,54 @@ identifier_collector :: ~identifier_collector() throw () } void -identifier_collector :: bump(const region_id& ri, uint64_t lb) +identifier_collector :: bump(const region_id &ri, uint64_t lb) { - e::compat::shared_ptr sc; - - if (!m_collectors.get(ri, &sc)) - { - abort(); - } - - sc->collect_up_to(lb); + e::compat::shared_ptr sc; + if (!m_collectors.get(ri, &sc)) + { + abort(); + } + sc->collect_up_to(lb); } void -identifier_collector :: collect(const region_id& ri, uint64_t seqno) +identifier_collector :: collect(const region_id &ri, uint64_t seqno) { - e::compat::shared_ptr sc; - - if (!m_collectors.get(ri, &sc)) - { - abort(); - } - - sc->collect(seqno); + e::compat::shared_ptr sc; + if (!m_collectors.get(ri, &sc)) + { + abort(); + } + sc->collect(seqno); } uint64_t -identifier_collector :: lower_bound(const region_id& ri) +identifier_collector :: lower_bound(const region_id &ri) { - e::compat::shared_ptr sc; - - if (!m_collectors.get(ri, &sc)) - { - abort(); - } - - uint64_t lb; - sc->lower_bound(&lb); - return lb; + e::compat::shared_ptr sc; + if (!m_collectors.get(ri, &sc)) + { + abort(); + } + uint64_t lb; + sc->lower_bound(&lb); + return lb; } void -identifier_collector :: adopt(region_id* ris, size_t ris_sz) +identifier_collector :: adopt(region_id *ris, size_t ris_sz) { - collector_map_t new_collectors; - - for (size_t i = 0; i < ris_sz; ++i) - { - e::compat::shared_ptr sc; - - if (!m_collectors.get(ris[i], &sc)) - { - sc = e::compat::shared_ptr(new e::seqno_collector(m_gc)); - sc->collect(0); - } - - assert(sc); - new_collectors.put(ris[i], sc); - } - - m_collectors.swap(&new_collectors); + collector_map_t new_collectors; + for (size_t i = 0; i < ris_sz; ++i) + { + e::compat::shared_ptr sc; + if (!m_collectors.get(ris[i], &sc)) + { + sc = e::compat::shared_ptr(new e::seqno_collector(m_gc)); + sc->collect(0); + } + assert(sc); + new_collectors.put(ris[i], sc); + } + m_collectors.swap(&new_collectors); } diff --git a/daemon/identifier_collector.h b/daemon/identifier_collector.h index 4fb775ec8..4b31a19fd 100644 --- a/daemon/identifier_collector.h +++ b/daemon/identifier_collector.h @@ -41,35 +41,35 @@ BEGIN_HYPERDEX_NAMESPACE class identifier_collector { - public: - identifier_collector(e::garbage_collector* gc); - ~identifier_collector() throw (); +public: + identifier_collector(e::garbage_collector *gc); + ~identifier_collector() throw (); - // concurrent methods - // these methods return "true" if ri is a managed region_id, else "false" - public: - // force the lower bound for "ri" to be "lb" or more - // equivalent to calling collect on 0 through lb - 1 - void bump(const region_id& ri, uint64_t lb); - // mark the identifier as collected - void collect(const region_id& ri, uint64_t id); - // store a value in "*lb" such that ids "< *lb" have been collected - uint64_t lower_bound(const region_id& ri); + // concurrent methods + // these methods return "true" if ri is a managed region_id, else "false" +public: + // force the lower bound for "ri" to be "lb" or more + // equivalent to calling collect on 0 through lb - 1 + void bump(const region_id &ri, uint64_t lb); + // mark the identifier as collected + void collect(const region_id &ri, uint64_t id); + // store a value in "*lb" such that ids "< *lb" have been collected + uint64_t lower_bound(const region_id &ri); - // external synchronization required; nothing can call other methods - public: - void adopt(region_id* ris, size_t ris_sz); + // external synchronization required; nothing can call other methods +public: + void adopt(region_id *ris, size_t ris_sz); - private: - identifier_collector(const identifier_collector&); - identifier_collector& operator = (const identifier_collector&); - static uint64_t id(region_id ri) { return ri.get(); } +private: + identifier_collector(const identifier_collector &); + identifier_collector &operator = (const identifier_collector &); + static uint64_t id(region_id ri) { return ri.get(); } - private: - const static region_id defaultri; - typedef e::ao_hash_map, id, defaultri> collector_map_t; - e::garbage_collector* m_gc; - collector_map_t m_collectors; +private: + const static region_id defaultri; + typedef e::ao_hash_map, id, defaultri> collector_map_t; + e::garbage_collector *m_gc; + collector_map_t m_collectors; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/identifier_generator.cc b/daemon/identifier_generator.cc index 29db60fad..706be5f3f 100644 --- a/daemon/identifier_generator.cc +++ b/daemon/identifier_generator.cc @@ -41,7 +41,7 @@ using hyperdex::region_id; const region_id identifier_generator::defaultri; identifier_generator :: identifier_generator() - : m_generators() + : m_generators() { } @@ -50,74 +50,62 @@ identifier_generator :: ~identifier_generator() throw () } bool -identifier_generator :: bump(const region_id& ri, uint64_t id) +identifier_generator :: bump(const region_id &ri, uint64_t id) { - uint64_t* val = NULL; - - if (!m_generators.mod(ri, &val)) - { - return false; - } - - uint64_t count = load_64_nobarrier(val); - - while (count <= id) - { - count = e::atomic::compare_and_swap_64_nobarrier(val, count, id + 1); - } - - return true; + uint64_t *val = NULL; + if (!m_generators.mod(ri, &val)) + { + return false; + } + uint64_t count = load_64_nobarrier(val); + while (count <= id) + { + count = e::atomic::compare_and_swap_64_nobarrier(val, count, id + 1); + } + return true; } uint64_t -identifier_generator :: peek(const region_id& ri) const +identifier_generator :: peek(const region_id &ri) const { - e::atomic::memory_barrier(); - uint64_t val = 0; - - if (!m_generators.get(ri, &val)) - { - abort(); - } - - return val; + e::atomic::memory_barrier(); + uint64_t val = 0; + if (!m_generators.get(ri, &val)) + { + abort(); + } + return val; } uint64_t -identifier_generator :: generate_id(const region_id& ri) +identifier_generator :: generate_id(const region_id &ri) { - uint64_t* val = NULL; - - if (!m_generators.mod(ri, &val)) - { - abort(); - } - - return e::atomic::increment_64_nobarrier(val, 1) - 1; + uint64_t *val = NULL; + if (!m_generators.mod(ri, &val)) + { + abort(); + } + return e::atomic::increment_64_nobarrier(val, 1) - 1; } void -identifier_generator :: adopt(region_id* ris, size_t ris_sz) +identifier_generator :: adopt(region_id *ris, size_t ris_sz) { - generator_map_t new_generators; - - for (size_t i = 0; i < ris_sz; ++i) - { - uint64_t count = 0; - - if (!m_generators.get(ris[i], &count)) - { - count = 1; - } - - new_generators.put(ris[i], count); - } - - m_generators.swap(&new_generators); + generator_map_t new_generators; + for (size_t i = 0; i < ris_sz; ++i) + { + uint64_t count = 0; + if (!m_generators.get(ris[i], &count)) + { + count = 1; + } + new_generators.put(ris[i], count); + } + m_generators.swap(&new_generators); } void -identifier_generator :: copy_from(const identifier_generator& ig) +identifier_generator :: copy_from(const identifier_generator &ig) { - m_generators.copy_from(ig.m_generators); + m_generators.copy_from(ig.m_generators); } diff --git a/daemon/identifier_generator.h b/daemon/identifier_generator.h index 7643c42d9..0153e6769 100644 --- a/daemon/identifier_generator.h +++ b/daemon/identifier_generator.h @@ -39,36 +39,36 @@ BEGIN_HYPERDEX_NAMESPACE class identifier_generator { - public: - identifier_generator(); - ~identifier_generator() throw (); +public: + identifier_generator(); + ~identifier_generator() throw (); - // concurrent methods - // these methods return "true" if ri is a managed region_id, else "false" - public: - // ensure that new identifiers are strictly greater than "id" - bool bump(const region_id& ri, uint64_t id); - // look at the next identifier, and store it in "id" - uint64_t peek(const region_id& ri) const; - // generate one unique identifier, and store it in "id" - uint64_t generate_id(const region_id& ri); + // concurrent methods + // these methods return "true" if ri is a managed region_id, else "false" +public: + // ensure that new identifiers are strictly greater than "id" + bool bump(const region_id &ri, uint64_t id); + // look at the next identifier, and store it in "id" + uint64_t peek(const region_id &ri) const; + // generate one unique identifier, and store it in "id" + uint64_t generate_id(const region_id &ri); - // external synchronization required; nothing can call other methods during - // adopt; copy_from must be mutually exclusive with adopt on either - // generator, and mutually exclusive with all on this generator - public: - void adopt(region_id* ris, size_t ris_sz); - void copy_from(const identifier_generator&); + // external synchronization required; nothing can call other methods during + // adopt; copy_from must be mutually exclusive with adopt on either + // generator, and mutually exclusive with all on this generator +public: + void adopt(region_id *ris, size_t ris_sz); + void copy_from(const identifier_generator &); - private: - identifier_generator(const identifier_generator&); - identifier_generator& operator = (const identifier_generator&); - static uint64_t hashid(region_id ri) { return ri.get(); } +private: + identifier_generator(const identifier_generator &); + identifier_generator &operator = (const identifier_generator &); + static uint64_t hashid(region_id ri) { return ri.get(); } - private: - const static region_id defaultri; - typedef e::ao_hash_map generator_map_t; - generator_map_t m_generators; +private: + const static region_id defaultri; + typedef e::ao_hash_map generator_map_t; + generator_map_t m_generators; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/index_container.cc b/daemon/index_container.cc index 0e2715e8a..310197d88 100644 --- a/daemon/index_container.cc +++ b/daemon/index_container.cc @@ -47,98 +47,91 @@ index_container :: ~index_container() throw () } void -index_container :: index_changes(const index* idx, - const region_id& ri, - const index_encoding* key_ie, - const e::slice& key, - const e::slice* old_value, - const e::slice* new_value, - leveldb::WriteBatch* updates) const +index_container :: index_changes(const index *idx, + const region_id &ri, + const index_encoding *key_ie, + const e::slice &key, + const e::slice *old_value, + const e::slice *new_value, + leveldb::WriteBatch *updates) const { - std::vector old_elems; - std::vector new_elems; - - if (old_value) - { - this->extract_elements(*old_value, &old_elems); - } - - if (new_value) - { - this->extract_elements(*new_value, &new_elems); - } - - std::sort(old_elems.begin(), old_elems.end()); - std::sort(new_elems.begin(), new_elems.end()); - std::vector::iterator it; - it = std::unique(old_elems.begin(), old_elems.end()); - old_elems.resize(it - old_elems.begin()); - it = std::unique(new_elems.begin(), new_elems.end()); - new_elems.resize(it - new_elems.begin()); - size_t old_idx = 0; - size_t new_idx = 0; - const index_info* ii = this->element_index_info(); - - while (old_idx < old_elems.size() && - new_idx < new_elems.size()) - { - if (old_elems[old_idx] == new_elems[new_idx]) - { - ii->index_changes(idx, ri, key_ie, key, - &old_elems[old_idx], &new_elems[new_idx], - updates); - ++old_idx; - ++new_idx; - } - else if (old_elems[old_idx] < new_elems[new_idx]) - { - ii->index_changes(idx, ri, key_ie, key, - &old_elems[old_idx], NULL, updates); - ++old_idx; - } - else if (old_elems[old_idx] > new_elems[new_idx]) - { - ii->index_changes(idx, ri, key_ie, key, - NULL, &new_elems[new_idx], updates); - ++new_idx; - } - } - - while (old_idx < old_elems.size()) - { - ii->index_changes(idx, ri, key_ie, key, - &old_elems[old_idx], NULL, updates); - ++old_idx; - } - - while (new_idx < new_elems.size()) - { - ii->index_changes(idx, ri, key_ie, key, - NULL, &new_elems[new_idx], updates); - ++new_idx; - } + std::vector old_elems; + std::vector new_elems; + if (old_value) + { + this->extract_elements(*old_value, &old_elems); + } + if (new_value) + { + this->extract_elements(*new_value, &new_elems); + } + std::sort(old_elems.begin(), old_elems.end()); + std::sort(new_elems.begin(), new_elems.end()); + std::vector::iterator it; + it = std::unique(old_elems.begin(), old_elems.end()); + old_elems.resize(it - old_elems.begin()); + it = std::unique(new_elems.begin(), new_elems.end()); + new_elems.resize(it - new_elems.begin()); + size_t old_idx = 0; + size_t new_idx = 0; + const index_info *ii = this->element_index_info(); + while (old_idx < old_elems.size() && + new_idx < new_elems.size()) + { + if (old_elems[old_idx] == new_elems[new_idx]) + { + ii->index_changes(idx, ri, key_ie, key, + &old_elems[old_idx], &new_elems[new_idx], + updates); + ++old_idx; + ++new_idx; + } + else if (old_elems[old_idx] < new_elems[new_idx]) + { + ii->index_changes(idx, ri, key_ie, key, + &old_elems[old_idx], NULL, updates); + ++old_idx; + } + else if (old_elems[old_idx] > new_elems[new_idx]) + { + ii->index_changes(idx, ri, key_ie, key, + NULL, &new_elems[new_idx], updates); + ++new_idx; + } + } + while (old_idx < old_elems.size()) + { + ii->index_changes(idx, ri, key_ie, key, + &old_elems[old_idx], NULL, updates); + ++old_idx; + } + while (new_idx < new_elems.size()) + { + ii->index_changes(idx, ri, key_ie, key, + NULL, &new_elems[new_idx], updates); + ++new_idx; + } } -datalayer::index_iterator* +datalayer::index_iterator * index_container :: iterator_from_check(leveldb_snapshot_ptr snap, - const region_id& ri, - const index_id& ii, - const attribute_check& c, - const index_encoding* key_ie) const + const region_id &ri, + const index_id &ii, + const attribute_check &c, + const index_encoding *key_ie) const { - if (c.predicate == HYPERPREDICATE_CONTAINS && - c.datatype == this->element_datatype_info()->datatype()) - { - range r; - r.attr = c.attr; - r.type = c.datatype; - r.start = c.value; - r.end = c.value; - r.has_start = true; - r.has_end = true; - r.invalid = false; - return this->element_index_info()->iterator_from_range(snap, ri, ii, r, key_ie); - } - - return NULL; + if (c.predicate == HYPERPREDICATE_CONTAINS && + c.datatype == this->element_datatype_info()->datatype()) + { + range r; + r.attr = c.attr; + r.type = c.datatype; + r.start = c.value; + r.end = c.value; + r.has_start = true; + r.has_end = true; + r.invalid = false; + return this->element_index_info()->iterator_from_range(snap, ri, ii, r, key_ie); + } + return NULL; } diff --git a/daemon/index_container.h b/daemon/index_container.h index d789b770b..e22d42475 100644 --- a/daemon/index_container.h +++ b/daemon/index_container.h @@ -36,29 +36,29 @@ BEGIN_HYPERDEX_NAMESPACE class index_container : public index_info { - protected: - index_container(); - virtual ~index_container() throw (); +protected: + index_container(); + virtual ~index_container() throw (); - public: - virtual void index_changes(const index* idx, - const region_id& ri, - const index_encoding* key_ie, - const e::slice& key, - const e::slice* old_value, - const e::slice* new_value, - leveldb::WriteBatch* updates) const; - virtual datalayer::index_iterator* iterator_from_check(leveldb_snapshot_ptr snap, - const region_id& ri, - const index_id& ii, - const attribute_check& c, - const index_encoding* key_ie) const; +public: + virtual void index_changes(const index *idx, + const region_id &ri, + const index_encoding *key_ie, + const e::slice &key, + const e::slice *old_value, + const e::slice *new_value, + leveldb::WriteBatch *updates) const; + virtual datalayer::index_iterator *iterator_from_check(leveldb_snapshot_ptr snap, + const region_id &ri, + const index_id &ii, + const attribute_check &c, + const index_encoding *key_ie) const; - private: - virtual void extract_elements(const e::slice& container, - std::vector* elems) const = 0; - virtual const datatype_info* element_datatype_info() const = 0; - virtual const index_info* element_index_info() const = 0; +private: + virtual void extract_elements(const e::slice &container, + std::vector *elems) const = 0; + virtual const datatype_info *element_datatype_info() const = 0; + virtual const index_info *element_index_info() const = 0; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/index_document.cc b/daemon/index_document.cc index 886455afe..2b88c4b90 100644 --- a/daemon/index_document.cc +++ b/daemon/index_document.cc @@ -42,11 +42,11 @@ using hyperdex::index_document; using hyperdex::index_encoding_document; -inline leveldb::Slice e2level(const e::slice& s) { return leveldb::Slice(reinterpret_cast(s.data()), s.size()); } -inline e::slice level2e(const leveldb::Slice& s) { return e::slice(s.data(), s.size()); } +inline leveldb::Slice e2level(const e::slice &s) { return leveldb::Slice(reinterpret_cast(s.data()), s.size()); } +inline e::slice level2e(const leveldb::Slice &s) { return e::slice(s.data(), s.size()); } index_document :: index_document() - : m_di() + : m_di() { } @@ -57,409 +57,374 @@ index_document :: ~index_document() throw () hyperdatatype index_document :: datatype() const { - return HYPERDATATYPE_DOCUMENT; + return HYPERDATATYPE_DOCUMENT; } void -index_document :: index_changes(const index* idx, - const region_id& ri, - const index_encoding* key_ie, - const e::slice& key, - const e::slice* old_document, - const e::slice* new_document, - leveldb::WriteBatch* updates) const +index_document :: index_changes(const index *idx, + const region_id &ri, + const index_encoding *key_ie, + const e::slice &key, + const e::slice *old_document, + const e::slice *new_document, + leveldb::WriteBatch *updates) const { - type_t t; - std::vector scratch_value; - e::slice value; - std::vector scratch_entry; - e::slice entry; - - if (old_document && new_document && *old_document == *new_document) - { - return; - } - - if (old_document && parse_path(idx, *old_document, &t, &scratch_value, &value)) - { - index_entry(ri, idx->id, t, key_ie, key, value, &scratch_entry, &entry); - updates->Delete(leveldb::Slice(reinterpret_cast(entry.data()), entry.size())); - } - - if (new_document && parse_path(idx, *new_document, &t, &scratch_value, &value)) - { - index_entry(ri, idx->id, t, key_ie, key, value, &scratch_entry, &entry); - updates->Put(leveldb::Slice(reinterpret_cast(entry.data()), entry.size()), leveldb::Slice()); - } + type_t t; + std::vector scratch_value; + e::slice value; + std::vector scratch_entry; + e::slice entry; + if (old_document && new_document && *old_document == *new_document) + { + return; + } + if (old_document && parse_path(idx, *old_document, &t, &scratch_value, &value)) + { + index_entry(ri, idx->id, t, key_ie, key, value, &scratch_entry, &entry); + updates->Delete(leveldb::Slice(reinterpret_cast(entry.data()), entry.size())); + } + if (new_document && parse_path(idx, *new_document, &t, &scratch_value, &value)) + { + index_entry(ri, idx->id, t, key_ie, key, value, &scratch_entry, &entry); + updates->Put(leveldb::Slice(reinterpret_cast(entry.data()), entry.size()), leveldb::Slice()); + } } -hyperdex::datalayer::index_iterator* +hyperdex::datalayer::index_iterator * index_document :: iterator_from_check(leveldb_snapshot_ptr snap, - const region_id& ri, - const index_id& ii, - const attribute_check& check, - const index_encoding* key_ie) const + const region_id &ri, + const index_id &ii, + const attribute_check &check, + const index_encoding *key_ie) const { - const char* path = reinterpret_cast(check.value.data()); - size_t path_sz = strnlen(path, check.value.size()); - - if (path_sz >= check.value.size()) - { - return NULL; - } - - if (check.datatype != HYPERDATATYPE_STRING && - check.datatype != HYPERDATATYPE_INT64 && - check.datatype != HYPERDATATYPE_FLOAT && - check.datatype != HYPERDATATYPE_DOCUMENT) - { - return NULL; - } - - char scratch_v[sizeof(int64_t) + sizeof(double)]; - e::slice value(path + path_sz + 1, check.value.size() - path_sz - 1); - - if (check.datatype == HYPERDATATYPE_INT64) - { - memset(scratch_v, 0, sizeof(int64_t)); - memmove(scratch_v, value.data(), std::min(value.size(), sizeof(int64_t))); - int64_t val_i; - e::unpack64le(scratch_v, &val_i); - double val_d = val_i; - e::pack64le(val_d, scratch_v); - value = e::slice(scratch_v, sizeof(double)); - } - - size_t range_prefix_sz = index_entry_prefix_size(ri, ii); - std::vector scratch_a; - std::vector scratch_b; - e::slice a; - e::slice b; - e::slice start; - e::slice limit; - bool has_start; - bool has_limit; - - type_t t; - - if(check.datatype == HYPERDATATYPE_STRING) - { - t = STRING; - } - else if(check.datatype == HYPERDATATYPE_DOCUMENT) - { - if(check.predicate != HYPERPREDICATE_EQUALS) - { - return NULL; - } - - t = DOCUMENT; - } - else - { - t = NUMBER; - } - - index_entry(ri, ii, t, value, &scratch_a, &a); - index_entry(ri, ii, t, &scratch_b, &b); - - switch (check.predicate) - { - case HYPERPREDICATE_EQUALS: - start = a; - limit = a; - break; - case HYPERPREDICATE_LESS_THAN: - case HYPERPREDICATE_LESS_EQUAL: - start = b; - limit = a; - break; - case HYPERPREDICATE_GREATER_EQUAL: - case HYPERPREDICATE_GREATER_THAN: - start = a; - limit = b; - break; - case HYPERPREDICATE_FAIL: - case HYPERPREDICATE_CONTAINS_LESS_THAN: - case HYPERPREDICATE_REGEX: - case HYPERPREDICATE_LENGTH_EQUALS: - case HYPERPREDICATE_LENGTH_LESS_EQUAL: - case HYPERPREDICATE_LENGTH_GREATER_EQUAL: - case HYPERPREDICATE_CONTAINS: - default: - return NULL; - } - - const index_encoding* ie = lookup_encoding(t); - - has_start = a.data() == start.data(); - has_limit = a.data() == limit.data(); - return new datalayer::range_index_iterator(snap, range_prefix_sz, - start, limit, - has_start, has_limit, - ie, key_ie); + const char *path = reinterpret_cast(check.value.data()); + size_t path_sz = strnlen(path, check.value.size()); + if (path_sz >= check.value.size()) + { + return NULL; + } + if (check.datatype != HYPERDATATYPE_STRING && + check.datatype != HYPERDATATYPE_INT64 && + check.datatype != HYPERDATATYPE_FLOAT && + check.datatype != HYPERDATATYPE_DOCUMENT) + { + return NULL; + } + char scratch_v[sizeof(int64_t) + sizeof(double)]; + e::slice value(path + path_sz + 1, check.value.size() - path_sz - 1); + if (check.datatype == HYPERDATATYPE_INT64) + { + memset(scratch_v, 0, sizeof(int64_t)); + memmove(scratch_v, value.data(), std::min(value.size(), sizeof(int64_t))); + int64_t val_i; + e::unpack64le(scratch_v, &val_i); + double val_d = val_i; + e::pack64le(val_d, scratch_v); + value = e::slice(scratch_v, sizeof(double)); + } + size_t range_prefix_sz = index_entry_prefix_size(ri, ii); + std::vector scratch_a; + std::vector scratch_b; + e::slice a; + e::slice b; + e::slice start; + e::slice limit; + bool has_start; + bool has_limit; + type_t t; + if (check.datatype == HYPERDATATYPE_STRING) + { + t = STRING; + } + else if (check.datatype == HYPERDATATYPE_DOCUMENT) + { + if (check.predicate != HYPERPREDICATE_EQUALS) + { + return NULL; + } + t = DOCUMENT; + } + else + { + t = NUMBER; + } + index_entry(ri, ii, t, value, &scratch_a, &a); + index_entry(ri, ii, t, &scratch_b, &b); + switch (check.predicate) + { + case HYPERPREDICATE_EQUALS: + start = a; + limit = a; + break; + case HYPERPREDICATE_LESS_THAN: + case HYPERPREDICATE_LESS_EQUAL: + start = b; + limit = a; + break; + case HYPERPREDICATE_GREATER_EQUAL: + case HYPERPREDICATE_GREATER_THAN: + start = a; + limit = b; + break; + case HYPERPREDICATE_FAIL: + case HYPERPREDICATE_CONTAINS_LESS_THAN: + case HYPERPREDICATE_REGEX: + case HYPERPREDICATE_LENGTH_EQUALS: + case HYPERPREDICATE_LENGTH_LESS_EQUAL: + case HYPERPREDICATE_LENGTH_GREATER_EQUAL: + case HYPERPREDICATE_CONTAINS: + default: + return NULL; + } + const index_encoding *ie = lookup_encoding(t); + has_start = a.data() == start.data(); + has_limit = a.data() == limit.data(); + return new datalayer::range_index_iterator(snap, range_prefix_sz, + start, limit, + has_start, has_limit, + ie, key_ie); } -const hyperdex::index_encoding* +const hyperdex::index_encoding * index_document :: lookup_encoding(type_t t) const { - switch (t) - { - case STRING: - return index_encoding::lookup(HYPERDATATYPE_STRING); - case NUMBER: - return index_encoding::lookup(HYPERDATATYPE_FLOAT); - case DOCUMENT: - return index_encoding::lookup(HYPERDATATYPE_DOCUMENT); - default: - abort(); - } - - return NULL; + switch (t) + { + case STRING: + return index_encoding::lookup(HYPERDATATYPE_STRING); + case NUMBER: + return index_encoding::lookup(HYPERDATATYPE_FLOAT); + case DOCUMENT: + return index_encoding::lookup(HYPERDATATYPE_DOCUMENT); + default: + abort(); + } + return NULL; } bool -index_document :: parse_path(const index* idx, - const e::slice& document, - type_t* t, - std::vector* scratch, - e::slice* value) const +index_document :: parse_path(const index *idx, + const e::slice &document, + type_t *t, + std::vector *scratch, + e::slice *value) const { - hyperdatatype type; - - if (m_di.extract_value(idx->extra.cdata(), document, &type, scratch, value)) - { - if (type == HYPERDATATYPE_STRING) - { - *t = STRING; - return true; - } - else if (type == HYPERDATATYPE_INT64 || type == HYPERDATATYPE_FLOAT) - { - *t = NUMBER; - return true; - } - else if (type == HYPERDATATYPE_DOCUMENT) - { - *t = DOCUMENT; - return true; - } - } - - return false; + hyperdatatype type; + if (m_di.extract_value(idx->extra.cdata(), document, &type, scratch, value)) + { + if (type == HYPERDATATYPE_STRING) + { + *t = STRING; + return true; + } + else if (type == HYPERDATATYPE_INT64 || type == HYPERDATATYPE_FLOAT) + { + *t = NUMBER; + return true; + } + else if (type == HYPERDATATYPE_DOCUMENT) + { + *t = DOCUMENT; + return true; + } + } + return false; } size_t -index_document :: index_entry_prefix_size(const region_id& ri, const index_id& ii) const +index_document :: index_entry_prefix_size(const region_id &ri, const index_id &ii) const { - return sizeof(uint8_t) - + e::varint_length(ri.get()) - + e::varint_length(ii.get()) - + sizeof(uint8_t); + return sizeof(uint8_t) + + e::varint_length(ri.get()) + + e::varint_length(ii.get()) + + sizeof(uint8_t); } void -index_document :: index_entry(const region_id& ri, - const index_id& ii, +index_document :: index_entry(const region_id &ri, + const index_id &ii, type_t t, - std::vector* scratch, - e::slice* slice) const + std::vector *scratch, + e::slice *slice) const { - size_t sz = sizeof(uint8_t) - + e::varint_length(ri.get()) - + e::varint_length(ii.get()) - + sizeof(uint8_t); - - if (scratch->size() < sz) - { - scratch->resize(sz); - } - - uint8_t t8; - if(t == STRING) - { - t8 = 's'; - } - else if(t == NUMBER) - { - t8 = 'i'; - } - else - { - t8 = 'd'; - } - - char* ptr = &scratch->front(); - ptr = e::pack8be('i', ptr); - ptr = e::packvarint64(ri.get(), ptr); - ptr = e::packvarint64(ii.get(), ptr); - ptr = e::pack8be(t8, ptr); - assert(ptr == &scratch->front() + sz); - *slice = e::slice(&scratch->front(), sz); + size_t sz = sizeof(uint8_t) + + e::varint_length(ri.get()) + + e::varint_length(ii.get()) + + sizeof(uint8_t); + if (scratch->size() < sz) + { + scratch->resize(sz); + } + uint8_t t8; + if (t == STRING) + { + t8 = 's'; + } + else if (t == NUMBER) + { + t8 = 'i'; + } + else + { + t8 = 'd'; + } + char *ptr = &scratch->front(); + ptr = e::pack8be('i', ptr); + ptr = e::packvarint64(ri.get(), ptr); + ptr = e::packvarint64(ii.get(), ptr); + ptr = e::pack8be(t8, ptr); + assert(ptr == &scratch->front() + sz); + *slice = e::slice(&scratch->front(), sz); } void -index_document :: index_entry(const region_id& ri, - const index_id& ii, +index_document :: index_entry(const region_id &ri, + const index_id &ii, type_t t, - const e::slice& value, - std::vector* scratch, - e::slice* slice) const + const e::slice &value, + std::vector *scratch, + e::slice *slice) const { - const index_encoding* val_ie = lookup_encoding(t); - - size_t val_sz = val_ie->encoded_size(value); - size_t sz = sizeof(uint8_t) - + e::varint_length(ri.get()) - + e::varint_length(ii.get()) - + sizeof(uint8_t) - + val_sz; - - if (scratch->size() < sz) - { - scratch->resize(sz); - } - - uint8_t t8; - if(t == STRING) - { - t8 = 's'; - } - else if(t == NUMBER) - { - t8 = 'i'; - } - else - { - t8 = 'd'; - } - - char* ptr = &scratch->front(); - ptr = e::pack8be('i', ptr); - ptr = e::packvarint64(ri.get(), ptr); - ptr = e::packvarint64(ii.get(), ptr); - ptr = e::pack8be(t8, ptr); - ptr = val_ie->encode(value, ptr); - assert(ptr == &scratch->front() + sz); - *slice = e::slice(&scratch->front(), sz); + const index_encoding *val_ie = lookup_encoding(t); + size_t val_sz = val_ie->encoded_size(value); + size_t sz = sizeof(uint8_t) + + e::varint_length(ri.get()) + + e::varint_length(ii.get()) + + sizeof(uint8_t) + + val_sz; + if (scratch->size() < sz) + { + scratch->resize(sz); + } + uint8_t t8; + if (t == STRING) + { + t8 = 's'; + } + else if (t == NUMBER) + { + t8 = 'i'; + } + else + { + t8 = 'd'; + } + char *ptr = &scratch->front(); + ptr = e::pack8be('i', ptr); + ptr = e::packvarint64(ri.get(), ptr); + ptr = e::packvarint64(ii.get(), ptr); + ptr = e::pack8be(t8, ptr); + ptr = val_ie->encode(value, ptr); + assert(ptr == &scratch->front() + sz); + *slice = e::slice(&scratch->front(), sz); } -hyperdex::datalayer::index_iterator* +hyperdex::datalayer::index_iterator * index_document :: iterator_for_keys(leveldb_snapshot_ptr snap, - const region_id& ri) const + const region_id &ri) const { - range scan; - scan.attr = 0; - scan.type = HYPERDATATYPE_DOCUMENT; - scan.has_start = false; - scan.has_end = false; - scan.invalid = false; - const index_encoding* ie = index_encoding::lookup(scan.type); - return iterator_key(snap, ri, scan, ie); + range scan; + scan.attr = 0; + scan.type = HYPERDATATYPE_DOCUMENT; + scan.has_start = false; + scan.has_end = false; + scan.invalid = false; + const index_encoding *ie = index_encoding::lookup(scan.type); + return iterator_key(snap, ri, scan, ie); } -hyperdex::datalayer::index_iterator* +hyperdex::datalayer::index_iterator * index_document :: iterator_key(leveldb_snapshot_ptr snap, - const region_id& ri, - const range& r, - const index_encoding* key_ie) const + const region_id &ri, + const range &r, + const index_encoding *key_ie) const { - std::vector scratch_start; - std::vector scratch_limit; - e::slice start; - e::slice limit; - - size_t range_prefix_sz = object_prefix_sz(ri); - - if (r.has_start) - { - leveldb::Slice _start; - encode_key(ri, r.type, r.start, &scratch_start, &_start); - start = level2e(_start); - } - else - { - leveldb::Slice _start; - encode_object_region(ri, &scratch_start, &_start); - start = level2e(_start); - } - - if (r.has_end) - { - leveldb::Slice _limit; - encode_key(ri, r.type, r.end, &scratch_limit, &_limit); - limit = level2e(_limit); - } - else - { - leveldb::Slice _limit; - encode_object_region(ri, &scratch_limit, &_limit); - limit = level2e(_limit); - } - - return new hyperdex::datalayer::range_index_iterator(snap, range_prefix_sz, - start, limit, - r.has_start, r.has_end, - NULL, key_ie); + std::vector scratch_start; + std::vector scratch_limit; + e::slice start; + e::slice limit; + size_t range_prefix_sz = object_prefix_sz(ri); + if (r.has_start) + { + leveldb::Slice _start; + encode_key(ri, r.type, r.start, &scratch_start, &_start); + start = level2e(_start); + } + else + { + leveldb::Slice _start; + encode_object_region(ri, &scratch_start, &_start); + start = level2e(_start); + } + if (r.has_end) + { + leveldb::Slice _limit; + encode_key(ri, r.type, r.end, &scratch_limit, &_limit); + limit = level2e(_limit); + } + else + { + leveldb::Slice _limit; + encode_object_region(ri, &scratch_limit, &_limit); + limit = level2e(_limit); + } + return new hyperdex::datalayer::range_index_iterator(snap, range_prefix_sz, + start, limit, + r.has_start, r.has_end, + NULL, key_ie); } void -index_document :: index_entry(const region_id& ri, - const index_id& ii, +index_document :: index_entry(const region_id &ri, + const index_id &ii, type_t t, - const index_encoding* key_ie, - const e::slice& key, - const e::slice& value, - std::vector* scratch, - e::slice* slice) const + const index_encoding *key_ie, + const e::slice &key, + const e::slice &value, + std::vector *scratch, + e::slice *slice) const { - const index_encoding* val_ie = lookup_encoding(t); - - size_t key_sz = key_ie->encoded_size(key); - size_t val_sz = val_ie->encoded_size(value); - bool variable = !key_ie->encoding_fixed() && !val_ie->encoding_fixed(); - size_t sz = sizeof(uint8_t) - + e::varint_length(ri.get()) - + e::varint_length(ii.get()) - + sizeof(uint8_t) - + val_sz - + key_sz - + (variable ? sizeof(uint32_t) : 0); - - if (scratch->size() < sz) - { - scratch->resize(sz); - } - - uint8_t t8; - if(t == STRING) - { - t8 = 's'; - } - else if(t == NUMBER) - { - t8 = 'i'; - } - else - { - t8 = 'd'; - } - - char* ptr = &scratch->front(); - ptr = e::pack8be('i', ptr); - ptr = e::packvarint64(ri.get(), ptr); - ptr = e::packvarint64(ii.get(), ptr); - ptr = e::pack8be(t8, ptr); - ptr = val_ie->encode(value, ptr); - ptr = key_ie->encode(key, ptr); - - if (variable) - { - ptr = e::pack32be(key_sz, ptr); - } - - assert(ptr == &scratch->front() + sz); - *slice = e::slice(&scratch->front(), sz); + const index_encoding *val_ie = lookup_encoding(t); + size_t key_sz = key_ie->encoded_size(key); + size_t val_sz = val_ie->encoded_size(value); + bool variable = !key_ie->encoding_fixed() && !val_ie->encoding_fixed(); + size_t sz = sizeof(uint8_t) + + e::varint_length(ri.get()) + + e::varint_length(ii.get()) + + sizeof(uint8_t) + + val_sz + + key_sz + + (variable ? sizeof(uint32_t) : 0); + if (scratch->size() < sz) + { + scratch->resize(sz); + } + uint8_t t8; + if (t == STRING) + { + t8 = 's'; + } + else if (t == NUMBER) + { + t8 = 'i'; + } + else + { + t8 = 'd'; + } + char *ptr = &scratch->front(); + ptr = e::pack8be('i', ptr); + ptr = e::packvarint64(ri.get(), ptr); + ptr = e::packvarint64(ii.get(), ptr); + ptr = e::pack8be(t8, ptr); + ptr = val_ie->encode(value, ptr); + ptr = key_ie->encode(key, ptr); + if (variable) + { + ptr = e::pack32be(key_sz, ptr); + } + assert(ptr == &scratch->front() + sz); + *slice = e::slice(&scratch->front(), sz); } index_encoding_document :: index_encoding_document() @@ -473,31 +438,31 @@ index_encoding_document :: ~index_encoding_document() throw () bool index_encoding_document :: encoding_fixed() const { - return false; + return false; } size_t -index_encoding_document :: encoded_size(const e::slice& decoded) const +index_encoding_document :: encoded_size(const e::slice &decoded) const { - return decoded.size(); + return decoded.size(); } -char* -index_encoding_document :: encode(const e::slice& decoded, char* encoded) const +char * +index_encoding_document :: encode(const e::slice &decoded, char *encoded) const { - memmove(encoded, decoded.data(), decoded.size()); - return encoded + decoded.size(); + memmove(encoded, decoded.data(), decoded.size()); + return encoded + decoded.size(); } size_t -index_encoding_document :: decoded_size(const e::slice& encoded) const +index_encoding_document :: decoded_size(const e::slice &encoded) const { - return encoded.size(); + return encoded.size(); } -char* -index_encoding_document :: decode(const e::slice& encoded, char* decoded) const +char * +index_encoding_document :: decode(const e::slice &encoded, char *decoded) const { - memmove(decoded, encoded.data(), encoded.size()); - return decoded + encoded.size(); + memmove(decoded, encoded.data(), encoded.size()); + return decoded + encoded.size(); } diff --git a/daemon/index_document.h b/daemon/index_document.h index a09264261..4c5c1b6c2 100644 --- a/daemon/index_document.h +++ b/daemon/index_document.h @@ -37,78 +37,78 @@ BEGIN_HYPERDEX_NAMESPACE class index_document : public index_info { - public: - index_document(); - virtual ~index_document() throw (); +public: + index_document(); + virtual ~index_document() throw (); - public: - virtual hyperdatatype datatype() const; - virtual void index_changes(const index* idx, - const region_id& ri, - const index_encoding* key_ie, - const e::slice& key, - const e::slice* old_document, - const e::slice* new_document, - leveldb::WriteBatch* updates) const; - virtual datalayer::index_iterator* iterator_from_check(leveldb_snapshot_ptr snap, - const region_id& ri, - const index_id& ii, - const attribute_check& c, - const index_encoding* key_ie) const; - virtual datalayer::index_iterator* iterator_for_keys(leveldb_snapshot_ptr snap, - const region_id& ri) const; +public: + virtual hyperdatatype datatype() const; + virtual void index_changes(const index *idx, + const region_id &ri, + const index_encoding *key_ie, + const e::slice &key, + const e::slice *old_document, + const e::slice *new_document, + leveldb::WriteBatch *updates) const; + virtual datalayer::index_iterator *iterator_from_check(leveldb_snapshot_ptr snap, + const region_id &ri, + const index_id &ii, + const attribute_check &c, + const index_encoding *key_ie) const; + virtual datalayer::index_iterator *iterator_for_keys(leveldb_snapshot_ptr snap, + const region_id &ri) const; - private: - enum type_t { STRING, NUMBER, DOCUMENT }; - bool parse_path(const index* idx, - const e::slice& document, - type_t* t, - std::vector* scratch, - e::slice* value) const; - size_t index_entry_prefix_size(const region_id& ri, const index_id& ii) const; - void index_entry(const region_id& ri, - const index_id& ii, - type_t t, - std::vector* scratch, - e::slice* slice) const; - void index_entry(const region_id& ri, - const index_id& ii, - type_t t, - const e::slice& value, - std::vector* scratch, - e::slice* slice) const; - void index_entry(const region_id& ri, - const index_id& ii, - type_t t, - const index_encoding* key_ie, - const e::slice& key, - const e::slice& value, - std::vector* scratch, - e::slice* slice) const; +private: + enum type_t { STRING, NUMBER, DOCUMENT }; + bool parse_path(const index *idx, + const e::slice &document, + type_t *t, + std::vector *scratch, + e::slice *value) const; + size_t index_entry_prefix_size(const region_id &ri, const index_id &ii) const; + void index_entry(const region_id &ri, + const index_id &ii, + type_t t, + std::vector *scratch, + e::slice *slice) const; + void index_entry(const region_id &ri, + const index_id &ii, + type_t t, + const e::slice &value, + std::vector *scratch, + e::slice *slice) const; + void index_entry(const region_id &ri, + const index_id &ii, + type_t t, + const index_encoding *key_ie, + const e::slice &key, + const e::slice &value, + std::vector *scratch, + e::slice *slice) const; - datalayer::index_iterator* iterator_key(leveldb_snapshot_ptr snap, - const region_id& ri, - const range& r, - const index_encoding* key_ie) const; + datalayer::index_iterator *iterator_key(leveldb_snapshot_ptr snap, + const region_id &ri, + const range &r, + const index_encoding *key_ie) const; - const index_encoding* lookup_encoding(type_t t) const; + const index_encoding *lookup_encoding(type_t t) const; - private: - const datatype_document m_di; +private: + const datatype_document m_di; }; class index_encoding_document : public index_encoding { - public: - index_encoding_document(); - virtual ~index_encoding_document() throw (); +public: + index_encoding_document(); + virtual ~index_encoding_document() throw (); - public: - virtual bool encoding_fixed() const; - virtual size_t encoded_size(const e::slice& decoded) const; - virtual char* encode(const e::slice& decoded, char* encoded) const; - virtual size_t decoded_size(const e::slice& encoded) const; - virtual char* decode(const e::slice& encoded, char* decoded) const; +public: + virtual bool encoding_fixed() const; + virtual size_t encoded_size(const e::slice &decoded) const; + virtual char *encode(const e::slice &decoded, char *encoded) const; + virtual size_t decoded_size(const e::slice &encoded) const; + virtual char *decode(const e::slice &encoded, char *decoded) const; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/index_float.cc b/daemon/index_float.cc index 2aad97e6d..9dffccd44 100644 --- a/daemon/index_float.cc +++ b/daemon/index_float.cc @@ -38,7 +38,7 @@ using hyperdex::index_float; using hyperdex::index_encoding_float; index_float :: index_float() - : index_primitive(index_encoding::lookup(HYPERDATATYPE_FLOAT)) + : index_primitive(index_encoding::lookup(HYPERDATATYPE_FLOAT)) { } @@ -49,7 +49,7 @@ index_float :: ~index_float() throw () hyperdatatype index_float :: datatype() const { - return HYPERDATATYPE_FLOAT; + return HYPERDATATYPE_FLOAT; } index_encoding_float :: index_encoding_float() @@ -63,48 +63,44 @@ index_encoding_float :: ~index_encoding_float() throw () bool index_encoding_float :: encoding_fixed() const { - return true; + return true; } size_t -index_encoding_float :: encoded_size(const e::slice&) const +index_encoding_float :: encoded_size(const e::slice &) const { - // why? - return 2 * sizeof(double); + // why? + return 2 * sizeof(double); } -char* -index_encoding_float :: encode(const e::slice& decoded, char* encoded) const +char * +index_encoding_float :: encode(const e::slice &decoded, char *encoded) const { - datatype_info* di = datatype_info::lookup(HYPERDATATYPE_FLOAT); - double number = 0; - - if (di->validate(decoded) && decoded.size() == sizeof(double)) - { - e::unpackdoublele(decoded.data(), &number); - } - - char* ptr = encoded; - ptr = e::pack64be(di->hash(decoded), ptr); - ptr = e::packdoublele(number, ptr); - return ptr; + datatype_info *di = datatype_info::lookup(HYPERDATATYPE_FLOAT); + double number = 0; + if (di->validate(decoded) && decoded.size() == sizeof(double)) + { + e::unpackdoublele(decoded.data(), &number); + } + char *ptr = encoded; + ptr = e::pack64be(di->hash(decoded), ptr); + ptr = e::packdoublele(number, ptr); + return ptr; } size_t -index_encoding_float :: decoded_size(const e::slice&) const +index_encoding_float :: decoded_size(const e::slice &) const { - return sizeof(double); + return sizeof(double); } -char* -index_encoding_float :: decode(const e::slice& encoded, char* decoded) const +char * +index_encoding_float :: decode(const e::slice &encoded, char *decoded) const { - double number = 0; - - if (encoded.size() == 2 * sizeof(double)) - { - e::unpackdoublele(decoded + sizeof(double), &number); - } - - return e::packdoublele(number, decoded); + double number = 0; + if (encoded.size() == 2 * sizeof(double)) + { + e::unpackdoublele(decoded + sizeof(double), &number); + } + return e::packdoublele(number, decoded); } diff --git a/daemon/index_float.h b/daemon/index_float.h index 7d63e9885..9a5914473 100644 --- a/daemon/index_float.h +++ b/daemon/index_float.h @@ -36,26 +36,26 @@ BEGIN_HYPERDEX_NAMESPACE class index_float : public index_primitive { - public: - index_float(); - virtual ~index_float() throw (); +public: + index_float(); + virtual ~index_float() throw (); - public: - virtual hyperdatatype datatype() const; +public: + virtual hyperdatatype datatype() const; }; class index_encoding_float : public index_encoding { - public: - index_encoding_float(); - virtual ~index_encoding_float() throw (); - - public: - virtual bool encoding_fixed() const; - virtual size_t encoded_size(const e::slice& decoded) const; - virtual char* encode(const e::slice& decoded, char* encoded) const; - virtual size_t decoded_size(const e::slice& encoded) const; - virtual char* decode(const e::slice& encoded, char* decoded) const; +public: + index_encoding_float(); + virtual ~index_encoding_float() throw (); + +public: + virtual bool encoding_fixed() const; + virtual size_t encoded_size(const e::slice &decoded) const; + virtual char *encode(const e::slice &decoded, char *encoded) const; + virtual size_t decoded_size(const e::slice &encoded) const; + virtual char *decode(const e::slice &encoded, char *decoded) const; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/index_info.cc b/daemon/index_info.cc index 44852f2dd..c9901b328 100644 --- a/daemon/index_info.cc +++ b/daemon/index_info.cc @@ -73,54 +73,54 @@ static const hyperdex::index_timestamp i_timestamp_day(HYPERDATATYPE_TIMESTAMP_D static const hyperdex::index_timestamp i_timestamp_week(HYPERDATATYPE_TIMESTAMP_WEEK); static const hyperdex::index_timestamp i_timestamp_month(HYPERDATATYPE_TIMESTAMP_MONTH); -const index_encoding* +const index_encoding * index_encoding :: lookup(hyperdatatype datatype) { - switch (datatype) - { - case HYPERDATATYPE_STRING: - return &e_string; - case HYPERDATATYPE_INT64: - return &e_int64; - case HYPERDATATYPE_FLOAT: - return &e_float; - case HYPERDATATYPE_TIMESTAMP_SECOND: - case HYPERDATATYPE_TIMESTAMP_MINUTE: - case HYPERDATATYPE_TIMESTAMP_HOUR: - case HYPERDATATYPE_TIMESTAMP_DAY: - case HYPERDATATYPE_TIMESTAMP_WEEK: - case HYPERDATATYPE_TIMESTAMP_MONTH: - return &e_timestamp; - case HYPERDATATYPE_DOCUMENT: - return &e_document; - case HYPERDATATYPE_GENERIC: - case HYPERDATATYPE_LIST_GENERIC: - case HYPERDATATYPE_LIST_STRING: - case HYPERDATATYPE_LIST_INT64: - case HYPERDATATYPE_LIST_FLOAT: - case HYPERDATATYPE_SET_GENERIC: - case HYPERDATATYPE_SET_STRING: - case HYPERDATATYPE_SET_INT64: - case HYPERDATATYPE_SET_FLOAT: - case HYPERDATATYPE_MAP_GENERIC: - case HYPERDATATYPE_TIMESTAMP_GENERIC: - case HYPERDATATYPE_MAP_STRING_KEYONLY: - case HYPERDATATYPE_MAP_STRING_STRING: - case HYPERDATATYPE_MAP_STRING_INT64: - case HYPERDATATYPE_MAP_STRING_FLOAT: - case HYPERDATATYPE_MAP_INT64_KEYONLY: - case HYPERDATATYPE_MAP_INT64_STRING: - case HYPERDATATYPE_MAP_INT64_INT64: - case HYPERDATATYPE_MAP_INT64_FLOAT: - case HYPERDATATYPE_MAP_FLOAT_KEYONLY: - case HYPERDATATYPE_MAP_FLOAT_STRING: - case HYPERDATATYPE_MAP_FLOAT_INT64: - case HYPERDATATYPE_MAP_FLOAT_FLOAT: - case HYPERDATATYPE_MACAROON_SECRET: - case HYPERDATATYPE_GARBAGE: - default: - abort(); - } + switch (datatype) + { + case HYPERDATATYPE_STRING: + return &e_string; + case HYPERDATATYPE_INT64: + return &e_int64; + case HYPERDATATYPE_FLOAT: + return &e_float; + case HYPERDATATYPE_TIMESTAMP_SECOND: + case HYPERDATATYPE_TIMESTAMP_MINUTE: + case HYPERDATATYPE_TIMESTAMP_HOUR: + case HYPERDATATYPE_TIMESTAMP_DAY: + case HYPERDATATYPE_TIMESTAMP_WEEK: + case HYPERDATATYPE_TIMESTAMP_MONTH: + return &e_timestamp; + case HYPERDATATYPE_DOCUMENT: + return &e_document; + case HYPERDATATYPE_GENERIC: + case HYPERDATATYPE_LIST_GENERIC: + case HYPERDATATYPE_LIST_STRING: + case HYPERDATATYPE_LIST_INT64: + case HYPERDATATYPE_LIST_FLOAT: + case HYPERDATATYPE_SET_GENERIC: + case HYPERDATATYPE_SET_STRING: + case HYPERDATATYPE_SET_INT64: + case HYPERDATATYPE_SET_FLOAT: + case HYPERDATATYPE_MAP_GENERIC: + case HYPERDATATYPE_TIMESTAMP_GENERIC: + case HYPERDATATYPE_MAP_STRING_KEYONLY: + case HYPERDATATYPE_MAP_STRING_STRING: + case HYPERDATATYPE_MAP_STRING_INT64: + case HYPERDATATYPE_MAP_STRING_FLOAT: + case HYPERDATATYPE_MAP_INT64_KEYONLY: + case HYPERDATATYPE_MAP_INT64_STRING: + case HYPERDATATYPE_MAP_INT64_INT64: + case HYPERDATATYPE_MAP_INT64_FLOAT: + case HYPERDATATYPE_MAP_FLOAT_KEYONLY: + case HYPERDATATYPE_MAP_FLOAT_STRING: + case HYPERDATATYPE_MAP_FLOAT_INT64: + case HYPERDATATYPE_MAP_FLOAT_FLOAT: + case HYPERDATATYPE_MACAROON_SECRET: + case HYPERDATATYPE_GARBAGE: + default: + abort(); + } } index_encoding :: index_encoding() @@ -131,74 +131,74 @@ index_encoding :: ~index_encoding() throw () { } -const index_info* +const index_info * index_info :: lookup(hyperdatatype datatype) { - switch (datatype) - { - case HYPERDATATYPE_STRING: - return &i_string; - case HYPERDATATYPE_INT64: - return &i_int64; - case HYPERDATATYPE_FLOAT: - return &i_float; - case HYPERDATATYPE_TIMESTAMP_SECOND: - return &i_timestamp_second; - case HYPERDATATYPE_TIMESTAMP_MINUTE: - return &i_timestamp_minute; - case HYPERDATATYPE_TIMESTAMP_HOUR: - return &i_timestamp_hour; - case HYPERDATATYPE_TIMESTAMP_DAY: - return &i_timestamp_day; - case HYPERDATATYPE_TIMESTAMP_WEEK: - return &i_timestamp_week; - case HYPERDATATYPE_TIMESTAMP_MONTH: - return &i_timestamp_month; - case HYPERDATATYPE_DOCUMENT: - return &i_document; - case HYPERDATATYPE_LIST_STRING: - return &i_list_string; - case HYPERDATATYPE_LIST_INT64: - return &i_list_int64; - case HYPERDATATYPE_LIST_FLOAT: - return &i_list_float; - case HYPERDATATYPE_SET_STRING: - return &i_set_string; - case HYPERDATATYPE_SET_INT64: - return &i_set_int64; - case HYPERDATATYPE_SET_FLOAT: - return &i_set_float; - case HYPERDATATYPE_MAP_STRING_STRING: - return &i_map_string_string; - case HYPERDATATYPE_MAP_STRING_INT64: - return &i_map_string_int64; - case HYPERDATATYPE_MAP_STRING_FLOAT: - return &i_map_string_float; - case HYPERDATATYPE_MAP_INT64_STRING: - return &i_map_int64_string; - case HYPERDATATYPE_MAP_INT64_INT64: - return &i_map_int64_int64; - case HYPERDATATYPE_MAP_INT64_FLOAT: - return &i_map_int64_float; - case HYPERDATATYPE_MAP_FLOAT_STRING: - return &i_map_float_string; - case HYPERDATATYPE_MAP_FLOAT_INT64: - return &i_map_float_int64; - case HYPERDATATYPE_MAP_FLOAT_FLOAT: - return &i_map_float_float; - case HYPERDATATYPE_GENERIC: - case HYPERDATATYPE_LIST_GENERIC: - case HYPERDATATYPE_SET_GENERIC: - case HYPERDATATYPE_MAP_GENERIC: - case HYPERDATATYPE_MAP_STRING_KEYONLY: - case HYPERDATATYPE_MAP_INT64_KEYONLY: - case HYPERDATATYPE_MAP_FLOAT_KEYONLY: - case HYPERDATATYPE_TIMESTAMP_GENERIC: - case HYPERDATATYPE_MACAROON_SECRET: - case HYPERDATATYPE_GARBAGE: - default: - abort(); - } + switch (datatype) + { + case HYPERDATATYPE_STRING: + return &i_string; + case HYPERDATATYPE_INT64: + return &i_int64; + case HYPERDATATYPE_FLOAT: + return &i_float; + case HYPERDATATYPE_TIMESTAMP_SECOND: + return &i_timestamp_second; + case HYPERDATATYPE_TIMESTAMP_MINUTE: + return &i_timestamp_minute; + case HYPERDATATYPE_TIMESTAMP_HOUR: + return &i_timestamp_hour; + case HYPERDATATYPE_TIMESTAMP_DAY: + return &i_timestamp_day; + case HYPERDATATYPE_TIMESTAMP_WEEK: + return &i_timestamp_week; + case HYPERDATATYPE_TIMESTAMP_MONTH: + return &i_timestamp_month; + case HYPERDATATYPE_DOCUMENT: + return &i_document; + case HYPERDATATYPE_LIST_STRING: + return &i_list_string; + case HYPERDATATYPE_LIST_INT64: + return &i_list_int64; + case HYPERDATATYPE_LIST_FLOAT: + return &i_list_float; + case HYPERDATATYPE_SET_STRING: + return &i_set_string; + case HYPERDATATYPE_SET_INT64: + return &i_set_int64; + case HYPERDATATYPE_SET_FLOAT: + return &i_set_float; + case HYPERDATATYPE_MAP_STRING_STRING: + return &i_map_string_string; + case HYPERDATATYPE_MAP_STRING_INT64: + return &i_map_string_int64; + case HYPERDATATYPE_MAP_STRING_FLOAT: + return &i_map_string_float; + case HYPERDATATYPE_MAP_INT64_STRING: + return &i_map_int64_string; + case HYPERDATATYPE_MAP_INT64_INT64: + return &i_map_int64_int64; + case HYPERDATATYPE_MAP_INT64_FLOAT: + return &i_map_int64_float; + case HYPERDATATYPE_MAP_FLOAT_STRING: + return &i_map_float_string; + case HYPERDATATYPE_MAP_FLOAT_INT64: + return &i_map_float_int64; + case HYPERDATATYPE_MAP_FLOAT_FLOAT: + return &i_map_float_float; + case HYPERDATATYPE_GENERIC: + case HYPERDATATYPE_LIST_GENERIC: + case HYPERDATATYPE_SET_GENERIC: + case HYPERDATATYPE_MAP_GENERIC: + case HYPERDATATYPE_MAP_STRING_KEYONLY: + case HYPERDATATYPE_MAP_INT64_KEYONLY: + case HYPERDATATYPE_MAP_FLOAT_KEYONLY: + case HYPERDATATYPE_TIMESTAMP_GENERIC: + case HYPERDATATYPE_MACAROON_SECRET: + case HYPERDATATYPE_GARBAGE: + default: + abort(); + } } index_info :: index_info() @@ -209,29 +209,29 @@ index_info :: ~index_info() throw () { } -datalayer::index_iterator* +datalayer::index_iterator * index_info :: iterator_for_keys(leveldb_snapshot_ptr, - const region_id&) const + const region_id &) const { - return NULL; + return NULL; } -datalayer::index_iterator* +datalayer::index_iterator * index_info :: iterator_from_range(leveldb_snapshot_ptr, - const region_id&, - const index_id&, - const range&, - const index_encoding*) const + const region_id &, + const index_id &, + const range &, + const index_encoding *) const { - return NULL; + return NULL; } -datalayer::index_iterator* +datalayer::index_iterator * index_info :: iterator_from_check(leveldb_snapshot_ptr, - const region_id&, - const index_id&, - const attribute_check&, - const index_encoding*) const + const region_id &, + const index_id &, + const attribute_check &, + const index_encoding *) const { - return NULL; + return NULL; } diff --git a/daemon/index_info.h b/daemon/index_info.h index 12453c093..e7ca3af34 100644 --- a/daemon/index_info.h +++ b/daemon/index_info.h @@ -46,70 +46,70 @@ BEGIN_HYPERDEX_NAMESPACE class index_encoding { - public: - // return NULL for unencodable type - static const index_encoding* lookup(hyperdatatype datatype); +public: + // return NULL for unencodable type + static const index_encoding *lookup(hyperdatatype datatype); - public: - index_encoding(); - virtual ~index_encoding() throw (); +public: + index_encoding(); + virtual ~index_encoding() throw (); - public: - // is this encoding fixed in size? are encoded_size() and - // decoded_size() invariant of the passed slice? - virtual bool encoding_fixed() const = 0; - // the number of bytes necessary to encode "decoded" - virtual size_t encoded_size(const e::slice& decoded) const = 0; - // write the encoded form of "decoded" to "encoded" which points to at - // least "encoded_size" bytes of memory - virtual char* encode(const e::slice& decoded, char* encoded) const = 0; - // the number of bytes necessary to decode "encoded" - virtual size_t decoded_size(const e::slice& encoded) const = 0; - // write the decoded form of "encoded" to "decoded" which points to at - // least "decoded_size" bytes of memory - virtual char* decode(const e::slice& encoded, char* decoded) const = 0; +public: + // is this encoding fixed in size? are encoded_size() and + // decoded_size() invariant of the passed slice? + virtual bool encoding_fixed() const = 0; + // the number of bytes necessary to encode "decoded" + virtual size_t encoded_size(const e::slice &decoded) const = 0; + // write the encoded form of "decoded" to "encoded" which points to at + // least "encoded_size" bytes of memory + virtual char *encode(const e::slice &decoded, char *encoded) const = 0; + // the number of bytes necessary to decode "encoded" + virtual size_t decoded_size(const e::slice &encoded) const = 0; + // write the decoded form of "encoded" to "decoded" which points to at + // least "decoded_size" bytes of memory + virtual char *decode(const e::slice &encoded, char *decoded) const = 0; }; class index_info { - public: - // return NULL for unindexable type - static const index_info* lookup(hyperdatatype datatype); +public: + // return NULL for unindexable type + static const index_info *lookup(hyperdatatype datatype); - public: - index_info(); - virtual ~index_info() throw (); +public: + index_info(); + virtual ~index_info() throw (); - public: - // what datatype is this index for? - virtual hyperdatatype datatype() const = 0; - // apply to updates all the writes necessary to transform the index from - // old_value to new_value - virtual void index_changes(const index* idx, - const region_id& ri, - const index_encoding* key_ie, - const e::slice& key, - const e::slice* old_value, - const e::slice* new_value, - leveldb::WriteBatch* updates) const = 0; - // return an iterator across all keys - // if not indexable (full scan), return NULL - virtual datalayer::index_iterator* iterator_for_keys(leveldb_snapshot_ptr snap, - const region_id& ri) const; - // return an iterator that retrieves at least the keys matching r - // if not indexable (full scan), return NULL - virtual datalayer::index_iterator* iterator_from_range(leveldb_snapshot_ptr snap, - const region_id& ri, - const index_id& ii, - const range& r, - const index_encoding* key_ie) const; - // return an iterator that retrieves at least the keys that pass c - // if not indexable (full scan), return NULL - virtual datalayer::index_iterator* iterator_from_check(leveldb_snapshot_ptr snap, - const region_id& ri, - const index_id& ii, - const attribute_check& c, - const index_encoding* key_ie) const; +public: + // what datatype is this index for? + virtual hyperdatatype datatype() const = 0; + // apply to updates all the writes necessary to transform the index from + // old_value to new_value + virtual void index_changes(const index *idx, + const region_id &ri, + const index_encoding *key_ie, + const e::slice &key, + const e::slice *old_value, + const e::slice *new_value, + leveldb::WriteBatch *updates) const = 0; + // return an iterator across all keys + // if not indexable (full scan), return NULL + virtual datalayer::index_iterator *iterator_for_keys(leveldb_snapshot_ptr snap, + const region_id &ri) const; + // return an iterator that retrieves at least the keys matching r + // if not indexable (full scan), return NULL + virtual datalayer::index_iterator *iterator_from_range(leveldb_snapshot_ptr snap, + const region_id &ri, + const index_id &ii, + const range &r, + const index_encoding *key_ie) const; + // return an iterator that retrieves at least the keys that pass c + // if not indexable (full scan), return NULL + virtual datalayer::index_iterator *iterator_from_check(leveldb_snapshot_ptr snap, + const region_id &ri, + const index_id &ii, + const attribute_check &c, + const index_encoding *key_ie) const; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/index_int64.cc b/daemon/index_int64.cc index b09d2ddf3..162b19294 100644 --- a/daemon/index_int64.cc +++ b/daemon/index_int64.cc @@ -38,7 +38,7 @@ using hyperdex::index_int64; using hyperdex::index_encoding_int64; index_int64 :: index_int64() - : index_primitive(index_encoding::lookup(HYPERDATATYPE_INT64)) + : index_primitive(index_encoding::lookup(HYPERDATATYPE_INT64)) { } @@ -49,7 +49,7 @@ index_int64 :: ~index_int64() throw () hyperdatatype index_int64 :: datatype() const { - return HYPERDATATYPE_INT64; + return HYPERDATATYPE_INT64; } index_encoding_int64 :: index_encoding_int64() @@ -63,37 +63,35 @@ index_encoding_int64 :: ~index_encoding_int64() throw () bool index_encoding_int64 :: encoding_fixed() const { - return true; + return true; } size_t -index_encoding_int64 :: encoded_size(const e::slice&) const +index_encoding_int64 :: encoded_size(const e::slice &) const { - return sizeof(int64_t); + return sizeof(int64_t); } -char* -index_encoding_int64 :: encode(const e::slice& decoded, char* encoded) const +char * +index_encoding_int64 :: encode(const e::slice &decoded, char *encoded) const { - return e::pack64be(datatype_info::lookup(HYPERDATATYPE_INT64)->hash(decoded), encoded); + return e::pack64be(datatype_info::lookup(HYPERDATATYPE_INT64)->hash(decoded), encoded); } size_t -index_encoding_int64 :: decoded_size(const e::slice&) const +index_encoding_int64 :: decoded_size(const e::slice &) const { - return sizeof(int64_t); + return sizeof(int64_t); } -char* -index_encoding_int64 :: decode(const e::slice& encoded, char* decoded) const +char * +index_encoding_int64 :: decode(const e::slice &encoded, char *decoded) const { - uint64_t x = 0; - - if (encoded.size() == sizeof(int64_t)) - { - e::unpack64be(encoded.data(), &x); - } - - int64_t number = ordered_decode_int64(x); - return e::pack64le(number, decoded); + uint64_t x = 0; + if (encoded.size() == sizeof(int64_t)) + { + e::unpack64be(encoded.data(), &x); + } + int64_t number = ordered_decode_int64(x); + return e::pack64le(number, decoded); } diff --git a/daemon/index_int64.h b/daemon/index_int64.h index 7cb903cba..69c1450c7 100644 --- a/daemon/index_int64.h +++ b/daemon/index_int64.h @@ -36,26 +36,26 @@ BEGIN_HYPERDEX_NAMESPACE class index_int64 : public index_primitive { - public: - index_int64(); - virtual ~index_int64() throw (); +public: + index_int64(); + virtual ~index_int64() throw (); - public: - virtual hyperdatatype datatype() const; +public: + virtual hyperdatatype datatype() const; }; class index_encoding_int64 : public index_encoding { - public: - index_encoding_int64(); - virtual ~index_encoding_int64() throw (); - - public: - virtual bool encoding_fixed() const; - virtual size_t encoded_size(const e::slice& decoded) const; - virtual char* encode(const e::slice& decoded, char* encoded) const; - virtual size_t decoded_size(const e::slice& encoded) const; - virtual char* decode(const e::slice& encoded, char* decoded) const; +public: + index_encoding_int64(); + virtual ~index_encoding_int64() throw (); + +public: + virtual bool encoding_fixed() const; + virtual size_t encoded_size(const e::slice &decoded) const; + virtual char *encode(const e::slice &decoded, char *encoded) const; + virtual size_t decoded_size(const e::slice &encoded) const; + virtual char *decode(const e::slice &encoded, char *decoded) const; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/index_list.cc b/daemon/index_list.cc index 0711263c1..d4242f7ab 100644 --- a/daemon/index_list.cc +++ b/daemon/index_list.cc @@ -36,7 +36,7 @@ using hyperdex::index_info; using hyperdex::index_list; index_list :: index_list(hyperdatatype dt) - : m_datatype(dt) + : m_datatype(dt) { } @@ -47,36 +47,34 @@ index_list :: ~index_list() throw () hyperdatatype index_list :: datatype() const { - return CREATE_CONTAINER(HYPERDATATYPE_LIST_GENERIC, m_datatype); + return CREATE_CONTAINER(HYPERDATATYPE_LIST_GENERIC, m_datatype); } void -index_list :: extract_elements(const e::slice& list, - std::vector* elems) const +index_list :: extract_elements(const e::slice &list, + std::vector *elems) const { - datatype_info* elem = datatype_info::lookup(m_datatype); - const uint8_t* ptr = list.data(); - const uint8_t* end = list.data() + list.size(); - e::slice e; - - while (ptr < end) - { - bool stepped = elem->step(&ptr, end, &e); - assert(stepped); - elems->push_back(e); - } - - assert(ptr == end); + datatype_info *elem = datatype_info::lookup(m_datatype); + const uint8_t *ptr = list.data(); + const uint8_t *end = list.data() + list.size(); + e::slice e; + while (ptr < end) + { + bool stepped = elem->step(&ptr, end, &e); + assert(stepped); + elems->push_back(e); + } + assert(ptr == end); } -const datatype_info* +const datatype_info * index_list :: element_datatype_info() const { - return datatype_info::lookup(m_datatype); + return datatype_info::lookup(m_datatype); } -const index_info* +const index_info * index_list :: element_index_info() const { - return index_info::lookup(m_datatype); + return index_info::lookup(m_datatype); } diff --git a/daemon/index_list.h b/daemon/index_list.h index 44219cb78..7a06d44fc 100644 --- a/daemon/index_list.h +++ b/daemon/index_list.h @@ -37,19 +37,19 @@ BEGIN_HYPERDEX_NAMESPACE class index_list : public index_container { - public: - index_list(hyperdatatype datatype); - virtual ~index_list() throw (); - - private: - virtual hyperdatatype datatype() const; - virtual void extract_elements(const e::slice& container, - std::vector* elems) const; - virtual const datatype_info* element_datatype_info() const; - virtual const index_info* element_index_info() const; - - private: - hyperdatatype m_datatype; +public: + index_list(hyperdatatype datatype); + virtual ~index_list() throw (); + +private: + virtual hyperdatatype datatype() const; + virtual void extract_elements(const e::slice &container, + std::vector *elems) const; + virtual const datatype_info *element_datatype_info() const; + virtual const index_info *element_index_info() const; + +private: + hyperdatatype m_datatype; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/index_map.cc b/daemon/index_map.cc index e1a2a83b2..5a5b40d33 100644 --- a/daemon/index_map.cc +++ b/daemon/index_map.cc @@ -37,8 +37,8 @@ using hyperdex::index_map; index_map :: index_map(hyperdatatype key_datatype, hyperdatatype val_datatype) - : m_key_datatype(key_datatype) - , m_val_datatype(val_datatype) + : m_key_datatype(key_datatype) + , m_val_datatype(val_datatype) { } @@ -49,43 +49,41 @@ index_map :: ~index_map() throw () hyperdatatype index_map :: datatype() const { - return CREATE_CONTAINER2(HYPERDATATYPE_MAP_GENERIC, - m_key_datatype, - m_val_datatype); + return CREATE_CONTAINER2(HYPERDATATYPE_MAP_GENERIC, + m_key_datatype, + m_val_datatype); } void -index_map :: extract_elements(const e::slice& map, - std::vector* elems) const +index_map :: extract_elements(const e::slice &map, + std::vector *elems) const { - datatype_info* elem_k = datatype_info::lookup(m_key_datatype); - datatype_info* elem_v = datatype_info::lookup(m_val_datatype); - const uint8_t* ptr = map.data(); - const uint8_t* end = map.data() + map.size(); - e::slice key; - e::slice val; - - while (ptr < end) - { - bool stepped; - stepped = elem_k->step(&ptr, end, &key); - assert(stepped); - stepped = elem_v->step(&ptr, end, &val); - assert(stepped); - elems->push_back(key); - } - - assert(ptr == end); + datatype_info *elem_k = datatype_info::lookup(m_key_datatype); + datatype_info *elem_v = datatype_info::lookup(m_val_datatype); + const uint8_t *ptr = map.data(); + const uint8_t *end = map.data() + map.size(); + e::slice key; + e::slice val; + while (ptr < end) + { + bool stepped; + stepped = elem_k->step(&ptr, end, &key); + assert(stepped); + stepped = elem_v->step(&ptr, end, &val); + assert(stepped); + elems->push_back(key); + } + assert(ptr == end); } -const datatype_info* +const datatype_info * index_map :: element_datatype_info() const { - return datatype_info::lookup(m_key_datatype); + return datatype_info::lookup(m_key_datatype); } -const index_info* +const index_info * index_map :: element_index_info() const { - return index_info::lookup(m_key_datatype); + return index_info::lookup(m_key_datatype); } diff --git a/daemon/index_map.h b/daemon/index_map.h index 0a0bdf3fd..df86d6749 100644 --- a/daemon/index_map.h +++ b/daemon/index_map.h @@ -37,21 +37,21 @@ BEGIN_HYPERDEX_NAMESPACE class index_map : public index_container { - public: - index_map(hyperdatatype key_datatype, - hyperdatatype val_datatype); - virtual ~index_map() throw (); - - private: - virtual hyperdatatype datatype() const; - virtual void extract_elements(const e::slice& container, - std::vector* elems) const; - virtual const datatype_info* element_datatype_info() const; - virtual const index_info* element_index_info() const; - - private: - hyperdatatype m_key_datatype; - hyperdatatype m_val_datatype; +public: + index_map(hyperdatatype key_datatype, + hyperdatatype val_datatype); + virtual ~index_map() throw (); + +private: + virtual hyperdatatype datatype() const; + virtual void extract_elements(const e::slice &container, + std::vector *elems) const; + virtual const datatype_info *element_datatype_info() const; + virtual const index_info *element_index_info() const; + +private: + hyperdatatype m_key_datatype; + hyperdatatype m_val_datatype; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/index_primitive.cc b/daemon/index_primitive.cc index 04bef5df4..06f95e3a4 100644 --- a/daemon/index_primitive.cc +++ b/daemon/index_primitive.cc @@ -37,11 +37,11 @@ using hyperdex::datalayer; using hyperdex::index_primitive; -inline leveldb::Slice e2level(const e::slice& s) { return leveldb::Slice(reinterpret_cast(s.data()), s.size()); } -inline e::slice level2e(const leveldb::Slice& s) { return e::slice(s.data(), s.size()); } +inline leveldb::Slice e2level(const e::slice &s) { return leveldb::Slice(reinterpret_cast(s.data()), s.size()); } +inline e::slice level2e(const leveldb::Slice &s) { return e::slice(s.data(), s.size()); } -index_primitive :: index_primitive(const index_encoding* ie) - : m_ie(ie) +index_primitive :: index_primitive(const index_encoding *ie) + : m_ie(ie) { } @@ -50,280 +50,258 @@ index_primitive :: ~index_primitive() throw () } void -index_primitive :: index_changes(const index* idx, - const region_id& ri, - const index_encoding* key_ie, - const e::slice& key, - const e::slice* old_value, - const e::slice* new_value, - leveldb::WriteBatch* updates) const +index_primitive :: index_changes(const index *idx, + const region_id &ri, + const index_encoding *key_ie, + const e::slice &key, + const e::slice *old_value, + const e::slice *new_value, + leveldb::WriteBatch *updates) const { - std::vector scratch; - e::slice slice; - - if (old_value && new_value && *old_value == *new_value) - { - return; - } - - if (old_value) - { - index_entry(ri, idx->id, key_ie, key, *old_value, &scratch, &slice); - updates->Delete(e2level(slice)); - } - - if (new_value) - { - index_entry(ri, idx->id, key_ie, key, *new_value, &scratch, &slice); - updates->Put(e2level(slice), leveldb::Slice()); - } + std::vector scratch; + e::slice slice; + if (old_value && new_value && *old_value == *new_value) + { + return; + } + if (old_value) + { + index_entry(ri, idx->id, key_ie, key, *old_value, &scratch, &slice); + updates->Delete(e2level(slice)); + } + if (new_value) + { + index_entry(ri, idx->id, key_ie, key, *new_value, &scratch, &slice); + updates->Put(e2level(slice), leveldb::Slice()); + } } -datalayer::index_iterator* +datalayer::index_iterator * index_primitive :: iterator_for_keys(leveldb_snapshot_ptr snap, - const region_id& ri) const + const region_id &ri) const { - range scan; - scan.attr = 0; - scan.type = this->datatype(); - scan.has_start = false; - scan.has_end = false; - scan.invalid = false; - const index_encoding* ie = index_encoding::lookup(scan.type); - return iterator_key(snap, ri, scan, ie); + range scan; + scan.attr = 0; + scan.type = this->datatype(); + scan.has_start = false; + scan.has_end = false; + scan.invalid = false; + const index_encoding *ie = index_encoding::lookup(scan.type); + return iterator_key(snap, ri, scan, ie); } -datalayer::index_iterator* +datalayer::index_iterator * index_primitive :: iterator_from_range(leveldb_snapshot_ptr snap, - const region_id& ri, - const index_id& ii, - const range& r, - const index_encoding* key_ie) const + const region_id &ri, + const index_id &ii, + const range &r, + const index_encoding *key_ie) const { - if (r.invalid) - { - return NULL; - } - - if (r.attr != 0) - { - return iterator_attr(snap, ri, ii, r, key_ie); - } - else - { - return iterator_key(snap, ri, r, key_ie); - } + if (r.invalid) + { + return NULL; + } + if (r.attr != 0) + { + return iterator_attr(snap, ri, ii, r, key_ie); + } + else + { + return iterator_key(snap, ri, r, key_ie); + } } -datalayer::index_iterator* +datalayer::index_iterator * index_primitive :: iterator_key(leveldb_snapshot_ptr snap, - const region_id& ri, - const range& r, - const index_encoding* key_ie) const + const region_id &ri, + const range &r, + const index_encoding *key_ie) const { - std::vector scratch_start; - std::vector scratch_limit; - e::slice start; - e::slice limit; - - size_t range_prefix_sz = object_prefix_sz(ri); - - if (r.has_start) - { - leveldb::Slice _start; - encode_key(ri, r.type, r.start, &scratch_start, &_start); - start = level2e(_start); - } - else - { - leveldb::Slice _start; - encode_object_region(ri, &scratch_start, &_start); - start = level2e(_start); - } - - if (r.has_end) - { - leveldb::Slice _limit; - encode_key(ri, r.type, r.end, &scratch_limit, &_limit); - limit = level2e(_limit); - } - else - { - leveldb::Slice _limit; - encode_object_region(ri, &scratch_limit, &_limit); - limit = level2e(_limit); - } - - return new datalayer::range_index_iterator(snap, range_prefix_sz, - start, limit, - r.has_start, r.has_end, - NULL, key_ie); + std::vector scratch_start; + std::vector scratch_limit; + e::slice start; + e::slice limit; + size_t range_prefix_sz = object_prefix_sz(ri); + if (r.has_start) + { + leveldb::Slice _start; + encode_key(ri, r.type, r.start, &scratch_start, &_start); + start = level2e(_start); + } + else + { + leveldb::Slice _start; + encode_object_region(ri, &scratch_start, &_start); + start = level2e(_start); + } + if (r.has_end) + { + leveldb::Slice _limit; + encode_key(ri, r.type, r.end, &scratch_limit, &_limit); + limit = level2e(_limit); + } + else + { + leveldb::Slice _limit; + encode_object_region(ri, &scratch_limit, &_limit); + limit = level2e(_limit); + } + return new datalayer::range_index_iterator(snap, range_prefix_sz, + start, limit, + r.has_start, r.has_end, + NULL, key_ie); } -datalayer::index_iterator* +datalayer::index_iterator * index_primitive :: iterator_attr(leveldb_snapshot_ptr snap, - const region_id& ri, - const index_id& ii, - const range& r, - const index_encoding* key_ie) const + const region_id &ri, + const index_id &ii, + const range &r, + const index_encoding *key_ie) const { - std::vector scratch_start; - std::vector scratch_limit; - e::slice start; - e::slice limit; - - size_t range_prefix_sz = index_entry_prefix_size(ri, ii); - - if (r.has_start) - { - index_entry(ri, ii, r.start, &scratch_start, &start); - } - else - { - index_entry(ri, ii, &scratch_start, &start); - } - - if (r.has_end) - { - index_entry(ri, ii, r.end, &scratch_limit, &limit); - } - else - { - index_entry(ri, ii, &scratch_limit, &limit); - } - - return new datalayer::range_index_iterator(snap, range_prefix_sz, - start, limit, - r.has_start, r.has_end, - m_ie, key_ie); + std::vector scratch_start; + std::vector scratch_limit; + e::slice start; + e::slice limit; + size_t range_prefix_sz = index_entry_prefix_size(ri, ii); + if (r.has_start) + { + index_entry(ri, ii, r.start, &scratch_start, &start); + } + else + { + index_entry(ri, ii, &scratch_start, &start); + } + if (r.has_end) + { + index_entry(ri, ii, r.end, &scratch_limit, &limit); + } + else + { + index_entry(ri, ii, &scratch_limit, &limit); + } + return new datalayer::range_index_iterator(snap, range_prefix_sz, + start, limit, + r.has_start, r.has_end, + m_ie, key_ie); } size_t -index_primitive :: index_entry_prefix_size(const region_id& ri, const index_id& ii) const +index_primitive :: index_entry_prefix_size(const region_id &ri, const index_id &ii) const { - return sizeof(uint8_t) - + e::varint_length(ri.get()) - + e::varint_length(ii.get()); + return sizeof(uint8_t) + + e::varint_length(ri.get()) + + e::varint_length(ii.get()); } void -index_primitive :: index_entry(const region_id& ri, - const index_id& ii, - std::vector* scratch, - e::slice* slice) const +index_primitive :: index_entry(const region_id &ri, + const index_id &ii, + std::vector *scratch, + e::slice *slice) const { - size_t sz = sizeof(uint8_t) - + e::varint_length(ri.get()) - + e::varint_length(ii.get()); - - if (scratch->size() < sz) - { - scratch->resize(sz); - } - - char* ptr = &scratch->front(); - ptr = e::pack8be('i', ptr); - ptr = e::packvarint64(ri.get(), ptr); - ptr = e::packvarint64(ii.get(), ptr); - assert(ptr == &scratch->front() + sz); - *slice = e::slice(&scratch->front(), sz); + size_t sz = sizeof(uint8_t) + + e::varint_length(ri.get()) + + e::varint_length(ii.get()); + if (scratch->size() < sz) + { + scratch->resize(sz); + } + char *ptr = &scratch->front(); + ptr = e::pack8be('i', ptr); + ptr = e::packvarint64(ri.get(), ptr); + ptr = e::packvarint64(ii.get(), ptr); + assert(ptr == &scratch->front() + sz); + *slice = e::slice(&scratch->front(), sz); } void -index_primitive :: index_entry(const region_id& ri, - const index_id& ii, - const e::slice& value, - std::vector* scratch, - e::slice* slice) const +index_primitive :: index_entry(const region_id &ri, + const index_id &ii, + const e::slice &value, + std::vector *scratch, + e::slice *slice) const { - size_t val_sz = m_ie->encoded_size(value); - size_t sz = sizeof(uint8_t) - + e::varint_length(ri.get()) - + e::varint_length(ii.get()) - + val_sz; - - if (scratch->size() < sz) - { - scratch->resize(sz); - } - - char* ptr = &scratch->front(); - ptr = e::pack8be('i', ptr); - ptr = e::packvarint64(ri.get(), ptr); - ptr = e::packvarint64(ii.get(), ptr); - ptr = m_ie->encode(value, ptr); - assert(ptr == &scratch->front() + sz); - *slice = e::slice(&scratch->front(), sz); + size_t val_sz = m_ie->encoded_size(value); + size_t sz = sizeof(uint8_t) + + e::varint_length(ri.get()) + + e::varint_length(ii.get()) + + val_sz; + if (scratch->size() < sz) + { + scratch->resize(sz); + } + char *ptr = &scratch->front(); + ptr = e::pack8be('i', ptr); + ptr = e::packvarint64(ri.get(), ptr); + ptr = e::packvarint64(ii.get(), ptr); + ptr = m_ie->encode(value, ptr); + assert(ptr == &scratch->front() + sz); + *slice = e::slice(&scratch->front(), sz); } void -index_primitive :: index_entry(const region_id& ri, - const index_id& ii, - const e::slice& internal_key, - const e::slice& value, - std::vector* scratch, - e::slice* slice) const +index_primitive :: index_entry(const region_id &ri, + const index_id &ii, + const e::slice &internal_key, + const e::slice &value, + std::vector *scratch, + e::slice *slice) const { - size_t key_sz = internal_key.size(); - size_t val_sz = m_ie->encoded_size(value); - size_t sz = sizeof(uint8_t) - + e::varint_length(ri.get()) - + e::varint_length(ii.get()) - + val_sz - + key_sz; - - if (scratch->size() < sz) - { - scratch->resize(sz); - } - - char* ptr = &scratch->front(); - ptr = e::pack8be('i', ptr); - ptr = e::packvarint64(ri.get(), ptr); - ptr = e::packvarint64(ii.get(), ptr); - ptr = m_ie->encode(value, ptr); - memmove(ptr, internal_key.data(), key_sz); - ptr += key_sz; - assert(ptr == &scratch->front() + sz); - *slice = e::slice(&scratch->front(), sz); + size_t key_sz = internal_key.size(); + size_t val_sz = m_ie->encoded_size(value); + size_t sz = sizeof(uint8_t) + + e::varint_length(ri.get()) + + e::varint_length(ii.get()) + + val_sz + + key_sz; + if (scratch->size() < sz) + { + scratch->resize(sz); + } + char *ptr = &scratch->front(); + ptr = e::pack8be('i', ptr); + ptr = e::packvarint64(ri.get(), ptr); + ptr = e::packvarint64(ii.get(), ptr); + ptr = m_ie->encode(value, ptr); + memmove(ptr, internal_key.data(), key_sz); + ptr += key_sz; + assert(ptr == &scratch->front() + sz); + *slice = e::slice(&scratch->front(), sz); } void -index_primitive :: index_entry(const region_id& ri, - const index_id& ii, - const index_encoding* key_ie, - const e::slice& key, - const e::slice& value, - std::vector* scratch, - e::slice* slice) const +index_primitive :: index_entry(const region_id &ri, + const index_id &ii, + const index_encoding *key_ie, + const e::slice &key, + const e::slice &value, + std::vector *scratch, + e::slice *slice) const { - size_t key_sz = key_ie->encoded_size(key); - size_t val_sz = m_ie->encoded_size(value); - bool variable = !key_ie->encoding_fixed() && !m_ie->encoding_fixed(); - size_t sz = sizeof(uint8_t) - + e::varint_length(ri.get()) - + e::varint_length(ii.get()) - + val_sz - + key_sz - + (variable ? sizeof(uint32_t) : 0); - - if (scratch->size() < sz) - { - scratch->resize(sz); - } - - char* ptr = &scratch->front(); - ptr = e::pack8be('i', ptr); - ptr = e::packvarint64(ri.get(), ptr); - ptr = e::packvarint64(ii.get(), ptr); - ptr = m_ie->encode(value, ptr); - ptr = key_ie->encode(key, ptr); - - if (variable) - { - ptr = e::pack32be(key_sz, ptr); - } - - assert(ptr == &scratch->front() + sz); - *slice = e::slice(&scratch->front(), sz); + size_t key_sz = key_ie->encoded_size(key); + size_t val_sz = m_ie->encoded_size(value); + bool variable = !key_ie->encoding_fixed() && !m_ie->encoding_fixed(); + size_t sz = sizeof(uint8_t) + + e::varint_length(ri.get()) + + e::varint_length(ii.get()) + + val_sz + + key_sz + + (variable ? sizeof(uint32_t) : 0); + if (scratch->size() < sz) + { + scratch->resize(sz); + } + char *ptr = &scratch->front(); + ptr = e::pack8be('i', ptr); + ptr = e::packvarint64(ri.get(), ptr); + ptr = e::packvarint64(ii.get(), ptr); + ptr = m_ie->encode(value, ptr); + ptr = key_ie->encode(key, ptr); + if (variable) + { + ptr = e::pack32be(key_sz, ptr); + } + assert(ptr == &scratch->front() + sz); + *slice = e::slice(&scratch->front(), sz); } diff --git a/daemon/index_primitive.h b/daemon/index_primitive.h index de60a187e..265c7a9a8 100644 --- a/daemon/index_primitive.h +++ b/daemon/index_primitive.h @@ -36,70 +36,70 @@ BEGIN_HYPERDEX_NAMESPACE class index_primitive : public index_info { - protected: - index_primitive(const index_encoding* ie); - virtual ~index_primitive() throw (); +protected: + index_primitive(const index_encoding *ie); + virtual ~index_primitive() throw (); - public: - virtual void index_changes(const index* idx, - const region_id& ri, - const index_encoding* key_ie, - const e::slice& key, - const e::slice* old_value, - const e::slice* new_value, - leveldb::WriteBatch* updates) const; - virtual datalayer::index_iterator* iterator_for_keys(leveldb_snapshot_ptr snap, - const region_id& ri) const; - virtual datalayer::index_iterator* iterator_from_range(leveldb_snapshot_ptr snap, - const region_id& ri, - const index_id& ii, - const range& r, - const index_encoding* key_ie) const; +public: + virtual void index_changes(const index *idx, + const region_id &ri, + const index_encoding *key_ie, + const e::slice &key, + const e::slice *old_value, + const e::slice *new_value, + leveldb::WriteBatch *updates) const; + virtual datalayer::index_iterator *iterator_for_keys(leveldb_snapshot_ptr snap, + const region_id &ri) const; + virtual datalayer::index_iterator *iterator_from_range(leveldb_snapshot_ptr snap, + const region_id &ri, + const index_id &ii, + const range &r, + const index_encoding *key_ie) const; - private: - class range_iterator; - class key_iterator; +private: + class range_iterator; + class key_iterator; - private: - datalayer::index_iterator* iterator_key(leveldb_snapshot_ptr snap, - const region_id& ri, - const range& r, - const index_encoding* key_ie) const; - datalayer::index_iterator* iterator_attr(leveldb_snapshot_ptr snap, - const region_id& ri, - const index_id& ii, - const range& r, - const index_encoding* key_ie) const; - size_t index_entry_prefix_size(const region_id& ri, const index_id& ii) const; - void index_entry(const region_id& ri, - const index_id& ii, - std::vector* scratch, - e::slice* slice) const; - void index_entry(const region_id& ri, - const index_id& ii, - const e::slice& value, - std::vector* scratch, - e::slice* slice) const; - void index_entry(const region_id& ri, - const index_id& ii, - const e::slice& internal_key, - const e::slice& value, - std::vector* scratch, - e::slice* slice) const; - void index_entry(const region_id& ri, - const index_id& ii, - const index_encoding* key_ie, - const e::slice& key, - const e::slice& value, - std::vector* scratch, - e::slice* slice) const; +private: + datalayer::index_iterator *iterator_key(leveldb_snapshot_ptr snap, + const region_id &ri, + const range &r, + const index_encoding *key_ie) const; + datalayer::index_iterator *iterator_attr(leveldb_snapshot_ptr snap, + const region_id &ri, + const index_id &ii, + const range &r, + const index_encoding *key_ie) const; + size_t index_entry_prefix_size(const region_id &ri, const index_id &ii) const; + void index_entry(const region_id &ri, + const index_id &ii, + std::vector *scratch, + e::slice *slice) const; + void index_entry(const region_id &ri, + const index_id &ii, + const e::slice &value, + std::vector *scratch, + e::slice *slice) const; + void index_entry(const region_id &ri, + const index_id &ii, + const e::slice &internal_key, + const e::slice &value, + std::vector *scratch, + e::slice *slice) const; + void index_entry(const region_id &ri, + const index_id &ii, + const index_encoding *key_ie, + const e::slice &key, + const e::slice &value, + std::vector *scratch, + e::slice *slice) const; - private: - index_primitive(const index_primitive&); - index_primitive& operator = (const index_primitive&); +private: + index_primitive(const index_primitive &); + index_primitive &operator = (const index_primitive &); - private: - const index_encoding *const m_ie; +private: + const index_encoding *const m_ie; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/index_set.cc b/daemon/index_set.cc index b122d7e35..01f7bb1af 100644 --- a/daemon/index_set.cc +++ b/daemon/index_set.cc @@ -36,7 +36,7 @@ using hyperdex::index_info; using hyperdex::index_set; index_set :: index_set(hyperdatatype dt) - : m_datatype(dt) + : m_datatype(dt) { } @@ -47,36 +47,34 @@ index_set :: ~index_set() throw () hyperdatatype index_set :: datatype() const { - return CREATE_CONTAINER(HYPERDATATYPE_SET_GENERIC, m_datatype); + return CREATE_CONTAINER(HYPERDATATYPE_SET_GENERIC, m_datatype); } void -index_set :: extract_elements(const e::slice& set, - std::vector* elems) const +index_set :: extract_elements(const e::slice &set, + std::vector *elems) const { - datatype_info* elem = datatype_info::lookup(m_datatype); - const uint8_t* ptr = set.data(); - const uint8_t* end = set.data() + set.size(); - e::slice e; - - while (ptr < end) - { - bool stepped = elem->step(&ptr, end, &e); - assert(stepped); - elems->push_back(e); - } - - assert(ptr == end); + datatype_info *elem = datatype_info::lookup(m_datatype); + const uint8_t *ptr = set.data(); + const uint8_t *end = set.data() + set.size(); + e::slice e; + while (ptr < end) + { + bool stepped = elem->step(&ptr, end, &e); + assert(stepped); + elems->push_back(e); + } + assert(ptr == end); } -const datatype_info* +const datatype_info * index_set :: element_datatype_info() const { - return datatype_info::lookup(m_datatype); + return datatype_info::lookup(m_datatype); } -const index_info* +const index_info * index_set :: element_index_info() const { - return index_info::lookup(m_datatype); + return index_info::lookup(m_datatype); } diff --git a/daemon/index_set.h b/daemon/index_set.h index 5e71b7b5a..b04828d78 100644 --- a/daemon/index_set.h +++ b/daemon/index_set.h @@ -37,19 +37,19 @@ BEGIN_HYPERDEX_NAMESPACE class index_set : public index_container { - public: - index_set(hyperdatatype datatype); - virtual ~index_set() throw (); - - private: - virtual hyperdatatype datatype() const; - virtual void extract_elements(const e::slice& container, - std::vector* elems) const; - virtual const datatype_info* element_datatype_info() const; - virtual const index_info* element_index_info() const; - - private: - hyperdatatype m_datatype; +public: + index_set(hyperdatatype datatype); + virtual ~index_set() throw (); + +private: + virtual hyperdatatype datatype() const; + virtual void extract_elements(const e::slice &container, + std::vector *elems) const; + virtual const datatype_info *element_datatype_info() const; + virtual const index_info *element_index_info() const; + +private: + hyperdatatype m_datatype; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/index_string.cc b/daemon/index_string.cc index 295ac8f62..c20ce5406 100644 --- a/daemon/index_string.cc +++ b/daemon/index_string.cc @@ -37,7 +37,7 @@ using hyperdex::index_string; using hyperdex::index_encoding_string; index_string :: index_string() - : index_primitive(index_encoding::lookup(HYPERDATATYPE_STRING)) + : index_primitive(index_encoding::lookup(HYPERDATATYPE_STRING)) { } @@ -48,7 +48,7 @@ index_string :: ~index_string() throw () hyperdatatype index_string :: datatype() const { - return HYPERDATATYPE_STRING; + return HYPERDATATYPE_STRING; } index_encoding_string :: index_encoding_string() @@ -62,31 +62,31 @@ index_encoding_string :: ~index_encoding_string() throw () bool index_encoding_string :: encoding_fixed() const { - return false; + return false; } size_t -index_encoding_string :: encoded_size(const e::slice& decoded) const +index_encoding_string :: encoded_size(const e::slice &decoded) const { - return decoded.size(); + return decoded.size(); } -char* -index_encoding_string :: encode(const e::slice& decoded, char* encoded) const +char * +index_encoding_string :: encode(const e::slice &decoded, char *encoded) const { - memmove(encoded, decoded.data(), decoded.size()); - return encoded + decoded.size(); + memmove(encoded, decoded.data(), decoded.size()); + return encoded + decoded.size(); } size_t -index_encoding_string :: decoded_size(const e::slice& encoded) const +index_encoding_string :: decoded_size(const e::slice &encoded) const { - return encoded.size(); + return encoded.size(); } -char* -index_encoding_string :: decode(const e::slice& encoded, char* decoded) const +char * +index_encoding_string :: decode(const e::slice &encoded, char *decoded) const { - memmove(decoded, encoded.data(), encoded.size()); - return decoded + encoded.size(); + memmove(decoded, encoded.data(), encoded.size()); + return decoded + encoded.size(); } diff --git a/daemon/index_string.h b/daemon/index_string.h index 0c8694661..8a64393da 100644 --- a/daemon/index_string.h +++ b/daemon/index_string.h @@ -36,26 +36,26 @@ BEGIN_HYPERDEX_NAMESPACE class index_string : public index_primitive { - public: - index_string(); - virtual ~index_string() throw (); +public: + index_string(); + virtual ~index_string() throw (); - public: - virtual hyperdatatype datatype() const; +public: + virtual hyperdatatype datatype() const; }; class index_encoding_string : public index_encoding { - public: - index_encoding_string(); - virtual ~index_encoding_string() throw (); - - public: - virtual bool encoding_fixed() const; - virtual size_t encoded_size(const e::slice& decoded) const; - virtual char* encode(const e::slice& decoded, char* encoded) const; - virtual size_t decoded_size(const e::slice& encoded) const; - virtual char* decode(const e::slice& encoded, char* decoded) const; +public: + index_encoding_string(); + virtual ~index_encoding_string() throw (); + +public: + virtual bool encoding_fixed() const; + virtual size_t encoded_size(const e::slice &decoded) const; + virtual char *encode(const e::slice &decoded, char *encoded) const; + virtual size_t decoded_size(const e::slice &encoded) const; + virtual char *decode(const e::slice &encoded, char *decoded) const; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/index_timestamp.cc b/daemon/index_timestamp.cc index 28b51ac3a..cd1e37b44 100644 --- a/daemon/index_timestamp.cc +++ b/daemon/index_timestamp.cc @@ -38,10 +38,10 @@ using hyperdex::index_timestamp; using hyperdex::index_encoding_timestamp; index_timestamp :: index_timestamp(hyperdatatype t) - : index_primitive(index_encoding::lookup(t)) - , m_type(t) + : index_primitive(index_encoding::lookup(t)) + , m_type(t) { - assert(CONTAINER_TYPE(m_type) == HYPERDATATYPE_TIMESTAMP_GENERIC); + assert(CONTAINER_TYPE(m_type) == HYPERDATATYPE_TIMESTAMP_GENERIC); } index_timestamp :: ~index_timestamp() throw () @@ -51,11 +51,11 @@ index_timestamp :: ~index_timestamp() throw () hyperdatatype index_timestamp :: datatype() const { - return m_type; + return m_type; } index_encoding_timestamp :: index_encoding_timestamp() - : m_iei() + : m_iei() { } @@ -66,29 +66,29 @@ index_encoding_timestamp :: ~index_encoding_timestamp() throw () bool index_encoding_timestamp :: encoding_fixed() const { - return m_iei.encoding_fixed(); + return m_iei.encoding_fixed(); } size_t -index_encoding_timestamp :: encoded_size(const e::slice& x) const +index_encoding_timestamp :: encoded_size(const e::slice &x) const { - return m_iei.encoded_size(x); + return m_iei.encoded_size(x); } -char* -index_encoding_timestamp :: encode(const e::slice& decoded, char* encoded) const +char * +index_encoding_timestamp :: encode(const e::slice &decoded, char *encoded) const { - return m_iei.encode(decoded, encoded); + return m_iei.encode(decoded, encoded); } size_t -index_encoding_timestamp :: decoded_size(const e::slice& x) const +index_encoding_timestamp :: decoded_size(const e::slice &x) const { - return m_iei.decoded_size(x); + return m_iei.decoded_size(x); } -char* -index_encoding_timestamp :: decode(const e::slice& encoded, char* decoded) const +char * +index_encoding_timestamp :: decode(const e::slice &encoded, char *decoded) const { - return m_iei.decode(encoded, decoded); + return m_iei.decode(encoded, decoded); } diff --git a/daemon/index_timestamp.h b/daemon/index_timestamp.h index 02f2e695e..25b010d07 100644 --- a/daemon/index_timestamp.h +++ b/daemon/index_timestamp.h @@ -38,32 +38,32 @@ BEGIN_HYPERDEX_NAMESPACE class index_timestamp : public index_primitive { - public: - index_timestamp(hyperdatatype t); - virtual ~index_timestamp() throw (); +public: + index_timestamp(hyperdatatype t); + virtual ~index_timestamp() throw (); - public: - virtual hyperdatatype datatype() const; +public: + virtual hyperdatatype datatype() const; - private: - hyperdatatype m_type; +private: + hyperdatatype m_type; }; class index_encoding_timestamp : public index_encoding { - public: - index_encoding_timestamp(); - virtual ~index_encoding_timestamp() throw (); +public: + index_encoding_timestamp(); + virtual ~index_encoding_timestamp() throw (); - public: - virtual bool encoding_fixed() const; - virtual size_t encoded_size(const e::slice& decoded) const; - virtual char* encode(const e::slice& decoded, char* encoded) const; - virtual size_t decoded_size(const e::slice& encoded) const; - virtual char* decode(const e::slice& encoded, char* decoded) const; +public: + virtual bool encoding_fixed() const; + virtual size_t encoded_size(const e::slice &decoded) const; + virtual char *encode(const e::slice &decoded, char *encoded) const; + virtual size_t decoded_size(const e::slice &encoded) const; + virtual char *decode(const e::slice &encoded, char *decoded) const; - private: - index_encoding_int64 m_iei; +private: + index_encoding_int64 m_iei; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/key_operation.cc b/daemon/key_operation.cc index 5087ecc4d..043a47a85 100644 --- a/daemon/key_operation.cc +++ b/daemon/key_operation.cc @@ -39,25 +39,25 @@ key_operation :: key_operation(uint64_t old_version, uint64_t new_version, bool _fresh, bool _has_value, - const std::vector& _value, + const std::vector &_value, std::auto_ptr memory) - : m_ref(0) - , m_prev_version(old_version) - , m_this_version(new_version) - , m_acked(false) - , m_fresh(_fresh) - , m_has_value(_has_value) - , m_recv_config_version() - , m_recv() - , m_sent_config_version() - , m_sent() - , m_value(_value) - , m_memory(memory) - , m_type(UNKNOWN) - , m_this_old_region() - , m_this_new_region() - , m_prev_region() - , m_next_region() + : m_ref(0) + , m_prev_version(old_version) + , m_this_version(new_version) + , m_acked(false) + , m_fresh(_fresh) + , m_has_value(_has_value) + , m_recv_config_version() + , m_recv() + , m_sent_config_version() + , m_sent() + , m_value(_value) + , m_memory(memory) + , m_type(UNKNOWN) + , m_this_old_region() + , m_this_new_region() + , m_prev_region() + , m_next_region() { } @@ -68,58 +68,56 @@ key_operation :: ~key_operation() throw () void key_operation :: set_continuous() { - assert(m_type == UNKNOWN); - m_type = CONTINUOUS; + assert(m_type == UNKNOWN); + m_type = CONTINUOUS; } void -key_operation :: set_continuous_hashes(const region_id& pr, - const region_id& tor, - const region_id& tnr, - const region_id& nr) +key_operation :: set_continuous_hashes(const region_id &pr, + const region_id &tor, + const region_id &tnr, + const region_id &nr) { - assert(m_type == CONTINUOUS); - assert(m_prev_region == region_id()); - assert(m_this_old_region == region_id()); - assert(m_this_new_region == region_id()); - assert(m_next_region == region_id()); - - m_prev_region = pr; - m_this_old_region = tor; - m_this_new_region = tnr; - m_next_region = nr; + assert(m_type == CONTINUOUS); + assert(m_prev_region == region_id()); + assert(m_this_old_region == region_id()); + assert(m_this_new_region == region_id()); + assert(m_next_region == region_id()); + m_prev_region = pr; + m_this_old_region = tor; + m_this_new_region = tnr; + m_next_region = nr; } void -key_operation :: set_discontinuous(const region_id& pr, - const region_id& tor, - const region_id& tnr, - const region_id& nr) +key_operation :: set_discontinuous(const region_id &pr, + const region_id &tor, + const region_id &tnr, + const region_id &nr) { - assert(m_type == UNKNOWN); - assert(m_prev_region == region_id()); - assert(m_this_old_region == region_id()); - assert(m_this_new_region == region_id()); - assert(m_next_region == region_id()); - m_type = DISCONTINUOUS; - - m_prev_region = pr; - m_this_old_region = tor; - m_this_new_region = tnr; - m_next_region = nr; + assert(m_type == UNKNOWN); + assert(m_prev_region == region_id()); + assert(m_this_old_region == region_id()); + assert(m_this_new_region == region_id()); + assert(m_next_region == region_id()); + m_type = DISCONTINUOUS; + m_prev_region = pr; + m_this_old_region = tor; + m_this_new_region = tnr; + m_next_region = nr; } void key_operation :: debug_dump() { - LOG(INFO) << " unique op id: prev=" << m_prev_version << " this=" << m_this_version; - LOG(INFO) << " has value: " << (m_has_value ? "yes" : "no"); - LOG(INFO) << " recv: version=" << m_recv_config_version << " from=" << m_recv; - LOG(INFO) << " sent: version=" << m_sent_config_version << " to=" << m_sent; - LOG(INFO) << " fresh: " << (m_fresh ? "yes" : "no"); - LOG(INFO) << " acked: " << (m_acked ? "yes" : "no"); - LOG(INFO) << " prev: " << m_prev_region; - LOG(INFO) << " this_old: " << m_this_old_region; - LOG(INFO) << " this_new: " << m_this_new_region; - LOG(INFO) << " next: " << m_next_region; + LOG(INFO) << " unique op id: prev=" << m_prev_version << " this=" << m_this_version; + LOG(INFO) << " has value: " << (m_has_value ? "yes" : "no"); + LOG(INFO) << " recv: version=" << m_recv_config_version << " from=" << m_recv; + LOG(INFO) << " sent: version=" << m_sent_config_version << " to=" << m_sent; + LOG(INFO) << " fresh: " << (m_fresh ? "yes" : "no"); + LOG(INFO) << " acked: " << (m_acked ? "yes" : "no"); + LOG(INFO) << " prev: " << m_prev_region; + LOG(INFO) << " this_old: " << m_this_old_region; + LOG(INFO) << " this_new: " << m_this_new_region; + LOG(INFO) << " next: " << m_next_region; } diff --git a/daemon/key_operation.h b/daemon/key_operation.h index 07a2b04ad..db56085b4 100644 --- a/daemon/key_operation.h +++ b/daemon/key_operation.h @@ -43,92 +43,92 @@ BEGIN_HYPERDEX_NAMESPACE class key_operation { - public: - key_operation(uint64_t old_version, - uint64_t new_version, - bool fresh, - bool has_value, - const std::vector& value, - std::auto_ptr memory); - ~key_operation() throw (); - - public: - uint64_t prev_version() const { return m_prev_version; } - uint64_t this_version() const { return m_this_version; } - - // the state of this op - void mark_acked() { m_acked = true; } - // can we ack this op AND remove it from local state? - bool ackable() const { return m_acked; } - - // who we recv/sent from/to along the chain - void set_recv(uint64_t version, const virtual_server_id& vsi) - { m_recv_config_version = version; m_recv = vsi; } - bool recv_from(uint64_t version) const { return version == m_recv_config_version; } - virtual_server_id recv_from() const { return m_recv; } - void set_sent(uint64_t version, const virtual_server_id& vsi) - { m_sent_config_version = version; m_sent = vsi; } - virtual_server_id sent_to() const { return m_sent; } - uint64_t sent_version() const { return m_sent_config_version; } - bool sent_to(uint64_t version, const virtual_server_id& vsi) const - { return m_sent_config_version == version && m_sent == vsi; } - - // the path of the op through the value-dependent chain - bool is_continuous() { return m_type == CONTINUOUS; } - bool is_discontinuous() { return m_type == DISCONTINUOUS; } - // call before hashing - void set_continuous(); - // call after hashing; must call above first - void set_continuous_hashes(const region_id& prev_region, - const region_id& this_old_region, - const region_id& this_new_region, - const region_id& next_region); - void set_discontinuous(const region_id& prev_region, - const region_id& this_old_region, - const region_id& this_new_region, - const region_id& next_region); - region_id prev_region() const { return m_prev_region; } - region_id this_old_region() const { return m_this_old_region; } - region_id this_new_region() const { return m_this_new_region; } - region_id next_region() const { return m_next_region; } - - // the value set by this op - bool is_fresh() { return m_fresh; } - bool has_value() { return m_has_value; } - const std::vector& value() { return m_value; } - - void debug_dump(); - - private: - friend class e::intrusive_ptr; - void inc() { ++m_ref; } - void dec() { if (--m_ref == 0) delete this; } - - private: - size_t m_ref; - const uint64_t m_prev_version; - const uint64_t m_this_version; - bool m_acked; - bool m_fresh; - const bool m_has_value; - - uint64_t m_recv_config_version; - virtual_server_id m_recv; // we recv from here - uint64_t m_sent_config_version; - virtual_server_id m_sent; // we sent to here - - const std::vector m_value; - const std::auto_ptr m_memory; - - enum { UNKNOWN, CONTINUOUS, DISCONTINUOUS } m_type; - region_id m_this_old_region; - region_id m_this_new_region; - region_id m_prev_region; - region_id m_next_region; - - private: - key_operation(const key_operation&); - key_operation& operator = (const key_operation&); +public: + key_operation(uint64_t old_version, + uint64_t new_version, + bool fresh, + bool has_value, + const std::vector &value, + std::auto_ptr memory); + ~key_operation() throw (); + +public: + uint64_t prev_version() const { return m_prev_version; } + uint64_t this_version() const { return m_this_version; } + + // the state of this op + void mark_acked() { m_acked = true; } + // can we ack this op AND remove it from local state? + bool ackable() const { return m_acked; } + + // who we recv/sent from/to along the chain + void set_recv(uint64_t version, const virtual_server_id &vsi) + { m_recv_config_version = version; m_recv = vsi; } + bool recv_from(uint64_t version) const { return version == m_recv_config_version; } + virtual_server_id recv_from() const { return m_recv; } + void set_sent(uint64_t version, const virtual_server_id &vsi) + { m_sent_config_version = version; m_sent = vsi; } + virtual_server_id sent_to() const { return m_sent; } + uint64_t sent_version() const { return m_sent_config_version; } + bool sent_to(uint64_t version, const virtual_server_id &vsi) const + { return m_sent_config_version == version && m_sent == vsi; } + + // the path of the op through the value-dependent chain + bool is_continuous() { return m_type == CONTINUOUS; } + bool is_discontinuous() { return m_type == DISCONTINUOUS; } + // call before hashing + void set_continuous(); + // call after hashing; must call above first + void set_continuous_hashes(const region_id &prev_region, + const region_id &this_old_region, + const region_id &this_new_region, + const region_id &next_region); + void set_discontinuous(const region_id &prev_region, + const region_id &this_old_region, + const region_id &this_new_region, + const region_id &next_region); + region_id prev_region() const { return m_prev_region; } + region_id this_old_region() const { return m_this_old_region; } + region_id this_new_region() const { return m_this_new_region; } + region_id next_region() const { return m_next_region; } + + // the value set by this op + bool is_fresh() { return m_fresh; } + bool has_value() { return m_has_value; } + const std::vector &value() { return m_value; } + + void debug_dump(); + +private: + friend class e::intrusive_ptr; + void inc() { ++m_ref; } + void dec() { if (--m_ref == 0) delete this; } + +private: + size_t m_ref; + const uint64_t m_prev_version; + const uint64_t m_this_version; + bool m_acked; + bool m_fresh; + const bool m_has_value; + + uint64_t m_recv_config_version; + virtual_server_id m_recv; // we recv from here + uint64_t m_sent_config_version; + virtual_server_id m_sent; // we sent to here + + const std::vector m_value; + const std::auto_ptr m_memory; + + enum { UNKNOWN, CONTINUOUS, DISCONTINUOUS } m_type; + region_id m_this_old_region; + region_id m_this_new_region; + region_id m_prev_region; + region_id m_next_region; + +private: + key_operation(const key_operation &); + key_operation &operator = (const key_operation &); }; END_HYPERDEX_NAMESPACE diff --git a/daemon/key_region.cc b/daemon/key_region.cc index 7d09e6597..e8f2f3d4e 100644 --- a/daemon/key_region.cc +++ b/daemon/key_region.cc @@ -31,48 +31,46 @@ using hyperdex::key_region; key_region :: key_region() - : region() - , key() + : region() + , key() { } -key_region :: key_region(const region_id& r, const e::slice& k) - : region(r) - , key(reinterpret_cast(k.data()), k.size()) +key_region :: key_region(const region_id &r, const e::slice &k) + : region(r) + , key(reinterpret_cast(k.data()), k.size()) { } -key_region :: key_region(const key_region& other) - : region(other.region) - , key(other.key) +key_region :: key_region(const key_region &other) + : region(other.region) + , key(other.key) { } bool -key_region :: operator < (const key_region& rhs) const +key_region :: operator < (const key_region &rhs) const { - if (region == rhs.region) - { - return key < rhs.key; - } - - return region < rhs.region; + if (region == rhs.region) + { + return key < rhs.key; + } + return region < rhs.region; } bool -key_region :: operator == (const key_region& rhs) const +key_region :: operator == (const key_region &rhs) const { - return region == rhs.region && key == rhs.key; + return region == rhs.region && key == rhs.key; } -key_region& -key_region :: operator = (const key_region& rhs) +key_region & +key_region :: operator = (const key_region &rhs) { - if (this != &rhs) - { - region = rhs.region; - key = rhs.key; - } - - return *this; + if (this != &rhs) + { + region = rhs.region; + key = rhs.key; + } + return *this; } diff --git a/daemon/key_region.h b/daemon/key_region.h index f26b3d2fb..dce1660a4 100644 --- a/daemon/key_region.h +++ b/daemon/key_region.h @@ -39,22 +39,22 @@ BEGIN_HYPERDEX_NAMESPACE class key_region { - public: - key_region(); - key_region(const region_id& r, const e::slice& k); - key_region(const key_region& other); +public: + key_region(); + key_region(const region_id &r, const e::slice &k); + key_region(const key_region &other); - public: - bool operator < (const key_region& rhs) const; - bool operator == (const key_region& rhs) const; - key_region& operator = (const key_region& rhs); +public: + bool operator < (const key_region &rhs) const; + bool operator == (const key_region &rhs) const; + key_region &operator = (const key_region &rhs); - public: - region_id region; - std::string key; +public: + region_id region; + std::string key; - private: - friend class e::compat::hash; +private: + friend class e::compat::hash; }; END_HYPERDEX_NAMESPACE @@ -64,12 +64,12 @@ BEGIN_E_COMPAT_NAMESPACE template <> struct hash { - size_t operator()(const hyperdex::key_region& kr) const - { - return CityHash64WithSeed(reinterpret_cast(kr.key.data()), - kr.key.size(), - e::compat::hash()(kr.region.get())); - } + size_t operator()(const hyperdex::key_region &kr) const + { + return CityHash64WithSeed(reinterpret_cast(kr.key.data()), + kr.key.size(), + e::compat::hash()(kr.region.get())); + } }; END_E_COMPAT_NAMESPACE diff --git a/daemon/key_state.cc b/daemon/key_state.cc index d0383f46a..e946da732 100644 --- a/daemon/key_state.cc +++ b/daemon/key_state.cc @@ -51,975 +51,886 @@ using hyperdex::key_state; struct key_state::deferred_key_change { - deferred_key_change(const server_id& _from, - uint64_t _nonce, uint64_t _version, - std::auto_ptr _kc, - std::auto_ptr _backing) - : from(_from) - , nonce(_nonce) - , version(_version) - , kc(_kc) - , backing(_backing) - , m_ref(0) - { - } - - void inc() { ++m_ref; } - void dec() { if (--m_ref == 0) delete this; } - - const server_id from; - const uint64_t nonce; - const uint64_t version; - const std::auto_ptr kc; - const std::auto_ptr backing; - - private: - size_t m_ref; - - private: - deferred_key_change(const deferred_key_change&); - deferred_key_change& operator = (const deferred_key_change&); + deferred_key_change(const server_id &_from, + uint64_t _nonce, uint64_t _version, + std::auto_ptr _kc, + std::auto_ptr _backing) + : from(_from) + , nonce(_nonce) + , version(_version) + , kc(_kc) + , backing(_backing) + , m_ref(0) + { + } + + void inc() { ++m_ref; } + void dec() { if (--m_ref == 0) delete this; } + + const server_id from; + const uint64_t nonce; + const uint64_t version; + const std::auto_ptr kc; + const std::auto_ptr backing; + +private: + size_t m_ref; + +private: + deferred_key_change(const deferred_key_change &); + deferred_key_change &operator = (const deferred_key_change &); }; struct key_state::client_response { - client_response() : respond_after(0), client(), nonce(), ret() {} - client_response(uint64_t _respond_after, - server_id _client, - uint64_t _nonce, - network_returncode _ret) - : respond_after(_respond_after) - , client(_client) - , nonce(_nonce) - , ret(_ret) - { - } - ~client_response() throw () {} - - // intentionally backwards so the max heap becomes min heap. - bool operator < (const client_response& rhs) - { - return respond_after > rhs.respond_after; - } - - uint64_t respond_after; - server_id client; - uint64_t nonce; - network_returncode ret; + client_response() : respond_after(0), client(), nonce(), ret() {} + client_response(uint64_t _respond_after, + server_id _client, + uint64_t _nonce, + network_returncode _ret) + : respond_after(_respond_after) + , client(_client) + , nonce(_nonce) + , ret(_ret) + { + } + ~client_response() throw () {} + + // intentionally backwards so the max heap becomes min heap. + bool operator < (const client_response &rhs) + { + return respond_after > rhs.respond_after; + } + + uint64_t respond_after; + server_id client; + uint64_t nonce; + network_returncode ret; }; -key_state :: key_state(const key_region& kr) - : m_ri(kr.region) - , m_key_backing(reinterpret_cast(kr.key.data()), kr.key.size()) - , m_key(m_key_backing.data(), m_key_backing.size()) - , m_client_atomics() - , m_chain_ops() - , m_chain_subspaces() - , m_chain_acks() - , m_lock() - , m_avail(&m_lock) - , m_someone_is_working_the_state_machine(false) - , m_someone_needs_to_work_the_state_machine(false) - , m_initialized(false) - , m_has_old_value(false) - , m_old_version(0) - , m_old_value() - , m_old_disk_ref() - , m_old_op() - , m_client_responses_heap() - , m_committable() - , m_committable_empty(true) - , m_blocked() - , m_blocked_empty(true) - , m_deferred() - , m_deferred_empty(true) - , m_changes() - , m_changes_empty(true) +key_state :: key_state(const key_region &kr) + : m_ri(kr.region) + , m_key_backing(reinterpret_cast(kr.key.data()), kr.key.size()) + , m_key(m_key_backing.data(), m_key_backing.size()) + , m_client_atomics() + , m_chain_ops() + , m_chain_subspaces() + , m_chain_acks() + , m_lock() + , m_avail(&m_lock) + , m_someone_is_working_the_state_machine(false) + , m_someone_needs_to_work_the_state_machine(false) + , m_initialized(false) + , m_has_old_value(false) + , m_old_version(0) + , m_old_value() + , m_old_disk_ref() + , m_old_op() + , m_client_responses_heap() + , m_committable() + , m_committable_empty(true) + , m_blocked() + , m_blocked_empty(true) + , m_deferred() + , m_deferred_empty(true) + , m_changes() + , m_changes_empty(true) { } key_state :: ~key_state() throw () { - m_lock.lock(); - m_lock.unlock(); + m_lock.lock(); + m_lock.unlock(); } key_region key_state :: state_key() const { - return key_region(m_ri, m_key); + return key_region(m_ri, m_key); } bool key_state :: finished() { - po6::threads::mutex::hold hold(&m_lock); - return !m_someone_is_working_the_state_machine && - !m_someone_needs_to_work_the_state_machine && - m_committable_empty && - m_blocked_empty && - m_deferred_empty && - m_changes_empty; + po6::threads::mutex::hold hold(&m_lock); + return !m_someone_is_working_the_state_machine && + !m_someone_needs_to_work_the_state_machine && + m_committable_empty && + m_blocked_empty && + m_deferred_empty && + m_changes_empty; } bool key_state :: initialized() { - po6::threads::mutex::hold hold(&m_lock); - return m_initialized; + po6::threads::mutex::hold hold(&m_lock); + return m_initialized; } hyperdex::datalayer::returncode -key_state :: initialize(datalayer* data, - const schema&, - const region_id& ri) +key_state :: initialize(datalayer *data, + const schema &, + const region_id &ri) { - po6::threads::mutex::hold hold(&m_lock); - - // maybe we get lucky - if (m_initialized) - { - return datalayer::SUCCESS; - } - - while (m_someone_is_working_the_state_machine) - { - m_avail.wait(); - } - - // make sure someone else didn't initialize while we waited - if (m_initialized) - { - return datalayer::SUCCESS; - } - - datalayer::returncode rc = data->get(ri, m_key, &m_old_value, &m_old_version, &m_old_disk_ref); - - switch (rc) - { - case datalayer::SUCCESS: - m_has_old_value = true; - break; - case datalayer::NOT_FOUND: - case datalayer::BAD_ENCODING: - case datalayer::CORRUPTION: - case datalayer::IO_ERROR: - case datalayer::LEVELDB_ERROR: - default: - m_has_old_value = false; - m_old_version = 0; - break; - } - - m_initialized = true; - CHECK_INVARIANTS(); - return rc; + po6::threads::mutex::hold hold(&m_lock); + // maybe we get lucky + if (m_initialized) + { + return datalayer::SUCCESS; + } + while (m_someone_is_working_the_state_machine) + { + m_avail.wait(); + } + // make sure someone else didn't initialize while we waited + if (m_initialized) + { + return datalayer::SUCCESS; + } + datalayer::returncode rc = data->get(ri, m_key, &m_old_value, &m_old_version, &m_old_disk_ref); + switch (rc) + { + case datalayer::SUCCESS: + m_has_old_value = true; + break; + case datalayer::NOT_FOUND: + case datalayer::BAD_ENCODING: + case datalayer::CORRUPTION: + case datalayer::IO_ERROR: + case datalayer::LEVELDB_ERROR: + default: + m_has_old_value = false; + m_old_version = 0; + break; + } + m_initialized = true; + CHECK_INVARIANTS(); + return rc; } struct key_state::stub_client_atomic { - stub_client_atomic(const server_id& f, - uint64_t n, - std::auto_ptr k, - std::auto_ptr b) - : from(f), nonce(n), kc(k), backing(b) {} - ~stub_client_atomic() throw () {} - - server_id from; - uint64_t nonce; - std::auto_ptr kc; - std::auto_ptr backing; + stub_client_atomic(const server_id &f, + uint64_t n, + std::auto_ptr k, + std::auto_ptr b) + : from(f), nonce(n), kc(k), backing(b) {} + ~stub_client_atomic() throw () {} + + server_id from; + uint64_t nonce; + std::auto_ptr kc; + std::auto_ptr backing; }; void -key_state :: enqueue_client_atomic(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - const server_id& from, +key_state :: enqueue_client_atomic(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + const server_id &from, uint64_t nonce, std::auto_ptr kc, std::auto_ptr backing) { - bool have_it = possibly_takeover_state_machine(); - - if (have_it) - { - do_client_atomic(rm, us, sc, from, nonce, kc, backing); - work_state_machine_with_work_bit(rm, us, sc); - } - else - { - m_client_atomics.push(new stub_client_atomic(from, nonce, kc, backing)); - someone_needs_to_work_the_state_machine(); - work_state_machine_or_pass_the_buck(rm, us, sc); - } + bool have_it = possibly_takeover_state_machine(); + if (have_it) + { + do_client_atomic(rm, us, sc, from, nonce, kc, backing); + work_state_machine_with_work_bit(rm, us, sc); + } + else + { + m_client_atomics.push(new stub_client_atomic(from, nonce, kc, backing)); + someone_needs_to_work_the_state_machine(); + work_state_machine_or_pass_the_buck(rm, us, sc); + } } struct key_state::stub_chain_op { - stub_chain_op(const virtual_server_id& _from, - uint64_t _old_version, - uint64_t _new_version, - bool _fresh, - bool _has_value, - const std::vector& _value, - std::auto_ptr _backing) - : from(_from) - , old_version(_old_version) - , new_version(_new_version) - , fresh(_fresh) - , has_value(_has_value) - , value(_value) - , backing(_backing) - { - } - ~stub_chain_op() throw () {} - - virtual_server_id from; - uint64_t old_version; - uint64_t new_version; - bool fresh; - bool has_value; - std::vector value; - std::auto_ptr backing; + stub_chain_op(const virtual_server_id &_from, + uint64_t _old_version, + uint64_t _new_version, + bool _fresh, + bool _has_value, + const std::vector &_value, + std::auto_ptr _backing) + : from(_from) + , old_version(_old_version) + , new_version(_new_version) + , fresh(_fresh) + , has_value(_has_value) + , value(_value) + , backing(_backing) + { + } + ~stub_chain_op() throw () {} + + virtual_server_id from; + uint64_t old_version; + uint64_t new_version; + bool fresh; + bool has_value; + std::vector value; + std::auto_ptr backing; }; void -key_state :: enqueue_chain_op(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - const virtual_server_id& from, +key_state :: enqueue_chain_op(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + const virtual_server_id &from, uint64_t old_version, uint64_t new_version, bool fresh, bool has_value, - const std::vector& value, + const std::vector &value, std::auto_ptr backing) { - bool have_it = possibly_takeover_state_machine(); - - if (have_it) - { - do_chain_op(rm, us, sc, from, old_version, new_version, fresh, has_value, value, backing); - work_state_machine_with_work_bit(rm, us, sc); - } - else - { - m_chain_ops.push(new stub_chain_op(from, old_version, new_version, fresh, has_value, value, backing)); - someone_needs_to_work_the_state_machine(); - work_state_machine_or_pass_the_buck(rm, us, sc); - } + bool have_it = possibly_takeover_state_machine(); + if (have_it) + { + do_chain_op(rm, us, sc, from, old_version, new_version, fresh, has_value, value, backing); + work_state_machine_with_work_bit(rm, us, sc); + } + else + { + m_chain_ops.push(new stub_chain_op(from, old_version, new_version, fresh, has_value, value, backing)); + someone_needs_to_work_the_state_machine(); + work_state_machine_or_pass_the_buck(rm, us, sc); + } } struct key_state::stub_chain_subspace { - stub_chain_subspace(const virtual_server_id& _from, - uint64_t _old_version, - uint64_t _new_version, - const std::vector& _value, - std::auto_ptr _backing, - const region_id& _prev_region, - const region_id& _this_old_region, - const region_id& _this_new_region, - const region_id& _next_region) - : from(_from) - , old_version(_old_version) - , new_version(_new_version) - , value(_value) - , backing(_backing) - , prev_region(_prev_region) - , this_old_region(_this_old_region) - , this_new_region(_this_new_region) - , next_region(_next_region) - { - } - ~stub_chain_subspace() throw () {} - - virtual_server_id from; - uint64_t old_version; - uint64_t new_version; - std::vector value; - std::auto_ptr backing; - region_id prev_region; - region_id this_old_region; - region_id this_new_region; - region_id next_region; + stub_chain_subspace(const virtual_server_id &_from, + uint64_t _old_version, + uint64_t _new_version, + const std::vector &_value, + std::auto_ptr _backing, + const region_id &_prev_region, + const region_id &_this_old_region, + const region_id &_this_new_region, + const region_id &_next_region) + : from(_from) + , old_version(_old_version) + , new_version(_new_version) + , value(_value) + , backing(_backing) + , prev_region(_prev_region) + , this_old_region(_this_old_region) + , this_new_region(_this_new_region) + , next_region(_next_region) + { + } + ~stub_chain_subspace() throw () {} + + virtual_server_id from; + uint64_t old_version; + uint64_t new_version; + std::vector value; + std::auto_ptr backing; + region_id prev_region; + region_id this_old_region; + region_id this_new_region; + region_id next_region; }; void -key_state :: enqueue_chain_subspace(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - const virtual_server_id& from, +key_state :: enqueue_chain_subspace(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + const virtual_server_id &from, uint64_t old_version, uint64_t new_version, - const std::vector& value, + const std::vector &value, std::auto_ptr backing, - const region_id& prev_region, - const region_id& this_old_region, - const region_id& this_new_region, - const region_id& next_region) + const region_id &prev_region, + const region_id &this_old_region, + const region_id &this_new_region, + const region_id &next_region) { - bool have_it = possibly_takeover_state_machine(); - - if (have_it) - { - do_chain_subspace(rm, us, sc, from, old_version, new_version, value, backing, prev_region, this_old_region, this_new_region, next_region); - work_state_machine_with_work_bit(rm, us, sc); - } - else - { - m_chain_subspaces.push(new stub_chain_subspace(from, old_version, new_version, value, backing, prev_region, this_old_region, this_new_region, next_region)); - someone_needs_to_work_the_state_machine(); - work_state_machine_or_pass_the_buck(rm, us, sc); - } + bool have_it = possibly_takeover_state_machine(); + if (have_it) + { + do_chain_subspace(rm, us, sc, from, old_version, new_version, value, backing, prev_region, this_old_region, this_new_region, next_region); + work_state_machine_with_work_bit(rm, us, sc); + } + else + { + m_chain_subspaces.push(new stub_chain_subspace(from, old_version, new_version, value, backing, prev_region, this_old_region, this_new_region, next_region)); + someone_needs_to_work_the_state_machine(); + work_state_machine_or_pass_the_buck(rm, us, sc); + } } struct key_state::stub_chain_ack { - stub_chain_ack(const virtual_server_id& _from, - uint64_t _version) - : from(_from) - , version(_version) - { - } - ~stub_chain_ack() throw () {} - - virtual_server_id from; - uint64_t version; + stub_chain_ack(const virtual_server_id &_from, + uint64_t _version) + : from(_from) + , version(_version) + { + } + ~stub_chain_ack() throw () {} + + virtual_server_id from; + uint64_t version; }; void -key_state :: enqueue_chain_ack(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - const virtual_server_id& from, +key_state :: enqueue_chain_ack(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + const virtual_server_id &from, uint64_t version) { - bool have_it = possibly_takeover_state_machine(); - - if (have_it) - { - do_chain_ack(rm, us, sc, from, version); - work_state_machine_with_work_bit(rm, us, sc); - } - else - { - m_chain_acks.push(new stub_chain_ack(from, version)); - someone_needs_to_work_the_state_machine(); - work_state_machine_or_pass_the_buck(rm, us, sc); - } + bool have_it = possibly_takeover_state_machine(); + if (have_it) + { + do_chain_ack(rm, us, sc, from, version); + work_state_machine_with_work_bit(rm, us, sc); + } + else + { + m_chain_acks.push(new stub_chain_ack(from, version)); + someone_needs_to_work_the_state_machine(); + work_state_machine_or_pass_the_buck(rm, us, sc); + } } void -key_state :: work_state_machine(replication_manager* rm, - const virtual_server_id& us, - const schema& sc) +key_state :: work_state_machine(replication_manager *rm, + const virtual_server_id &us, + const schema &sc) { - work_state_machine_or_pass_the_buck(rm, us, sc); + work_state_machine_or_pass_the_buck(rm, us, sc); } uint64_t key_state :: max_version() { - po6::threads::mutex::hold hold(&m_lock); - - while (m_someone_is_working_the_state_machine) - { - m_avail.wait(); - } - - uint64_t ret = 0; - - for (key_operation_list_t::const_iterator it = m_committable.begin(); - it != m_committable.end(); ++it) - { - ret = std::max(ret, (*it)->this_version()); - } - - for (key_operation_list_t::const_iterator it = m_blocked.begin(); - it != m_blocked.end(); ++it) - { - ret = std::max(ret, (*it)->this_version()); - } - - for (key_operation_list_t::const_iterator it = m_deferred.begin(); - it != m_deferred.end(); ++it) - { - ret = std::max(ret, (*it)->this_version()); - } - - for (key_change_list_t::const_iterator it = m_changes.begin(); - it != m_changes.end(); ++it) - { - ret = std::max(ret, (*it)->version); - } - - return ret; + po6::threads::mutex::hold hold(&m_lock); + while (m_someone_is_working_the_state_machine) + { + m_avail.wait(); + } + uint64_t ret = 0; + for (key_operation_list_t::const_iterator it = m_committable.begin(); + it != m_committable.end(); ++it) + { + ret = std::max(ret, (*it)->this_version()); + } + for (key_operation_list_t::const_iterator it = m_blocked.begin(); + it != m_blocked.end(); ++it) + { + ret = std::max(ret, (*it)->this_version()); + } + for (key_operation_list_t::const_iterator it = m_deferred.begin(); + it != m_deferred.end(); ++it) + { + ret = std::max(ret, (*it)->this_version()); + } + for (key_change_list_t::const_iterator it = m_changes.begin(); + it != m_changes.end(); ++it) + { + ret = std::max(ret, (*it)->version); + } + return ret; } void -key_state :: reconfigure(e::garbage_collector* gc) +key_state :: reconfigure(e::garbage_collector *gc) { - po6::threads::mutex::hold hold(&m_lock); - - while (m_someone_is_working_the_state_machine) - { - m_avail.wait(); - } - - stub_client_atomic* sca; - stub_chain_op* sco; - stub_chain_subspace* scs; - stub_chain_ack* scack; - - while (m_client_atomics.pop(gc, &sca)) - { - delete sca; - } - - while (m_chain_ops.pop(gc, &sco)) - { - delete sco; - } - - while (m_chain_subspaces.pop(gc, &scs)) - { - delete scs; - } - - while (m_chain_acks.pop(gc, &scack)) - { - delete scack; - } - - m_deferred.clear(); - CHECK_INVARIANTS(); + po6::threads::mutex::hold hold(&m_lock); + while (m_someone_is_working_the_state_machine) + { + m_avail.wait(); + } + stub_client_atomic *sca; + stub_chain_op *sco; + stub_chain_subspace *scs; + stub_chain_ack *scack; + while (m_client_atomics.pop(gc, &sca)) + { + delete sca; + } + while (m_chain_ops.pop(gc, &sco)) + { + delete sco; + } + while (m_chain_subspaces.pop(gc, &scs)) + { + delete scs; + } + while (m_chain_acks.pop(gc, &scack)) + { + delete scack; + } + m_deferred.clear(); + CHECK_INVARIANTS(); } void -key_state :: reset(e::garbage_collector* gc) +key_state :: reset(e::garbage_collector *gc) { - po6::threads::mutex::hold hold(&m_lock); - - while (m_someone_is_working_the_state_machine) - { - m_avail.wait(); - } - - stub_client_atomic* sca; - stub_chain_op* sco; - stub_chain_subspace* scs; - stub_chain_ack* scack; - - while (m_client_atomics.pop(gc, &sca)) - { - delete sca; - } - - while (m_chain_ops.pop(gc, &sco)) - { - delete sco; - } - - while (m_chain_subspaces.pop(gc, &scs)) - { - delete scs; - } - - while (m_chain_acks.pop(gc, &scack)) - { - delete scack; - } - - m_someone_is_working_the_state_machine = false; - m_someone_needs_to_work_the_state_machine = false; - m_avail.broadcast(); - - m_committable.clear(); - m_blocked.clear(); - m_deferred.clear(); - m_changes.clear(); - CHECK_INVARIANTS(); + po6::threads::mutex::hold hold(&m_lock); + while (m_someone_is_working_the_state_machine) + { + m_avail.wait(); + } + stub_client_atomic *sca; + stub_chain_op *sco; + stub_chain_subspace *scs; + stub_chain_ack *scack; + while (m_client_atomics.pop(gc, &sca)) + { + delete sca; + } + while (m_chain_ops.pop(gc, &sco)) + { + delete sco; + } + while (m_chain_subspaces.pop(gc, &scs)) + { + delete scs; + } + while (m_chain_acks.pop(gc, &scack)) + { + delete scack; + } + m_someone_is_working_the_state_machine = false; + m_someone_needs_to_work_the_state_machine = false; + m_avail.broadcast(); + m_committable.clear(); + m_blocked.clear(); + m_deferred.clear(); + m_changes.clear(); + CHECK_INVARIANTS(); } void -key_state :: resend_committable(replication_manager* rm, - const virtual_server_id& us) +key_state :: resend_committable(replication_manager *rm, + const virtual_server_id &us) { - po6::threads::mutex::hold hold(&m_lock); - - while (m_someone_is_working_the_state_machine) - { - m_avail.wait(); - } - - CHECK_INVARIANTS(); - - for (key_operation_list_t::iterator it = m_committable.begin(); - it != m_committable.end(); ++it) - { - // skip those messages already sent in this version - if ((*it)->sent_version() >= rm->m_daemon->m_config.version()) - { - continue; - } - - (*it)->set_sent(0, virtual_server_id()); - rm->send_message(us, m_key, *it); - } - - CHECK_INVARIANTS(); + po6::threads::mutex::hold hold(&m_lock); + while (m_someone_is_working_the_state_machine) + { + m_avail.wait(); + } + CHECK_INVARIANTS(); + for (key_operation_list_t::iterator it = m_committable.begin(); + it != m_committable.end(); ++it) + { + // skip those messages already sent in this version + if ((*it)->sent_version() >= rm->m_daemon->m_config.version()) + { + continue; + } + (*it)->set_sent(0, virtual_server_id()); + rm->send_message(us, m_key, *it); + } + CHECK_INVARIANTS(); } void -key_state :: append_all_versions(std::vector >* versions) +key_state :: append_all_versions(std::vector > *versions) { - po6::threads::mutex::hold hold(&m_lock); - - while (m_someone_is_working_the_state_machine) - { - m_avail.wait(); - } - - size_t sz = versions->size() + m_committable.size() + m_blocked.size() + m_deferred.size(); - - if (versions->capacity() < sz) - { - versions->reserve(std::max(sz, versions->capacity() + (versions->capacity() >> 1ULL))); - } - - for (key_operation_list_t::iterator it = m_committable.begin(); - it != m_committable.end(); ++it) - { - versions->push_back(std::make_pair(m_ri, (*it)->this_version())); - } - - for (key_operation_list_t::iterator it = m_blocked.begin(); - it != m_blocked.end(); ++it) - { - versions->push_back(std::make_pair(m_ri, (*it)->this_version())); - } - - for (key_operation_list_t::iterator it = m_deferred.begin(); - it != m_deferred.end(); ++it) - { - versions->push_back(std::make_pair(m_ri, (*it)->this_version())); - } - - // XXX + po6::threads::mutex::hold hold(&m_lock); + while (m_someone_is_working_the_state_machine) + { + m_avail.wait(); + } + size_t sz = versions->size() + m_committable.size() + m_blocked.size() + m_deferred.size(); + if (versions->capacity() < sz) + { + versions->reserve(std::max(sz, versions->capacity() + (versions->capacity() >> 1ULL))); + } + for (key_operation_list_t::iterator it = m_committable.begin(); + it != m_committable.end(); ++it) + { + versions->push_back(std::make_pair(m_ri, (*it)->this_version())); + } + for (key_operation_list_t::iterator it = m_blocked.begin(); + it != m_blocked.end(); ++it) + { + versions->push_back(std::make_pair(m_ri, (*it)->this_version())); + } + for (key_operation_list_t::iterator it = m_deferred.begin(); + it != m_deferred.end(); ++it) + { + versions->push_back(std::make_pair(m_ri, (*it)->this_version())); + } + // XXX } void key_state :: debug_dump() { - po6::threads::mutex::hold hold(&m_lock); - - while (m_someone_is_working_the_state_machine) - { - m_avail.wait(); - } - - LOG(INFO) << " old " << m_old_version; - - for (key_operation_list_t::const_iterator it = m_committable.begin(); - it != m_committable.end(); ++it) - { - LOG(INFO) << " committable " << (*it)->this_version(); - (*it)->debug_dump(); - } - - for (key_operation_list_t::const_iterator it = m_blocked.begin(); - it != m_blocked.end(); ++it) - { - LOG(INFO) << " blocked " << (*it)->this_version(); - (*it)->debug_dump(); - } - - for (key_operation_list_t::const_iterator it = m_deferred.begin(); - it != m_deferred.end(); ++it) - { - LOG(INFO) << " deferred " << (*it)->this_version(); - (*it)->debug_dump(); - } + po6::threads::mutex::hold hold(&m_lock); + while (m_someone_is_working_the_state_machine) + { + m_avail.wait(); + } + LOG(INFO) << " old " << m_old_version; + for (key_operation_list_t::const_iterator it = m_committable.begin(); + it != m_committable.end(); ++it) + { + LOG(INFO) << " committable " << (*it)->this_version(); + (*it)->debug_dump(); + } + for (key_operation_list_t::const_iterator it = m_blocked.begin(); + it != m_blocked.end(); ++it) + { + LOG(INFO) << " blocked " << (*it)->this_version(); + (*it)->debug_dump(); + } + for (key_operation_list_t::const_iterator it = m_deferred.begin(); + it != m_deferred.end(); ++it) + { + LOG(INFO) << " deferred " << (*it)->this_version(); + (*it)->debug_dump(); + } } void key_state :: check_invariants() const { - assert(m_initialized); - uint64_t version = 0; - - for (key_operation_list_t::const_iterator it = m_committable.begin(); - it != m_committable.end(); ++it) - { - key_operation* op = it->get(); - assert(op); - assert(op->prev_version() < op->this_version()); - assert(version == 0 || version == op->prev_version()); - version = op->this_version(); - assert(op->is_continuous() || op->is_discontinuous()); - } - - for (key_operation_list_t::const_iterator it = m_blocked.begin(); - it != m_blocked.end(); ++it) - { - key_operation* op = it->get(); - assert(op); - assert(op->prev_version() < op->this_version()); - assert(version == 0 || version == op->prev_version()); - version = op->this_version(); - assert(op->is_continuous() || op->is_discontinuous()); - } - - uint64_t deferred_max_version = version; - - for (key_operation_list_t::const_iterator it = m_deferred.begin(); - it != m_deferred.end(); ++it) - { - key_operation* op = it->get(); - assert(op); - assert(op->prev_version() < op->this_version()); - assert(version == 0 || version <= op->prev_version()); - assert(version == 0 || version < op->this_version()); - deferred_max_version = std::max(op->this_version(), deferred_max_version); - assert(op->is_continuous() || op->is_discontinuous()); - } - - version = deferred_max_version; - - for (key_change_list_t::const_iterator it = m_changes.begin(); - it != m_changes.end(); ++it) - { - deferred_key_change* dkc = it->get(); - assert(dkc); - assert(version == 0 || version < dkc->version); - version = dkc->version; - } - - assert(m_committable.empty() || m_old_version <= m_committable.back()->this_version()); - assert(m_blocked.empty() || m_old_version < m_blocked.front()->this_version()); - assert(m_deferred.empty() || m_old_version < m_deferred.front()->this_version()); - assert(m_changes.empty() || m_old_version < m_changes.front()->version); - - assert(m_committable_empty == m_committable.empty()); - assert(m_blocked_empty == m_blocked.empty()); - assert(m_deferred_empty == m_deferred.empty()); - assert(m_changes_empty == m_changes.empty()); + assert(m_initialized); + uint64_t version = 0; + for (key_operation_list_t::const_iterator it = m_committable.begin(); + it != m_committable.end(); ++it) + { + key_operation *op = it->get(); + assert(op); + assert(op->prev_version() < op->this_version()); + assert(version == 0 || version == op->prev_version()); + version = op->this_version(); + assert(op->is_continuous() || op->is_discontinuous()); + } + for (key_operation_list_t::const_iterator it = m_blocked.begin(); + it != m_blocked.end(); ++it) + { + key_operation *op = it->get(); + assert(op); + assert(op->prev_version() < op->this_version()); + assert(version == 0 || version == op->prev_version()); + version = op->this_version(); + assert(op->is_continuous() || op->is_discontinuous()); + } + uint64_t deferred_max_version = version; + for (key_operation_list_t::const_iterator it = m_deferred.begin(); + it != m_deferred.end(); ++it) + { + key_operation *op = it->get(); + assert(op); + assert(op->prev_version() < op->this_version()); + assert(version == 0 || version <= op->prev_version()); + assert(version == 0 || version < op->this_version()); + deferred_max_version = std::max(op->this_version(), deferred_max_version); + assert(op->is_continuous() || op->is_discontinuous()); + } + version = deferred_max_version; + for (key_change_list_t::const_iterator it = m_changes.begin(); + it != m_changes.end(); ++it) + { + deferred_key_change *dkc = it->get(); + assert(dkc); + assert(version == 0 || version < dkc->version); + version = dkc->version; + } + assert(m_committable.empty() || m_old_version <= m_committable.back()->this_version()); + assert(m_blocked.empty() || m_old_version < m_blocked.front()->this_version()); + assert(m_deferred.empty() || m_old_version < m_deferred.front()->this_version()); + assert(m_changes.empty() || m_old_version < m_changes.front()->version); + assert(m_committable_empty == m_committable.empty()); + assert(m_blocked_empty == m_blocked.empty()); + assert(m_deferred_empty == m_deferred.empty()); + assert(m_changes_empty == m_changes.empty()); } void key_state :: someone_needs_to_work_the_state_machine() { - po6::threads::mutex::hold hold(&m_lock); - m_someone_needs_to_work_the_state_machine = true; + po6::threads::mutex::hold hold(&m_lock); + m_someone_needs_to_work_the_state_machine = true; } void -key_state :: work_state_machine_or_pass_the_buck(replication_manager* rm, - const virtual_server_id& us, - const schema& sc) +key_state :: work_state_machine_or_pass_the_buck(replication_manager *rm, + const virtual_server_id &us, + const schema &sc) { - if (possibly_takeover_state_machine()) - { - work_state_machine_with_work_bit(rm, us, sc); - } + if (possibly_takeover_state_machine()) + { + work_state_machine_with_work_bit(rm, us, sc); + } } void key_state :: takeover_state_machine() { - po6::threads::mutex::hold hold(&m_lock); - - while (m_someone_is_working_the_state_machine) - { - m_avail.wait(); - } - - m_someone_is_working_the_state_machine = true; + po6::threads::mutex::hold hold(&m_lock); + while (m_someone_is_working_the_state_machine) + { + m_avail.wait(); + } + m_someone_is_working_the_state_machine = true; } bool key_state :: possibly_takeover_state_machine() { - po6::threads::mutex::hold hold(&m_lock); - bool have_it = !m_someone_is_working_the_state_machine; - m_someone_is_working_the_state_machine = true; - return have_it; + po6::threads::mutex::hold hold(&m_lock); + bool have_it = !m_someone_is_working_the_state_machine; + m_someone_is_working_the_state_machine = true; + return have_it; } void -key_state :: work_state_machine_with_work_bit(replication_manager* rm, - const virtual_server_id& us, - const schema& sc) +key_state :: work_state_machine_with_work_bit(replication_manager *rm, + const virtual_server_id &us, + const schema &sc) { - while (true) - { - m_lock.lock(); - m_someone_needs_to_work_the_state_machine = false; - m_lock.unlock(); - e::garbage_collector* gc = &rm->m_daemon->m_gc; - stub_client_atomic* sca; - stub_chain_op* sco; - stub_chain_subspace* scs; - stub_chain_ack* scack; - - while (m_client_atomics.pop(gc, &sca)) - { - do_client_atomic(rm, us, sc, sca->from, sca->nonce, sca->kc, sca->backing); - delete sca; - } - - while (m_chain_ops.pop(gc, &sco)) - { - do_chain_op(rm, us, sc, sco->from, sco->old_version, sco->new_version, sco->fresh, sco->has_value, sco->value, sco->backing); - delete sco; - } - - while (m_chain_subspaces.pop(gc, &scs)) - { - do_chain_subspace(rm, us, sc, scs->from, scs->old_version, scs->new_version, scs->value, scs->backing, - scs->prev_region, scs->this_old_region, scs->this_new_region, scs->next_region); - delete scs; - } - - while (m_chain_acks.pop(gc, &scack)) - { - do_chain_ack(rm, us, sc, scack->from, scack->version); - delete scack; - } - - bool did_work = false; - CHECK_INVARIANTS(); - - // Drain the blocked and deferred items first, because order does not - // matter. - // - // Then drain the changes queue as it relies upon the deferred queue to - // be empty. - // - // Finally drain the committable queue to batch-write as many items as - // possible to the disk. - - if (drain_queue(rm, us, sc, &m_blocked, &key_state::drain_blocked)) - { - did_work = true; - } - - if (drain_queue(rm, us, sc, &m_deferred, &key_state::drain_deferred)) - { - did_work = true; - } - - if (drain_queue(rm, us, sc, &m_changes, &key_state::drain_changes)) - { - did_work = true; - } - - if (did_work && m_committable.size() < 64) - { - // continue here because it will not hurt, and the more we can build - // up the "committable" queue, the more progress we can make - continue; - } - - if (drain_queue(rm, us, sc, &m_committable, &key_state::drain_committable)) - { - did_work = true; - } - - CHECK_INVARIANTS(); - send_responses(rm, us); - - if (did_work) - { - continue; - } - - bool done = false; - po6::threads::mutex::hold hold(&m_lock); - done = !m_someone_needs_to_work_the_state_machine; - m_someone_is_working_the_state_machine = !done; - - if (done) - { - m_committable_empty = m_committable.empty(); - m_blocked_empty = m_blocked.empty(); - m_deferred_empty = m_deferred.empty(); - m_changes_empty = m_changes.empty(); - m_avail.broadcast(); - break; - } - } + while (true) + { + m_lock.lock(); + m_someone_needs_to_work_the_state_machine = false; + m_lock.unlock(); + e::garbage_collector *gc = &rm->m_daemon->m_gc; + stub_client_atomic *sca; + stub_chain_op *sco; + stub_chain_subspace *scs; + stub_chain_ack *scack; + while (m_client_atomics.pop(gc, &sca)) + { + do_client_atomic(rm, us, sc, sca->from, sca->nonce, sca->kc, sca->backing); + delete sca; + } + while (m_chain_ops.pop(gc, &sco)) + { + do_chain_op(rm, us, sc, sco->from, sco->old_version, sco->new_version, sco->fresh, sco->has_value, sco->value, sco->backing); + delete sco; + } + while (m_chain_subspaces.pop(gc, &scs)) + { + do_chain_subspace(rm, us, sc, scs->from, scs->old_version, scs->new_version, scs->value, scs->backing, + scs->prev_region, scs->this_old_region, scs->this_new_region, scs->next_region); + delete scs; + } + while (m_chain_acks.pop(gc, &scack)) + { + do_chain_ack(rm, us, sc, scack->from, scack->version); + delete scack; + } + bool did_work = false; + CHECK_INVARIANTS(); + // Drain the blocked and deferred items first, because order does not + // matter. + // + // Then drain the changes queue as it relies upon the deferred queue to + // be empty. + // + // Finally drain the committable queue to batch-write as many items as + // possible to the disk. + if (drain_queue(rm, us, sc, &m_blocked, &key_state::drain_blocked)) + { + did_work = true; + } + if (drain_queue(rm, us, sc, &m_deferred, &key_state::drain_deferred)) + { + did_work = true; + } + if (drain_queue(rm, us, sc, &m_changes, &key_state::drain_changes)) + { + did_work = true; + } + if (did_work && m_committable.size() < 64) + { + // continue here because it will not hurt, and the more we can build + // up the "committable" queue, the more progress we can make + continue; + } + if (drain_queue(rm, us, sc, &m_committable, &key_state::drain_committable)) + { + did_work = true; + } + CHECK_INVARIANTS(); + send_responses(rm, us); + if (did_work) + { + continue; + } + bool done = false; + po6::threads::mutex::hold hold(&m_lock); + done = !m_someone_needs_to_work_the_state_machine; + m_someone_is_working_the_state_machine = !done; + if (done) + { + m_committable_empty = m_committable.empty(); + m_blocked_empty = m_blocked.empty(); + m_deferred_empty = m_deferred.empty(); + m_changes_empty = m_changes.empty(); + m_avail.broadcast(); + break; + } + } } void -key_state :: do_client_atomic(replication_manager* rm, - const virtual_server_id&, - const schema&, - const server_id& from, +key_state :: do_client_atomic(replication_manager *rm, + const virtual_server_id &, + const schema &, + const server_id &from, uint64_t nonce, std::auto_ptr kc, std::auto_ptr backing) { - uint64_t version = rm->m_idgen.generate_id(m_ri); - - if (version % datalayer::REGION_PERIODIC == 0) - { - rm->m_daemon->m_data.bump_version(m_ri, version); - } - - e::intrusive_ptr dkc; - dkc = new deferred_key_change(from, nonce, version, kc, backing); - m_changes.push_back(dkc); + uint64_t version = rm->m_idgen.generate_id(m_ri); + if (version % datalayer::REGION_PERIODIC == 0) + { + rm->m_daemon->m_data.bump_version(m_ri, version); + } + e::intrusive_ptr dkc; + dkc = new deferred_key_change(from, nonce, version, kc, backing); + m_changes.push_back(dkc); } void -key_state :: do_chain_op(replication_manager* rm, - const virtual_server_id& us, - const schema&, - const virtual_server_id& from, +key_state :: do_chain_op(replication_manager *rm, + const virtual_server_id &us, + const schema &, + const virtual_server_id &from, uint64_t old_version, uint64_t new_version, bool fresh, bool has_value, - const std::vector& value, + const std::vector &value, std::auto_ptr backing) { - e::intrusive_ptr op = get(new_version); - std::auto_ptr memory(new e::arena()); - memory->takeover(backing.release()); - - if (!op) - { - op = enqueue_continuous_key_op(old_version, new_version, fresh, - has_value, value, memory); - } - - assert(op); - op->set_recv(rm->m_daemon->m_config.version(), from); - - if (op->ackable()) - { - rm->send_ack(us, m_key, op); - } + e::intrusive_ptr op = get(new_version); + std::auto_ptr memory(new e::arena()); + memory->takeover(backing.release()); + if (!op) + { + op = enqueue_continuous_key_op(old_version, new_version, fresh, + has_value, value, memory); + } + assert(op); + op->set_recv(rm->m_daemon->m_config.version(), from); + if (op->ackable()) + { + rm->send_ack(us, m_key, op); + } } void -key_state :: do_chain_subspace(replication_manager* rm, - const virtual_server_id& us, - const schema&, - const virtual_server_id& from, +key_state :: do_chain_subspace(replication_manager *rm, + const virtual_server_id &us, + const schema &, + const virtual_server_id &from, uint64_t old_version, uint64_t new_version, - const std::vector& value, + const std::vector &value, std::auto_ptr backing, - const region_id& prev_region, - const region_id& this_old_region, - const region_id& this_new_region, - const region_id& next_region) + const region_id &prev_region, + const region_id &this_old_region, + const region_id &this_new_region, + const region_id &next_region) { - e::intrusive_ptr op = get(new_version); - std::auto_ptr memory(new e::arena()); - memory->takeover(backing.release()); - - if (!op) - { - op = enqueue_discontinuous_key_op(old_version, new_version, - value, memory, - prev_region, this_old_region, - this_new_region, next_region); - } - - assert(op); - op->set_recv(rm->m_daemon->m_config.version(), from); - - if (op->ackable()) - { - rm->send_ack(us, m_key, op); - } + e::intrusive_ptr op = get(new_version); + std::auto_ptr memory(new e::arena()); + memory->takeover(backing.release()); + if (!op) + { + op = enqueue_discontinuous_key_op(old_version, new_version, + value, memory, + prev_region, this_old_region, + this_new_region, next_region); + } + assert(op); + op->set_recv(rm->m_daemon->m_config.version(), from); + if (op->ackable()) + { + rm->send_ack(us, m_key, op); + } } void -key_state :: do_chain_ack(replication_manager* rm, - const virtual_server_id& us, - const schema&, - const virtual_server_id& from, +key_state :: do_chain_ack(replication_manager *rm, + const virtual_server_id &us, + const schema &, + const virtual_server_id &from, uint64_t version) { - e::intrusive_ptr op = get(version); - - if (!op) - { - LOG(ERROR) << "dropping CHAIN_ACK for update we haven't seen"; - LOG(ERROR) << "troubleshoot info: from=" << from << " to=" << us - << " version=" << version << " key=" << m_key.hex(); - return; - } - - if (!op->sent_to(rm->m_daemon->m_config.version(), from)) - { - return; - } - - op->mark_acked(); - rm->send_ack(us, m_key, op); - rm->collect(m_ri, op); + e::intrusive_ptr op = get(version); + if (!op) + { + LOG(ERROR) << "dropping CHAIN_ACK for update we haven't seen"; + LOG(ERROR) << "troubleshoot info: from=" << from << " to=" << us + << " version=" << version << " key=" << m_key.hex(); + return; + } + if (!op->sent_to(rm->m_daemon->m_config.version(), from)) + { + return; + } + op->mark_acked(); + rm->send_ack(us, m_key, op); + rm->collect(m_ri, op); } void -key_state :: add_response(const client_response& cr) +key_state :: add_response(const client_response &cr) { - m_client_responses_heap.push_back(cr); - std::push_heap(m_client_responses_heap.begin(), - m_client_responses_heap.end()); + m_client_responses_heap.push_back(cr); + std::push_heap(m_client_responses_heap.begin(), + m_client_responses_heap.end()); } void -key_state :: send_responses(replication_manager* rm, - const virtual_server_id& us) +key_state :: send_responses(replication_manager *rm, + const virtual_server_id &us) { - while (!m_client_responses_heap.empty() && - m_client_responses_heap[0].respond_after <= m_old_version) - { - const client_response& cr(m_client_responses_heap[0]); - rm->respond_to_client(us, cr.client, cr.nonce, cr.ret); - - std::pop_heap(m_client_responses_heap.begin(), - m_client_responses_heap.end()); - m_client_responses_heap.pop_back(); - } + while (!m_client_responses_heap.empty() && + m_client_responses_heap[0].respond_after <= m_old_version) + { + const client_response &cr(m_client_responses_heap[0]); + rm->respond_to_client(us, cr.client, cr.nonce, cr.ret); + std::pop_heap(m_client_responses_heap.begin(), + m_client_responses_heap.end()); + m_client_responses_heap.pop_back(); + } } namespace { bool -get_by_version(const std::list >& list, - uint64_t version, e::intrusive_ptr* op) +get_by_version(const std::list > &list, + uint64_t version, e::intrusive_ptr *op) { - if (list.empty() || list.back()->this_version() < version) - { - return false; - } - - for (std::list >::const_iterator it = list.begin(); - it != list.end(); ++it) - { - uint64_t v = (*it)->this_version(); - - if (v == version) - { - *op = *it; - return true; - } - else if (v > version) - { - return false; - } - } - - return false; + if (list.empty() || list.back()->this_version() < version) + { + return false; + } + for (std::list >::const_iterator it = list.begin(); + it != list.end(); ++it) + { + uint64_t v = (*it)->this_version(); + if (v == version) + { + *op = *it; + return true; + } + else if (v > version) + { + return false; + } + } + return false; } } // namespace @@ -1027,18 +938,16 @@ get_by_version(const std::list >& list, e::intrusive_ptr key_state :: get(uint64_t new_version) { - CHECK_INVARIANTS(); - e::intrusive_ptr op; - - if (get_by_version(m_committable, new_version, &op) || - get_by_version(m_blocked, new_version, &op) || - get_by_version(m_deferred, new_version, &op)) - { - assert(op); - return op; - } - - return NULL; + CHECK_INVARIANTS(); + e::intrusive_ptr op; + if (get_by_version(m_committable, new_version, &op) || + get_by_version(m_blocked, new_version, &op) || + get_by_version(m_deferred, new_version, &op)) + { + assert(op); + return op; + } + return NULL; } e::intrusive_ptr @@ -1046,498 +955,445 @@ key_state :: enqueue_continuous_key_op(uint64_t old_version, uint64_t new_version, bool fresh, bool has_value, - const std::vector& value, + const std::vector &value, std::auto_ptr memory) { - e::intrusive_ptr op; - op = new key_operation(old_version, new_version, fresh, - has_value, value, memory); - op->set_continuous(); - - if ((!has_value && !m_has_old_value) || - (new_version <= m_old_version)) - { - op->mark_acked(); - return op; - } - - m_deferred.push_back(op); - return op; + e::intrusive_ptr op; + op = new key_operation(old_version, new_version, fresh, + has_value, value, memory); + op->set_continuous(); + if ((!has_value && !m_has_old_value) || + (new_version <= m_old_version)) + { + op->mark_acked(); + return op; + } + m_deferred.push_back(op); + return op; } e::intrusive_ptr key_state :: enqueue_discontinuous_key_op(uint64_t old_version, uint64_t new_version, - const std::vector& value, + const std::vector &value, std::auto_ptr memory, - const region_id& prev_region, - const region_id& this_old_region, - const region_id& this_new_region, - const region_id& next_region) + const region_id &prev_region, + const region_id &this_old_region, + const region_id &this_new_region, + const region_id &next_region) { - e::intrusive_ptr op; - op = new key_operation(old_version, new_version, false, - true, value, memory); - op->set_discontinuous(prev_region, this_old_region, this_new_region, next_region); - m_deferred.push_back(op); - return op; + e::intrusive_ptr op; + op = new key_operation(old_version, new_version, false, + true, value, memory); + op->set_discontinuous(prev_region, this_old_region, this_new_region, next_region); + m_deferred.push_back(op); + return op; } void -key_state :: get_latest(bool* has_old_value, - uint64_t* old_version, - const std::vector** old_value) +key_state :: get_latest(bool *has_old_value, + uint64_t *old_version, + const std::vector **old_value) { - CHECK_INVARIANTS(); - *old_version = 0; - - // We try to pick the highest version of the key we know of here - // We know that the pending and commitable operations are sorted so we only look at their back - - if (!m_blocked.empty() && m_blocked.back()->this_version() > *old_version) - { - *has_old_value = m_blocked.back()->has_value(); - *old_version = m_blocked.back()->this_version(); - *old_value = &m_blocked.back()->value(); - } - - if (!m_committable.empty() && m_committable.back()->this_version() > *old_version) - { - *has_old_value = m_committable.back()->has_value(); - *old_version = m_committable.back()->this_version(); - *old_value = &m_committable.back()->value(); - } - - if (m_old_version > *old_version) - { - *has_old_value = m_has_old_value; - *old_version = m_old_version; - *old_value = &m_old_value; - } + CHECK_INVARIANTS(); + *old_version = 0; + // We try to pick the highest version of the key we know of here + // We know that the pending and commitable operations are sorted so we only look at their back + if (!m_blocked.empty() && m_blocked.back()->this_version() > *old_version) + { + *has_old_value = m_blocked.back()->has_value(); + *old_version = m_blocked.back()->this_version(); + *old_value = &m_blocked.back()->value(); + } + if (!m_committable.empty() && m_committable.back()->this_version() > *old_version) + { + *has_old_value = m_committable.back()->has_value(); + *old_version = m_committable.back()->this_version(); + *old_value = &m_committable.back()->value(); + } + if (m_old_version > *old_version) + { + *has_old_value = m_has_old_value; + *old_version = m_old_version; + *old_value = &m_old_value; + } } bool -key_state :: drain_queue(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - key_operation_list_t* q, - void (key_state::*f)(replication_manager* rm, - const virtual_server_id& us, - const schema& sc)) +key_state :: drain_queue(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + key_operation_list_t *q, + void (key_state::*f)(replication_manager *rm, + const virtual_server_id &us, + const schema &sc)) { - bool did_work = false; - - while (!q->empty()) - { - CHECK_INVARIANTS(); - size_t before = q->size(); - (this->*f)(rm, us, sc); - size_t after = q->size(); - - if (before > after) - { - did_work = true; - } - else - { - break; - } - } - - return did_work; + bool did_work = false; + while (!q->empty()) + { + CHECK_INVARIANTS(); + size_t before = q->size(); + (this->*f)(rm, us, sc); + size_t after = q->size(); + if (before > after) + { + did_work = true; + } + else + { + break; + } + } + return did_work; } bool -key_state :: drain_queue(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - key_change_list_t* q, - void (key_state::*f)(replication_manager* rm, - const virtual_server_id& us, - const schema& sc)) +key_state :: drain_queue(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + key_change_list_t *q, + void (key_state::*f)(replication_manager *rm, + const virtual_server_id &us, + const schema &sc)) { - bool did_work = false; - - while (!q->empty()) - { - CHECK_INVARIANTS(); - size_t before = q->size(); - (this->*f)(rm, us, sc); - size_t after = q->size(); - - if (before > after) - { - did_work = true; - } - else - { - break; - } - } - - return did_work; + bool did_work = false; + while (!q->empty()) + { + CHECK_INVARIANTS(); + size_t before = q->size(); + (this->*f)(rm, us, sc); + size_t after = q->size(); + if (before > after) + { + did_work = true; + } + else + { + break; + } + } + return did_work; } void -key_state :: drain_changes(replication_manager*, - const virtual_server_id&, - const schema& sc) +key_state :: drain_changes(replication_manager *, + const virtual_server_id &, + const schema &sc) { - assert(!m_changes.empty()); - - if (!m_deferred.empty()) - { - return; - } - - assert(sc.attrs_sz > 0); - bool has_old_value = false; - uint64_t old_version = 0; - const std::vector* old_value = NULL; - get_latest(&has_old_value, &old_version, &old_value); - - e::intrusive_ptr dkc = m_changes.front(); - m_changes.pop_front(); - key_change* kc = dkc->kc.get(); - - if (!auth_verify_write(sc, has_old_value, old_value, *kc)) - { - add_response(client_response(old_version, dkc->from, dkc->nonce, NET_UNAUTHORIZED)); - return; - } - - network_returncode nrc = kc->check(sc, has_old_value, old_value); - - if (nrc != NET_SUCCESS) - { - add_response(client_response(old_version, dkc->from, dkc->nonce, nrc)); - return; - } - - if (kc->erase) - { - e::intrusive_ptr op; - op = new key_operation(old_version, dkc->version, false, - false, std::vector(sc.attrs_sz - 1), - std::auto_ptr()); - op->set_continuous(); - add_response(client_response(dkc->version, dkc->from, dkc->nonce, NET_SUCCESS)); - m_deferred.push_back(op); - return; - } - - std::auto_ptr memory(new e::arena()); - std::vector new_value(sc.attrs_sz - 1); - - // if there is no old value, pretend it is "new_value" which is - // zero-initialized - if (!has_old_value) - { - old_value = &new_value; - } - - size_t funcs_passed = apply_funcs(sc, kc->funcs, m_key, *old_value, memory.get(), &new_value); - - if (funcs_passed < kc->funcs.size()) - { - add_response(client_response(old_version, dkc->from, dkc->nonce, NET_CMPFAIL)); - return; - } - - e::intrusive_ptr op; - op = new key_operation(old_version, dkc->version, !has_old_value, - true, new_value, memory); - op->set_continuous(); - add_response(client_response(dkc->version, dkc->from, dkc->nonce, NET_SUCCESS)); - m_deferred.push_back(op); + assert(!m_changes.empty()); + if (!m_deferred.empty()) + { + return; + } + assert(sc.attrs_sz > 0); + bool has_old_value = false; + uint64_t old_version = 0; + const std::vector *old_value = NULL; + get_latest(&has_old_value, &old_version, &old_value); + e::intrusive_ptr dkc = m_changes.front(); + m_changes.pop_front(); + key_change *kc = dkc->kc.get(); + if (!auth_verify_write(sc, has_old_value, old_value, *kc)) + { + add_response(client_response(old_version, dkc->from, dkc->nonce, NET_UNAUTHORIZED)); + return; + } + network_returncode nrc = kc->check(sc, has_old_value, old_value); + if (nrc != NET_SUCCESS) + { + add_response(client_response(old_version, dkc->from, dkc->nonce, nrc)); + return; + } + if (kc->erase) + { + e::intrusive_ptr op; + op = new key_operation(old_version, dkc->version, false, + false, std::vector(sc.attrs_sz - 1), + std::auto_ptr()); + op->set_continuous(); + add_response(client_response(dkc->version, dkc->from, dkc->nonce, NET_SUCCESS)); + m_deferred.push_back(op); + return; + } + std::auto_ptr memory(new e::arena()); + std::vector new_value(sc.attrs_sz - 1); + // if there is no old value, pretend it is "new_value" which is + // zero-initialized + if (!has_old_value) + { + old_value = &new_value; + } + size_t funcs_passed = apply_funcs(sc, kc->funcs, m_key, *old_value, memory.get(), &new_value); + if (funcs_passed < kc->funcs.size()) + { + add_response(client_response(old_version, dkc->from, dkc->nonce, NET_CMPFAIL)); + return; + } + e::intrusive_ptr op; + op = new key_operation(old_version, dkc->version, !has_old_value, + true, new_value, memory); + op->set_continuous(); + add_response(client_response(dkc->version, dkc->from, dkc->nonce, NET_SUCCESS)); + m_deferred.push_back(op); } bool -key_state :: compare_key_op_ptrs(const e::intrusive_ptr& lhs, - const e::intrusive_ptr& rhs) +key_state :: compare_key_op_ptrs(const e::intrusive_ptr &lhs, + const e::intrusive_ptr &rhs) { - return lhs->this_version() < rhs->this_version(); + return lhs->this_version() < rhs->this_version(); } void -key_state :: drain_deferred(replication_manager* rm, - const virtual_server_id& us, - const schema& sc) +key_state :: drain_deferred(replication_manager *rm, + const virtual_server_id &us, + const schema &sc) { - assert(!m_deferred.empty()); - m_deferred.sort(compare_key_op_ptrs); - bool has_old_value = false; - uint64_t old_version = 0; - const std::vector* old_value = NULL; - get_latest(&has_old_value, &old_version, &old_value); - e::intrusive_ptr op = m_deferred.front(); - - if (old_version >= op->this_version()) - { - LOG(WARNING) << "dropping deferred CHAIN_* which was sent out of order: " - << "we're using key " << e::slice(state_key().key).hex() << " in region " - << state_key().region - << ". We've already seen " << old_version << " and the CHAIN_* " - << "is for version " << op->this_version(); - m_deferred.pop_front(); - return; - } - - // if the op is continous (the version numbers are assumed to line up), and - // the op is not fresh (the only case a continuous op can have discontinuous - // version numbers), then it cannot be applied yet - if (op->is_continuous() && !op->is_fresh() && old_version != op->prev_version()) - { - return; - } - - if (op->is_continuous()) - { - hash_objects(&rm->m_daemon->m_config, m_ri, sc, - op->has_value(), op->value(), - has_old_value, old_value ? *old_value : op->value(), op); - } - - // check that this host is supposed to process this op - if (op->this_old_region() != m_ri && op->this_new_region() != m_ri) - { - LOG(WARNING) << "dropping deferred CHAIN_* which didn't get sent to the right host: " - << "we're using key " << e::slice(state_key().key).hex() << " in region " - << state_key().region - << ". We've already seen " << old_version << " and the CHAIN_* " - << "is for version " << op->this_version(); - m_deferred.pop_front(); - return; - } - - // check that the sender was the correct sender - if (op->is_continuous() && - op->recv_from() != virtual_server_id() && - rm->m_daemon->m_config.next_in_region(op->recv_from()) != us && - !rm->m_daemon->m_config.subspace_adjacent(op->recv_from(), us)) - { - LOG(WARNING) << "dropping deferred CHAIN_OP which didn't come from the right host: " - << "we're using key " << e::slice(state_key().key).hex() << " in region " - << state_key().region - << ". We received the bad update from " << op->recv_from(); - m_deferred.pop_front(); - return; - } - - if (op->is_discontinuous() && - op->recv_from() != virtual_server_id() && - rm->m_daemon->m_config.next_in_region(op->recv_from()) != us && - rm->m_daemon->m_config.tail_of_region(op->this_old_region()) != op->recv_from()) - { - LOG(WARNING) << "dropping deferred CHAIN_SUBSPACE which didn't come from the right host: " - << "we're using key " << e::slice(state_key().key).hex() << " in region " - << state_key().region - << ". We received the bad update from " << op->recv_from(); - m_deferred.pop_front(); - return; - } - - if (op->is_fresh() || op->is_discontinuous() || old_version == op->prev_version()) - { - m_blocked.push_back(op); - m_deferred.pop_front(); - return; - } + assert(!m_deferred.empty()); + m_deferred.sort(compare_key_op_ptrs); + bool has_old_value = false; + uint64_t old_version = 0; + const std::vector *old_value = NULL; + get_latest(&has_old_value, &old_version, &old_value); + e::intrusive_ptr op = m_deferred.front(); + if (old_version >= op->this_version()) + { + LOG(WARNING) << "dropping deferred CHAIN_* which was sent out of order: " + << "we're using key " << e::slice(state_key().key).hex() << " in region " + << state_key().region + << ". We've already seen " << old_version << " and the CHAIN_* " + << "is for version " << op->this_version(); + m_deferred.pop_front(); + return; + } + // if the op is continous (the version numbers are assumed to line up), and + // the op is not fresh (the only case a continuous op can have discontinuous + // version numbers), then it cannot be applied yet + if (op->is_continuous() && !op->is_fresh() && old_version != op->prev_version()) + { + return; + } + if (op->is_continuous()) + { + hash_objects(&rm->m_daemon->m_config, m_ri, sc, + op->has_value(), op->value(), + has_old_value, old_value ? *old_value : op->value(), op); + } + // check that this host is supposed to process this op + if (op->this_old_region() != m_ri && op->this_new_region() != m_ri) + { + LOG(WARNING) << "dropping deferred CHAIN_* which didn't get sent to the right host: " + << "we're using key " << e::slice(state_key().key).hex() << " in region " + << state_key().region + << ". We've already seen " << old_version << " and the CHAIN_* " + << "is for version " << op->this_version(); + m_deferred.pop_front(); + return; + } + // check that the sender was the correct sender + if (op->is_continuous() && + op->recv_from() != virtual_server_id() && + rm->m_daemon->m_config.next_in_region(op->recv_from()) != us && + !rm->m_daemon->m_config.subspace_adjacent(op->recv_from(), us)) + { + LOG(WARNING) << "dropping deferred CHAIN_OP which didn't come from the right host: " + << "we're using key " << e::slice(state_key().key).hex() << " in region " + << state_key().region + << ". We received the bad update from " << op->recv_from(); + m_deferred.pop_front(); + return; + } + if (op->is_discontinuous() && + op->recv_from() != virtual_server_id() && + rm->m_daemon->m_config.next_in_region(op->recv_from()) != us && + rm->m_daemon->m_config.tail_of_region(op->this_old_region()) != op->recv_from()) + { + LOG(WARNING) << "dropping deferred CHAIN_SUBSPACE which didn't come from the right host: " + << "we're using key " << e::slice(state_key().key).hex() << " in region " + << state_key().region + << ". We received the bad update from " << op->recv_from(); + m_deferred.pop_front(); + return; + } + if (op->is_fresh() || op->is_discontinuous() || old_version == op->prev_version()) + { + m_blocked.push_back(op); + m_deferred.pop_front(); + return; + } } void -key_state :: drain_blocked(replication_manager* rm, - const virtual_server_id& us, - const schema&) +key_state :: drain_blocked(replication_manager *rm, + const virtual_server_id &us, + const schema &) { - assert(!m_blocked.empty()); - e::intrusive_ptr op = m_blocked.front(); - bool withold = false; - // if the op is on either side of a delete, or is a delete itself - withold = withold || op->is_fresh(); - withold = withold || !op->has_value(); - withold = withold || (!m_committable.empty() && !m_committable.back()->has_value()); - withold = withold || op->is_discontinuous(); - withold = withold || (!m_committable.empty() && m_committable.back()->is_discontinuous()); - - if (withold && !m_committable.empty()) - { - return; - } - - m_committable.push_back(op); - m_blocked.pop_front(); - rm->send_message(us, m_key, op); + assert(!m_blocked.empty()); + e::intrusive_ptr op = m_blocked.front(); + bool withold = false; + // if the op is on either side of a delete, or is a delete itself + withold = withold || op->is_fresh(); + withold = withold || !op->has_value(); + withold = withold || (!m_committable.empty() && !m_committable.back()->has_value()); + withold = withold || op->is_discontinuous(); + withold = withold || (!m_committable.empty() && m_committable.back()->is_discontinuous()); + if (withold && !m_committable.empty()) + { + return; + } + m_committable.push_back(op); + m_blocked.pop_front(); + rm->send_message(us, m_key, op); } void -key_state :: drain_committable(replication_manager* rm, - const virtual_server_id&, - const schema&) +key_state :: drain_committable(replication_manager *rm, + const virtual_server_id &, + const schema &) { - assert(!m_committable.empty()); - bool found = false; - uint64_t version = 0; - - for (key_operation_list_t::iterator it = m_committable.begin(); - it != m_committable.end(); ++it) - { - key_operation* op = it->get(); - - if (op->ackable()) - { - found = true; - assert(version <= op->this_version()); - version = op->this_version(); - } - } - - if (found && m_old_version < version) - { - CHECK_INVARIANTS(); - e::intrusive_ptr op = get(version); - assert(op); - assert(op->this_version() == version); - datalayer::returncode rc = datalayer::SUCCESS; - - // if this is a case where we are to remove the object from disk - // because of a delete or the first half of a subspace transfer - if (!op->has_value() || - (op->this_old_region() != op->this_new_region() && m_ri == op->this_old_region())) - { - if (m_has_old_value) - { - rc = rm->m_daemon->m_data.del(m_ri, m_key, m_old_value); - } - } - // otherwise it is a case where we are to place this object on disk - else - { - if (m_has_old_value) - { - rc = rm->m_daemon->m_data.overput(m_ri, m_key, m_old_value, op->value(), version); - } - else - { - rc = rm->m_daemon->m_data.put(m_ri, m_key, op->value(), version); - } - } - - switch (rc) - { - case datalayer::SUCCESS: - break; - case datalayer::NOT_FOUND: - case datalayer::BAD_ENCODING: - case datalayer::CORRUPTION: - case datalayer::IO_ERROR: - case datalayer::LEVELDB_ERROR: - return; // XXX - default: - return; // XXX - } - - m_has_old_value = op->has_value(); - m_old_version = version; - m_old_value = op->value(); - m_old_op = op; - CHECK_INVARIANTS(); - } - - while (!m_committable.empty() && m_committable.front()->ackable()) - { - assert(m_committable.front()->this_version() <= m_old_version); - m_committable.pop_front(); - CHECK_INVARIANTS(); - } + assert(!m_committable.empty()); + bool found = false; + uint64_t version = 0; + for (key_operation_list_t::iterator it = m_committable.begin(); + it != m_committable.end(); ++it) + { + key_operation *op = it->get(); + if (op->ackable()) + { + found = true; + assert(version <= op->this_version()); + version = op->this_version(); + } + } + if (found && m_old_version < version) + { + CHECK_INVARIANTS(); + e::intrusive_ptr op = get(version); + assert(op); + assert(op->this_version() == version); + datalayer::returncode rc = datalayer::SUCCESS; + // if this is a case where we are to remove the object from disk + // because of a delete or the first half of a subspace transfer + if (!op->has_value() || + (op->this_old_region() != op->this_new_region() && m_ri == op->this_old_region())) + { + if (m_has_old_value) + { + rc = rm->m_daemon->m_data.del(m_ri, m_key, m_old_value); + } + } + // otherwise it is a case where we are to place this object on disk + else + { + if (m_has_old_value) + { + rc = rm->m_daemon->m_data.overput(m_ri, m_key, m_old_value, op->value(), version); + } + else + { + rc = rm->m_daemon->m_data.put(m_ri, m_key, op->value(), version); + } + } + switch (rc) + { + case datalayer::SUCCESS: + break; + case datalayer::NOT_FOUND: + case datalayer::BAD_ENCODING: + case datalayer::CORRUPTION: + case datalayer::IO_ERROR: + case datalayer::LEVELDB_ERROR: + return; // XXX + default: + return; // XXX + } + m_has_old_value = op->has_value(); + m_old_version = version; + m_old_value = op->value(); + m_old_op = op; + CHECK_INVARIANTS(); + } + while (!m_committable.empty() && m_committable.front()->ackable()) + { + assert(m_committable.front()->this_version() <= m_old_version); + m_committable.pop_front(); + CHECK_INVARIANTS(); + } } void -key_state :: hash_objects(const configuration* config, - const region_id& reg, - const schema& sc, +key_state :: hash_objects(const configuration *config, + const region_id ®, + const schema &sc, bool has_new_value, - const std::vector& new_value, + const std::vector &new_value, bool has_old_value, - const std::vector& old_value, + const std::vector &old_value, e::intrusive_ptr op) { - std::vector old_hashes(sc.attrs_sz); - std::vector new_hashes(sc.attrs_sz); - region_id this_old_region; - region_id this_new_region; - region_id prev_region; - region_id next_region; - subspace_id subspace_this = config->subspace_of(reg); - subspace_id subspace_prev = config->subspace_prev(subspace_this); - subspace_id subspace_next = config->subspace_next(subspace_this); - - if (has_old_value && has_new_value) - { - hyperdex::hash(sc, m_key, new_value, &new_hashes.front()); - hyperdex::hash(sc, m_key, old_value, &old_hashes.front()); - - if (subspace_prev != subspace_id()) - { - config->lookup_region(subspace_prev, new_hashes, &prev_region); - } - - config->lookup_region(subspace_this, old_hashes, &this_old_region); - config->lookup_region(subspace_this, new_hashes, &this_new_region); - - if (subspace_next != subspace_id()) - { - config->lookup_region(subspace_next, old_hashes, &next_region); - } - } - else if (has_old_value) - { - hyperdex::hash(sc, m_key, old_value, &old_hashes.front()); - - for (size_t i = 0; i < sc.attrs_sz; ++i) - { - new_hashes[i] = old_hashes[i]; - } - - if (subspace_prev != subspace_id()) - { - config->lookup_region(subspace_prev, old_hashes, &prev_region); - } - - config->lookup_region(subspace_this, old_hashes, &this_old_region); - this_new_region = this_old_region; - - if (subspace_next != subspace_id()) - { - config->lookup_region(subspace_next, old_hashes, &next_region); - } - } - else if (has_new_value) - { - hyperdex::hash(sc, m_key, new_value, &new_hashes.front()); - - for (size_t i = 0; i < sc.attrs_sz; ++i) - { - old_hashes[i] = new_hashes[i]; - } - - if (subspace_prev != subspace_id()) - { - config->lookup_region(subspace_prev, old_hashes, &prev_region); - } - - config->lookup_region(subspace_this, old_hashes, &this_new_region); - this_old_region = this_new_region; - - if (subspace_next != subspace_id()) - { - config->lookup_region(subspace_next, old_hashes, &next_region); - } - } - else - { - abort(); - } - - op->set_continuous_hashes(prev_region, this_old_region, this_new_region, next_region); + std::vector old_hashes(sc.attrs_sz); + std::vector new_hashes(sc.attrs_sz); + region_id this_old_region; + region_id this_new_region; + region_id prev_region; + region_id next_region; + subspace_id subspace_this = config->subspace_of(reg); + subspace_id subspace_prev = config->subspace_prev(subspace_this); + subspace_id subspace_next = config->subspace_next(subspace_this); + if (has_old_value && has_new_value) + { + hyperdex::hash(sc, m_key, new_value, &new_hashes.front()); + hyperdex::hash(sc, m_key, old_value, &old_hashes.front()); + if (subspace_prev != subspace_id()) + { + config->lookup_region(subspace_prev, new_hashes, &prev_region); + } + config->lookup_region(subspace_this, old_hashes, &this_old_region); + config->lookup_region(subspace_this, new_hashes, &this_new_region); + if (subspace_next != subspace_id()) + { + config->lookup_region(subspace_next, old_hashes, &next_region); + } + } + else if (has_old_value) + { + hyperdex::hash(sc, m_key, old_value, &old_hashes.front()); + for (size_t i = 0; i < sc.attrs_sz; ++i) + { + new_hashes[i] = old_hashes[i]; + } + if (subspace_prev != subspace_id()) + { + config->lookup_region(subspace_prev, old_hashes, &prev_region); + } + config->lookup_region(subspace_this, old_hashes, &this_old_region); + this_new_region = this_old_region; + if (subspace_next != subspace_id()) + { + config->lookup_region(subspace_next, old_hashes, &next_region); + } + } + else if (has_new_value) + { + hyperdex::hash(sc, m_key, new_value, &new_hashes.front()); + for (size_t i = 0; i < sc.attrs_sz; ++i) + { + old_hashes[i] = new_hashes[i]; + } + if (subspace_prev != subspace_id()) + { + config->lookup_region(subspace_prev, old_hashes, &prev_region); + } + config->lookup_region(subspace_this, old_hashes, &this_new_region); + this_old_region = this_new_region; + if (subspace_next != subspace_id()) + { + config->lookup_region(subspace_next, old_hashes, &next_region); + } + } + else + { + abort(); + } + op->set_continuous_hashes(prev_region, this_old_region, this_new_region, next_region); } diff --git a/daemon/key_state.h b/daemon/key_state.h index 2f0925fa0..c89787e6c 100644 --- a/daemon/key_state.h +++ b/daemon/key_state.h @@ -44,241 +44,241 @@ class replication_manager; class key_state { - public: - key_state(const key_region& kr); - ~key_state() throw (); +public: + key_state(const key_region &kr); + ~key_state() throw (); - public: - key_region state_key() const; - bool finished(); +public: + key_region state_key() const; + bool finished(); - public: - bool initialized(); - datalayer::returncode initialize(datalayer* data, - const schema& sc, - const region_id& ri); +public: + bool initialized(); + datalayer::returncode initialize(datalayer *data, + const schema &sc, + const region_id &ri); - void enqueue_client_atomic(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - const server_id& from, - uint64_t nonce, - std::auto_ptr kc, - std::auto_ptr backing); - void enqueue_chain_op(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - const virtual_server_id& from, - uint64_t old_version, - uint64_t new_version, - bool fresh, - bool has_value, - const std::vector& value, - std::auto_ptr backing); - void enqueue_chain_subspace(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - const virtual_server_id& from, - uint64_t old_version, - uint64_t new_version, - const std::vector& value, - std::auto_ptr backing, - const region_id& prev_region, - const region_id& this_old_region, - const region_id& this_new_region, - const region_id& next_region); - void enqueue_chain_ack(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - const virtual_server_id& from, - uint64_t version); - void work_state_machine(replication_manager* rm, - const virtual_server_id& us, - const schema& sc); + void enqueue_client_atomic(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + const server_id &from, + uint64_t nonce, + std::auto_ptr kc, + std::auto_ptr backing); + void enqueue_chain_op(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + const virtual_server_id &from, + uint64_t old_version, + uint64_t new_version, + bool fresh, + bool has_value, + const std::vector &value, + std::auto_ptr backing); + void enqueue_chain_subspace(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + const virtual_server_id &from, + uint64_t old_version, + uint64_t new_version, + const std::vector &value, + std::auto_ptr backing, + const region_id &prev_region, + const region_id &this_old_region, + const region_id &this_new_region, + const region_id &next_region); + void enqueue_chain_ack(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + const virtual_server_id &from, + uint64_t version); + void work_state_machine(replication_manager *rm, + const virtual_server_id &us, + const schema &sc); - uint64_t max_version(); - void reconfigure(e::garbage_collector* gc); - void reset(e::garbage_collector* gc); + uint64_t max_version(); + void reconfigure(e::garbage_collector *gc); + void reset(e::garbage_collector *gc); - void resend_committable(replication_manager* rm, - const virtual_server_id& us); + void resend_committable(replication_manager *rm, + const virtual_server_id &us); - void append_all_versions(std::vector >* versions); + void append_all_versions(std::vector > *versions); - void debug_dump(); + void debug_dump(); - private: - struct deferred_key_change; - struct stub_client_atomic; - struct stub_chain_op; - struct stub_chain_subspace; - struct stub_chain_ack; - struct client_response; - typedef std::list > key_operation_list_t; - typedef std::list > key_change_list_t; +private: + struct deferred_key_change; + struct stub_client_atomic; + struct stub_chain_op; + struct stub_chain_subspace; + struct stub_chain_ack; + struct client_response; + typedef std::list > key_operation_list_t; + typedef std::list > key_change_list_t; - private: - void check_invariants() const; - void someone_needs_to_work_the_state_machine(); - void work_state_machine_or_pass_the_buck(replication_manager* rm, - const virtual_server_id& us, - const schema& sc); - // returns when m_someone_is_working; must call wsm_with_work_bit after - void takeover_state_machine(); - // returns whether or not the caller took over the state machine, will - // return true if must call wsm_with_work_bit after; false otherwise - bool possibly_takeover_state_machine(); - // releases inner state by setting m_someone_is_working = false. - void work_state_machine_with_work_bit(replication_manager* rm, - const virtual_server_id& us, - const schema& sc); - void do_client_atomic(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - const server_id& from, - uint64_t nonce, - std::auto_ptr kc, - std::auto_ptr backing); - void do_chain_op(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - const virtual_server_id& from, - uint64_t old_version, - uint64_t new_version, - bool fresh, - bool has_value, - const std::vector& value, - std::auto_ptr backing); - void do_chain_subspace(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - const virtual_server_id& from, - uint64_t old_version, - uint64_t new_version, - const std::vector& value, - std::auto_ptr backing, - const region_id& prev_region, - const region_id& this_old_region, - const region_id& this_new_region, - const region_id& next_region); - void do_chain_ack(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - const virtual_server_id& from, - uint64_t version); - void add_response(const client_response& cr); - void send_responses(replication_manager* rm, - const virtual_server_id& us); - e::intrusive_ptr get(uint64_t new_version); - e::intrusive_ptr - enqueue_continuous_key_op(uint64_t old_version, - uint64_t new_version, - bool fresh, - bool has_value, - const std::vector& value, - std::auto_ptr memory); - e::intrusive_ptr - enqueue_discontinuous_key_op(uint64_t old_version, - uint64_t new_version, - const std::vector& value, - std::auto_ptr memory, - const region_id& prev_region, - const region_id& this_old_region, - const region_id& this_new_region, - const region_id& next_region); - void get_latest(bool* has_old_value, - uint64_t* old_version, - const std::vector** old_value); - bool drain_queue(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - key_operation_list_t* q, - void (key_state::*f)(replication_manager* rm, - const virtual_server_id& us, - const schema& sc)); - bool drain_queue(replication_manager* rm, - const virtual_server_id& us, - const schema& sc, - key_change_list_t* q, - void (key_state::*f)(replication_manager* rm, - const virtual_server_id& us, - const schema& sc)); - void drain_changes(replication_manager* rm, - const virtual_server_id& us, - const schema& sc); - static bool compare_key_op_ptrs(const e::intrusive_ptr& lhs, - const e::intrusive_ptr& rhs); - void drain_deferred(replication_manager* rm, - const virtual_server_id& us, - const schema& sc); - void drain_blocked(replication_manager* rm, - const virtual_server_id& us, - const schema& sc); - void drain_committable(replication_manager* rm, - const virtual_server_id& us, - const schema& sc); - void hash_objects(const configuration* config, - const region_id& reg, - const schema& sc, - bool has_new_value, - const std::vector& new_value, - bool has_old_value, - const std::vector& old_value, - e::intrusive_ptr pend); +private: + void check_invariants() const; + void someone_needs_to_work_the_state_machine(); + void work_state_machine_or_pass_the_buck(replication_manager *rm, + const virtual_server_id &us, + const schema &sc); + // returns when m_someone_is_working; must call wsm_with_work_bit after + void takeover_state_machine(); + // returns whether or not the caller took over the state machine, will + // return true if must call wsm_with_work_bit after; false otherwise + bool possibly_takeover_state_machine(); + // releases inner state by setting m_someone_is_working = false. + void work_state_machine_with_work_bit(replication_manager *rm, + const virtual_server_id &us, + const schema &sc); + void do_client_atomic(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + const server_id &from, + uint64_t nonce, + std::auto_ptr kc, + std::auto_ptr backing); + void do_chain_op(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + const virtual_server_id &from, + uint64_t old_version, + uint64_t new_version, + bool fresh, + bool has_value, + const std::vector &value, + std::auto_ptr backing); + void do_chain_subspace(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + const virtual_server_id &from, + uint64_t old_version, + uint64_t new_version, + const std::vector &value, + std::auto_ptr backing, + const region_id &prev_region, + const region_id &this_old_region, + const region_id &this_new_region, + const region_id &next_region); + void do_chain_ack(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + const virtual_server_id &from, + uint64_t version); + void add_response(const client_response &cr); + void send_responses(replication_manager *rm, + const virtual_server_id &us); + e::intrusive_ptr get(uint64_t new_version); + e::intrusive_ptr + enqueue_continuous_key_op(uint64_t old_version, + uint64_t new_version, + bool fresh, + bool has_value, + const std::vector &value, + std::auto_ptr memory); + e::intrusive_ptr + enqueue_discontinuous_key_op(uint64_t old_version, + uint64_t new_version, + const std::vector &value, + std::auto_ptr memory, + const region_id &prev_region, + const region_id &this_old_region, + const region_id &this_new_region, + const region_id &next_region); + void get_latest(bool *has_old_value, + uint64_t *old_version, + const std::vector **old_value); + bool drain_queue(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + key_operation_list_t *q, + void (key_state::*f)(replication_manager *rm, + const virtual_server_id &us, + const schema &sc)); + bool drain_queue(replication_manager *rm, + const virtual_server_id &us, + const schema &sc, + key_change_list_t *q, + void (key_state::*f)(replication_manager *rm, + const virtual_server_id &us, + const schema &sc)); + void drain_changes(replication_manager *rm, + const virtual_server_id &us, + const schema &sc); + static bool compare_key_op_ptrs(const e::intrusive_ptr &lhs, + const e::intrusive_ptr &rhs); + void drain_deferred(replication_manager *rm, + const virtual_server_id &us, + const schema &sc); + void drain_blocked(replication_manager *rm, + const virtual_server_id &us, + const schema &sc); + void drain_committable(replication_manager *rm, + const virtual_server_id &us, + const schema &sc); + void hash_objects(const configuration *config, + const region_id ®, + const schema &sc, + bool has_new_value, + const std::vector &new_value, + bool has_old_value, + const std::vector &old_value, + e::intrusive_ptr pend); - // state synchronized without m_lock (either read-only or otherwise - // synchronized) - private: - const region_id m_ri; - const std::string m_key_backing; - const e::slice m_key; + // state synchronized without m_lock (either read-only or otherwise + // synchronized) +private: + const region_id m_ri; + const std::string m_key_backing; + const e::slice m_key; - e::lockfree_mpsc_fifo m_client_atomics; - e::lockfree_mpsc_fifo m_chain_ops; - e::lockfree_mpsc_fifo m_chain_subspaces; - e::lockfree_mpsc_fifo m_chain_acks; + e::lockfree_mpsc_fifo m_client_atomics; + e::lockfree_mpsc_fifo m_chain_ops; + e::lockfree_mpsc_fifo m_chain_subspaces; + e::lockfree_mpsc_fifo m_chain_acks; - // protected state, synchronized by m_lock; - private: - po6::threads::mutex m_lock; - po6::threads::cond m_avail; - bool m_someone_is_working_the_state_machine; - bool m_someone_needs_to_work_the_state_machine; + // protected state, synchronized by m_lock; +private: + po6::threads::mutex m_lock; + po6::threads::cond m_avail; + bool m_someone_is_working_the_state_machine; + bool m_someone_needs_to_work_the_state_machine; - bool m_initialized; + bool m_initialized; - // Does this key have a value (before operations are applied) - bool m_has_old_value; - uint64_t m_old_version; + // Does this key have a value (before operations are applied) + bool m_has_old_value; + uint64_t m_old_version; - std::vector m_old_value; - datalayer::reference m_old_disk_ref; - e::intrusive_ptr m_old_op; + std::vector m_old_value; + datalayer::reference m_old_disk_ref; + e::intrusive_ptr m_old_op; - std::vector m_client_responses_heap; + std::vector m_client_responses_heap; - // These operations are being actively replicated by HyperDex - // and were passed to subsequent nodes in the value dependent chain. - key_operation_list_t m_committable; - bool m_committable_empty; + // These operations are being actively replicated by HyperDex + // and were passed to subsequent nodes in the value dependent chain. + key_operation_list_t m_committable; + bool m_committable_empty; - // These operations delayed pending completion of all operations - // in the committable state. Generally, it happens on different sides - // of deletions in order to enforce proper order of arrival for - // operations. It's like a memory barrier, but for distributed systems. - key_operation_list_t m_blocked; - bool m_blocked_empty; + // These operations delayed pending completion of all operations + // in the committable state. Generally, it happens on different sides + // of deletions in order to enforce proper order of arrival for + // operations. It's like a memory barrier, but for distributed systems. + key_operation_list_t m_blocked; + bool m_blocked_empty; - // These messages arrived out of order and will be processed - // pending future messages arrival. - key_operation_list_t m_deferred; - bool m_deferred_empty; + // These messages arrived out of order and will be processed + // pending future messages arrival. + key_operation_list_t m_deferred; + bool m_deferred_empty; - // These are client-submitted operations enqueued to be - // processed. Generally the changes queue will be moved to - // blocked/committable immediate. - key_change_list_t m_changes; - bool m_changes_empty; + // These are client-submitted operations enqueued to be + // processed. Generally the changes queue will be moved to + // blocked/committable immediate. + key_change_list_t m_changes; + bool m_changes_empty; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/leveldb.h b/daemon/leveldb.h index aa1559279..1ca3a7995 100644 --- a/daemon/leveldb.h +++ b/daemon/leveldb.h @@ -54,79 +54,78 @@ typedef e::compat::shared_ptr leveldb_db_ptr; template struct leveldb_dtor { - typedef void (leveldb::DB::*func)(T* t); - static func get_func(); + typedef void (leveldb::DB::*func)(T *t); + static func get_func(); }; template <> inline leveldb_dtor::func leveldb_dtor :: get_func() { - return &leveldb::DB::ReleaseSnapshot; + return &leveldb::DB::ReleaseSnapshot; } template <> inline leveldb_dtor::func leveldb_dtor :: get_func() { - return &leveldb::DB::ReleaseReplayIterator; + return &leveldb::DB::ReleaseReplayIterator; } template class leveldb_release_ptr { - public: - leveldb_release_ptr() - : m_db(), m_resource() {} - leveldb_release_ptr(leveldb_db_ptr d, T* t) - : m_db(), m_resource() { reset(d, t); } - leveldb_release_ptr(const leveldb_release_ptr& other) - : m_db(other.m_db), m_resource(other.m_resource) {} - ~leveldb_release_ptr() throw () {} - - public: - T* get() const { return m_resource->ptr; } - leveldb::DB* db() const { return m_db.get(); } - void reset(leveldb_db_ptr d, T* t) - { m_db = d; m_resource.reset(new wrapper(d, t)); } - - public: - T* operator * () const throw () { return get(); } - T* operator -> () const throw () { return get(); } - leveldb_release_ptr& operator = (const leveldb_release_ptr& rhs) - { - if (this != &rhs) - { - m_resource = rhs.m_resource; - m_db = rhs.m_db; - } - - return *this; - } - - private: - struct wrapper - { - wrapper(leveldb_db_ptr d, T* t) : db(d), ptr(t) {} - ~wrapper() throw () - { - if (ptr) - { - (*db.*leveldb_dtor::get_func())(ptr); - } - } - - leveldb_db_ptr db; - T* ptr; - - private: - wrapper(const wrapper&); - wrapper& operator = (const wrapper&); - }; - - private: - leveldb_db_ptr m_db; - e::compat::shared_ptr m_resource; +public: + leveldb_release_ptr() + : m_db(), m_resource() {} + leveldb_release_ptr(leveldb_db_ptr d, T *t) + : m_db(), m_resource() { reset(d, t); } + leveldb_release_ptr(const leveldb_release_ptr &other) + : m_db(other.m_db), m_resource(other.m_resource) {} + ~leveldb_release_ptr() throw () {} + +public: + T *get() const { return m_resource->ptr; } + leveldb::DB *db() const { return m_db.get(); } + void reset(leveldb_db_ptr d, T *t) + { m_db = d; m_resource.reset(new wrapper(d, t)); } + +public: + T *operator * () const throw () { return get(); } + T *operator -> () const throw () { return get(); } + leveldb_release_ptr &operator = (const leveldb_release_ptr &rhs) + { + if (this != &rhs) + { + m_resource = rhs.m_resource; + m_db = rhs.m_db; + } + return *this; + } + +private: + struct wrapper + { + wrapper(leveldb_db_ptr d, T *t) : db(d), ptr(t) {} + ~wrapper() throw () + { + if (ptr) + { + (*db.*leveldb_dtor::get_func())(ptr); + } + } + + leveldb_db_ptr db; + T *ptr; + + private: + wrapper(const wrapper &); + wrapper &operator = (const wrapper &); + }; + +private: + leveldb_db_ptr m_db; + e::compat::shared_ptr m_resource; }; typedef leveldb_release_ptr leveldb_snapshot_ptr; @@ -134,22 +133,22 @@ typedef leveldb_release_ptr leveldb_replay_iterator_ptr class leveldb_iterator_ptr { - public: - leveldb_iterator_ptr() : m_snap(), m_iter() {} - ~leveldb_iterator_ptr() {} - - public: - void reset(leveldb_snapshot_ptr s, leveldb::Iterator* iter) - { m_iter.reset(iter); m_snap = s; } - leveldb::Iterator* get() const { return m_iter.get(); } - leveldb_snapshot_ptr snap() const { return m_snap; } - - public: - leveldb::Iterator* operator -> () const throw () { return get(); } - - private: - leveldb_snapshot_ptr m_snap; - e::compat::shared_ptr m_iter; +public: + leveldb_iterator_ptr() : m_snap(), m_iter() {} + ~leveldb_iterator_ptr() {} + +public: + void reset(leveldb_snapshot_ptr s, leveldb::Iterator *iter) + { m_iter.reset(iter); m_snap = s; } + leveldb::Iterator *get() const { return m_iter.get(); } + leveldb_snapshot_ptr snap() const { return m_snap; } + +public: + leveldb::Iterator *operator -> () const throw () { return get(); } + +private: + leveldb_snapshot_ptr m_snap; + e::compat::shared_ptr m_iter; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/main.cc b/daemon/main.cc index 6859bddcc..8731d5d50 100644 --- a/daemon/main.cc +++ b/daemon/main.cc @@ -47,160 +47,143 @@ #include "daemon/daemon.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - bool daemonize = true; - const char* data = "."; - const char* log = NULL; - const char* pidfile = ""; - bool has_pidfile = false; - bool listen = false; - const char* listen_host = "auto"; - long listen_port = 2012; - bool coordinator = false; - const char* coordinator_host = "127.0.0.1"; - long coordinator_port = 1982; - long threads = 0; - bool log_immediate = false; - - e::argparser ap; - ap.autohelp(); - ap.arg().name('d', "daemon") - .description("run in the background") - .set_true(&daemonize); - ap.arg().name('f', "foreground") - .description("run in the foreground") - .set_false(&daemonize); - ap.arg().name('D', "data") - .description("store persistent state in this directory (default: .)") - .metavar("dir").as_string(&data); - ap.arg().name('L', "log") - .description("store logs in this directory (default: --data)") - .metavar("dir").as_string(&log); - ap.arg().long_name("pidfile") - .description("write the PID to a file (default: don't)") - .metavar("file").as_string(&pidfile).set_true(&has_pidfile); - ap.arg().name('l', "listen") - .description("listen on a specific IP address (default: auto)") - .metavar("IP").as_string(&listen_host).set_true(&listen); - ap.arg().name('p', "listen-port") - .description("listen on an alternative port (default: 1982)") - .metavar("port").as_long(&listen_port).set_true(&listen); - ap.arg().name('c', "coordinator") - .description("join an existing HyperDex cluster through IP address or hostname") - .metavar("addr").as_string(&coordinator_host).set_true(&coordinator); - ap.arg().name('P', "coordinator-port") - .description("connect to an alternative port on the coordinator (default: 1982)") - .metavar("port").as_long(&coordinator_port).set_true(&coordinator); - ap.arg().name('t', "threads") - .description("the number of threads which will handle network traffic") - .metavar("N").as_long(&threads); - ap.arg().long_name("log-immediate") - .description("immediately flush all log output") - .set_true(&log_immediate).hidden(); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (ap.args_sz() != 0) - { - std::cerr << "command takes no positional arguments\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (listen_port >= (1 << 16)) - { - std::cerr << "listen-port is out of range" << std::endl; - return EXIT_FAILURE; - } - - if (coordinator_port >= (1 << 16)) - { - std::cerr << "coordinator-port is out of range" << std::endl; - return EXIT_FAILURE; - } - - po6::net::ipaddr listen_ip; - po6::net::location bind_to; - - if (strcmp(listen_host, "auto") == 0) - { - if (!busybee_discover(&listen_ip)) - { - std::cerr << "cannot automatically discover local address; specify one manually" << std::endl; - return EXIT_FAILURE; - } - - bind_to = po6::net::location(listen_ip, listen_port); - } - else - { - if (listen_ip.set(listen_host)) - { - bind_to = po6::net::location(listen_ip, listen_port); - } - - if (bind_to == po6::net::location()) - { - bind_to = po6::net::hostname(listen_host, 0).lookup(AF_UNSPEC, IPPROTO_TCP); - bind_to.port = listen_port; - } - } - - if (bind_to == po6::net::location()) - { - std::cerr << "cannot interpret listen address as hostname or IP address" << std::endl; - return EXIT_FAILURE; - } - - if (bind_to.address == po6::net::ipaddr::ANY()) - { - std::cerr << "cannot bind to " << bind_to << " because it is not routable" << std::endl; - return EXIT_FAILURE; - } - - google::InitGoogleLogging(argv[0]); - google::InstallFailureSignalHandler(); - - if (log_immediate) - { - FLAGS_logbufsecs = 0; - } - - try - { - hyperdex::daemon d; - - if (threads <= 0) - { - threads += sysconf(_SC_NPROCESSORS_ONLN); - - if (threads <= 0) - { - std::cerr << "cannot create a non-positive number of threads" << std::endl; - return EXIT_FAILURE; - } - } - else if (threads > 512) - { - std::cerr << "refusing to create more than 512 threads" << std::endl; - return EXIT_FAILURE; - } - - return d.run(daemonize, - std::string(data), - std::string(log ? log : data), - std::string(pidfile), has_pidfile, - listen, bind_to, - coordinator, po6::net::hostname(coordinator_host, coordinator_port), - threads); - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + bool daemonize = true; + const char *data = "."; + const char *log = NULL; + const char *pidfile = ""; + bool has_pidfile = false; + bool listen = false; + const char *listen_host = "auto"; + long listen_port = 2012; + bool coordinator = false; + const char *coordinator_host = "127.0.0.1"; + long coordinator_port = 1982; + long threads = 0; + bool log_immediate = false; + e::argparser ap; + ap.autohelp(); + ap.arg().name('d', "daemon") + .description("run in the background") + .set_true(&daemonize); + ap.arg().name('f', "foreground") + .description("run in the foreground") + .set_false(&daemonize); + ap.arg().name('D', "data") + .description("store persistent state in this directory (default: .)") + .metavar("dir").as_string(&data); + ap.arg().name('L', "log") + .description("store logs in this directory (default: --data)") + .metavar("dir").as_string(&log); + ap.arg().long_name("pidfile") + .description("write the PID to a file (default: don't)") + .metavar("file").as_string(&pidfile).set_true(&has_pidfile); + ap.arg().name('l', "listen") + .description("listen on a specific IP address (default: auto)") + .metavar("IP").as_string(&listen_host).set_true(&listen); + ap.arg().name('p', "listen-port") + .description("listen on an alternative port (default: 1982)") + .metavar("port").as_long(&listen_port).set_true(&listen); + ap.arg().name('c', "coordinator") + .description("join an existing HyperDex cluster through IP address or hostname") + .metavar("addr").as_string(&coordinator_host).set_true(&coordinator); + ap.arg().name('P', "coordinator-port") + .description("connect to an alternative port on the coordinator (default: 1982)") + .metavar("port").as_long(&coordinator_port).set_true(&coordinator); + ap.arg().name('t', "threads") + .description("the number of threads which will handle network traffic") + .metavar("N").as_long(&threads); + ap.arg().long_name("log-immediate") + .description("immediately flush all log output") + .set_true(&log_immediate).hidden(); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (ap.args_sz() != 0) + { + std::cerr << "command takes no positional arguments\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (listen_port >= (1 << 16)) + { + std::cerr << "listen-port is out of range" << std::endl; + return EXIT_FAILURE; + } + if (coordinator_port >= (1 << 16)) + { + std::cerr << "coordinator-port is out of range" << std::endl; + return EXIT_FAILURE; + } + po6::net::ipaddr listen_ip; + po6::net::location bind_to; + if (strcmp(listen_host, "auto") == 0) + { + if (!busybee_discover(&listen_ip)) + { + std::cerr << "cannot automatically discover local address; specify one manually" << std::endl; + return EXIT_FAILURE; + } + bind_to = po6::net::location(listen_ip, listen_port); + } + else + { + if (listen_ip.set(listen_host)) + { + bind_to = po6::net::location(listen_ip, listen_port); + } + if (bind_to == po6::net::location()) + { + bind_to = po6::net::hostname(listen_host, 0).lookup(AF_UNSPEC, IPPROTO_TCP); + bind_to.port = listen_port; + } + } + if (bind_to == po6::net::location()) + { + std::cerr << "cannot interpret listen address as hostname or IP address" << std::endl; + return EXIT_FAILURE; + } + if (bind_to.address == po6::net::ipaddr::ANY()) + { + std::cerr << "cannot bind to " << bind_to << " because it is not routable" << std::endl; + return EXIT_FAILURE; + } + google::InitGoogleLogging(argv[0]); + google::InstallFailureSignalHandler(); + if (log_immediate) + { + FLAGS_logbufsecs = 0; + } + try + { + hyperdex::daemon d; + if (threads <= 0) + { + threads += sysconf(_SC_NPROCESSORS_ONLN); + if (threads <= 0) + { + std::cerr << "cannot create a non-positive number of threads" << std::endl; + return EXIT_FAILURE; + } + } + else if (threads > 512) + { + std::cerr << "refusing to create more than 512 threads" << std::endl; + return EXIT_FAILURE; + } + return d.run(daemonize, + std::string(data), + std::string(log ? log : data), + std::string(pidfile), has_pidfile, + listen, bind_to, + coordinator, po6::net::hostname(coordinator_host, coordinator_port), + threads); + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/daemon/performance_counter.h b/daemon/performance_counter.h index 968a4f1a6..f0063dffe 100644 --- a/daemon/performance_counter.h +++ b/daemon/performance_counter.h @@ -36,23 +36,23 @@ BEGIN_HYPERDEX_NAMESPACE // a threadsafe counter class performance_counter { - public: - performance_counter() : m_count(0) {} - ~performance_counter() throw () {} - - public: - // increment the counter - // any number of threads can tap simultaneously - void tap() { e::atomic::increment_64_nobarrier(&m_count, 1); } - // any number of threads can call "read" simultaneously - uint64_t read() const { return e::atomic::load_64_nobarrier(&m_count); } - - private: - performance_counter(const performance_counter&); - performance_counter& operator = (const performance_counter&); - - private: - uint64_t m_count; +public: + performance_counter() : m_count(0) {} + ~performance_counter() throw () {} + +public: + // increment the counter + // any number of threads can tap simultaneously + void tap() { e::atomic::increment_64_nobarrier(&m_count, 1); } + // any number of threads can call "read" simultaneously + uint64_t read() const { return e::atomic::load_64_nobarrier(&m_count); } + +private: + performance_counter(const performance_counter &); + performance_counter &operator = (const performance_counter &); + +private: + uint64_t m_count; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/reconfigure_returncode.h b/daemon/reconfigure_returncode.h index 8daf758f3..cefeb8667 100644 --- a/daemon/reconfigure_returncode.h +++ b/daemon/reconfigure_returncode.h @@ -39,14 +39,14 @@ BEGIN_HYPERDEX_NAMESPACE // reconfigure_returncode occupies [8704, 8832) enum reconfigure_returncode { - RECONFIGURE_SUCCESS = 8704, - RECONFIGURE_WARNING = 8705, - RECONFIGURE_FAIL = 8706, - RECONFIGURE_FATAL = 8707 + RECONFIGURE_SUCCESS = 8704, + RECONFIGURE_WARNING = 8705, + RECONFIGURE_FAIL = 8706, + RECONFIGURE_FATAL = 8707 }; -std::ostream& -operator << (std::ostream& lhs, reconfigure_returncode rhs); +std::ostream & +operator << (std::ostream &lhs, reconfigure_returncode rhs); END_HYPERDEX_NAMESPACE diff --git a/daemon/region_timestamp.h b/daemon/region_timestamp.h index 6e011206e..d0947d881 100644 --- a/daemon/region_timestamp.h +++ b/daemon/region_timestamp.h @@ -36,17 +36,17 @@ BEGIN_HYPERDEX_NAMESPACE class region_timestamp { - public: - region_timestamp() : rid(), checkpoint(), local_timestamp() {} - region_timestamp(const region_id& r, - uint64_t c, - const std::string& t) - : rid(r), checkpoint(c), local_timestamp(t) {} +public: + region_timestamp() : rid(), checkpoint(), local_timestamp() {} + region_timestamp(const region_id &r, + uint64_t c, + const std::string &t) + : rid(r), checkpoint(c), local_timestamp(t) {} - public: - region_id rid; - uint64_t checkpoint; - std::string local_timestamp; +public: + region_id rid; + uint64_t checkpoint; + std::string local_timestamp; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/replication_manager.cc b/daemon/replication_manager.cc index 942cdd2ab..e8abc2667 100644 --- a/daemon/replication_manager.cc +++ b/daemon/replication_manager.cc @@ -52,798 +52,724 @@ using hyperdex::replication_manager; class replication_manager::retransmitter_thread : public hyperdex::background_thread { - public: - retransmitter_thread(daemon* d); - ~retransmitter_thread() throw (); - - public: - virtual const char* thread_name() { return "replication"; } - virtual bool have_work(); - virtual void copy_work(); - virtual void do_work(); - - public: - void trigger(); - - public: - replication_manager* m_rm; - uint64_t m_trigger; - - private: - retransmitter_thread(const retransmitter_thread&); - retransmitter_thread& operator = (const retransmitter_thread&); +public: + retransmitter_thread(daemon *d); + ~retransmitter_thread() throw (); + +public: + virtual const char *thread_name() { return "replication"; } + virtual bool have_work(); + virtual void copy_work(); + virtual void do_work(); + +public: + void trigger(); + +public: + replication_manager *m_rm; + uint64_t m_trigger; + +private: + retransmitter_thread(const retransmitter_thread &); + retransmitter_thread &operator = (const retransmitter_thread &); }; -replication_manager :: replication_manager(daemon* d) - : m_daemon(d) - , m_key_states(&d->m_gc) - , m_idgen() - , m_idcol(&d->m_gc) - , m_stable() - , m_retransmitter(new retransmitter_thread(d)) - , m_protect_stable_stuff() - , m_checkpoint(0) - , m_need_check(0) - , m_timestamps() - , m_unstable() +replication_manager :: replication_manager(daemon *d) + : m_daemon(d) + , m_key_states(&d->m_gc) + , m_idgen() + , m_idcol(&d->m_gc) + , m_stable() + , m_retransmitter(new retransmitter_thread(d)) + , m_protect_stable_stuff() + , m_checkpoint(0) + , m_need_check(0) + , m_timestamps() + , m_unstable() { - po6::threads::mutex::hold hold(&m_protect_stable_stuff); - check_is_needed(); + po6::threads::mutex::hold hold(&m_protect_stable_stuff); + check_is_needed(); } replication_manager :: ~replication_manager() throw () { - m_retransmitter->shutdown(); + m_retransmitter->shutdown(); } bool replication_manager :: setup() { - m_retransmitter->start(); - return true; + m_retransmitter->start(); + return true; } void replication_manager :: teardown() { - m_retransmitter->shutdown(); + m_retransmitter->shutdown(); } void replication_manager :: pause() { - m_retransmitter->initiate_pause(); + m_retransmitter->initiate_pause(); } void replication_manager :: unpause() { - m_retransmitter->unpause(); - m_retransmitter->trigger(); + m_retransmitter->unpause(); + m_retransmitter->trigger(); } void -replication_manager :: reconfigure(const configuration&, - const configuration& new_config, - const server_id&) -{ - m_retransmitter->wait_until_paused(); - m_retransmitter->trigger(); - - std::vector key_regions; - new_config.key_regions(m_daemon->m_us, &key_regions); - m_idgen.adopt(&key_regions[0], key_regions.size()); - m_idcol.adopt(&key_regions[0], key_regions.size()); - - std::vector transfers_in_regions; - new_config.transfers_in_regions(m_daemon->m_us, &transfers_in_regions); - - // iterate over all key states; cleanup dead ones, and bump idgen - for (key_map_t::iterator it(&m_key_states); it.valid(); ++it) - { - key_state* ks = *it; - ks->reconfigure(&m_daemon->m_gc); - region_id ri = ks->state_key().region; - - if (std::binary_search(transfers_in_regions.begin(), - transfers_in_regions.end(), ri)) - { - ks->reset(&m_daemon->m_gc); - } - - if (std::binary_search(key_regions.begin(), - key_regions.end(), ri)) - { - m_idgen.bump(ri, ks->max_version()); - } - } - - // iterate over all regions on disk/lb, and bump idgen - for (size_t i = 0; i < key_regions.size(); ++i) - { - uint64_t disk_ver = m_daemon->m_data.max_version(key_regions[i]); - uint64_t mem_ver = m_idcol.lower_bound(key_regions[i]); - uint64_t max_ver = std::max(disk_ver, mem_ver); - - if (max_ver > 0) - { - m_idgen.bump(key_regions[i], max_ver - 1); - } - } - - // figure out when we're stable - m_stable.copy_from(m_idgen); - - // clear timestamps for regions we no longer manage - std::vector mapped_regions; - m_daemon->m_config.mapped_regions(m_daemon->m_us, &mapped_regions); - po6::threads::mutex::hold hold(&m_protect_stable_stuff); - reset_to_unstable(); - - for (size_t i = 0; i < m_timestamps.size(); ) - { - if (!std::binary_search(mapped_regions.begin(), - mapped_regions.end(), - m_timestamps[i].rid)) - { - m_timestamps[i] = m_timestamps.back(); - m_timestamps.pop_back(); - } - else - { - ++i; - } - } +replication_manager :: reconfigure(const configuration &, + const configuration &new_config, + const server_id &) +{ + m_retransmitter->wait_until_paused(); + m_retransmitter->trigger(); + std::vector key_regions; + new_config.key_regions(m_daemon->m_us, &key_regions); + m_idgen.adopt(&key_regions[0], key_regions.size()); + m_idcol.adopt(&key_regions[0], key_regions.size()); + std::vector transfers_in_regions; + new_config.transfers_in_regions(m_daemon->m_us, &transfers_in_regions); + // iterate over all key states; cleanup dead ones, and bump idgen + for (key_map_t::iterator it(&m_key_states); it.valid(); ++it) + { + key_state *ks = *it; + ks->reconfigure(&m_daemon->m_gc); + region_id ri = ks->state_key().region; + if (std::binary_search(transfers_in_regions.begin(), + transfers_in_regions.end(), ri)) + { + ks->reset(&m_daemon->m_gc); + } + if (std::binary_search(key_regions.begin(), + key_regions.end(), ri)) + { + m_idgen.bump(ri, ks->max_version()); + } + } + // iterate over all regions on disk/lb, and bump idgen + for (size_t i = 0; i < key_regions.size(); ++i) + { + uint64_t disk_ver = m_daemon->m_data.max_version(key_regions[i]); + uint64_t mem_ver = m_idcol.lower_bound(key_regions[i]); + uint64_t max_ver = std::max(disk_ver, mem_ver); + if (max_ver > 0) + { + m_idgen.bump(key_regions[i], max_ver - 1); + } + } + // figure out when we're stable + m_stable.copy_from(m_idgen); + // clear timestamps for regions we no longer manage + std::vector mapped_regions; + m_daemon->m_config.mapped_regions(m_daemon->m_us, &mapped_regions); + po6::threads::mutex::hold hold(&m_protect_stable_stuff); + reset_to_unstable(); + for (size_t i = 0; i < m_timestamps.size(); ) + { + if (!std::binary_search(mapped_regions.begin(), + mapped_regions.end(), + m_timestamps[i].rid)) + { + m_timestamps[i] = m_timestamps.back(); + m_timestamps.pop_back(); + } + else + { + ++i; + } + } } void replication_manager :: debug_dump() { - m_retransmitter->initiate_pause(); - m_retransmitter->wait_until_paused(); - std::vector regions; - m_daemon->m_config.key_regions(m_daemon->m_us, ®ions); - - // print counters - LOG(INFO) << "region counters ==============================================================="; - - for (size_t i = 0; i < regions.size(); ++i) - { - uint64_t idgen = m_idgen.peek(regions[i]); - uint64_t lb = m_idcol.lower_bound(regions[i]); - uint64_t stable = m_stable.peek(regions[i]); - LOG(INFO) << regions[i] << " idgen=" << idgen << " lb=" << lb << " stable=" << stable; - } - - // print key state - LOG(INFO) << "key states ===================================================================="; - - for (key_map_t::iterator it(&m_key_states); it.valid(); ++it) - { - key_state* ks = *it; - LOG(INFO) << "state for " << ks->state_key().region << " " << e::slice(ks->state_key().key).hex(); - ks->debug_dump(); - } - - m_retransmitter->unpause(); - m_retransmitter->trigger(); + m_retransmitter->initiate_pause(); + m_retransmitter->wait_until_paused(); + std::vector regions; + m_daemon->m_config.key_regions(m_daemon->m_us, ®ions); + // print counters + LOG(INFO) << "region counters ==============================================================="; + for (size_t i = 0; i < regions.size(); ++i) + { + uint64_t idgen = m_idgen.peek(regions[i]); + uint64_t lb = m_idcol.lower_bound(regions[i]); + uint64_t stable = m_stable.peek(regions[i]); + LOG(INFO) << regions[i] << " idgen=" << idgen << " lb=" << lb << " stable=" << stable; + } + // print key state + LOG(INFO) << "key states ===================================================================="; + for (key_map_t::iterator it(&m_key_states); it.valid(); ++it) + { + key_state *ks = *it; + LOG(INFO) << "state for " << ks->state_key().region << " " << e::slice(ks->state_key().key).hex(); + ks->debug_dump(); + } + m_retransmitter->unpause(); + m_retransmitter->trigger(); } void -replication_manager :: client_atomic(const server_id& from, - const virtual_server_id& to, +replication_manager :: client_atomic(const server_id &from, + const virtual_server_id &to, uint64_t nonce, std::auto_ptr kc, std::auto_ptr backing) { - const region_id ri(m_daemon->m_config.get_region_id(to)); - const schema& sc(*m_daemon->m_config.get_schema(ri)); - - if (m_daemon->m_config.read_only()) - { - respond_to_client(to, from, nonce, NET_READONLY); - return; - } - - if (!kc->validate(sc)) - { - LOG(ERROR) << "dropping nonce=" << nonce << " from client=" << from - << " because the key, checks, or funcs don't validate"; - respond_to_client(to, from, nonce, NET_BADDIMSPEC); - return; - } - - if (m_daemon->m_config.point_leader(ri, kc->key) != to) - { - LOG(ERROR) << "dropping nonce=" << nonce << " from client=" << from - << " because it doesn't map to " << ri; - respond_to_client(to, from, nonce, NET_NOTUS); - return; - } - - key_map_t::state_reference ksr; - key_state* ks = get_or_create_key_state(ri, kc->key, &ksr); - ks->enqueue_client_atomic(this, to, sc, from, nonce, kc, backing); + const region_id ri(m_daemon->m_config.get_region_id(to)); + const schema &sc(*m_daemon->m_config.get_schema(ri)); + if (m_daemon->m_config.read_only()) + { + respond_to_client(to, from, nonce, NET_READONLY); + return; + } + if (!kc->validate(sc)) + { + LOG(ERROR) << "dropping nonce=" << nonce << " from client=" << from + << " because the key, checks, or funcs don't validate"; + respond_to_client(to, from, nonce, NET_BADDIMSPEC); + return; + } + if (m_daemon->m_config.point_leader(ri, kc->key) != to) + { + LOG(ERROR) << "dropping nonce=" << nonce << " from client=" << from + << " because it doesn't map to " << ri; + respond_to_client(to, from, nonce, NET_NOTUS); + return; + } + key_map_t::state_reference ksr; + key_state *ks = get_or_create_key_state(ri, kc->key, &ksr); + ks->enqueue_client_atomic(this, to, sc, from, nonce, kc, backing); } void -replication_manager :: chain_op(const virtual_server_id& from, - const virtual_server_id& to, +replication_manager :: chain_op(const virtual_server_id &from, + const virtual_server_id &to, uint64_t old_version, uint64_t new_version, bool fresh, bool has_value, - const e::slice& key, - const std::vector& value, + const e::slice &key, + const std::vector &value, std::auto_ptr backing) { - const region_id ri(m_daemon->m_config.get_region_id(to)); - const schema& sc(*m_daemon->m_config.get_schema(ri)); - bool valid = sc.attrs_sz == value.size() + 1 && - datatype_info::lookup(sc.attrs[0].type)->validate(key); - - if (has_value) - { - valid = valid && sc.attrs_sz == value.size() + 1; - - for (size_t i = 0; valid && i + 1 < sc.attrs_sz; ++i) - { - valid = datatype_info::lookup(sc.attrs[i + 1].type)->validate(value[i]); - } - } - - if (!valid) - { - LOG(ERROR) << "dropping CHAIN_OP because the dimensions are incorrect"; - return; - } - - key_map_t::state_reference ksr; - key_state* ks = get_or_create_key_state(ri, key, &ksr); - ks->enqueue_chain_op(this, to, sc, from, old_version, new_version, fresh, has_value, value, backing); + const region_id ri(m_daemon->m_config.get_region_id(to)); + const schema &sc(*m_daemon->m_config.get_schema(ri)); + bool valid = sc.attrs_sz == value.size() + 1 && + datatype_info::lookup(sc.attrs[0].type)->validate(key); + if (has_value) + { + valid = valid && sc.attrs_sz == value.size() + 1; + for (size_t i = 0; valid && i + 1 < sc.attrs_sz; ++i) + { + valid = datatype_info::lookup(sc.attrs[i + 1].type)->validate(value[i]); + } + } + if (!valid) + { + LOG(ERROR) << "dropping CHAIN_OP because the dimensions are incorrect"; + return; + } + key_map_t::state_reference ksr; + key_state *ks = get_or_create_key_state(ri, key, &ksr); + ks->enqueue_chain_op(this, to, sc, from, old_version, new_version, fresh, has_value, value, backing); } void -replication_manager :: chain_subspace(const virtual_server_id& from, - const virtual_server_id& to, +replication_manager :: chain_subspace(const virtual_server_id &from, + const virtual_server_id &to, uint64_t old_version, uint64_t new_version, - const e::slice& key, - const std::vector& value, + const e::slice &key, + const std::vector &value, std::auto_ptr backing, - const region_id& prev_region, - const region_id& this_old_region, - const region_id& this_new_region, - const region_id& next_region) -{ - const region_id ri(m_daemon->m_config.get_region_id(to)); - const schema& sc(*m_daemon->m_config.get_schema(ri)); - bool valid = sc.attrs_sz == value.size() + 1 && - datatype_info::lookup(sc.attrs[0].type)->validate(key); - - for (size_t i = 0; valid && i + 1 < sc.attrs_sz; ++i) - { - valid = datatype_info::lookup(sc.attrs[i + 1].type)->validate(value[i]); - } - - if (!valid) - { - LOG(ERROR) << "dropping CHAIN_SUBSPACE because the dimensions are incorrect"; - return; - } - - key_map_t::state_reference ksr; - key_state* ks = get_or_create_key_state(ri, key, &ksr); - ks->enqueue_chain_subspace(this, to, sc, from, old_version, new_version, value, backing, - prev_region, this_old_region, this_new_region, next_region); + const region_id &prev_region, + const region_id &this_old_region, + const region_id &this_new_region, + const region_id &next_region) +{ + const region_id ri(m_daemon->m_config.get_region_id(to)); + const schema &sc(*m_daemon->m_config.get_schema(ri)); + bool valid = sc.attrs_sz == value.size() + 1 && + datatype_info::lookup(sc.attrs[0].type)->validate(key); + for (size_t i = 0; valid && i + 1 < sc.attrs_sz; ++i) + { + valid = datatype_info::lookup(sc.attrs[i + 1].type)->validate(value[i]); + } + if (!valid) + { + LOG(ERROR) << "dropping CHAIN_SUBSPACE because the dimensions are incorrect"; + return; + } + key_map_t::state_reference ksr; + key_state *ks = get_or_create_key_state(ri, key, &ksr); + ks->enqueue_chain_subspace(this, to, sc, from, old_version, new_version, value, backing, + prev_region, this_old_region, this_new_region, next_region); } void -replication_manager :: chain_ack(const virtual_server_id& from, - const virtual_server_id& to, +replication_manager :: chain_ack(const virtual_server_id &from, + const virtual_server_id &to, uint64_t version, - const e::slice& key) -{ - const region_id ri(m_daemon->m_config.get_region_id(to)); - const schema& sc(*m_daemon->m_config.get_schema(ri)); - key_map_t::state_reference ksr; - key_state* ks = get_key_state(ri, key, &ksr); - - if (!ks) - { - LOG(ERROR) << "dropping CHAIN_ACK for update we haven't seen"; - LOG(ERROR) << "troubleshoot info: from=" << from << " to=" << to - << " version=" << version << " key=" << key.hex(); - return; - } - - ks->enqueue_chain_ack(this, to, sc, from, version); + const e::slice &key) +{ + const region_id ri(m_daemon->m_config.get_region_id(to)); + const schema &sc(*m_daemon->m_config.get_schema(ri)); + key_map_t::state_reference ksr; + key_state *ks = get_key_state(ri, key, &ksr); + if (!ks) + { + LOG(ERROR) << "dropping CHAIN_ACK for update we haven't seen"; + LOG(ERROR) << "troubleshoot info: from=" << from << " to=" << to + << " version=" << version << " key=" << key.hex(); + return; + } + ks->enqueue_chain_ack(this, to, sc, from, version); } void replication_manager :: begin_checkpoint(uint64_t checkpoint_num) { - m_retransmitter->initiate_pause(); - m_retransmitter->wait_until_paused(); - std::string timestamp = m_daemon->m_data.get_timestamp(); - - { - std::vector mapped_regions; - m_daemon->m_config.mapped_regions(m_daemon->m_us, &mapped_regions); - po6::threads::mutex::hold hold(&m_protect_stable_stuff); - m_checkpoint = std::max(m_checkpoint, checkpoint_num); - reset_to_unstable(); - - for (size_t i = 0; i < mapped_regions.size(); ++i) - { - m_timestamps.push_back(region_timestamp(mapped_regions[i], checkpoint_num, timestamp)); - } - } - - std::vector key_regions; - m_daemon->m_config.key_regions(m_daemon->m_us, &key_regions); - - for (size_t i = 0; i < key_regions.size(); ++i) - { - uint64_t id = m_idgen.peek(key_regions[i]); - - if (id > 0) - { - bool x = m_stable.bump(key_regions[i], id - 1); - assert(x); - } - - check_stable(key_regions[i]); - } - - check_stable(); - m_retransmitter->unpause(); - m_retransmitter->trigger(); + m_retransmitter->initiate_pause(); + m_retransmitter->wait_until_paused(); + std::string timestamp = m_daemon->m_data.get_timestamp(); + { + std::vector mapped_regions; + m_daemon->m_config.mapped_regions(m_daemon->m_us, &mapped_regions); + po6::threads::mutex::hold hold(&m_protect_stable_stuff); + m_checkpoint = std::max(m_checkpoint, checkpoint_num); + reset_to_unstable(); + for (size_t i = 0; i < mapped_regions.size(); ++i) + { + m_timestamps.push_back(region_timestamp(mapped_regions[i], checkpoint_num, timestamp)); + } + } + std::vector key_regions; + m_daemon->m_config.key_regions(m_daemon->m_us, &key_regions); + for (size_t i = 0; i < key_regions.size(); ++i) + { + uint64_t id = m_idgen.peek(key_regions[i]); + if (id > 0) + { + bool x = m_stable.bump(key_regions[i], id - 1); + assert(x); + } + check_stable(key_regions[i]); + } + check_stable(); + m_retransmitter->unpause(); + m_retransmitter->trigger(); } void replication_manager :: end_checkpoint(uint64_t checkpoint_num) { - m_retransmitter->initiate_pause(); - m_retransmitter->wait_until_paused(); - po6::threads::mutex::hold hold(&m_protect_stable_stuff); - - for (size_t i = 0; i < m_timestamps.size(); ) - { - if (m_timestamps[i].checkpoint <= checkpoint_num) - { - m_daemon->m_data.create_checkpoint(m_timestamps[i]); - std::swap(m_timestamps[i], m_timestamps.back()); - m_timestamps.pop_back(); - } - else - { - ++i; - } - } - - m_retransmitter->unpause(); - m_retransmitter->trigger(); -} - -key_state* -replication_manager :: get_key_state(const region_id& ri, - const e::slice& key, - key_map_t::state_reference* ksr) -{ - key_region kr(ri, key); - key_state* ks = m_key_states.get_state(kr, ksr); - return post_get_key_state_init(ri, ks); -} - -key_state* -replication_manager :: get_or_create_key_state(const region_id& ri, - const e::slice& key, - key_map_t::state_reference* ksr) -{ - key_region kr(ri, key); - key_state* ks = m_key_states.get_or_create_state(kr, ksr); - return post_get_key_state_init(ri, ks); -} - -key_state* -replication_manager :: post_get_key_state_init(region_id ri, key_state* ks) -{ - if (!ks || ks->initialized()) - { - return ks; - } - - const schema& sc(*m_daemon->m_config.get_schema(ri)); - - switch (ks->initialize(&m_daemon->m_data, sc, ri)) - { - case datalayer::SUCCESS: - case datalayer::NOT_FOUND: - return ks; - case datalayer::BAD_ENCODING: - case datalayer::CORRUPTION: - case datalayer::IO_ERROR: - case datalayer::LEVELDB_ERROR: - default: - LOG(ERROR) << "Data layer returned unexpected result when reading old value."; - return NULL; - } + m_retransmitter->initiate_pause(); + m_retransmitter->wait_until_paused(); + po6::threads::mutex::hold hold(&m_protect_stable_stuff); + for (size_t i = 0; i < m_timestamps.size(); ) + { + if (m_timestamps[i].checkpoint <= checkpoint_num) + { + m_daemon->m_data.create_checkpoint(m_timestamps[i]); + std::swap(m_timestamps[i], m_timestamps.back()); + m_timestamps.pop_back(); + } + else + { + ++i; + } + } + m_retransmitter->unpause(); + m_retransmitter->trigger(); +} + +key_state * +replication_manager :: get_key_state(const region_id &ri, + const e::slice &key, + key_map_t::state_reference *ksr) +{ + key_region kr(ri, key); + key_state *ks = m_key_states.get_state(kr, ksr); + return post_get_key_state_init(ri, ks); +} + +key_state * +replication_manager :: get_or_create_key_state(const region_id &ri, + const e::slice &key, + key_map_t::state_reference *ksr) +{ + key_region kr(ri, key); + key_state *ks = m_key_states.get_or_create_state(kr, ksr); + return post_get_key_state_init(ri, ks); +} + +key_state * +replication_manager :: post_get_key_state_init(region_id ri, key_state *ks) +{ + if (!ks || ks->initialized()) + { + return ks; + } + const schema &sc(*m_daemon->m_config.get_schema(ri)); + switch (ks->initialize(&m_daemon->m_data, sc, ri)) + { + case datalayer::SUCCESS: + case datalayer::NOT_FOUND: + return ks; + case datalayer::BAD_ENCODING: + case datalayer::CORRUPTION: + case datalayer::IO_ERROR: + case datalayer::LEVELDB_ERROR: + default: + LOG(ERROR) << "Data layer returned unexpected result when reading old value."; + return NULL; + } } void -replication_manager :: respond_to_client(const virtual_server_id& us, - const server_id& client, +replication_manager :: respond_to_client(const virtual_server_id &us, + const server_id &client, uint64_t nonce, network_returncode ret) { - size_t sz = HYPERDEX_HEADER_SIZE_VC - + sizeof(uint64_t) - + sizeof(uint16_t); - std::auto_ptr msg(e::buffer::create(sz)); - uint16_t result = static_cast(ret); - msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << result; - m_daemon->m_comm.send_client(us, client, RESP_ATOMIC, msg); + size_t sz = HYPERDEX_HEADER_SIZE_VC + + sizeof(uint64_t) + + sizeof(uint16_t); + std::auto_ptr msg(e::buffer::create(sz)); + uint16_t result = static_cast(ret); + msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << result; + m_daemon->m_comm.send_client(us, client, RESP_ATOMIC, msg); } bool -replication_manager :: send_message(const virtual_server_id& us, - const e::slice& key, +replication_manager :: send_message(const virtual_server_id &us, + const e::slice &key, e::intrusive_ptr op) { - // If we've sent it somewhere, we shouldn't resend. If the sender intends a - // resend, they should clear "sent" first. - assert(op->sent_to() == virtual_server_id()); - region_id ri(m_daemon->m_config.get_region_id(us)); - - // If there's an ongoing transfer, don't actually send - if (m_daemon->m_config.is_server_blocked_by_live_transfer(m_daemon->m_us, ri)) - { - return false; - } - - // facts we use to decide what to do - assert(ri == op->this_old_region() || ri == op->this_new_region()); - bool last_in_chain = m_daemon->m_config.tail_of_region(ri) == us; - bool has_next_subspace = op->next_region() != region_id(); - - // variables we fill in to determine the message type/destination - virtual_server_id dest; - network_msgtype type = CHAIN_OP; - - if (op->this_old_region() == op->this_new_region()) - { - if (last_in_chain) - { - if (has_next_subspace) - { - dest = m_daemon->m_config.head_of_region(op->next_region()); - type = CHAIN_OP; - } - else - { - if (!op->ackable()) - { - op->mark_acked(); - collect(ri, op); - } - - return send_ack(us, key, op); - } - } - else - { - dest = m_daemon->m_config.next_in_region(us); - type = CHAIN_OP; - } - } - else if (op->this_old_region() == ri) - { - if (last_in_chain) - { - assert(op->has_value()); - dest = m_daemon->m_config.head_of_region(op->this_new_region()); - type = CHAIN_SUBSPACE; - } - else - { - dest = m_daemon->m_config.next_in_region(us); - type = CHAIN_OP; - } - } - else if (op->this_new_region() == ri) - { - if (last_in_chain) - { - if (has_next_subspace) - { - dest = m_daemon->m_config.head_of_region(op->next_region()); - type = CHAIN_OP; - } - else - { - if (!op->ackable()) - { - op->mark_acked(); - collect(ri, op); - } - - return send_ack(us, key, op); - } - } - else - { - assert(op->has_value()); - dest = m_daemon->m_config.next_in_region(us); - type = CHAIN_SUBSPACE; - } - } - else - { - abort(); - } - - std::auto_ptr msg; - - if (type == CHAIN_OP) - { - uint8_t flags = (op->is_fresh() ? 1 : 0) - | (op->has_value() ? 2 : 0); - size_t sz = HYPERDEX_HEADER_SIZE_VV - + sizeof(uint8_t) - + sizeof(uint64_t) - + sizeof(uint64_t) - + pack_size(key) - + pack_size(op->value()); - msg.reset(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VV) - << flags << op->prev_version() << op->this_version() - << key << op->value(); - } - else if (type == CHAIN_SUBSPACE) - { - size_t sz = HYPERDEX_HEADER_SIZE_VV - + sizeof(uint64_t) - + sizeof(uint64_t) - + pack_size(key) - + pack_size(op->value()) - + pack_size(op->prev_region()) - + pack_size(op->this_old_region()) - + pack_size(op->this_new_region()) - + pack_size(op->next_region()); - msg.reset(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VV) - << op->prev_version() << op->this_version() - << key << op->value() - << op->prev_region() - << op->this_old_region() - << op->this_new_region() - << op->next_region(); - } - else - { - abort(); - } - - op->set_sent(m_daemon->m_config.version(), dest); - return m_daemon->m_comm.send_exact(us, dest, type, msg); + // If we've sent it somewhere, we shouldn't resend. If the sender intends a + // resend, they should clear "sent" first. + assert(op->sent_to() == virtual_server_id()); + region_id ri(m_daemon->m_config.get_region_id(us)); + // If there's an ongoing transfer, don't actually send + if (m_daemon->m_config.is_server_blocked_by_live_transfer(m_daemon->m_us, ri)) + { + return false; + } + // facts we use to decide what to do + assert(ri == op->this_old_region() || ri == op->this_new_region()); + bool last_in_chain = m_daemon->m_config.tail_of_region(ri) == us; + bool has_next_subspace = op->next_region() != region_id(); + // variables we fill in to determine the message type/destination + virtual_server_id dest; + network_msgtype type = CHAIN_OP; + if (op->this_old_region() == op->this_new_region()) + { + if (last_in_chain) + { + if (has_next_subspace) + { + dest = m_daemon->m_config.head_of_region(op->next_region()); + type = CHAIN_OP; + } + else + { + if (!op->ackable()) + { + op->mark_acked(); + collect(ri, op); + } + return send_ack(us, key, op); + } + } + else + { + dest = m_daemon->m_config.next_in_region(us); + type = CHAIN_OP; + } + } + else if (op->this_old_region() == ri) + { + if (last_in_chain) + { + assert(op->has_value()); + dest = m_daemon->m_config.head_of_region(op->this_new_region()); + type = CHAIN_SUBSPACE; + } + else + { + dest = m_daemon->m_config.next_in_region(us); + type = CHAIN_OP; + } + } + else if (op->this_new_region() == ri) + { + if (last_in_chain) + { + if (has_next_subspace) + { + dest = m_daemon->m_config.head_of_region(op->next_region()); + type = CHAIN_OP; + } + else + { + if (!op->ackable()) + { + op->mark_acked(); + collect(ri, op); + } + return send_ack(us, key, op); + } + } + else + { + assert(op->has_value()); + dest = m_daemon->m_config.next_in_region(us); + type = CHAIN_SUBSPACE; + } + } + else + { + abort(); + } + std::auto_ptr msg; + if (type == CHAIN_OP) + { + uint8_t flags = (op->is_fresh() ? 1 : 0) + | (op->has_value() ? 2 : 0); + size_t sz = HYPERDEX_HEADER_SIZE_VV + + sizeof(uint8_t) + + sizeof(uint64_t) + + sizeof(uint64_t) + + pack_size(key) + + pack_size(op->value()); + msg.reset(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VV) + << flags << op->prev_version() << op->this_version() + << key << op->value(); + } + else if (type == CHAIN_SUBSPACE) + { + size_t sz = HYPERDEX_HEADER_SIZE_VV + + sizeof(uint64_t) + + sizeof(uint64_t) + + pack_size(key) + + pack_size(op->value()) + + pack_size(op->prev_region()) + + pack_size(op->this_old_region()) + + pack_size(op->this_new_region()) + + pack_size(op->next_region()); + msg.reset(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VV) + << op->prev_version() << op->this_version() + << key << op->value() + << op->prev_region() + << op->this_old_region() + << op->this_new_region() + << op->next_region(); + } + else + { + abort(); + } + op->set_sent(m_daemon->m_config.version(), dest); + return m_daemon->m_comm.send_exact(us, dest, type, msg); } bool -replication_manager :: send_ack(const virtual_server_id& us, - const e::slice& key, +replication_manager :: send_ack(const virtual_server_id &us, + const e::slice &key, e::intrusive_ptr op) { - if (!op->ackable() || !op->recv_from(m_daemon->m_config.version())) - { - return false; - } - - size_t sz = HYPERDEX_HEADER_SIZE_VV + sizeof(uint64_t) + pack_size(key); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << op->this_version() << key; - return m_daemon->m_comm.send_exact(us, op->recv_from(), CHAIN_ACK, msg); + if (!op->ackable() || !op->recv_from(m_daemon->m_config.version())) + { + return false; + } + size_t sz = HYPERDEX_HEADER_SIZE_VV + sizeof(uint64_t) + pack_size(key); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << op->this_version() << key; + return m_daemon->m_comm.send_exact(us, op->recv_from(), CHAIN_ACK, msg); } void -replication_manager :: retransmit(const std::vector& point_leaders, - std::vector >* versions) -{ - for (key_map_t::iterator it(&m_key_states); it.valid(); ++it) - { - key_state* ks = *it; - region_id ri = ks->state_key().region; - - if (std::binary_search(point_leaders.begin(), - point_leaders.end(), ri)) - { - ks->append_all_versions(versions); - } - - if (m_daemon->m_config.is_server_blocked_by_live_transfer(m_daemon->m_us, ri)) - { - continue; - } - - virtual_server_id us = m_daemon->m_config.get_virtual(ri, m_daemon->m_us); - - if (us == virtual_server_id() || ks->finished()) - { - ks->reset(&m_daemon->m_gc); - continue; - } - - const schema& sc(*m_daemon->m_config.get_schema(ri)); - ks->resend_committable(this, us); - ks->work_state_machine(this, us, sc); - } - - m_daemon->m_comm.wake_one(); +replication_manager :: retransmit(const std::vector &point_leaders, + std::vector > *versions) +{ + for (key_map_t::iterator it(&m_key_states); it.valid(); ++it) + { + key_state *ks = *it; + region_id ri = ks->state_key().region; + if (std::binary_search(point_leaders.begin(), + point_leaders.end(), ri)) + { + ks->append_all_versions(versions); + } + if (m_daemon->m_config.is_server_blocked_by_live_transfer(m_daemon->m_us, ri)) + { + continue; + } + virtual_server_id us = m_daemon->m_config.get_virtual(ri, m_daemon->m_us); + if (us == virtual_server_id() || ks->finished()) + { + ks->reset(&m_daemon->m_gc); + continue; + } + const schema &sc(*m_daemon->m_config.get_schema(ri)); + ks->resend_committable(this, us); + ks->work_state_machine(this, us, sc); + } + m_daemon->m_comm.wake_one(); } void -replication_manager :: collect(const region_id& ri, e::intrusive_ptr op) +replication_manager :: collect(const region_id &ri, e::intrusive_ptr op) { - if (op->prev_region() == region_id()) - { - collect(ri, op->this_version()); - } - - check_stable(); + if (op->prev_region() == region_id()) + { + collect(ri, op->this_version()); + } + check_stable(); } void -replication_manager :: collect(const region_id& ri, uint64_t version) +replication_manager :: collect(const region_id &ri, uint64_t version) { - m_idcol.collect(ri, version); - check_stable(ri); + m_idcol.collect(ri, version); + check_stable(ri); } void -replication_manager :: close_gaps(const std::vector& point_leaders, - const identifier_generator& peek_ids, - std::vector >* versions) -{ - std::sort(versions->begin(), versions->end()); - - for (size_t i = 0; i < point_leaders.size(); ++i) - { - // figure out the start and end ptrs within versions - // s.t. [start, limit) contains all point_leaders[i] - std::pair* start = &(*versions)[0]; - std::pair* const end = start + versions->size(); - - while (start < end && start->first == point_leaders[i]) - { - ++start; - } - - std::pair* limit = start; - - while (limit < end && limit->first == start->first) - { - ++limit; - } - - // find the next ID to generate for point_leaders[i] (cant_touch_this) - uint64_t cant_touch_this = peek_ids.peek(point_leaders[i]); - - // if start == limit, then there are no versions and everything less than - // cant_touch_this is collectable and we can short-circuit the - // complexity below - if (start == limit) - { - m_idcol.bump(point_leaders[i], cant_touch_this); - continue; - } - - // find the lower bound for point_leaders[i] (lb) - uint64_t lb = m_idcol.lower_bound(point_leaders[i]); - - // for every value [lb, cant_touch_this), call collect if not found in - // versions [start, limit) - for (uint64_t maybe_next_to_collect = lb; - maybe_next_to_collect < cant_touch_this; ++maybe_next_to_collect) - { - if (!std::binary_search(start, limit, - std::make_pair(point_leaders[i], maybe_next_to_collect))) - { - m_idcol.collect(point_leaders[i], maybe_next_to_collect); - } - } - - // compute the lower bound on point_leaders[i] to squash gaps - uint64_t tmp = m_idcol.lower_bound(point_leaders[i]); - (void) tmp; - } +replication_manager :: close_gaps(const std::vector &point_leaders, + const identifier_generator &peek_ids, + std::vector > *versions) +{ + std::sort(versions->begin(), versions->end()); + for (size_t i = 0; i < point_leaders.size(); ++i) + { + // figure out the start and end ptrs within versions + // s.t. [start, limit) contains all point_leaders[i] + std::pair *start = &(*versions)[0]; + std::pair *const end = start + versions->size(); + while (start < end && start->first == point_leaders[i]) + { + ++start; + } + std::pair *limit = start; + while (limit < end && limit->first == start->first) + { + ++limit; + } + // find the next ID to generate for point_leaders[i] (cant_touch_this) + uint64_t cant_touch_this = peek_ids.peek(point_leaders[i]); + // if start == limit, then there are no versions and everything less than + // cant_touch_this is collectable and we can short-circuit the + // complexity below + if (start == limit) + { + m_idcol.bump(point_leaders[i], cant_touch_this); + continue; + } + // find the lower bound for point_leaders[i] (lb) + uint64_t lb = m_idcol.lower_bound(point_leaders[i]); + // for every value [lb, cant_touch_this), call collect if not found in + // versions [start, limit) + for (uint64_t maybe_next_to_collect = lb; + maybe_next_to_collect < cant_touch_this; ++maybe_next_to_collect) + { + if (!std::binary_search(start, limit, + std::make_pair(point_leaders[i], maybe_next_to_collect))) + { + m_idcol.collect(point_leaders[i], maybe_next_to_collect); + } + } + // compute the lower bound on point_leaders[i] to squash gaps + uint64_t tmp = m_idcol.lower_bound(point_leaders[i]); + (void) tmp; + } } void replication_manager :: reset_to_unstable() { - m_unstable.clear(); - m_daemon->m_config.point_leaders(m_daemon->m_us, &m_unstable); - check_is_needed(); - m_retransmitter->trigger(); + m_unstable.clear(); + m_daemon->m_config.point_leaders(m_daemon->m_us, &m_unstable); + check_is_needed(); + m_retransmitter->trigger(); } void replication_manager :: check_stable() { - bool tell_coord_stable = false; - uint64_t checkpoint = 0; - - if (is_check_needed()) - { - po6::threads::mutex::hold hold(&m_protect_stable_stuff); - tell_coord_stable = m_unstable.empty(); - checkpoint = m_checkpoint; - - if (tell_coord_stable) - { - check_is_not_needed(); - } - } - - if (tell_coord_stable) - { - m_daemon->m_coord->config_stable(m_daemon->m_config.version()); - m_daemon->m_coord->checkpoint_report_stable(checkpoint); - } + bool tell_coord_stable = false; + uint64_t checkpoint = 0; + if (is_check_needed()) + { + po6::threads::mutex::hold hold(&m_protect_stable_stuff); + tell_coord_stable = m_unstable.empty(); + checkpoint = m_checkpoint; + if (tell_coord_stable) + { + check_is_not_needed(); + } + } + if (tell_coord_stable) + { + m_daemon->m_coord->config_stable(m_daemon->m_config.version()); + m_daemon->m_coord->checkpoint_report_stable(checkpoint); + } } void -replication_manager :: check_stable(const region_id& ri) -{ - if (!is_check_needed()) - { - return; - } - - bool tell_coord_stable = false; - uint64_t checkpoint = 0; - uint64_t lb = m_idcol.lower_bound(ri); - uint64_t stable = m_stable.peek(ri); - - if (stable <= lb) - { - po6::threads::mutex::hold hold(&m_protect_stable_stuff); - bool popped = false; - - for (size_t i = 0; i < m_unstable.size(); ) - { - if (m_unstable[i] == ri) - { - std::swap(m_unstable[i], m_unstable.back()); - m_unstable.pop_back(); - popped = true; - } - else - { - ++i; - } - } - - tell_coord_stable = popped && m_unstable.empty(); - checkpoint = m_checkpoint; - - if (tell_coord_stable) - { - check_is_not_needed(); - } - } - - if (tell_coord_stable) - { - m_daemon->m_coord->config_stable(m_daemon->m_config.version()); - m_daemon->m_coord->checkpoint_report_stable(checkpoint); - } -} - -replication_manager :: retransmitter_thread :: retransmitter_thread(daemon* d) - : background_thread(d) - , m_rm(&d->m_repl) - , m_trigger(0) +replication_manager :: check_stable(const region_id &ri) +{ + if (!is_check_needed()) + { + return; + } + bool tell_coord_stable = false; + uint64_t checkpoint = 0; + uint64_t lb = m_idcol.lower_bound(ri); + uint64_t stable = m_stable.peek(ri); + if (stable <= lb) + { + po6::threads::mutex::hold hold(&m_protect_stable_stuff); + bool popped = false; + for (size_t i = 0; i < m_unstable.size(); ) + { + if (m_unstable[i] == ri) + { + std::swap(m_unstable[i], m_unstable.back()); + m_unstable.pop_back(); + popped = true; + } + else + { + ++i; + } + } + tell_coord_stable = popped && m_unstable.empty(); + checkpoint = m_checkpoint; + if (tell_coord_stable) + { + check_is_not_needed(); + } + } + if (tell_coord_stable) + { + m_daemon->m_coord->config_stable(m_daemon->m_config.version()); + m_daemon->m_coord->checkpoint_report_stable(checkpoint); + } +} + +replication_manager :: retransmitter_thread :: retransmitter_thread(daemon *d) + : background_thread(d) + , m_rm(&d->m_repl) + , m_trigger(0) { } @@ -854,49 +780,44 @@ replication_manager :: retransmitter_thread :: ~retransmitter_thread() throw () bool replication_manager :: retransmitter_thread :: have_work() { - return m_trigger > 0; + return m_trigger > 0; } void replication_manager :: retransmitter_thread :: copy_work() { - assert(m_trigger > 0); - --m_trigger; + assert(m_trigger > 0); + --m_trigger; } void replication_manager :: retransmitter_thread :: do_work() { - // get the list of point leaders - std::vector point_leaders; - m_rm->m_daemon->m_config.point_leaders(m_rm->m_daemon->m_us, &point_leaders); - std::sort(point_leaders.begin(), point_leaders.end()); - - // peek at the next-to-generate values of m_idgen - identifier_generator peeked_values; - peeked_values.copy_from(m_rm->m_idgen); - std::vector > versions; - - // retransmit everything - m_rm->retransmit(point_leaders, &versions); - - // now close all gaps - m_rm->close_gaps(point_leaders, peeked_values, &versions); - - for (size_t i = 0; i < point_leaders.size(); ++i) - { - m_rm->check_stable(point_leaders[i]); - } - - m_rm->check_stable(); - m_rm->m_daemon->m_comm.wake_one(); + // get the list of point leaders + std::vector point_leaders; + m_rm->m_daemon->m_config.point_leaders(m_rm->m_daemon->m_us, &point_leaders); + std::sort(point_leaders.begin(), point_leaders.end()); + // peek at the next-to-generate values of m_idgen + identifier_generator peeked_values; + peeked_values.copy_from(m_rm->m_idgen); + std::vector > versions; + // retransmit everything + m_rm->retransmit(point_leaders, &versions); + // now close all gaps + m_rm->close_gaps(point_leaders, peeked_values, &versions); + for (size_t i = 0; i < point_leaders.size(); ++i) + { + m_rm->check_stable(point_leaders[i]); + } + m_rm->check_stable(); + m_rm->m_daemon->m_comm.wake_one(); } void replication_manager :: retransmitter_thread :: trigger() { - this->lock(); - ++m_trigger; - this->wakeup(); - this->unlock(); + this->lock(); + ++m_trigger; + this->wakeup(); + this->unlock(); } diff --git a/daemon/replication_manager.h b/daemon/replication_manager.h index 7fb1ff6a8..c73e006b5 100644 --- a/daemon/replication_manager.h +++ b/daemon/replication_manager.h @@ -65,117 +65,117 @@ class daemon; // Manage replication. class replication_manager { - public: - replication_manager(daemon*); - ~replication_manager() throw (); +public: + replication_manager(daemon *); + ~replication_manager() throw (); - // Reconfigure this layer. - public: - bool setup(); - void teardown(); - void pause(); - void unpause(); - void reconfigure(const configuration& old_config, - const configuration& new_config, - const server_id& us); - void debug_dump(); + // Reconfigure this layer. +public: + bool setup(); + void teardown(); + void pause(); + void unpause(); + void reconfigure(const configuration &old_config, + const configuration &new_config, + const server_id &us); + void debug_dump(); - // Network workers call these methods. - public: - // These are called when the client initiates the action. This implies - // that only the point leader should call these methods. - void client_atomic(const server_id& from, - const virtual_server_id& to, - uint64_t nonce, - std::auto_ptr kc, - std::auto_ptr backing); - // These are called in response to messages from other hosts. - void chain_op(const virtual_server_id& from, - const virtual_server_id& to, - uint64_t old_version, - uint64_t new_version, - bool fresh, - bool has_value, - const e::slice& key, - const std::vector& value, - std::auto_ptr backing); - void chain_subspace(const virtual_server_id& from, - const virtual_server_id& to, - uint64_t old_version, - uint64_t new_version, - const e::slice& key, - const std::vector& value, - std::auto_ptr backing, - const region_id& prev_region, - const region_id& this_old_region, - const region_id& this_new_region, - const region_id& next_region); - void chain_ack(const virtual_server_id& from, - const virtual_server_id& to, - uint64_t version, - const e::slice& key); - void begin_checkpoint(uint64_t seq); - void end_checkpoint(uint64_t seq); + // Network workers call these methods. +public: + // These are called when the client initiates the action. This implies + // that only the point leader should call these methods. + void client_atomic(const server_id &from, + const virtual_server_id &to, + uint64_t nonce, + std::auto_ptr kc, + std::auto_ptr backing); + // These are called in response to messages from other hosts. + void chain_op(const virtual_server_id &from, + const virtual_server_id &to, + uint64_t old_version, + uint64_t new_version, + bool fresh, + bool has_value, + const e::slice &key, + const std::vector &value, + std::auto_ptr backing); + void chain_subspace(const virtual_server_id &from, + const virtual_server_id &to, + uint64_t old_version, + uint64_t new_version, + const e::slice &key, + const std::vector &value, + std::auto_ptr backing, + const region_id &prev_region, + const region_id &this_old_region, + const region_id &this_new_region, + const region_id &next_region); + void chain_ack(const virtual_server_id &from, + const virtual_server_id &to, + uint64_t version, + const e::slice &key); + void begin_checkpoint(uint64_t seq); + void end_checkpoint(uint64_t seq); - private: - class retransmitter_thread; - typedef state_hash_table key_map_t; - friend class key_state; +private: + class retransmitter_thread; + typedef state_hash_table key_map_t; + friend class key_state; - private: - // Get the state for the specified key. - // Returns NULL if there is no key_state that's currently in use. - key_state* get_key_state(const region_id& ri, - const e::slice& key, - key_map_t::state_reference* ksr); - // Get the state for the specified key. - // Will retrieve the state from disk and create the key_state when - // necessary. - key_state* get_or_create_key_state(const region_id& ri, - const e::slice& key, - key_map_t::state_reference* ksr); - key_state* post_get_key_state_init(region_id ri, key_state* ks); - void respond_to_client(const virtual_server_id& us, - const server_id& client, - uint64_t nonce, - network_returncode ret); - bool send_message(const virtual_server_id& us, - const e::slice& key, - e::intrusive_ptr op); - bool send_ack(const virtual_server_id& us, - const e::slice& key, - e::intrusive_ptr op); - void retransmit(const std::vector& point_leaders, - std::vector >* versions); - void collect(const region_id& ri, e::intrusive_ptr op); - void collect(const region_id& ri, uint64_t version); - void close_gaps(const std::vector& point_leaders, - const identifier_generator& peek_ids, - std::vector >* versions); - // call reset_to_unstable holding m_protect_stable_stuff - void reset_to_unstable(); - bool is_check_needed() { return e::atomic::compare_and_swap_32_nobarrier(&m_need_check, 0, 0) == 1; } - void check_is_needed() { e::atomic::compare_and_swap_32_nobarrier(&m_need_check, 0, 1); } - void check_is_not_needed() { e::atomic::compare_and_swap_32_nobarrier(&m_need_check, 1, 0); } - void check_stable(); - void check_stable(const region_id& ri); +private: + // Get the state for the specified key. + // Returns NULL if there is no key_state that's currently in use. + key_state *get_key_state(const region_id &ri, + const e::slice &key, + key_map_t::state_reference *ksr); + // Get the state for the specified key. + // Will retrieve the state from disk and create the key_state when + // necessary. + key_state *get_or_create_key_state(const region_id &ri, + const e::slice &key, + key_map_t::state_reference *ksr); + key_state *post_get_key_state_init(region_id ri, key_state *ks); + void respond_to_client(const virtual_server_id &us, + const server_id &client, + uint64_t nonce, + network_returncode ret); + bool send_message(const virtual_server_id &us, + const e::slice &key, + e::intrusive_ptr op); + bool send_ack(const virtual_server_id &us, + const e::slice &key, + e::intrusive_ptr op); + void retransmit(const std::vector &point_leaders, + std::vector > *versions); + void collect(const region_id &ri, e::intrusive_ptr op); + void collect(const region_id &ri, uint64_t version); + void close_gaps(const std::vector &point_leaders, + const identifier_generator &peek_ids, + std::vector > *versions); + // call reset_to_unstable holding m_protect_stable_stuff + void reset_to_unstable(); + bool is_check_needed() { return e::atomic::compare_and_swap_32_nobarrier(&m_need_check, 0, 0) == 1; } + void check_is_needed() { e::atomic::compare_and_swap_32_nobarrier(&m_need_check, 0, 1); } + void check_is_not_needed() { e::atomic::compare_and_swap_32_nobarrier(&m_need_check, 1, 0); } + void check_stable(); + void check_stable(const region_id &ri); - private: - daemon* m_daemon; - key_map_t m_key_states; - identifier_generator m_idgen; - identifier_collector m_idcol; - identifier_generator m_stable; - const std::auto_ptr m_retransmitter; - po6::threads::mutex m_protect_stable_stuff; - uint64_t m_checkpoint; - uint32_t m_need_check; - std::vector m_timestamps; - std::vector m_unstable; +private: + daemon *m_daemon; + key_map_t m_key_states; + identifier_generator m_idgen; + identifier_collector m_idcol; + identifier_generator m_stable; + const std::auto_ptr m_retransmitter; + po6::threads::mutex m_protect_stable_stuff; + uint64_t m_checkpoint; + uint32_t m_need_check; + std::vector m_timestamps; + std::vector m_unstable; - private: - replication_manager(const replication_manager&); - replication_manager& operator = (const replication_manager&); +private: + replication_manager(const replication_manager &); + replication_manager &operator = (const replication_manager &); }; END_HYPERDEX_NAMESPACE diff --git a/daemon/search_manager.cc b/daemon/search_manager.cc index 4d84c32d9..9727c327d 100644 --- a/daemon/search_manager.cc +++ b/daemon/search_manager.cc @@ -57,26 +57,26 @@ using hyperdex::reconfigure_returncode; class search_manager::id { - public: - id(const region_id re, const server_id cl, uint64_t sid); - ~id() throw (); - - public: - bool operator < (const id& rhs) const; - bool operator == (const id& rhs) const; - - public: - region_id region; - server_id client; - uint64_t search_id; +public: + id(const region_id re, const server_id cl, uint64_t sid); + ~id() throw (); + +public: + bool operator < (const id &rhs) const; + bool operator == (const id &rhs) const; + +public: + region_id region; + server_id client; + uint64_t search_id; }; search_manager :: id :: id(const region_id re, const server_id cl, uint64_t sid) - : region(re) - , client(cl) - , search_id(sid) + : region(re) + , client(cl) + , search_id(sid) { } @@ -85,68 +85,66 @@ search_manager :: id :: ~id() throw () } bool -search_manager :: id :: operator < (const id& rhs) const +search_manager :: id :: operator < (const id &rhs) const { - if (region == rhs.region) - { - if (client == rhs.client) - { - return search_id < rhs.search_id; - } - - return client < rhs.client; - } - - return region < rhs.region; + if (region == rhs.region) + { + if (client == rhs.client) + { + return search_id < rhs.search_id; + } + return client < rhs.client; + } + return region < rhs.region; } bool -search_manager :: id :: operator == (const id& rhs) const +search_manager :: id :: operator == (const id &rhs) const { - return region == rhs.region && - client == rhs.client && - search_id == rhs.search_id; + return region == rhs.region && + client == rhs.client && + search_id == rhs.search_id; } ///////////////////////////// Search Manager State ///////////////////////////// class search_manager::state { - public: - state(const region_id& region, - std::auto_ptr msg, - std::vector* checks); - ~state() throw (); +public: + state(const region_id ®ion, + std::auto_ptr msg, + std::vector *checks); + ~state() throw (); - public: - po6::threads::mutex lock; - const region_id region; - const std::auto_ptr backing; - std::vector checks; - e::intrusive_ptr iter; +public: + po6::threads::mutex lock; + const region_id region; + const std::auto_ptr backing; + std::vector checks; + e::intrusive_ptr iter; - private: - friend class e::intrusive_ptr; +private: + friend class e::intrusive_ptr; - private: - void inc() { __sync_add_and_fetch(&m_ref, 1); } - void dec() { if (__sync_sub_and_fetch(&m_ref, 1) == 0) delete this; } +private: + void inc() { __sync_add_and_fetch(&m_ref, 1); } + void dec() { if (__sync_sub_and_fetch(&m_ref, 1) == 0) delete this; } - private: - size_t m_ref; +private: + size_t m_ref; }; -search_manager :: state :: state(const region_id& r, +search_manager :: state :: state(const region_id &r, std::auto_ptr msg, - std::vector* c) - : lock() - , region(r) - , backing(msg) - , checks() - , iter() - , m_ref(0) -{ - checks.swap(*c); + std::vector *c) + : lock() + , region(r) + , backing(msg) + , checks() + , iter() + , m_ref(0) +{ + checks.swap(*c); } search_manager :: state :: ~state() throw () @@ -155,9 +153,9 @@ search_manager :: state :: ~state() throw () //////////////////////////////// Search Manager //////////////////////////////// -search_manager :: search_manager(daemon* d) - : m_daemon(d) - , m_searches(10) +search_manager :: search_manager(daemon *d) + : m_daemon(d) + , m_searches(10) { } @@ -168,7 +166,7 @@ search_manager :: ~search_manager() throw () bool search_manager :: setup() { - return true; + return true; } void @@ -187,117 +185,108 @@ search_manager :: unpause() } void -search_manager :: reconfigure(const configuration&, - const configuration&, - const server_id&) +search_manager :: reconfigure(const configuration &, + const configuration &, + const server_id &) { - // XXX cleanup dead or old searches + // XXX cleanup dead or old searches } void -search_manager :: start(const server_id& from, - const virtual_server_id& to, +search_manager :: start(const server_id &from, + const virtual_server_id &to, std::auto_ptr msg, uint64_t nonce, uint64_t search_id, - std::vector* checks) -{ - region_id ri(m_daemon->m_config.get_region_id(to)); - const schema* sc = m_daemon->m_config.get_schema(ri); - - if (sc->authorization) - { - return; - } - - id sid(ri, from, search_id); - - if (m_searches.contains(sid)) - { - LOG(WARNING) << "received request for search " << search_id << " from client " - << from << " but the search is already in progress"; - return; - } - - e::intrusive_ptr st = new state(ri, msg, checks); - std::stable_sort(st->checks.begin(), st->checks.end()); - datalayer::returncode rc = datalayer::SUCCESS; - datalayer::snapshot snap = m_daemon->m_data.make_snapshot(); - st->iter = m_daemon->m_data.make_search_iterator(snap, ri, st->checks, NULL); - - switch (rc) - { - case datalayer::SUCCESS: - break; - case datalayer::NOT_FOUND: - case datalayer::BAD_ENCODING: - case datalayer::CORRUPTION: - case datalayer::IO_ERROR: - case datalayer::LEVELDB_ERROR: - LOG(ERROR) << "could not make snapshot for search: " << rc; - return; - default: - abort(); - } - - m_searches.insert(sid, st); - next(from, to, nonce, search_id); + std::vector *checks) +{ + region_id ri(m_daemon->m_config.get_region_id(to)); + const schema *sc = m_daemon->m_config.get_schema(ri); + if (sc->authorization) + { + return; + } + id sid(ri, from, search_id); + if (m_searches.contains(sid)) + { + LOG(WARNING) << "received request for search " << search_id << " from client " + << from << " but the search is already in progress"; + return; + } + e::intrusive_ptr st = new state(ri, msg, checks); + std::stable_sort(st->checks.begin(), st->checks.end()); + datalayer::returncode rc = datalayer::SUCCESS; + datalayer::snapshot snap = m_daemon->m_data.make_snapshot(); + st->iter = m_daemon->m_data.make_search_iterator(snap, ri, st->checks, NULL); + switch (rc) + { + case datalayer::SUCCESS: + break; + case datalayer::NOT_FOUND: + case datalayer::BAD_ENCODING: + case datalayer::CORRUPTION: + case datalayer::IO_ERROR: + case datalayer::LEVELDB_ERROR: + LOG(ERROR) << "could not make snapshot for search: " << rc; + return; + default: + abort(); + } + m_searches.insert(sid, st); + next(from, to, nonce, search_id); } void -search_manager :: next(const server_id& from, - const virtual_server_id& to, +search_manager :: next(const server_id &from, + const virtual_server_id &to, uint64_t nonce, uint64_t search_id) { - region_id ri(m_daemon->m_config.get_region_id(to)); - const schema& sc(*m_daemon->m_config.get_schema(ri)); - id sid(ri, from, search_id); - e::intrusive_ptr st; - - if (!m_searches.lookup(sid, &st)) - { - std::auto_ptr msg(e::buffer::create(HYPERDEX_HEADER_SIZE_VC + sizeof(uint64_t))); - msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce; - m_daemon->m_comm.send_client(to, from, RESP_SEARCH_DONE, msg); - return; - } - - po6::threads::mutex::hold hold(&st->lock); - - if (st->iter->valid()) - { - e::slice key; - std::vector val; - uint64_t ver; - datalayer::reference tmp; - m_daemon->m_data.get_from_iterator(ri, sc, st->iter.get(), &key, &val, &ver, &tmp); - size_t sz = HYPERDEX_HEADER_SIZE_VC - + sizeof(uint64_t) - + pack_size(key) - + pack_size(val); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << key << val; - m_daemon->m_comm.send_client(to, from, RESP_SEARCH_ITEM, msg); - st->iter->next(); - } - else - { - std::auto_ptr msg(e::buffer::create(HYPERDEX_HEADER_SIZE_VC + sizeof(uint64_t))); - msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce; - m_daemon->m_comm.send_client(to, from, RESP_SEARCH_DONE, msg); - stop(from, to, search_id); - } + region_id ri(m_daemon->m_config.get_region_id(to)); + const schema &sc(*m_daemon->m_config.get_schema(ri)); + id sid(ri, from, search_id); + e::intrusive_ptr st; + if (!m_searches.lookup(sid, &st)) + { + std::auto_ptr msg(e::buffer::create(HYPERDEX_HEADER_SIZE_VC + sizeof(uint64_t))); + msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce; + m_daemon->m_comm.send_client(to, from, RESP_SEARCH_DONE, msg); + return; + } + po6::threads::mutex::hold hold(&st->lock); + if (st->iter->valid()) + { + e::slice key; + std::vector val; + uint64_t ver; + datalayer::reference tmp; + m_daemon->m_data.get_from_iterator(ri, sc, st->iter.get(), &key, &val, &ver, &tmp); + size_t sz = HYPERDEX_HEADER_SIZE_VC + + sizeof(uint64_t) + + pack_size(key) + + pack_size(val); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << key << val; + m_daemon->m_comm.send_client(to, from, RESP_SEARCH_ITEM, msg); + st->iter->next(); + } + else + { + std::auto_ptr msg(e::buffer::create(HYPERDEX_HEADER_SIZE_VC + sizeof(uint64_t))); + msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce; + m_daemon->m_comm.send_client(to, from, RESP_SEARCH_DONE, msg); + stop(from, to, search_id); + } } void -search_manager :: stop(const server_id& from, - const virtual_server_id& to, +search_manager :: stop(const server_id &from, + const virtual_server_id &to, uint64_t search_id) { - region_id ri(m_daemon->m_config.get_region_id(to)); - id sid(ri, from, search_id); - m_searches.remove(sid); + region_id ri(m_daemon->m_config.get_region_id(to)); + id sid(ri, from, search_id); + m_searches.remove(sid); } namespace hyperdex @@ -305,517 +294,474 @@ namespace hyperdex struct _sorted_search_params { - _sorted_search_params(const schema* _sc, - uint16_t _sort_by, - bool _maximize) - : sc(_sc), sort_by(_sort_by), maximize(_maximize) {} - ~_sorted_search_params() throw () {} - const schema* sc; - uint16_t sort_by; - bool maximize; - - private: - _sorted_search_params(const _sorted_search_params&); - _sorted_search_params& operator = (const _sorted_search_params&); + _sorted_search_params(const schema *_sc, + uint16_t _sort_by, + bool _maximize) + : sc(_sc), sort_by(_sort_by), maximize(_maximize) {} + ~_sorted_search_params() throw () {} + const schema *sc; + uint16_t sort_by; + bool maximize; + +private: + _sorted_search_params(const _sorted_search_params &); + _sorted_search_params &operator = (const _sorted_search_params &); }; struct _sorted_search_item { - _sorted_search_item(_sorted_search_params* p) - : params(p), key(), value(), version(), ref() {} - _sorted_search_item(_sorted_search_params* p, uint16_t val_sz) - : params(p), key_str(), version(), ref() + _sorted_search_item(_sorted_search_params *p) + : params(p), key(), value(), version(), ref() {} + _sorted_search_item(_sorted_search_params *p, uint16_t val_sz) + : params(p), key_str(), version(), ref() { value.reserve(val_sz); value_str.reserve(val_sz); } - _sorted_search_item(const _sorted_search_item& other); - ~_sorted_search_item() throw () {} - _sorted_search_item& operator = (const _sorted_search_item& other); - void assign(); - _sorted_search_params* params; - std::string key_str; - e::slice key; - std::vector value_str; - std::vector value; - uint64_t version; - datalayer::reference ref; + _sorted_search_item(const _sorted_search_item &other); + ~_sorted_search_item() throw () {} + _sorted_search_item &operator = (const _sorted_search_item &other); + void assign(); + _sorted_search_params *params; + std::string key_str; + e::slice key; + std::vector value_str; + std::vector value; + uint64_t version; + datalayer::reference ref; }; -_sorted_search_item :: _sorted_search_item(const _sorted_search_item& other) - : params(other.params) - , key_str(other.key_str) - , key(other.key) - , value_str(other.value_str) - , value(other.value) - , version(other.version) - , ref(other.ref) +_sorted_search_item :: _sorted_search_item(const _sorted_search_item &other) + : params(other.params) + , key_str(other.key_str) + , key(other.key) + , value_str(other.value_str) + , value(other.value) + , version(other.version) + , ref(other.ref) { } -_sorted_search_item& -_sorted_search_item :: _sorted_search_item :: operator = (const _sorted_search_item& other) -{ - params = other.params; - key_str = other.key_str; - key = other.key; - value_str = other.value_str; - value = other.value; - version = other.version; - ref = other.ref; - return *this; +_sorted_search_item & +_sorted_search_item :: _sorted_search_item :: operator = (const _sorted_search_item &other) +{ + params = other.params; + key_str = other.key_str; + key = other.key; + value_str = other.value_str; + value = other.value; + version = other.version; + ref = other.ref; + return *this; } void _sorted_search_item :: assign () { - key = e::slice(key_str); - value.clear(); - for (size_t i = 0; i < value_str.size(); i ++) - { - value.push_back(e::slice(value_str[i])); - } + key = e::slice(key_str); + value.clear(); + for (size_t i = 0; i < value_str.size(); i ++) + { + value.push_back(e::slice(value_str[i])); + } } bool -operator < (const _sorted_search_item& lhs, const _sorted_search_item& rhs) -{ - assert(lhs.params == rhs.params); - _sorted_search_params* params = lhs.params; - - if (params->sort_by >= params->sc->attrs_sz) - { - return false; - } - - int cmp = 0; - - if (params->sort_by == 0) - { - datatype_info* di = datatype_info::lookup(params->sc->attrs[0].type); - e::slice lhs_key(lhs.key_str); - e::slice rhs_key(rhs.key_str); - cmp = di->compare(lhs_key, rhs_key); - } - else - { - datatype_info* di = datatype_info::lookup(params->sc->attrs[params->sort_by].type); - e::slice lhs_value(lhs.value_str[params->sort_by - 1]); - e::slice rhs_value(rhs.value_str[params->sort_by - 1]); - cmp = di->compare(lhs_value, rhs_value); - } - - if (params->maximize) - { - return cmp < 0; - } - else - { - return cmp > 0; - } +operator < (const _sorted_search_item &lhs, const _sorted_search_item &rhs) +{ + assert(lhs.params == rhs.params); + _sorted_search_params *params = lhs.params; + if (params->sort_by >= params->sc->attrs_sz) + { + return false; + } + int cmp = 0; + if (params->sort_by == 0) + { + datatype_info *di = datatype_info::lookup(params->sc->attrs[0].type); + e::slice lhs_key(lhs.key_str); + e::slice rhs_key(rhs.key_str); + cmp = di->compare(lhs_key, rhs_key); + } + else + { + datatype_info *di = datatype_info::lookup(params->sc->attrs[params->sort_by].type); + e::slice lhs_value(lhs.value_str[params->sort_by - 1]); + e::slice rhs_value(rhs.value_str[params->sort_by - 1]); + cmp = di->compare(lhs_value, rhs_value); + } + if (params->maximize) + { + return cmp < 0; + } + else + { + return cmp > 0; + } } bool -operator > (const _sorted_search_item& lhs, const _sorted_search_item& rhs) -{ - assert(lhs.params == rhs.params); - _sorted_search_params* params = lhs.params; - - if (params->sort_by >= params->sc->attrs_sz) - { - return false; - } - - int cmp = 0; - - if (params->sort_by == 0) - { - datatype_info* di = datatype_info::lookup(params->sc->attrs[0].type); - e::slice lhs_key(lhs.key_str); - e::slice rhs_key(rhs.key_str); - cmp = di->compare(lhs_key, rhs_key); - } - else - { - datatype_info* di = datatype_info::lookup(params->sc->attrs[params->sort_by].type); - e::slice lhs_value(lhs.value_str[params->sort_by - 1]); - e::slice rhs_value(rhs.value_str[params->sort_by - 1]); - cmp = di->compare(lhs_value, rhs_value); - } - - if (params->maximize) - { - return cmp > 0; - } - else - { - return cmp < 0; - } +operator > (const _sorted_search_item &lhs, const _sorted_search_item &rhs) +{ + assert(lhs.params == rhs.params); + _sorted_search_params *params = lhs.params; + if (params->sort_by >= params->sc->attrs_sz) + { + return false; + } + int cmp = 0; + if (params->sort_by == 0) + { + datatype_info *di = datatype_info::lookup(params->sc->attrs[0].type); + e::slice lhs_key(lhs.key_str); + e::slice rhs_key(rhs.key_str); + cmp = di->compare(lhs_key, rhs_key); + } + else + { + datatype_info *di = datatype_info::lookup(params->sc->attrs[params->sort_by].type); + e::slice lhs_value(lhs.value_str[params->sort_by - 1]); + e::slice rhs_value(rhs.value_str[params->sort_by - 1]); + cmp = di->compare(lhs_value, rhs_value); + } + if (params->maximize) + { + return cmp > 0; + } + else + { + return cmp < 0; + } } } // namespace hyperdex void -search_manager :: sorted_search(const server_id& from, - const virtual_server_id& to, +search_manager :: sorted_search(const server_id &from, + const virtual_server_id &to, uint64_t nonce, - std::vector* checks, + std::vector *checks, uint64_t limit, uint16_t sort_by, bool maximize) { - region_id ri(m_daemon->m_config.get_region_id(to)); - const schema* sc = m_daemon->m_config.get_schema(ri); - - if (sc->authorization) - { - return; - } - - std::stable_sort(checks->begin(), checks->end()); - datalayer::returncode rc = datalayer::SUCCESS; - datalayer::snapshot snap = m_daemon->m_data.make_snapshot(); - e::intrusive_ptr iter; - iter = m_daemon->m_data.make_search_iterator(snap, ri, *checks, NULL); - - switch (rc) - { - case datalayer::SUCCESS: - break; - case datalayer::NOT_FOUND: - case datalayer::BAD_ENCODING: - case datalayer::CORRUPTION: - case datalayer::IO_ERROR: - case datalayer::LEVELDB_ERROR: - LOG(ERROR) << "could not make snapshot for search: " << rc; - break; - default: - abort(); - } - - _sorted_search_params params(sc, sort_by, maximize); - std::vector<_sorted_search_item> top_n; - top_n.reserve(limit + 1); - - while (iter->valid()) - { - e::slice key; - std::vector val; - uint64_t ver; - datalayer::reference tmp; - m_daemon->m_data.get_from_iterator(ri, *sc, iter.get(), &key, &val, &ver, &tmp); - _sorted_search_item ssi(¶ms, sc->attrs_sz); - ssi.key_str = key.str(); - for (size_t i = 0; i < val.size(); i ++) - { - ssi.value_str.push_back(val[i].str()); - } - top_n.push_back(ssi); - std::push_heap(top_n.begin(), top_n.end()); - - if (top_n.size() > limit) - { - std::pop_heap(top_n.begin(), top_n.end()); - top_n.pop_back(); - } - - iter->next(); - } - - std::sort(top_n.begin(), top_n.end(), std::greater<_sorted_search_item>()); - size_t sz = HYPERDEX_HEADER_SIZE_VC + sizeof(uint64_t) + sizeof(uint64_t); - - for (size_t i = 0; i < top_n.size(); ++i) - { - top_n[i].assign(); - sz += pack_size(top_n[i].key) + pack_size(top_n[i].value); - } - - std::auto_ptr msg(e::buffer::create(sz)); - e::packer pa = msg->pack_at(HYPERDEX_HEADER_SIZE_VC); - pa = pa << nonce << static_cast(top_n.size()); - - for (size_t i = 0; i < top_n.size(); ++i) - { - pa = pa << top_n[i].key << top_n[i].value; - } - - m_daemon->m_comm.send_client(to, from, RESP_SORTED_SEARCH, msg); + region_id ri(m_daemon->m_config.get_region_id(to)); + const schema *sc = m_daemon->m_config.get_schema(ri); + if (sc->authorization) + { + return; + } + std::stable_sort(checks->begin(), checks->end()); + datalayer::returncode rc = datalayer::SUCCESS; + datalayer::snapshot snap = m_daemon->m_data.make_snapshot(); + e::intrusive_ptr iter; + iter = m_daemon->m_data.make_search_iterator(snap, ri, *checks, NULL); + switch (rc) + { + case datalayer::SUCCESS: + break; + case datalayer::NOT_FOUND: + case datalayer::BAD_ENCODING: + case datalayer::CORRUPTION: + case datalayer::IO_ERROR: + case datalayer::LEVELDB_ERROR: + LOG(ERROR) << "could not make snapshot for search: " << rc; + break; + default: + abort(); + } + _sorted_search_params params(sc, sort_by, maximize); + std::vector<_sorted_search_item> top_n; + top_n.reserve(limit + 1); + while (iter->valid()) + { + e::slice key; + std::vector val; + uint64_t ver; + datalayer::reference tmp; + m_daemon->m_data.get_from_iterator(ri, *sc, iter.get(), &key, &val, &ver, &tmp); + _sorted_search_item ssi(¶ms, sc->attrs_sz); + ssi.key_str = key.str(); + for (size_t i = 0; i < val.size(); i ++) + { + ssi.value_str.push_back(val[i].str()); + } + top_n.push_back(ssi); + std::push_heap(top_n.begin(), top_n.end()); + if (top_n.size() > limit) + { + std::pop_heap(top_n.begin(), top_n.end()); + top_n.pop_back(); + } + iter->next(); + } + std::sort(top_n.begin(), top_n.end(), std::greater<_sorted_search_item>()); + size_t sz = HYPERDEX_HEADER_SIZE_VC + sizeof(uint64_t) + sizeof(uint64_t); + for (size_t i = 0; i < top_n.size(); ++i) + { + top_n[i].assign(); + sz += pack_size(top_n[i].key) + pack_size(top_n[i].value); + } + std::auto_ptr msg(e::buffer::create(sz)); + e::packer pa = msg->pack_at(HYPERDEX_HEADER_SIZE_VC); + pa = pa << nonce << static_cast(top_n.size()); + for (size_t i = 0; i < top_n.size(); ++i) + { + pa = pa << top_n[i].key << top_n[i].value; + } + m_daemon->m_comm.send_client(to, from, RESP_SORTED_SEARCH, msg); } void -search_manager :: group_keyop(const server_id& from, - const virtual_server_id& to, +search_manager :: group_keyop(const server_id &from, + const virtual_server_id &to, uint64_t nonce, - std::vector* checks, + std::vector *checks, network_msgtype mt, - const e::slice& remain, + const e::slice &remain, network_msgtype resp) { - region_id ri(m_daemon->m_config.get_region_id(to)); - const schema* sc = m_daemon->m_config.get_schema(ri); - - if (sc->authorization) - { - return; - } - - std::stable_sort(checks->begin(), checks->end()); - datalayer::returncode rc = datalayer::SUCCESS; - datalayer::snapshot snap = m_daemon->m_data.make_snapshot(); - e::intrusive_ptr iter; - iter = m_daemon->m_data.make_search_iterator(snap, ri, *checks, NULL); - uint64_t result = 0; - - switch (rc) - { - case datalayer::SUCCESS: - break; - case datalayer::NOT_FOUND: - case datalayer::BAD_ENCODING: - case datalayer::CORRUPTION: - case datalayer::IO_ERROR: - case datalayer::LEVELDB_ERROR: - LOG(ERROR) << "could not make snapshot for search: " << rc; - result = UINT64_MAX; - break; - default: - abort(); - } - - while (iter->valid() && result < UINT64_MAX) - { - e::slice key; - std::vector val; - uint64_t ver; - datalayer::reference tmp; - m_daemon->m_data.get_from_iterator(ri, *sc, iter.get(), &key, &val, &ver, &tmp); - size_t sz = HYPERDEX_HEADER_SIZE_SV // SV because we imitate a client - + sizeof(uint64_t) - + pack_size(key) - + remain.size(); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_SV) - << uint64_t(0) << key << e::pack_memmove(remain.data(), remain.size()); - virtual_server_id vsi = m_daemon->m_config.point_leader(ri, key); - - if (vsi != virtual_server_id()) - { - m_daemon->m_comm.send(vsi, mt, msg); - result++; - } - - iter->next(); - } - - size_t sz = HYPERDEX_HEADER_SIZE_VC - + sizeof(uint64_t) - + sizeof(uint64_t); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << result; - m_daemon->m_comm.send_client(to, from, resp, msg); + region_id ri(m_daemon->m_config.get_region_id(to)); + const schema *sc = m_daemon->m_config.get_schema(ri); + if (sc->authorization) + { + return; + } + std::stable_sort(checks->begin(), checks->end()); + datalayer::returncode rc = datalayer::SUCCESS; + datalayer::snapshot snap = m_daemon->m_data.make_snapshot(); + e::intrusive_ptr iter; + iter = m_daemon->m_data.make_search_iterator(snap, ri, *checks, NULL); + uint64_t result = 0; + switch (rc) + { + case datalayer::SUCCESS: + break; + case datalayer::NOT_FOUND: + case datalayer::BAD_ENCODING: + case datalayer::CORRUPTION: + case datalayer::IO_ERROR: + case datalayer::LEVELDB_ERROR: + LOG(ERROR) << "could not make snapshot for search: " << rc; + result = UINT64_MAX; + break; + default: + abort(); + } + while (iter->valid() && result < UINT64_MAX) + { + e::slice key; + std::vector val; + uint64_t ver; + datalayer::reference tmp; + m_daemon->m_data.get_from_iterator(ri, *sc, iter.get(), &key, &val, &ver, &tmp); + size_t sz = HYPERDEX_HEADER_SIZE_SV // SV because we imitate a client + + sizeof(uint64_t) + + pack_size(key) + + remain.size(); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_SV) + << uint64_t(0) << key << e::pack_memmove(remain.data(), remain.size()); + virtual_server_id vsi = m_daemon->m_config.point_leader(ri, key); + if (vsi != virtual_server_id()) + { + m_daemon->m_comm.send(vsi, mt, msg); + result++; + } + iter->next(); + } + size_t sz = HYPERDEX_HEADER_SIZE_VC + + sizeof(uint64_t) + + sizeof(uint64_t); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << result; + m_daemon->m_comm.send_client(to, from, resp, msg); } void -search_manager :: count(const server_id& from, - const virtual_server_id& to, +search_manager :: count(const server_id &from, + const virtual_server_id &to, uint64_t nonce, - std::vector* checks) -{ - region_id ri(m_daemon->m_config.get_region_id(to)); - const schema* sc = m_daemon->m_config.get_schema(ri); - - if (sc->authorization) - { - return; - } - - std::stable_sort(checks->begin(), checks->end()); - datalayer::returncode rc = datalayer::SUCCESS; - datalayer::snapshot snap = m_daemon->m_data.make_snapshot(); - e::intrusive_ptr iter; - iter = m_daemon->m_data.make_search_iterator(snap, ri, *checks, NULL); - uint64_t result = 0; - - switch (rc) - { - case datalayer::SUCCESS: - break; - case datalayer::NOT_FOUND: - case datalayer::BAD_ENCODING: - case datalayer::CORRUPTION: - case datalayer::IO_ERROR: - case datalayer::LEVELDB_ERROR: - LOG(ERROR) << "could not make snapshot for search: " << rc; - result = UINT64_MAX; - break; - default: - abort(); - } - - while (iter->valid() && result < UINT64_MAX) - { - ++result; - iter->next(); - } - - size_t sz = HYPERDEX_HEADER_SIZE_VC - + sizeof(uint64_t) - + sizeof(uint64_t); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << result; - m_daemon->m_comm.send_client(to, from, RESP_COUNT, msg); + std::vector *checks) +{ + region_id ri(m_daemon->m_config.get_region_id(to)); + const schema *sc = m_daemon->m_config.get_schema(ri); + if (sc->authorization) + { + return; + } + std::stable_sort(checks->begin(), checks->end()); + datalayer::returncode rc = datalayer::SUCCESS; + datalayer::snapshot snap = m_daemon->m_data.make_snapshot(); + e::intrusive_ptr iter; + iter = m_daemon->m_data.make_search_iterator(snap, ri, *checks, NULL); + uint64_t result = 0; + switch (rc) + { + case datalayer::SUCCESS: + break; + case datalayer::NOT_FOUND: + case datalayer::BAD_ENCODING: + case datalayer::CORRUPTION: + case datalayer::IO_ERROR: + case datalayer::LEVELDB_ERROR: + LOG(ERROR) << "could not make snapshot for search: " << rc; + result = UINT64_MAX; + break; + default: + abort(); + } + while (iter->valid() && result < UINT64_MAX) + { + ++result; + iter->next(); + } + size_t sz = HYPERDEX_HEADER_SIZE_VC + + sizeof(uint64_t) + + sizeof(uint64_t); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << result; + m_daemon->m_comm.send_client(to, from, RESP_COUNT, msg); } void -search_manager :: sum(const server_id& from, - const virtual_server_id& to, - uint64_t nonce, - std::vector* checks, - uint16_t sum_idx) -{ - region_id ri(m_daemon->m_config.get_region_id(to)); - const schema* sc = m_daemon->m_config.get_schema(ri); - - if (sc->authorization) - { - return; - } - - std::stable_sort(checks->begin(), checks->end()); - datalayer::returncode rc = datalayer::SUCCESS; - datalayer::snapshot snap = m_daemon->m_data.make_snapshot(); - e::intrusive_ptr iter; - iter = m_daemon->m_data.make_search_iterator(snap, ri, *checks, NULL); - uint64_t result = 0; - - switch (rc) - { - case datalayer::SUCCESS: - break; - case datalayer::NOT_FOUND: - case datalayer::BAD_ENCODING: - case datalayer::CORRUPTION: - case datalayer::IO_ERROR: - case datalayer::LEVELDB_ERROR: - LOG(ERROR) << "could not make snapshot for search: " << rc; - result = UINT64_MAX; - break; - default: - abort(); - } - - while (iter->valid() && result < UINT64_MAX) - { - e::slice key; - std::vector val; - uint64_t ver; - datalayer::reference tmp; - m_daemon->m_data.get_from_iterator(ri, *sc, iter.get(), &key, &val, &ver, &tmp); +search_manager :: sum(const server_id &from, + const virtual_server_id &to, + uint64_t nonce, + std::vector *checks, + uint16_t sum_idx) +{ + region_id ri(m_daemon->m_config.get_region_id(to)); + const schema *sc = m_daemon->m_config.get_schema(ri); + if (sc->authorization) + { + return; + } + std::stable_sort(checks->begin(), checks->end()); + datalayer::returncode rc = datalayer::SUCCESS; + datalayer::snapshot snap = m_daemon->m_data.make_snapshot(); + e::intrusive_ptr iter; + iter = m_daemon->m_data.make_search_iterator(snap, ri, *checks, NULL); + uint64_t result = 0; + switch (rc) + { + case datalayer::SUCCESS: + break; + case datalayer::NOT_FOUND: + case datalayer::BAD_ENCODING: + case datalayer::CORRUPTION: + case datalayer::IO_ERROR: + case datalayer::LEVELDB_ERROR: + LOG(ERROR) << "could not make snapshot for search: " << rc; + result = UINT64_MAX; + break; + default: + abort(); + } + while (iter->valid() && result < UINT64_MAX) + { + e::slice key; + std::vector val; + uint64_t ver; + datalayer::reference tmp; + m_daemon->m_data.get_from_iterator(ri, *sc, iter.get(), &key, &val, &ver, &tmp); if (val.size() < sum_idx) { LOG(ERROR) << "occur some error for sum: " << val.size(); } switch (sc->attrs[sum_idx].type) { - case HYPERDATATYPE_INT64: - { - uint64_t num = 0; - e::unpack64le(val[sum_idx-1].cdata(), &num); - result += num; - } - break; - case HYPERDATATYPE_FLOAT: - { - double num = 0; - e::unpackdoublele(val[sum_idx-1].cdata(), &num); - result += (uint64_t)num; - } - break; - case HYPERDATATYPE_STRING: - default: - LOG(ERROR) << "could not sum item because of not int and double(" << sc->attrs[sum_idx].type << ")"; + case HYPERDATATYPE_INT64: + { + uint64_t num = 0; + e::unpack64le(val[sum_idx - 1].cdata(), &num); + result += num; + } + break; + case HYPERDATATYPE_FLOAT: + { + double num = 0; + e::unpackdoublele(val[sum_idx - 1].cdata(), &num); + result += (uint64_t)num; + } + break; + case HYPERDATATYPE_STRING: + default: + LOG(ERROR) << "could not sum item because of not int and double(" << sc->attrs[sum_idx].type << ")"; } - iter->next(); - } + iter->next(); + } //LOG(INFO) << "result(" << result << ")"; - - size_t sz = HYPERDEX_HEADER_SIZE_VC - + sizeof(uint64_t) - + sizeof(uint64_t); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << result; - m_daemon->m_comm.send_client(to, from, RESP_SUM, msg); + size_t sz = HYPERDEX_HEADER_SIZE_VC + + sizeof(uint64_t) + + sizeof(uint64_t); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << result; + m_daemon->m_comm.send_client(to, from, RESP_SUM, msg); } void -search_manager :: search_describe(const server_id& from, - const virtual_server_id& to, +search_manager :: search_describe(const server_id &from, + const virtual_server_id &to, uint64_t nonce, - std::vector* checks) -{ - region_id ri(m_daemon->m_config.get_region_id(to)); - const schema* sc = m_daemon->m_config.get_schema(ri); - - if (sc->authorization) - { - return; - } - - std::stable_sort(checks->begin(), checks->end()); - datalayer::returncode rc = datalayer::SUCCESS; - std::ostringstream ostr; - ostr << "search\n"; - uint64_t t_start = po6::monotonic_time(); - datalayer::snapshot snap = m_daemon->m_data.make_snapshot(); - uint64_t t_end = po6::monotonic_time(); - ostr << " snapshot took " << t_end - t_start << "ns\n"; - e::intrusive_ptr iter; - t_start = po6::monotonic_time(); - iter = m_daemon->m_data.make_search_iterator(snap, ri, *checks, &ostr); - t_end = po6::monotonic_time(); - ostr << " iterator took " << t_end - t_start << "ns\n"; - - switch (rc) - { - case datalayer::SUCCESS: - break; - case datalayer::NOT_FOUND: - case datalayer::BAD_ENCODING: - case datalayer::CORRUPTION: - case datalayer::IO_ERROR: - case datalayer::LEVELDB_ERROR: - LOG(ERROR) << "could not make snapshot for search: " << rc; - break; - default: - abort(); - } - - uint64_t num = 0; - t_start = po6::monotonic_time(); - - while (iter->valid()) - { - ++num; - iter->next(); - } - - t_end = po6::monotonic_time(); - ostr << " retrieved " << num << " objects in " << t_end - t_start << "ns\n"; - std::string str(ostr.str()); - const char* text = str.c_str(); - size_t text_sz = strlen(text); - size_t sz = HYPERDEX_HEADER_SIZE_VC - + sizeof(uint64_t) - + text_sz; - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VC) - << nonce << e::pack_memmove(text, text_sz); - m_daemon->m_comm.send_client(to, from, RESP_SEARCH_DESCRIBE, msg); + std::vector *checks) +{ + region_id ri(m_daemon->m_config.get_region_id(to)); + const schema *sc = m_daemon->m_config.get_schema(ri); + if (sc->authorization) + { + return; + } + std::stable_sort(checks->begin(), checks->end()); + datalayer::returncode rc = datalayer::SUCCESS; + std::ostringstream ostr; + ostr << "search\n"; + uint64_t t_start = po6::monotonic_time(); + datalayer::snapshot snap = m_daemon->m_data.make_snapshot(); + uint64_t t_end = po6::monotonic_time(); + ostr << " snapshot took " << t_end - t_start << "ns\n"; + e::intrusive_ptr iter; + t_start = po6::monotonic_time(); + iter = m_daemon->m_data.make_search_iterator(snap, ri, *checks, &ostr); + t_end = po6::monotonic_time(); + ostr << " iterator took " << t_end - t_start << "ns\n"; + switch (rc) + { + case datalayer::SUCCESS: + break; + case datalayer::NOT_FOUND: + case datalayer::BAD_ENCODING: + case datalayer::CORRUPTION: + case datalayer::IO_ERROR: + case datalayer::LEVELDB_ERROR: + LOG(ERROR) << "could not make snapshot for search: " << rc; + break; + default: + abort(); + } + uint64_t num = 0; + t_start = po6::monotonic_time(); + while (iter->valid()) + { + ++num; + iter->next(); + } + t_end = po6::monotonic_time(); + ostr << " retrieved " << num << " objects in " << t_end - t_start << "ns\n"; + std::string str(ostr.str()); + const char *text = str.c_str(); + size_t text_sz = strlen(text); + size_t sz = HYPERDEX_HEADER_SIZE_VC + + sizeof(uint64_t) + + text_sz; + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VC) + << nonce << e::pack_memmove(text, text_sz); + m_daemon->m_comm.send_client(to, from, RESP_SEARCH_DESCRIBE, msg); } uint64_t -search_manager :: hash(const id& sid) +search_manager :: hash(const id &sid) { - return sid.region.get() + sid.client.get() + sid.search_id; + return sid.region.get() + sid.client.get() + sid.search_id; } diff --git a/daemon/search_manager.h b/daemon/search_manager.h index 501b9b425..1eefa4074 100644 --- a/daemon/search_manager.h +++ b/daemon/search_manager.h @@ -44,82 +44,82 @@ class daemon; class search_manager { - public: - search_manager(daemon*); - ~search_manager() throw (); - - public: - bool setup(); - void teardown(); - void pause(); - void unpause(); - void reconfigure(const configuration& old_config, - const configuration& new_config, - const server_id& us); - - public: - void start(const server_id& from, - const virtual_server_id& to, - std::auto_ptr msg, - uint64_t nonce, - uint64_t search_id, - std::vector* checks); - void next(const server_id& from, - const virtual_server_id& to, - uint64_t nonce, - uint64_t search_id); - void stop(const server_id& from, - const virtual_server_id& to, - uint64_t search_id); - void sorted_search(const server_id& from, - const virtual_server_id& to, - uint64_t nonce, - std::vector* checks, - uint64_t limit, - uint16_t sort_by, - bool maximize); - - // Find keys that match the check and forward ops to the corresponding servers - // Essentially this splits out the group operation in several seperate operations - // (by acting like it was a client) - void group_keyop(const server_id& from, - const virtual_server_id& to, - uint64_t nonce, - std::vector* checks, - network_msgtype mt, - const e::slice& remain, - network_msgtype resp); - - // Calculate the amount of entries that match the checks - void count(const server_id& from, - const virtual_server_id& to, - uint64_t nonce, - std::vector* checks); - void sum(const server_id& from, - const virtual_server_id& to, - uint64_t nonce, - std::vector* checks, - uint16_t sum_idx); - - void search_describe(const server_id& from, - const virtual_server_id& to, - uint64_t nonce, - std::vector* checks); - - private: - class id; - class state; - - private: - search_manager(const search_manager&); - search_manager& operator = (const search_manager&); - - private: - static uint64_t hash(const id&); - - private: - daemon* m_daemon; - e::lockfree_hash_map, hash> m_searches; +public: + search_manager(daemon *); + ~search_manager() throw (); + +public: + bool setup(); + void teardown(); + void pause(); + void unpause(); + void reconfigure(const configuration &old_config, + const configuration &new_config, + const server_id &us); + +public: + void start(const server_id &from, + const virtual_server_id &to, + std::auto_ptr msg, + uint64_t nonce, + uint64_t search_id, + std::vector *checks); + void next(const server_id &from, + const virtual_server_id &to, + uint64_t nonce, + uint64_t search_id); + void stop(const server_id &from, + const virtual_server_id &to, + uint64_t search_id); + void sorted_search(const server_id &from, + const virtual_server_id &to, + uint64_t nonce, + std::vector *checks, + uint64_t limit, + uint16_t sort_by, + bool maximize); + + // Find keys that match the check and forward ops to the corresponding servers + // Essentially this splits out the group operation in several seperate operations + // (by acting like it was a client) + void group_keyop(const server_id &from, + const virtual_server_id &to, + uint64_t nonce, + std::vector *checks, + network_msgtype mt, + const e::slice &remain, + network_msgtype resp); + + // Calculate the amount of entries that match the checks + void count(const server_id &from, + const virtual_server_id &to, + uint64_t nonce, + std::vector *checks); + void sum(const server_id &from, + const virtual_server_id &to, + uint64_t nonce, + std::vector *checks, + uint16_t sum_idx); + + void search_describe(const server_id &from, + const virtual_server_id &to, + uint64_t nonce, + std::vector *checks); + +private: + class id; + class state; + +private: + search_manager(const search_manager &); + search_manager &operator = (const search_manager &); + +private: + static uint64_t hash(const id &); + +private: + daemon *m_daemon; + e::lockfree_hash_map, hash> m_searches; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/state_hash_table.h b/daemon/state_hash_table.h index fc0055a8f..0065d933b 100644 --- a/daemon/state_hash_table.h +++ b/daemon/state_hash_table.h @@ -53,378 +53,354 @@ BEGIN_HYPERDEX_NAMESPACE template uint64_t -default_state_hash(const T& t) +default_state_hash(const T &t) { - e::compat::hash h; - return h(t); + e::compat::hash h; + return h(t); } -template +template class state_hash_table { - public: - class state_reference; - class iterator; - - public: - state_hash_table(e::garbage_collector* gc); - ~state_hash_table() throw (); - - public: - T* create_state(const K& key, state_reference* sr); - T* get_state(const K& key, state_reference* sr); - T* get_or_create_state(const K& key, state_reference* sr); - - private: - class state; - typedef typename e::nwf_hash_map, H> state_map_t; - state_map_t m_table; +public: + class state_reference; + class iterator; + +public: + state_hash_table(e::garbage_collector *gc); + ~state_hash_table() throw (); + +public: + T *create_state(const K &key, state_reference *sr); + T *get_state(const K &key, state_reference *sr); + T *get_or_create_state(const K &key, state_reference *sr); + +private: + class state; + typedef typename e::nwf_hash_map, H> state_map_t; + state_map_t m_table; }; -template +template class state_hash_table::state_reference { - public: - state_reference(); - ~state_reference() throw (); - - public: - void release(); - T* get(); - - private: - friend class state_hash_table; - void acquire(state_hash_table* sht, e::intrusive_ptr s); - void unlock(); // still acquired, but state unlocked - - private: - state_hash_table* m_sht; - e::intrusive_ptr m_state; - bool m_locked; - - private: - state_reference(state_reference&); - state_reference& operator = (state_reference&); +public: + state_reference(); + ~state_reference() throw (); + +public: + void release(); + T *get(); + +private: + friend class state_hash_table; + void acquire(state_hash_table *sht, e::intrusive_ptr s); + void unlock(); // still acquired, but state unlocked + +private: + state_hash_table *m_sht; + e::intrusive_ptr m_state; + bool m_locked; + +private: + state_reference(state_reference &); + state_reference &operator = (state_reference &); }; -template +template class state_hash_table::iterator { - public: - iterator(state_hash_table* sht); - ~iterator() throw (); - - public: - bool valid(); - T* operator * (); - T* operator -> (); - iterator& operator ++ (); - - private: - void prime(); - - private: - state_hash_table* m_sht; - typename state_map_t::iterator m_iter; - state_reference m_sr; - bool m_primed; - - private: - iterator(iterator&); - iterator& operator = (iterator&); +public: + iterator(state_hash_table *sht); + ~iterator() throw (); + +public: + bool valid(); + T *operator * (); + T *operator -> (); + iterator &operator ++ (); + +private: + void prime(); + +private: + state_hash_table *m_sht; + typename state_map_t::iterator m_iter; + state_reference m_sr; + bool m_primed; + +private: + iterator(iterator &); + iterator &operator = (iterator &); }; -template +template class state_hash_table::state { - public: - state(const K& k); - ~state() throw (); - - public: - T t; - po6::threads::mutex mtx; - uint64_t acquires; - bool garbage; - - public: - size_t ref; - void inc() { __sync_add_and_fetch(&ref, 1); } - void dec() { if (__sync_sub_and_fetch(&ref, 1) == 0) delete this; } +public: + state(const K &k); + ~state() throw (); + +public: + T t; + po6::threads::mutex mtx; + uint64_t acquires; + bool garbage; + +public: + size_t ref; + void inc() { __sync_add_and_fetch(&ref, 1); } + void dec() { if (__sync_sub_and_fetch(&ref, 1) == 0) delete this; } }; -template -state_hash_table :: state_hash_table(e::garbage_collector* gc) - : m_table(gc) +template +state_hash_table :: state_hash_table(e::garbage_collector *gc) + : m_table(gc) { } -template +template state_hash_table :: ~state_hash_table() throw () { } -template -T* -state_hash_table :: create_state(const K& key, state_reference* sr) +template +T * +state_hash_table :: create_state(const K &key, state_reference *sr) { - sr->release(); - - e::intrusive_ptr s = new state(key); - sr->acquire(this, s); - - if (m_table.put_ine(key, s)) - { - sr->unlock(); - return sr->get(); - } - - sr->release(); - return NULL; + sr->release(); + e::intrusive_ptr s = new state(key); + sr->acquire(this, s); + if (m_table.put_ine(key, s)) + { + sr->unlock(); + return sr->get(); + } + sr->release(); + return NULL; } -template -T* -state_hash_table :: get_state(const K& key, state_reference* sr) +template +T * +state_hash_table :: get_state(const K &key, state_reference *sr) { - sr->release(); - - while (true) - { - e::intrusive_ptr s; - - if (!m_table.get(key, &s)) - { - return NULL; - } - - sr->acquire(this, s); - - if (s->garbage) - { - sr->release(); - continue; - } - - sr->unlock(); - return sr->get(); - } + sr->release(); + while (true) + { + e::intrusive_ptr s; + if (!m_table.get(key, &s)) + { + return NULL; + } + sr->acquire(this, s); + if (s->garbage) + { + sr->release(); + continue; + } + sr->unlock(); + return sr->get(); + } } -template -T* -state_hash_table :: get_or_create_state(const K& key, state_reference* sr) +template +T * +state_hash_table :: get_or_create_state(const K &key, state_reference *sr) { - sr->release(); - - while (true) - { - e::intrusive_ptr s; - - if (m_table.get(key, &s)) - { - sr->acquire(this, s); - } - else - { - assert(!s); - s = new state(key); - sr->acquire(this, s); - - if (!m_table.put_ine(key, s)) - { - sr->release(); - continue; - } - } - - assert(s); - - if (s->garbage) - { - sr->release(); - continue; - } - - sr->unlock(); - return sr->get(); - } + sr->release(); + while (true) + { + e::intrusive_ptr s; + if (m_table.get(key, &s)) + { + sr->acquire(this, s); + } + else + { + assert(!s); + s = new state(key); + sr->acquire(this, s); + if (!m_table.put_ine(key, s)) + { + sr->release(); + continue; + } + } + assert(s); + if (s->garbage) + { + sr->release(); + continue; + } + sr->unlock(); + return sr->get(); + } } -template +template state_hash_table :: state_reference :: state_reference() - : m_sht(NULL) - , m_state() - , m_locked(false) + : m_sht(NULL) + , m_state() + , m_locked(false) { } -template +template state_hash_table :: state_reference :: ~state_reference() throw () { - release(); + release(); } -template +template void state_hash_table :: state_reference :: release() { - if (!m_sht || !m_state) - { - assert(!m_sht); - assert(!m_state); - assert(!m_locked); - return; - } - - assert(m_sht); - assert(m_state); - - if (!m_locked) - { - m_state->mtx.lock(); - m_locked = true; - } - - assert(m_state->acquires > 0); - --m_state->acquires; - - if (m_state->acquires == 0 && - !m_state->garbage && - m_state->t.finished()) - { - m_state->garbage = true; - m_sht->m_table.del_if(m_state->t.state_key(), m_state); - } - - m_state->mtx.unlock(); - m_sht = NULL; - m_state = NULL; - m_locked = false; + if (!m_sht || !m_state) + { + assert(!m_sht); + assert(!m_state); + assert(!m_locked); + return; + } + assert(m_sht); + assert(m_state); + if (!m_locked) + { + m_state->mtx.lock(); + m_locked = true; + } + assert(m_state->acquires > 0); + --m_state->acquires; + if (m_state->acquires == 0 && + !m_state->garbage && + m_state->t.finished()) + { + m_state->garbage = true; + m_sht->m_table.del_if(m_state->t.state_key(), m_state); + } + m_state->mtx.unlock(); + m_sht = NULL; + m_state = NULL; + m_locked = false; } -template -T* +template +T * state_hash_table :: state_reference :: get() { - return &m_state->t; + return &m_state->t; } -template +template void -state_hash_table :: state_reference :: acquire(state_hash_table* sht, e::intrusive_ptr s) +state_hash_table :: state_reference :: acquire(state_hash_table *sht, e::intrusive_ptr s) { - if (m_sht || m_state || m_locked) - { - release(); - } - - m_sht = sht; - m_state = s; - m_state->mtx.lock(); - m_locked = true; - ++m_state->acquires; + if (m_sht || m_state || m_locked) + { + release(); + } + m_sht = sht; + m_state = s; + m_state->mtx.lock(); + m_locked = true; + ++m_state->acquires; } -template +template void state_hash_table :: state_reference :: unlock() { - if (m_locked) - { - m_locked = false; - m_state->mtx.unlock(); - } + if (m_locked) + { + m_locked = false; + m_state->mtx.unlock(); + } } -template -state_hash_table :: iterator :: iterator(state_hash_table* sht) - : m_sht(sht) - , m_iter(m_sht->m_table.begin()) - , m_sr() - , m_primed(false) +template +state_hash_table :: iterator :: iterator(state_hash_table *sht) + : m_sht(sht) + , m_iter(m_sht->m_table.begin()) + , m_sr() + , m_primed(false) { - prime(); + prime(); } -template +template state_hash_table :: iterator :: ~iterator() throw () { } -template +template bool state_hash_table :: iterator :: valid() { - prime(); - return m_iter != m_sht->m_table.end(); + prime(); + return m_iter != m_sht->m_table.end(); } -template -T* +template +T * state_hash_table :: iterator :: operator * () { - assert(valid()); - return m_sr.get(); + assert(valid()); + return m_sr.get(); } -template -T* +template +T * state_hash_table :: iterator :: operator -> () { - assert(valid()); - return m_sr.get(); + assert(valid()); + return m_sr.get(); } -template -typename state_hash_table::iterator& +template +typename state_hash_table::iterator & state_hash_table :: iterator :: operator ++ () { - m_primed = false; - ++m_iter; - prime(); - return *this; + m_primed = false; + ++m_iter; + prime(); + return *this; } -template +template void state_hash_table :: iterator :: prime() { - if (m_primed) - { - return; - } - - while (true) - { - m_sr.release(); - - if (m_iter == m_sht->m_table.end() || - m_sht->get_state(m_iter->first, &m_sr)) - { - break; - } - - ++m_iter; - } - - m_primed = true; + if (m_primed) + { + return; + } + while (true) + { + m_sr.release(); + if (m_iter == m_sht->m_table.end() || + m_sht->get_state(m_iter->first, &m_sr)) + { + break; + } + ++m_iter; + } + m_primed = true; } -template -state_hash_table :: state :: state(const K& k) - : t(k) - , mtx() - , acquires(0) - , garbage(false) - , ref(0) +template +state_hash_table :: state :: state(const K &k) + : t(k) + , mtx() + , acquires(0) + , garbage(false) + , ref(0) { } -template +template state_hash_table :: state :: ~state() throw () { - assert(acquires == 0); + assert(acquires == 0); } END_HYPERDEX_NAMESPACE diff --git a/daemon/state_transfer_manager.cc b/daemon/state_transfer_manager.cc index 3be2dfdb7..7b1930285 100644 --- a/daemon/state_transfer_manager.cc +++ b/daemon/state_transfer_manager.cc @@ -52,658 +52,594 @@ using hyperdex::transfer_id; class state_transfer_manager::background_thread : public ::hyperdex::background_thread { - public: - background_thread(state_transfer_manager* stm); - ~background_thread() throw (); - - public: - virtual const char* thread_name(); - virtual bool have_work(); - virtual void copy_work(); - virtual void do_work(); - - public: - void kick(); - - private: - background_thread(const background_thread&); - background_thread& operator = (const background_thread&); - - private: - state_transfer_manager* m_stm; - bool m_need_kickstart; +public: + background_thread(state_transfer_manager *stm); + ~background_thread() throw (); + +public: + virtual const char *thread_name(); + virtual bool have_work(); + virtual void copy_work(); + virtual void do_work(); + +public: + void kick(); + +private: + background_thread(const background_thread &); + background_thread &operator = (const background_thread &); + +private: + state_transfer_manager *m_stm; + bool m_need_kickstart; }; -state_transfer_manager :: state_transfer_manager(daemon* d) - : m_daemon(d) - , m_transfers_in() - , m_transfers_out() - , m_background_thread(new background_thread(this)) +state_transfer_manager :: state_transfer_manager(daemon *d) + : m_daemon(d) + , m_transfers_in() + , m_transfers_out() + , m_background_thread(new background_thread(this)) { } state_transfer_manager :: ~state_transfer_manager() throw () { - m_background_thread->shutdown(); + m_background_thread->shutdown(); } bool state_transfer_manager :: setup() { - m_background_thread->start(); - return true; + m_background_thread->start(); + return true; } void state_transfer_manager :: teardown() { - m_background_thread->shutdown(); - m_transfers_in.clear(); - m_transfers_out.clear(); + m_background_thread->shutdown(); + m_transfers_in.clear(); + m_transfers_out.clear(); } void state_transfer_manager :: pause() { - m_background_thread->initiate_pause(); + m_background_thread->initiate_pause(); } void state_transfer_manager :: unpause() { - m_background_thread->kick(); - m_background_thread->unpause(); + m_background_thread->kick(); + m_background_thread->unpause(); } template static void -setup_transfer_state(const char* desc, +setup_transfer_state(const char *desc, const std::vector transfers, - std::vector >* transfer_states) -{ - std::vector > tmp; - tmp.reserve(transfers.size()); - size_t t_idx = 0; - size_t ts_idx = 0; - - while (t_idx < transfers.size() && ts_idx < transfer_states->size()) - { - if (transfers[t_idx].id == (*transfer_states)[ts_idx]->xfer.id) - { - tmp.push_back((*transfer_states)[ts_idx]); - ++t_idx; - ++ts_idx; - } - else if (transfers[t_idx].id < (*transfer_states)[ts_idx]->xfer.id) - { - LOG(INFO) << "initiating " << desc << " " << transfers[t_idx]; - e::intrusive_ptr new_state(new S(transfers[t_idx])); - tmp.push_back(new_state); - ++t_idx; - } - else if (transfers[t_idx].id > (*transfer_states)[ts_idx]->xfer.id) - { - LOG(INFO) << "ending " << desc << " " << (*transfer_states)[ts_idx]->xfer.id; - ++ts_idx; - } - } - - while (t_idx < transfers.size()) - { - LOG(INFO) << "initiating " << desc << " " << transfers[t_idx]; - e::intrusive_ptr new_state(new S(transfers[t_idx])); - tmp.push_back(new_state); - ++t_idx; - } - - while (ts_idx < transfer_states->size()) - { - LOG(INFO) << "ending " << desc << " " << (*transfer_states)[ts_idx]->xfer.id; - ++ts_idx; - } - - tmp.swap(*transfer_states); + std::vector > *transfer_states) +{ + std::vector > tmp; + tmp.reserve(transfers.size()); + size_t t_idx = 0; + size_t ts_idx = 0; + while (t_idx < transfers.size() && ts_idx < transfer_states->size()) + { + if (transfers[t_idx].id == (*transfer_states)[ts_idx]->xfer.id) + { + tmp.push_back((*transfer_states)[ts_idx]); + ++t_idx; + ++ts_idx; + } + else if (transfers[t_idx].id < (*transfer_states)[ts_idx]->xfer.id) + { + LOG(INFO) << "initiating " << desc << " " << transfers[t_idx]; + e::intrusive_ptr new_state(new S(transfers[t_idx])); + tmp.push_back(new_state); + ++t_idx; + } + else if (transfers[t_idx].id > (*transfer_states)[ts_idx]->xfer.id) + { + LOG(INFO) << "ending " << desc << " " << (*transfer_states)[ts_idx]->xfer.id; + ++ts_idx; + } + } + while (t_idx < transfers.size()) + { + LOG(INFO) << "initiating " << desc << " " << transfers[t_idx]; + e::intrusive_ptr new_state(new S(transfers[t_idx])); + tmp.push_back(new_state); + ++t_idx; + } + while (ts_idx < transfer_states->size()) + { + LOG(INFO) << "ending " << desc << " " << (*transfer_states)[ts_idx]->xfer.id; + ++ts_idx; + } + tmp.swap(*transfer_states); } void -state_transfer_manager :: reconfigure(const configuration&, - const configuration& new_config, - const server_id&) -{ - m_background_thread->wait_until_paused(); - - // Setup transfers in - std::vector transfers_in; - new_config.transfers_in(m_daemon->m_us, &transfers_in); - std::sort(transfers_in.begin(), transfers_in.end()); - setup_transfer_state("incoming", transfers_in, &m_transfers_in); - - // Setup transfers out - std::vector transfers_out; - new_config.transfers_out(m_daemon->m_us, &transfers_out); - std::sort(transfers_out.begin(), transfers_out.end()); - setup_transfer_state("outgoing", transfers_out, &m_transfers_out); +state_transfer_manager :: reconfigure(const configuration &, + const configuration &new_config, + const server_id &) +{ + m_background_thread->wait_until_paused(); + // Setup transfers in + std::vector transfers_in; + new_config.transfers_in(m_daemon->m_us, &transfers_in); + std::sort(transfers_in.begin(), transfers_in.end()); + setup_transfer_state("incoming", transfers_in, &m_transfers_in); + // Setup transfers out + std::vector transfers_out; + new_config.transfers_out(m_daemon->m_us, &transfers_out); + std::sort(transfers_out.begin(), transfers_out.end()); + setup_transfer_state("outgoing", transfers_out, &m_transfers_out); } void state_transfer_manager :: debug_dump() { - LOG(INFO) << "state transfer manager ========================================================"; - pause(); - m_background_thread->wait_until_paused(); - LOG(INFO) << "transfer-in states ============================================================"; - - for (size_t i = 0; i < m_transfers_in.size(); ++i) - { - m_transfers_in[i]->debug_dump(); - } - - LOG(INFO) << "transfer-out states ==========================================================="; - - for (size_t i = 0; i < m_transfers_out.size(); ++i) - { - m_transfers_out[i]->debug_dump(); - } - - unpause(); + LOG(INFO) << "state transfer manager ========================================================"; + pause(); + m_background_thread->wait_until_paused(); + LOG(INFO) << "transfer-in states ============================================================"; + for (size_t i = 0; i < m_transfers_in.size(); ++i) + { + m_transfers_in[i]->debug_dump(); + } + LOG(INFO) << "transfer-out states ==========================================================="; + for (size_t i = 0; i < m_transfers_out.size(); ++i) + { + m_transfers_out[i]->debug_dump(); + } + unpause(); } void -state_transfer_manager :: handshake_syn(const virtual_server_id& from, - const transfer_id& xid) -{ - transfer_in_state* tis = get_tis(xid); - - if (!tis) - { - LOG(INFO) << "dropping XFER_HS for " << xid << " which we don't know about"; - return; - } - - po6::threads::mutex::hold hold(&tis->mtx); - - if (tis->xfer.vsrc != from || tis->xfer.id != xid) - { - LOG(INFO) << "dropping XFER_HS that came from the wrong host"; - return; - } - - uint64_t timestamp = 0; - m_daemon->m_data.largest_checkpoint_for(tis->xfer.rid, ×tamp); - send_handshake_synack(tis->xfer, timestamp); - LOG(INFO) << "received handshake_syn for " << xid; +state_transfer_manager :: handshake_syn(const virtual_server_id &from, + const transfer_id &xid) +{ + transfer_in_state *tis = get_tis(xid); + if (!tis) + { + LOG(INFO) << "dropping XFER_HS for " << xid << " which we don't know about"; + return; + } + po6::threads::mutex::hold hold(&tis->mtx); + if (tis->xfer.vsrc != from || tis->xfer.id != xid) + { + LOG(INFO) << "dropping XFER_HS that came from the wrong host"; + return; + } + uint64_t timestamp = 0; + m_daemon->m_data.largest_checkpoint_for(tis->xfer.rid, ×tamp); + send_handshake_synack(tis->xfer, timestamp); + LOG(INFO) << "received handshake_syn for " << xid; } void -state_transfer_manager :: handshake_synack(const server_id& from, - const virtual_server_id& to, - const transfer_id& xid, +state_transfer_manager :: handshake_synack(const server_id &from, + const virtual_server_id &to, + const transfer_id &xid, uint64_t timestamp) { - transfer_out_state* tos = get_tos(xid); - - if (!tos) - { - LOG(INFO) << "dropping XFER_HSA for " << xid << " which we don't know about"; - return; - } - - po6::threads::mutex::hold hold(&tos->mtx); - - if (tos->xfer.dst != from || tos->xfer.vsrc != to || tos->xfer.id != xid) - { - LOG(INFO) << "dropping XFER_HSA that came from the wrong host"; - return; - } - - bool wipe = false; - std::auto_ptr iter; - iter.reset(m_daemon->m_data.replay_region_from_checkpoint(tos->xfer.rid, timestamp, &wipe)); - tos->handshake_syn = true; - tos->wipe = wipe; - tos->iter = iter; - send_handshake_ack(tos->xfer, tos->wipe); - transfer_more_state(tos); - LOG(INFO) << "received handshake_synack for " << xid << " @ " << timestamp; + transfer_out_state *tos = get_tos(xid); + if (!tos) + { + LOG(INFO) << "dropping XFER_HSA for " << xid << " which we don't know about"; + return; + } + po6::threads::mutex::hold hold(&tos->mtx); + if (tos->xfer.dst != from || tos->xfer.vsrc != to || tos->xfer.id != xid) + { + LOG(INFO) << "dropping XFER_HSA that came from the wrong host"; + return; + } + bool wipe = false; + std::auto_ptr iter; + iter.reset(m_daemon->m_data.replay_region_from_checkpoint(tos->xfer.rid, timestamp, &wipe)); + tos->handshake_syn = true; + tos->wipe = wipe; + tos->iter = iter; + send_handshake_ack(tos->xfer, tos->wipe); + transfer_more_state(tos); + LOG(INFO) << "received handshake_synack for " << xid << " @ " << timestamp; } void -state_transfer_manager :: handshake_ack(const virtual_server_id& from, - const transfer_id& xid, +state_transfer_manager :: handshake_ack(const virtual_server_id &from, + const transfer_id &xid, bool wipe) { - transfer_in_state* tis = get_tis(xid); - - if (!tis) - { - LOG(INFO) << "dropping XFER_HA for " << xid << " which we don't know about"; - return; - } - - po6::threads::mutex::hold hold(&tis->mtx); - - if (tis->xfer.vsrc != from || tis->xfer.id != xid) - { - LOG(INFO) << "dropping XFER_HA that came from the wrong host"; - return; - } - - if (!tis->handshake_complete) - { - tis->handshake_complete = true; - tis->wipe = wipe; - LOG(INFO) << "received handshake_ack for " << xid << (wipe ? " (and we must wipe our previous state)" : ""); - } - - put_to_disk_and_send_acks(tis); + transfer_in_state *tis = get_tis(xid); + if (!tis) + { + LOG(INFO) << "dropping XFER_HA for " << xid << " which we don't know about"; + return; + } + po6::threads::mutex::hold hold(&tis->mtx); + if (tis->xfer.vsrc != from || tis->xfer.id != xid) + { + LOG(INFO) << "dropping XFER_HA that came from the wrong host"; + return; + } + if (!tis->handshake_complete) + { + tis->handshake_complete = true; + tis->wipe = wipe; + LOG(INFO) << "received handshake_ack for " << xid << (wipe ? " (and we must wipe our previous state)" : ""); + } + put_to_disk_and_send_acks(tis); } void -state_transfer_manager :: handshake_wiped(const server_id& from, - const virtual_server_id& to, - const transfer_id& xid) -{ - transfer_out_state* tos = get_tos(xid); - - if (!tos) - { - LOG(INFO) << "dropping XFER_HW for " << xid << " which we don't know about"; - return; - } - - po6::threads::mutex::hold hold(&tos->mtx); - - if (tos->xfer.dst != from || tos->xfer.vsrc != to || tos->xfer.id != xid) - { - LOG(INFO) << "dropping XFER_HW that came from the wrong host"; - return; - } - - tos->handshake_ack = true; - transfer_more_state(tos); - LOG(INFO) << "received handshake_wiped for " << xid; +state_transfer_manager :: handshake_wiped(const server_id &from, + const virtual_server_id &to, + const transfer_id &xid) +{ + transfer_out_state *tos = get_tos(xid); + if (!tos) + { + LOG(INFO) << "dropping XFER_HW for " << xid << " which we don't know about"; + return; + } + po6::threads::mutex::hold hold(&tos->mtx); + if (tos->xfer.dst != from || tos->xfer.vsrc != to || tos->xfer.id != xid) + { + LOG(INFO) << "dropping XFER_HW that came from the wrong host"; + return; + } + tos->handshake_ack = true; + transfer_more_state(tos); + LOG(INFO) << "received handshake_wiped for " << xid; } void -state_transfer_manager :: report_wiped(const transfer_id& xid) -{ - transfer_in_state* tis = get_tis(xid); - - if (!tis) - { - return; - } - - m_daemon->m_data.inhibit_wiping(); - - if (!m_daemon->m_data.region_will_be_wiped(tis->xfer.rid)) - { - po6::threads::mutex::hold hold(&tis->mtx); - tis->wiped = true; - put_to_disk_and_send_acks(tis); - LOG(INFO) << "we've wiped our state for " << xid; - } - - m_daemon->m_data.permit_wiping(); +state_transfer_manager :: report_wiped(const transfer_id &xid) +{ + transfer_in_state *tis = get_tis(xid); + if (!tis) + { + return; + } + m_daemon->m_data.inhibit_wiping(); + if (!m_daemon->m_data.region_will_be_wiped(tis->xfer.rid)) + { + po6::threads::mutex::hold hold(&tis->mtx); + tis->wiped = true; + put_to_disk_and_send_acks(tis); + LOG(INFO) << "we've wiped our state for " << xid; + } + m_daemon->m_data.permit_wiping(); } void -state_transfer_manager :: xfer_op(const virtual_server_id& from, - const transfer_id& xid, +state_transfer_manager :: xfer_op(const virtual_server_id &from, + const transfer_id &xid, uint64_t seq_no, bool has_value, uint64_t version, std::auto_ptr msg, - const e::slice& key, - const std::vector& value) -{ - transfer_in_state* tis = get_tis(xid); - - if (!tis) - { - LOG(INFO) << "dropping XFER_OP for " << xid << " which we don't know about"; - return; - } - - po6::threads::mutex::hold hold(&tis->mtx); - - if (tis->xfer.vsrc != from || tis->xfer.id != xid) - { - LOG(INFO) << "dropping XFER_OP that came from the wrong host"; - return; - } - - if (seq_no < tis->upper_bound_acked) - { - return send_ack(tis->xfer, seq_no); - } - - std::list >::iterator where_to_put_it; - - for (where_to_put_it = tis->queued.begin(); - where_to_put_it != tis->queued.end(); ++where_to_put_it) - { - if ((*where_to_put_it)->seq_no == seq_no) - { - // silently drop it - return; - } - - if ((*where_to_put_it)->seq_no > seq_no) - { - break; - } - } - - e::intrusive_ptr op(new pending()); - op->seq_no = seq_no; - op->has_value = has_value; - op->version = version; - op->key = key; - op->value = value; - op->msg = msg; - tis->queued.insert(where_to_put_it, op); - put_to_disk_and_send_acks(tis); + const e::slice &key, + const std::vector &value) +{ + transfer_in_state *tis = get_tis(xid); + if (!tis) + { + LOG(INFO) << "dropping XFER_OP for " << xid << " which we don't know about"; + return; + } + po6::threads::mutex::hold hold(&tis->mtx); + if (tis->xfer.vsrc != from || tis->xfer.id != xid) + { + LOG(INFO) << "dropping XFER_OP that came from the wrong host"; + return; + } + if (seq_no < tis->upper_bound_acked) + { + return send_ack(tis->xfer, seq_no); + } + std::list >::iterator where_to_put_it; + for (where_to_put_it = tis->queued.begin(); + where_to_put_it != tis->queued.end(); ++where_to_put_it) + { + if ((*where_to_put_it)->seq_no == seq_no) + { + // silently drop it + return; + } + if ((*where_to_put_it)->seq_no > seq_no) + { + break; + } + } + e::intrusive_ptr op(new pending()); + op->seq_no = seq_no; + op->has_value = has_value; + op->version = version; + op->key = key; + op->value = value; + op->msg = msg; + tis->queued.insert(where_to_put_it, op); + put_to_disk_and_send_acks(tis); } void -state_transfer_manager :: xfer_ack(const server_id& from, - const virtual_server_id& to, - const transfer_id& xid, +state_transfer_manager :: xfer_ack(const server_id &from, + const virtual_server_id &to, + const transfer_id &xid, uint64_t seq_no) { - transfer_out_state* tos = get_tos(xid); - - if (!tos) - { - LOG(INFO) << "dropping XFER_ACK for " << xid << " which we don't know about"; - return; - } - - po6::threads::mutex::hold hold(&tos->mtx); - - if (tos->xfer.dst != from || tos->xfer.vsrc != to || tos->xfer.id != xid) - { - LOG(INFO) << "dropping XFER_ACK that came from the wrong host"; - return; - } - - std::list >::iterator it; - - for (it = tos->window.begin(); it != tos->window.end(); ++it) - { - if ((*it)->seq_no == seq_no) - { - break; - } - } - - if (it != tos->window.end()) - { - (*it)->acked = true; - tos->handshake_ack = true; - - if (tos->window_sz < 1024) - { - ++tos->window_sz; - } - } - - while (!tos->window.empty() && (*tos->window.begin())->acked) - { - tos->window.pop_front(); - } - - transfer_more_state(tos); -} - -state_transfer_manager::transfer_in_state* -state_transfer_manager :: get_tis(const transfer_id& xid) -{ - for (size_t i = 0; i < m_transfers_in.size(); ++i) - { - if (m_transfers_in[i]->xfer.id == xid) - { - return m_transfers_in[i].get(); - } - } - - return NULL; -} - -state_transfer_manager::transfer_out_state* -state_transfer_manager :: get_tos(const transfer_id& xid) -{ - for (size_t i = 0; i < m_transfers_out.size(); ++i) - { - if (m_transfers_out[i]->xfer.id == xid) - { - return m_transfers_out[i].get(); - } - } - - return NULL; + transfer_out_state *tos = get_tos(xid); + if (!tos) + { + LOG(INFO) << "dropping XFER_ACK for " << xid << " which we don't know about"; + return; + } + po6::threads::mutex::hold hold(&tos->mtx); + if (tos->xfer.dst != from || tos->xfer.vsrc != to || tos->xfer.id != xid) + { + LOG(INFO) << "dropping XFER_ACK that came from the wrong host"; + return; + } + std::list >::iterator it; + for (it = tos->window.begin(); it != tos->window.end(); ++it) + { + if ((*it)->seq_no == seq_no) + { + break; + } + } + if (it != tos->window.end()) + { + (*it)->acked = true; + tos->handshake_ack = true; + if (tos->window_sz < 1024) + { + ++tos->window_sz; + } + } + while (!tos->window.empty() && (*tos->window.begin())->acked) + { + tos->window.pop_front(); + } + transfer_more_state(tos); +} + +state_transfer_manager::transfer_in_state * +state_transfer_manager :: get_tis(const transfer_id &xid) +{ + for (size_t i = 0; i < m_transfers_in.size(); ++i) + { + if (m_transfers_in[i]->xfer.id == xid) + { + return m_transfers_in[i].get(); + } + } + return NULL; +} + +state_transfer_manager::transfer_out_state * +state_transfer_manager :: get_tos(const transfer_id &xid) +{ + for (size_t i = 0; i < m_transfers_out.size(); ++i) + { + if (m_transfers_out[i]->xfer.id == xid) + { + return m_transfers_out[i].get(); + } + } + return NULL; } void -state_transfer_manager :: transfer_more_state(transfer_out_state* tos) -{ - if (!tos->handshake_syn) - { - send_handshake_syn(tos->xfer); - return; - } - - if (!tos->handshake_ack) - { - send_handshake_ack(tos->xfer, tos->wipe); - } - - assert(tos->iter.get()); - - while (tos->window.size() < tos->window_sz && tos->iter->valid()) - { - e::intrusive_ptr op(new pending()); - op->seq_no = tos->next_seq_no; - ++tos->next_seq_no; - op->kref.assign(reinterpret_cast(tos->iter->key().data()), tos->iter->key().size()); - op->key = e::slice(op->kref); - - if (tos->iter->has_value()) - { - op->has_value = true; - - if (tos->iter->unpack_value(&op->value, &op->version, &op->vref) != datalayer::SUCCESS) - { - LOG(ERROR) << "error doing state transfer"; - break; - } - } - else - { - op->has_value = false; - op->version = 0; - } - - tos->window.push_back(op); - send_object(tos->xfer, op.get()); - tos->iter->next(); - } - - if (!tos->handshake_ack) - { - // pass! we need the other end to give us some sign that it's ready, - // otherwise we cannot consider moving forward, even if we're ready. - } - else if (tos->window.empty() && m_daemon->m_config.is_transfer_live(tos->xfer.id)) - { - m_daemon->m_coord->transfer_complete(tos->xfer.id); - } - else if (tos->window.empty()) - { - m_daemon->m_coord->transfer_go_live(tos->xfer.id); - } +state_transfer_manager :: transfer_more_state(transfer_out_state *tos) +{ + if (!tos->handshake_syn) + { + send_handshake_syn(tos->xfer); + return; + } + if (!tos->handshake_ack) + { + send_handshake_ack(tos->xfer, tos->wipe); + } + assert(tos->iter.get()); + while (tos->window.size() < tos->window_sz && tos->iter->valid()) + { + e::intrusive_ptr op(new pending()); + op->seq_no = tos->next_seq_no; + ++tos->next_seq_no; + op->kref.assign(reinterpret_cast(tos->iter->key().data()), tos->iter->key().size()); + op->key = e::slice(op->kref); + if (tos->iter->has_value()) + { + op->has_value = true; + if (tos->iter->unpack_value(&op->value, &op->version, &op->vref) != datalayer::SUCCESS) + { + LOG(ERROR) << "error doing state transfer"; + break; + } + } + else + { + op->has_value = false; + op->version = 0; + } + tos->window.push_back(op); + send_object(tos->xfer, op.get()); + tos->iter->next(); + } + if (!tos->handshake_ack) + { + // pass! we need the other end to give us some sign that it's ready, + // otherwise we cannot consider moving forward, even if we're ready. + } + else if (tos->window.empty() && m_daemon->m_config.is_transfer_live(tos->xfer.id)) + { + m_daemon->m_coord->transfer_complete(tos->xfer.id); + } + else if (tos->window.empty()) + { + m_daemon->m_coord->transfer_go_live(tos->xfer.id); + } } void -state_transfer_manager :: retransmit(transfer_out_state* tos) +state_transfer_manager :: retransmit(transfer_out_state *tos) { - for (std::list >::iterator it = tos->window.begin(); - it != tos->window.end(); ++it) - { - send_object(tos->xfer, it->get()); - } + for (std::list >::iterator it = tos->window.begin(); + it != tos->window.end(); ++it) + { + send_object(tos->xfer, it->get()); + } } void -state_transfer_manager :: put_to_disk_and_send_acks(transfer_in_state* tis) -{ - if (!tis->handshake_complete) - { - return; - } - - if (tis->wipe && !tis->wiped) - { - m_daemon->m_data.request_wipe(tis->xfer.id, tis->xfer.rid); - return; - } - - if (tis->queued.empty()) - { - send_handshake_wiped(tis->xfer); - } - - while (!tis->queued.empty() && - tis->queued.front()->seq_no == tis->upper_bound_acked) - { - e::intrusive_ptr op = tis->queued.front(); - - if (op->has_value) - { - datalayer::returncode rc = m_daemon->m_data.uncertain_put(tis->xfer.rid, op->key, op->value, op->version); - - switch (rc) - { - case datalayer::SUCCESS: - break; - case datalayer::NOT_FOUND: - case datalayer::BAD_ENCODING: - case datalayer::CORRUPTION: - case datalayer::IO_ERROR: - case datalayer::LEVELDB_ERROR: - LOG(ERROR) << "state transfer caused error " << rc; - break; - default: - LOG(ERROR) << "state transfer caused unknown error"; - break; - } - } - else - { - datalayer::returncode rc = m_daemon->m_data.uncertain_del(tis->xfer.rid, op->key); - - switch (rc) - { - case datalayer::SUCCESS: - case datalayer::NOT_FOUND: - break; - case datalayer::BAD_ENCODING: - case datalayer::CORRUPTION: - case datalayer::IO_ERROR: - case datalayer::LEVELDB_ERROR: - LOG(ERROR) << "state transfer caused error " << rc; - break; - default: - LOG(ERROR) << "state transfer caused unknown error"; - break; - } - } - - send_ack(tis->xfer, op->seq_no); - tis->upper_bound_acked = std::max(tis->upper_bound_acked, op->seq_no + 1); - tis->queued.pop_front(); - } +state_transfer_manager :: put_to_disk_and_send_acks(transfer_in_state *tis) +{ + if (!tis->handshake_complete) + { + return; + } + if (tis->wipe && !tis->wiped) + { + m_daemon->m_data.request_wipe(tis->xfer.id, tis->xfer.rid); + return; + } + if (tis->queued.empty()) + { + send_handshake_wiped(tis->xfer); + } + while (!tis->queued.empty() && + tis->queued.front()->seq_no == tis->upper_bound_acked) + { + e::intrusive_ptr op = tis->queued.front(); + if (op->has_value) + { + datalayer::returncode rc = m_daemon->m_data.uncertain_put(tis->xfer.rid, op->key, op->value, op->version); + switch (rc) + { + case datalayer::SUCCESS: + break; + case datalayer::NOT_FOUND: + case datalayer::BAD_ENCODING: + case datalayer::CORRUPTION: + case datalayer::IO_ERROR: + case datalayer::LEVELDB_ERROR: + LOG(ERROR) << "state transfer caused error " << rc; + break; + default: + LOG(ERROR) << "state transfer caused unknown error"; + break; + } + } + else + { + datalayer::returncode rc = m_daemon->m_data.uncertain_del(tis->xfer.rid, op->key); + switch (rc) + { + case datalayer::SUCCESS: + case datalayer::NOT_FOUND: + break; + case datalayer::BAD_ENCODING: + case datalayer::CORRUPTION: + case datalayer::IO_ERROR: + case datalayer::LEVELDB_ERROR: + LOG(ERROR) << "state transfer caused error " << rc; + break; + default: + LOG(ERROR) << "state transfer caused unknown error"; + break; + } + } + send_ack(tis->xfer, op->seq_no); + tis->upper_bound_acked = std::max(tis->upper_bound_acked, op->seq_no + 1); + tis->queued.pop_front(); + } } void -state_transfer_manager :: send_handshake_syn(const transfer& xfer) +state_transfer_manager :: send_handshake_syn(const transfer &xfer) { - size_t sz = HYPERDEX_HEADER_SIZE_VV - + sizeof(uint64_t); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << xfer.id; - m_daemon->m_comm.send_exact(xfer.vsrc, xfer.vdst, XFER_HS, msg); + size_t sz = HYPERDEX_HEADER_SIZE_VV + + sizeof(uint64_t); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << xfer.id; + m_daemon->m_comm.send_exact(xfer.vsrc, xfer.vdst, XFER_HS, msg); } void -state_transfer_manager :: send_handshake_synack(const transfer& xfer, uint64_t timestamp) +state_transfer_manager :: send_handshake_synack(const transfer &xfer, uint64_t timestamp) { - size_t sz = HYPERDEX_HEADER_SIZE_VV - + sizeof(uint64_t) - + sizeof(uint64_t); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << xfer.id << timestamp; - m_daemon->m_comm.send_exact(xfer.vdst, xfer.vsrc, XFER_HSA, msg); + size_t sz = HYPERDEX_HEADER_SIZE_VV + + sizeof(uint64_t) + + sizeof(uint64_t); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << xfer.id << timestamp; + m_daemon->m_comm.send_exact(xfer.vdst, xfer.vsrc, XFER_HSA, msg); } void -state_transfer_manager :: send_handshake_ack(const transfer& xfer, bool wipe) +state_transfer_manager :: send_handshake_ack(const transfer &xfer, bool wipe) { - uint8_t flags = wipe ? 0x1 : 0; - size_t sz = HYPERDEX_HEADER_SIZE_VV - + sizeof(uint64_t) - + sizeof(uint8_t); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << xfer.id << flags; - m_daemon->m_comm.send_exact(xfer.vsrc, xfer.vdst, XFER_HA, msg); + uint8_t flags = wipe ? 0x1 : 0; + size_t sz = HYPERDEX_HEADER_SIZE_VV + + sizeof(uint64_t) + + sizeof(uint8_t); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << xfer.id << flags; + m_daemon->m_comm.send_exact(xfer.vsrc, xfer.vdst, XFER_HA, msg); } void -state_transfer_manager :: send_handshake_wiped(const transfer& xfer) +state_transfer_manager :: send_handshake_wiped(const transfer &xfer) { - size_t sz = HYPERDEX_HEADER_SIZE_VV - + sizeof(uint64_t); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << xfer.id; - m_daemon->m_comm.send_exact(xfer.vdst, xfer.vsrc, XFER_HW, msg); + size_t sz = HYPERDEX_HEADER_SIZE_VV + + sizeof(uint64_t); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << xfer.id; + m_daemon->m_comm.send_exact(xfer.vdst, xfer.vsrc, XFER_HW, msg); } void -state_transfer_manager :: send_object(const transfer& xfer, - pending* op) -{ - uint8_t flags = (op->has_value ? 1 : 0); - size_t sz = HYPERDEX_HEADER_SIZE_VV - + sizeof(uint8_t) - + sizeof(uint64_t) - + sizeof(uint64_t) - + sizeof(uint64_t) - + sizeof(uint32_t) + op->key.size() - + pack_size(op->value); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << flags << xfer.id.get() << op->seq_no - << op->version << op->key << op->value; - m_daemon->m_comm.send_exact(xfer.vsrc, xfer.vdst, XFER_OP, msg); +state_transfer_manager :: send_object(const transfer &xfer, + pending *op) +{ + uint8_t flags = (op->has_value ? 1 : 0); + size_t sz = HYPERDEX_HEADER_SIZE_VV + + sizeof(uint8_t) + + sizeof(uint64_t) + + sizeof(uint64_t) + + sizeof(uint64_t) + + sizeof(uint32_t) + op->key.size() + + pack_size(op->value); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << flags << xfer.id.get() << op->seq_no + << op->version << op->key << op->value; + m_daemon->m_comm.send_exact(xfer.vsrc, xfer.vdst, XFER_OP, msg); } void -state_transfer_manager :: send_ack(const transfer& xfer, uint64_t seq_no) +state_transfer_manager :: send_ack(const transfer &xfer, uint64_t seq_no) { - uint8_t flags = 0; - size_t sz = HYPERDEX_HEADER_SIZE_VV - + sizeof(uint8_t) - + sizeof(uint64_t) - + sizeof(uint64_t); - std::auto_ptr msg(e::buffer::create(sz)); - msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << flags << xfer.id.get() << seq_no; - m_daemon->m_comm.send_exact(xfer.vdst, xfer.vsrc, XFER_ACK, msg); + uint8_t flags = 0; + size_t sz = HYPERDEX_HEADER_SIZE_VV + + sizeof(uint8_t) + + sizeof(uint64_t) + + sizeof(uint64_t); + std::auto_ptr msg(e::buffer::create(sz)); + msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << flags << xfer.id.get() << seq_no; + m_daemon->m_comm.send_exact(xfer.vdst, xfer.vsrc, XFER_ACK, msg); } -state_transfer_manager :: background_thread :: background_thread(state_transfer_manager* stm) - : hyperdex::background_thread(stm->m_daemon) - , m_stm(stm) - , m_need_kickstart(false) +state_transfer_manager :: background_thread :: background_thread(state_transfer_manager *stm) + : hyperdex::background_thread(stm->m_daemon) + , m_stm(stm) + , m_need_kickstart(false) { } @@ -711,43 +647,42 @@ state_transfer_manager :: background_thread :: ~background_thread() throw () { } -const char* +const char * state_transfer_manager :: background_thread :: thread_name() { - return "state transfer"; + return "state transfer"; } bool state_transfer_manager :: background_thread :: have_work() { - return m_need_kickstart; + return m_need_kickstart; } void state_transfer_manager :: background_thread :: copy_work() { - m_need_kickstart = false; + m_need_kickstart = false; } void state_transfer_manager :: background_thread :: do_work() { - for (size_t idx = 0; idx < m_stm->m_transfers_out.size(); ++idx) - { - po6::threads::mutex::hold hold2(&m_stm->m_transfers_out[idx]->mtx); - m_stm->retransmit(m_stm->m_transfers_out[idx].get()); - m_stm->transfer_more_state(m_stm->m_transfers_out[idx].get()); - ++idx; - } - - m_stm->m_daemon->m_comm.wake_one(); + for (size_t idx = 0; idx < m_stm->m_transfers_out.size(); ++idx) + { + po6::threads::mutex::hold hold2(&m_stm->m_transfers_out[idx]->mtx); + m_stm->retransmit(m_stm->m_transfers_out[idx].get()); + m_stm->transfer_more_state(m_stm->m_transfers_out[idx].get()); + ++idx; + } + m_stm->m_daemon->m_comm.wake_one(); } void state_transfer_manager :: background_thread :: kick() { - this->lock(); - m_need_kickstart = true; - this->wakeup(); - this->unlock(); + this->lock(); + m_need_kickstart = true; + this->wakeup(); + this->unlock(); } diff --git a/daemon/state_transfer_manager.h b/daemon/state_transfer_manager.h index 49b811d8a..df7a74843 100644 --- a/daemon/state_transfer_manager.h +++ b/daemon/state_transfer_manager.h @@ -50,81 +50,81 @@ class daemon; class state_transfer_manager { - public: - state_transfer_manager(daemon*); - ~state_transfer_manager() throw (); +public: + state_transfer_manager(daemon *); + ~state_transfer_manager() throw (); - // Reconfigure this layer. - public: - bool setup(); - void teardown(); - void pause(); - void unpause(); - void reconfigure(const configuration& old_config, - const configuration& new_config, - const server_id& us); - void debug_dump(); + // Reconfigure this layer. +public: + bool setup(); + void teardown(); + void pause(); + void unpause(); + void reconfigure(const configuration &old_config, + const configuration &new_config, + const server_id &us); + void debug_dump(); - public: - void handshake_syn(const virtual_server_id& from, - const transfer_id& xid); - void handshake_synack(const server_id& from, - const virtual_server_id& to, - const transfer_id& xid, - uint64_t timestamp); - void handshake_ack(const virtual_server_id& from, - const transfer_id& xid, - bool wipe); - void handshake_wiped(const server_id& from, - const virtual_server_id& to, - const transfer_id& xid); - void report_wiped(const transfer_id& xid); - void xfer_op(const virtual_server_id& from, - const transfer_id& xid, - uint64_t seq_no, - bool has_value, - uint64_t version, - std::auto_ptr msg, - const e::slice& key, - const std::vector& value); - void xfer_ack(const server_id& from, - const virtual_server_id& to, - const transfer_id& xid, - uint64_t seq_no); +public: + void handshake_syn(const virtual_server_id &from, + const transfer_id &xid); + void handshake_synack(const server_id &from, + const virtual_server_id &to, + const transfer_id &xid, + uint64_t timestamp); + void handshake_ack(const virtual_server_id &from, + const transfer_id &xid, + bool wipe); + void handshake_wiped(const server_id &from, + const virtual_server_id &to, + const transfer_id &xid); + void report_wiped(const transfer_id &xid); + void xfer_op(const virtual_server_id &from, + const transfer_id &xid, + uint64_t seq_no, + bool has_value, + uint64_t version, + std::auto_ptr msg, + const e::slice &key, + const std::vector &value); + void xfer_ack(const server_id &from, + const virtual_server_id &to, + const transfer_id &xid, + uint64_t seq_no); - private: - class pending; - class transfer_in_state; - class transfer_out_state; - class background_thread; +private: + class pending; + class transfer_in_state; + class transfer_out_state; + class background_thread; - private: - // get the appropriate state - transfer_in_state* get_tis(const transfer_id& xid); - transfer_out_state* get_tos(const transfer_id& xid); - // caller must hold mtx on tos - void transfer_more_state(transfer_out_state* tos); - void retransmit(transfer_out_state* tos); - // caller must hold mtx on tis - void put_to_disk_and_send_acks(transfer_in_state* tis); - // caller must hold mtx on tos - // send the last object in tos - void send_handshake_syn(const transfer& xfer); - void send_handshake_synack(const transfer& xfer, uint64_t timestamp); - void send_handshake_ack(const transfer& xfer, bool wipe); - void send_handshake_wiped(const transfer& xfer); - void send_object(const transfer& xfer, pending* op); - void send_ack(const transfer& xfer, uint64_t seq_id); +private: + // get the appropriate state + transfer_in_state *get_tis(const transfer_id &xid); + transfer_out_state *get_tos(const transfer_id &xid); + // caller must hold mtx on tos + void transfer_more_state(transfer_out_state *tos); + void retransmit(transfer_out_state *tos); + // caller must hold mtx on tis + void put_to_disk_and_send_acks(transfer_in_state *tis); + // caller must hold mtx on tos + // send the last object in tos + void send_handshake_syn(const transfer &xfer); + void send_handshake_synack(const transfer &xfer, uint64_t timestamp); + void send_handshake_ack(const transfer &xfer, bool wipe); + void send_handshake_wiped(const transfer &xfer); + void send_object(const transfer &xfer, pending *op); + void send_ack(const transfer &xfer, uint64_t seq_id); - private: - state_transfer_manager(const state_transfer_manager&); - state_transfer_manager& operator = (const state_transfer_manager&); +private: + state_transfer_manager(const state_transfer_manager &); + state_transfer_manager &operator = (const state_transfer_manager &); - private: - daemon* m_daemon; - std::vector > m_transfers_in; - std::vector > m_transfers_out; - const std::auto_ptr m_background_thread; +private: + daemon *m_daemon; + std::vector > m_transfers_in; + std::vector > m_transfers_out; + const std::auto_ptr m_background_thread; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/state_transfer_manager_pending.cc b/daemon/state_transfer_manager_pending.cc index 09114735e..43d63d5ed 100644 --- a/daemon/state_transfer_manager_pending.cc +++ b/daemon/state_transfer_manager_pending.cc @@ -33,16 +33,16 @@ using hyperdex::state_transfer_manager; state_transfer_manager :: state_transfer_manager :: pending :: pending() - : seq_no(0) - , has_value(false) - , version(0) - , key() - , value() - , acked(false) - , msg() - , kref() - , vref() - , m_ref(0) + : seq_no(0) + , has_value(false) + , version(0) + , key() + , value() + , acked(false) + , msg() + , kref() + , vref() + , m_ref(0) { } diff --git a/daemon/state_transfer_manager_pending.h b/daemon/state_transfer_manager_pending.h index a12904e70..845607cf4 100644 --- a/daemon/state_transfer_manager_pending.h +++ b/daemon/state_transfer_manager_pending.h @@ -34,30 +34,30 @@ class hyperdex::state_transfer_manager::pending { - public: - pending(); - ~pending() throw (); - - public: - uint64_t seq_no; - bool has_value; - uint64_t version; - e::slice key; - std::vector value; - bool acked; - std::auto_ptr msg; - std::string kref; - datalayer::reference vref; - - private: - friend class e::intrusive_ptr; - - private: - void inc() { ++m_ref; } - void dec() { --m_ref; if (m_ref == 0) delete this; } - - private: - size_t m_ref; +public: + pending(); + ~pending() throw (); + +public: + uint64_t seq_no; + bool has_value; + uint64_t version; + e::slice key; + std::vector value; + bool acked; + std::auto_ptr msg; + std::string kref; + datalayer::reference vref; + +private: + friend class e::intrusive_ptr; + +private: + void inc() { ++m_ref; } + void dec() { --m_ref; if (m_ref == 0) delete this; } + +private: + size_t m_ref; }; #endif // hyperdex_daemon_state_transfer_manager_pending_h_ diff --git a/daemon/state_transfer_manager_transfer_in_state.cc b/daemon/state_transfer_manager_transfer_in_state.cc index 0c6556b70..809e2f847 100644 --- a/daemon/state_transfer_manager_transfer_in_state.cc +++ b/daemon/state_transfer_manager_transfer_in_state.cc @@ -38,15 +38,15 @@ using hyperdex::state_transfer_manager; -state_transfer_manager :: transfer_in_state :: transfer_in_state(const transfer& _xfer) - : xfer(_xfer) - , mtx() - , upper_bound_acked(1) - , queued() - , handshake_complete(false) - , wipe(false) - , wiped(false) - , m_ref(0) +state_transfer_manager :: transfer_in_state :: transfer_in_state(const transfer &_xfer) + : xfer(_xfer) + , mtx() + , upper_bound_acked(1) + , queued() + , handshake_complete(false) + , wipe(false) + , wiped(false) + , m_ref(0) { } @@ -57,9 +57,9 @@ state_transfer_manager :: transfer_in_state :: ~transfer_in_state() throw () void state_transfer_manager :: transfer_in_state :: debug_dump() { - po6::threads::mutex::hold hold(&mtx); - LOG(INFO) << " transfer=" << xfer; - LOG(INFO) << " upper_bound_acked=" << upper_bound_acked; - LOG(INFO) << " wipe=" << wipe; - LOG(INFO) << " wiped=" << wiped; + po6::threads::mutex::hold hold(&mtx); + LOG(INFO) << " transfer=" << xfer; + LOG(INFO) << " upper_bound_acked=" << upper_bound_acked; + LOG(INFO) << " wipe=" << wipe; + LOG(INFO) << " wiped=" << wiped; } diff --git a/daemon/state_transfer_manager_transfer_in_state.h b/daemon/state_transfer_manager_transfer_in_state.h index 7b36e399c..4c4b0a739 100644 --- a/daemon/state_transfer_manager_transfer_in_state.h +++ b/daemon/state_transfer_manager_transfer_in_state.h @@ -36,31 +36,31 @@ class hyperdex::state_transfer_manager::transfer_in_state { - public: - transfer_in_state(const transfer& xfer); - ~transfer_in_state() throw (); +public: + transfer_in_state(const transfer &xfer); + ~transfer_in_state() throw (); - public: - void debug_dump(); +public: + void debug_dump(); - public: - transfer xfer; - po6::threads::mutex mtx; - uint64_t upper_bound_acked; - std::list > queued; - bool handshake_complete; - bool wipe; - bool wiped; +public: + transfer xfer; + po6::threads::mutex mtx; + uint64_t upper_bound_acked; + std::list > queued; + bool handshake_complete; + bool wipe; + bool wiped; - private: - friend class e::intrusive_ptr; +private: + friend class e::intrusive_ptr; - private: - void inc() { __sync_add_and_fetch(&m_ref, 1); } - void dec() { if (__sync_sub_and_fetch(&m_ref, 1) == 0) delete this; } +private: + void inc() { __sync_add_and_fetch(&m_ref, 1); } + void dec() { if (__sync_sub_and_fetch(&m_ref, 1) == 0) delete this; } - private: - size_t m_ref; +private: + size_t m_ref; }; #endif // hyperdex_daemon_state_transfer_manager_transfer_in_state_h_ diff --git a/daemon/state_transfer_manager_transfer_out_state.cc b/daemon/state_transfer_manager_transfer_out_state.cc index 7fa036448..39c02b28b 100644 --- a/daemon/state_transfer_manager_transfer_out_state.cc +++ b/daemon/state_transfer_manager_transfer_out_state.cc @@ -37,17 +37,17 @@ using hyperdex::state_transfer_manager; -state_transfer_manager :: transfer_out_state :: transfer_out_state(const transfer& _xfer) - : xfer(_xfer) - , mtx() - , next_seq_no(1) - , window() - , window_sz(1) - , iter() - , handshake_syn(false) - , handshake_ack(false) - , wipe(false) - , m_ref(0) +state_transfer_manager :: transfer_out_state :: transfer_out_state(const transfer &_xfer) + : xfer(_xfer) + , mtx() + , next_seq_no(1) + , window() + , window_sz(1) + , iter() + , handshake_syn(false) + , handshake_ack(false) + , wipe(false) + , m_ref(0) { } @@ -58,11 +58,11 @@ state_transfer_manager :: transfer_out_state :: ~transfer_out_state() throw () void state_transfer_manager :: transfer_out_state :: debug_dump() { - po6::threads::mutex::hold hold(&mtx); - LOG(INFO) << " transfer=" << xfer; - LOG(INFO) << " next_seq_no=" << next_seq_no; - LOG(INFO) << " window_sz=" << window_sz; - LOG(INFO) << " handshake_syn=" << handshake_syn; - LOG(INFO) << " handshake_ack=" << handshake_ack; - LOG(INFO) << " wipe=" << wipe; + po6::threads::mutex::hold hold(&mtx); + LOG(INFO) << " transfer=" << xfer; + LOG(INFO) << " next_seq_no=" << next_seq_no; + LOG(INFO) << " window_sz=" << window_sz; + LOG(INFO) << " handshake_syn=" << handshake_syn; + LOG(INFO) << " handshake_ack=" << handshake_ack; + LOG(INFO) << " wipe=" << wipe; } diff --git a/daemon/state_transfer_manager_transfer_out_state.h b/daemon/state_transfer_manager_transfer_out_state.h index 6ced99c56..e00f7d274 100644 --- a/daemon/state_transfer_manager_transfer_out_state.h +++ b/daemon/state_transfer_manager_transfer_out_state.h @@ -45,37 +45,37 @@ using hyperdex::state_transfer_manager; class state_transfer_manager::transfer_out_state { - public: - transfer_out_state(const transfer& xfer); - ~transfer_out_state() throw (); +public: + transfer_out_state(const transfer &xfer); + ~transfer_out_state() throw (); - public: - void debug_dump(); +public: + void debug_dump(); - public: - transfer xfer; - po6::threads::mutex mtx; - uint64_t next_seq_no; - std::list > window; - size_t window_sz; - std::auto_ptr iter; - bool handshake_syn; // do we know the other end got a syn? - bool handshake_ack; // do we know the other end got a ack? - bool wipe; +public: + transfer xfer; + po6::threads::mutex mtx; + uint64_t next_seq_no; + std::list > window; + size_t window_sz; + std::auto_ptr iter; + bool handshake_syn; // do we know the other end got a syn? + bool handshake_ack; // do we know the other end got a ack? + bool wipe; - private: - friend class e::intrusive_ptr; +private: + friend class e::intrusive_ptr; - private: - void inc() { __sync_add_and_fetch(&m_ref, 1); } - void dec() { if (__sync_sub_and_fetch(&m_ref, 1) == 0) delete this; } +private: + void inc() { __sync_add_and_fetch(&m_ref, 1); } + void dec() { if (__sync_sub_and_fetch(&m_ref, 1) == 0) delete this; } - private: - size_t m_ref; +private: + size_t m_ref; - private: - transfer_out_state(const transfer_out_state&); - transfer_out_state& operator = (const transfer_out_state&); +private: + transfer_out_state(const transfer_out_state &); + transfer_out_state &operator = (const transfer_out_state &); }; #endif // hyperdex_daemon_state_transfer_manager_transfer_out_state_h_ diff --git a/daemon/test/identifier_collector.cc b/daemon/test/identifier_collector.cc index db613b0bc..be5982572 100644 --- a/daemon/test/identifier_collector.cc +++ b/daemon/test/identifier_collector.cc @@ -40,50 +40,49 @@ using hyperdex::region_id; TEST(IdentifierCollector, Test) { - e::garbage_collector gc; - identifier_collector ic(&gc); - uint64_t id; - // adopt a region - region_id ri(1); - ic.adopt(&ri, 1); - // first try, nothing collected - id = ic.lower_bound(ri); - ASSERT_EQ(id, 1U); - // collect one - ic.collect(ri, 1); - id = ic.lower_bound(ri); - ASSERT_EQ(id, 2U); - // collect three - ic.collect(ri, 3); - id = ic.lower_bound(ri); - ASSERT_EQ(id, 2U); - // collect three again - ic.collect(ri, 3); - id = ic.lower_bound(ri); - ASSERT_EQ(id, 2U); - // collect two - ic.collect(ri, 2); - id = ic.lower_bound(ri); - ASSERT_EQ(id, 4U); - // resize - region_id ris[2]; - ris[0] = region_id(2); - ris[1] = region_id(1); - ic.adopt(ris, 2); - // check lower bound - id = ic.lower_bound(ri); - ASSERT_EQ(id, 4U); - // bump! - ic.bump(ri, 9); - id = ic.lower_bound(ri); - ASSERT_EQ(id, 9U); - id = ic.lower_bound(ri); - ASSERT_EQ(id, 9U); - - for (uint64_t i = 9; i < 65536; ++i) - { - ic.collect(ri, i); - id = ic.lower_bound(ri); - ASSERT_EQ(id, i + 1); - } + e::garbage_collector gc; + identifier_collector ic(&gc); + uint64_t id; + // adopt a region + region_id ri(1); + ic.adopt(&ri, 1); + // first try, nothing collected + id = ic.lower_bound(ri); + ASSERT_EQ(id, 1U); + // collect one + ic.collect(ri, 1); + id = ic.lower_bound(ri); + ASSERT_EQ(id, 2U); + // collect three + ic.collect(ri, 3); + id = ic.lower_bound(ri); + ASSERT_EQ(id, 2U); + // collect three again + ic.collect(ri, 3); + id = ic.lower_bound(ri); + ASSERT_EQ(id, 2U); + // collect two + ic.collect(ri, 2); + id = ic.lower_bound(ri); + ASSERT_EQ(id, 4U); + // resize + region_id ris[2]; + ris[0] = region_id(2); + ris[1] = region_id(1); + ic.adopt(ris, 2); + // check lower bound + id = ic.lower_bound(ri); + ASSERT_EQ(id, 4U); + // bump! + ic.bump(ri, 9); + id = ic.lower_bound(ri); + ASSERT_EQ(id, 9U); + id = ic.lower_bound(ri); + ASSERT_EQ(id, 9U); + for (uint64_t i = 9; i < 65536; ++i) + { + ic.collect(ri, i); + id = ic.lower_bound(ri); + ASSERT_EQ(id, i + 1); + } } diff --git a/daemon/test/identifier_generator.cc b/daemon/test/identifier_generator.cc index 076a16242..74ba5c0e2 100644 --- a/daemon/test/identifier_generator.cc +++ b/daemon/test/identifier_generator.cc @@ -40,30 +40,30 @@ using hyperdex::region_id; TEST(IdentifierGenerator, Test) { - identifier_generator ig; - uint64_t id; - // adopt a region - region_id ri(1); - ig.adopt(&ri, 1); - // try again - id = ig.generate_id(ri); - ASSERT_EQ(id, 1U); - id = ig.generate_id(ri); - ASSERT_EQ(id, 2U); - id = ig.generate_id(ri); - ASSERT_EQ(id, 3U); - // resize - region_id ris[2]; - ris[0] = region_id(2); - ris[1] = region_id(1); - ig.adopt(ris, 2); - // generate - id = ig.generate_id(ri); - ASSERT_EQ(id, 4U); - // bump! - bool did_it = ig.bump(ri, 8); - ASSERT_TRUE(did_it); - // generate - id = ig.generate_id(ri); - ASSERT_EQ(id, 9U); + identifier_generator ig; + uint64_t id; + // adopt a region + region_id ri(1); + ig.adopt(&ri, 1); + // try again + id = ig.generate_id(ri); + ASSERT_EQ(id, 1U); + id = ig.generate_id(ri); + ASSERT_EQ(id, 2U); + id = ig.generate_id(ri); + ASSERT_EQ(id, 3U); + // resize + region_id ris[2]; + ris[0] = region_id(2); + ris[1] = region_id(1); + ig.adopt(ris, 2); + // generate + id = ig.generate_id(ri); + ASSERT_EQ(id, 4U); + // bump! + bool did_it = ig.bump(ri, 8); + ASSERT_TRUE(did_it); + // generate + id = ig.generate_id(ri); + ASSERT_EQ(id, 9U); } diff --git a/doc/2013-06-28-cloudphysics.pdf b/doc/2013-06-28-cloudphysics.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ddc437159c36ba38fcef6f560d38564d4a89794a GIT binary patch literal 1722299 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�m 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

|2;L%Ud&p=E9U|v;IuC%*p56gJ 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

  • gnz0C)ThK{qcE&qtyfB;3mC9_S~FkISy1=+-O67 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∋EaOfRX<}Rh9XYSMQ~u7wMV# z<>BYg(o(eVJ&$R$4sN{_4++AuaFEQuKwV+5wbq3dB;RBW`fG8nsh{lS6 zwc5d6a0}i3*znW1Q>t0#Nf4%+z*Z(2u@B$QkwlJhsE(U$bz{8-k{m?u=tS>OKRC?< zWnR?lAoB$wpi1P0=NjzC$p;HV8w?ehoE~7$z3C!&;5wSPngD

    y@}xVYlUf$l)&h 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%0A3dp*uS45PpJyWAxa?f32;C}nq;LT_| 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 z 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 z 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

    G!^H=lU?(_moDILv+;vLw8JJl|Qr`w- zEs@|eX9BD@!|PvUyn>U7;d&^H9_8)GW9;!Yo`JC9c*70};tVUwfMNQM`Q`&F9-~9< z(Nb0Kx3;KD!Kpf8&ZjhsKnZy-Lu z$$16Tib5d>D4$!_iTh^9Px(QGXe2W&&|`0>)|x`X1%$icdDoam4i!4O@jjf9G(x}~ zH8k((lbIKP5VAutle zodQ)FwjAvnTKHu?&)E)jHAUz^LhBybS74_-H7uA%*8}rR@ zAYOO=N=cOLl5WAITR{c1u@aRSE;wQT6zEhU9D~jbZ501b!Wt&-OoOEiI$;du5wYvi zTfDKmE32^Sp z`AQ7h4W-}_WJRsu80(FoYG{wD^|Rvd);Cf z2>0A5*ThRpi7U4|IN?%g+XnPqTu0qJO$_ELZQwDSazl9aPPUPDr`WEO> zbISk@9Pk1$^cvmUOfe3C#YGZ=%sDy>9{U@>wDE#si6A8t<6Gk4DH&6cY%YRTwxB|Z zIAKpYFjLysJ2X;7|9+hrM3 z{9fq?05N;GgPw7C=E2k?v zN5GDj2~61OsGRDOk~$L!+1*I$th!%CS^1Sse~UZQkCbYH-~PzD z0-EkOYQNw}zb+Jxe=v~hxj?EV>pD&pU9zQR|$#P2dq{*_G#zxBk z?vTuz#=xb+d7m{OyK_Hd=StDl{1f*g~kcM&u%w501RcS?_kWt5BuVmAo%pXtm zYGirOpJH$eLtZJYFGp%2Y`PyD`#y3wohES~84Ux-hha?%TH;Yms3wS-fRS$EeH{S4 zI&;`N7sozQ*}edX_Q$Jr-vFWLGT42)t357DHksjPbi}1W|;u?Oqz&L^ovjKQoLvjh~%0-tGKfdnVp_rIBfeB|`9m!Y&9^E(h zl%u@xP}d-aOrh*6#!*K3T-t7qR3xUQJ_HFXsi7F+mNAq8l1D{pW--*dhf3+DDIHKr zwN>s8)KwaFKi~<-inQii)i7RlAtPbiKb$$KhFXhtH)lo*Xm-@Bk*b8NH?hpgMO6%F zpM{d8!Dgbq1l6P+Uf1>R(T1VZn-W-GTd!1qrf+C4SL5`9$AnNVI*DB~{<^Pv*E%$; zJ#;rkzqLBLOUU4aGauaLxMj2`8aW@*3H(tgc}u9LN}&7DV>gQI3@R3~zL0e$a5#?M z-AL1fwpWl#_@SZH5Y#>WBdeh{M03I;+tA?S<4UTqkIQ`70F+i2)Pr{@Z+9Su-tg7# zh)1}Ar9vAP0V~eq$thGhR1oxm-9SJpki8t8TN+Z)aGfR;>*lxlW}aOQmB_c&i|$3? z%zAcM8jVjL6VjvKy55*$b}xsF?M;PN?>vJHSW-hUP$yG&)MwcR&e$syzxUL%QZqg1Ii-b46lb-w66pb373Hg){sPHtQBQAvlW~QCzvT z-1PSI?tKD}y5>`|Dlr`*1;9~A{`RhXzJ7i<$Cy>j( znQ9dNDkcq1Y3{xUXqN!|2F#jnZ=|y`yU|;=kh>6h)SM92fLp{gRGFHrgT|O~d=;P* zf|&TeF&Oji&2|am_?82nJLtCRxF6iHp7s`V6w(tOIlKq4eq4fx z50S8M0#(qO;89;JepxB4!l2V~X((DIXY`3ewczZC zks4+>(-<}6ijIG&I6+o#liaOg1a^;vmvt2sS`UeH3((lR^i=NSrAE0bTUom`Z>qBa z@wKY0FxEtOZ+#}KvrscnicU1mi+vg{K}vX58VY5MZc``;XDxzD->JyMO`ql^qpx$6 zy)Ggg<%*4-JfDIj9n1#Q&zTE3yDyyQ(nH=*<5JlXdhyY-=}Irx^4nAMZ!L1jfk#F! zDLcPz6vb-}hydQi@YVUr!Pe4R;)MaH0H>hZ#R7VpC2}}xiDd<~4rx7$Qd*t{pXi)e z(@JR20OJ$YgKJ{iSG_3qi|Y65@LWRgT~CQQpx&UL$a;T@lbOkc1lvRf?o-ST8i26MB6VD*E>RI&1BTaz%oX12w6BQOEGk?0(ABh6cCcX~Q zxdV&oVq_XGwIZzjwvi^zM@j^o!JY>VtB!!y%@vGXHkiguEkXu%3mtMZma>v7w7jdGGuJ72jJQ`v=J=s~B^+gz$4`1c8A*V_&V| z78NCIzT)Uwj#G+Zb=cF)SGy1e2Xmf5+sm_KcG1HVELEuOPUdWvH_{%-j0G9a@tBzt zQKJ~O9Xo8HdKNCe zprwBkqX<8fySUK@li>sbf}4g54;-jC0&8#>l)OlA*w_D!Ve>0@^`4#1;J;gHwRy)? z+k}lcPY8lYoMy#FUXkrEi-V#B&VU0}Fl72BEhwSqt(2qgmd%!Hl-x8)k!b+RAh|1w zDg^d;#+;vDHYL~wp9qsfsXGEsmQb`cc%KF^AR@!=3}8$JETUa7S7oy~1SYGb#V0`l zMbHS@bJHP`6vGLU;yJam1u&WqK?4E`IF#eEir$;LA*j@XBCj6$@te(?BUDhECP6*^%H2{9e_$MSlY{v06$GyaU=9~`{Ci4_P>-h!zADwJsQA9~_*SJ1C*zIk-hdC@1 z*e!>TNHy(KcLI`0OdYQ}45ckJ`i#x{zG==4TsGd2!i*Bch&gDe(16_1kOLi(eb}82 z83r&TPRSb^-6)ra!wPo6OYtiXc0h6B+_q>aYBXbz{LIHMz&TOf;yB`f z7@lb}71vk-4M>$aiV?X>+2mdDpAm!Zg_E)*;h+<^WhTrT}_((!;(QBF*=PcbuVN+x|iBrW>k}MAmK+iVA0_xFc8nc z*{mE<|AS5m)iqCjYKFmGG~J%HRY@I_GV70Dl=@Hg>j=6gmGb*q(LuIgwjA36&KLOo z$I%@f$w0*WoE<({K!wPCD50~U>AZg0n06AQ_@t%L9*zrr`v5gib9pFck4+VD4q|S@ z&l94`ZF><9!5+#SbAcuJLEgWZqX&D+=SyYn-dEke=za@3?XqTi*G$O>XlWv=f=505 zu2zv|PvtZOpBmw&p`@pS@uE#TV{b^Gy6xLNC(4Hl4{n@lafZHdy}9M6ICO5_y{f?n zPqyultk52n6@(`WSV*O1Ezno|eCkShi?s4J0UWM(XK<@GQR}0?J7so&Lcs|Wj1fS? zo%FVfNwR3Q5boPKx9B^!(rBY9>_`P0B76H$Pp<3dnyQ^|LNf#F5+xrq3L5x^MtI5r zK}!YPfHBnvq^uNI%v-H*o@w4sIW(%z*V^A?RyU@3x@aF?en7;&K8RMT$qvJh4r!Q= zCklqZZ^%Z}vzINKtE3f<>3K6BMt{~>iQ0#NafK5~)M1`dbsRdQ2rBEgP8xSacx9JG z%T`m023O<$0Ep*_!+N1ZAg{xkf4bG7$Wr(&jT=u@&Fw2(N%6M`fuW2jC^2Ui6d+zG zGkI$5Iwsf}O>>zWFf^vO<}!E-k(x_;6(i=$ryYCdT3d-qA0Xl;12qJAaRHY-cn|eiH4j81!kI)p$=zDmh+_ttvGe)-TsKs|<4nctqiyHgWHH7L+{}5LzeonH@zbFX1h|Z^|GbVV^!@gkVzu zSXVm)jMM`Zh_IknpnRE-cy9a;;SHAmOe{>q-;eQUZWNo)uY@cwpDNvaOm)OqG~LXc;?v4O_1*~8Vh@!ND1w9Hv_U>7Y9r_1 z17v1Kz{7GO9yf2-qTJh>>isjFjfajm!L8L`}Mc&eECu)a79+otgxWDP=~f-VOtUJ ztP(J}un5C?D|oVX0|tDAmC5a0)lhu6Pvw#0Q_7Z-Fs@3ntzOCV7J^KGU+?)O#)DCA zy6qYxkPOVWhbYfc8kIO_i9$rQQCqxRDK((Pi1uLHg!AbAsbc)VrlEBIUV_`>0(qI| z&TSpuQE6@Z5cfb~#+AvdckZ92{c!i*&XK%2QA}!onl8Euk)16aqc?zfHKeZ+If*Tl z%7&M*lW9ORCqum?4pO6jG(+-@lc2~2YCfUCUg`a-j%w{PfVmJ=hGl0-zB!@xUr>?DHG<~8!n zGp7xnxNDya4;&CdDTd0E!C^C~mKSyoZ-Hrs+?Bye@w$DCi`P*W6=euWZV8=^@=Mnv zm*U4`-~nw8#PT#WVe$Ur8C>`}5n~zEjIzTMlW1_T-HJJWe7mg;Nbd*M&?nD@RGe59a!0UzsKb`mMXQEkW(*GPudz=fLP&-{3397J+(&@1JGNGh60 zKgfU@;K32g6jOObc_0l;_^M8p`bN;#>2%fhgcXTbr0B&*v z4_khG+vtQzVw;jGCc|a6r3yS(u7R79+?Rx_G?$+r!BJ8cGLi;{rT=*n5R~J%pD-U& zfv^)xoJR>vjJ7g%Ekvn>v-e2Jk}5B}kFuy3368<@eRgC@4vhr31r?{jz7if)H_kSm zj_1&H3F27_D|C@KX%$M(fxfDe8x@03F;4obXW4KoB3B^UknEA|+xvcwIx!P70g|4I zeM$a);20%dHMH7qWC@iDZk+;mR&(_MDmpPXlOtbK+fB$wkFFem2o_(dv$54ub^2E3 z7GCx#WALKuxi#8Rz2hr(wpyv@tfkOidGtQnn(hqyW@Am=NP{%mTHGcDxs1DsBFB3@;LW$vxH|BW1-p8{?wqVw7P4E~J=%F5wFXD8 zb!~1eGG-duXWxK@(zvihnT%eOf+DN3d%wwd8fg zdM47bx}T5Ppnu}v;Idqlaj{&=VdRZQwJ{jAZ=qKReeA!_=DUiwdUgc3W4lfd5}~l& zg=mA+qEQM0u#Bex2a>+ZH)xYfijz;hGsw}be&SGqJNxQ45=ZTbJ{EXlYqK^Hc;FQE zj!Zue7<5TJry_5!SA}@g9TAF#ywxOuJBdpr=TNzR4|ChOP3poH_g!68DG#pbnB2jp zE)b?-NlHAQn$Q?fKp57eJx5vDMZa%AGCKiH3Rjtp&-=9wGguL@DrZrFu{N$UU+VeT zlvJOBa9By;plywKcZrs~D`P5{x88H?+Tg*lDu5`XN%F4?{#7==9 zGC>rYa;y^BD0ILfnerWGqxl~eRV*cw8boe3-?gYe$+WcO;mBpso$}$Wt_Bc}?=8C2 z;h4m&W+Ecz)eA-DpGOs$lD>6@W}(pZEiM>kg?sn;7}@-JazQ(YNZbbXSP|e}oYEv` z`D$61Ey4V4f{Gp@Z$mNz?9G0fxm?%Y`Q*{f3P~zxbrIdfd1M7X2npWs4bK^s%CL-Z zogjBC?6AjIORll8H7b7*+B@4iwMKRMi%dQ#7C3FQ7Odr3?PVj}$|_G;WF(CnKXb)i zmn9`+K#4^H;?Ct|r7wY?Z?*6GVsjf#%0%32U?QZ?WnthFxd>a=vJ9$_`zg+1hx|Gl z@`P!X=gt&>Tu_oFr2;kI((?E;eN;Z8%qwWDO`&47`||ZbHMwF}oHJi{&LYc;!o3C>~Sn!_fx$LBb#~NuzO28%P?g&+fjE#_ppkgen@Wb|Ki0z0dYmb44 z9v+8_v8@!pF?7v9n}&2Lx1U#2=DcOVO;_eFusD}$PeAh~+WMvpa4;rQq{uF?c6H3l z`9bwzby+x@m6J-{F=fvN!I4fgL&;9wgt>XOq}1u#EPGQ?K2Q+OIWaM-HP^j~P?zIS zSZLu=lU{4EzI6f?TdKKggwJL?V$yR9oKw6EIaZz@tjZT}Wg3u39U8`Ap&2FzJ{?u|T$;C!A2dE>3SqG)R73T%k~LIAB~~TBewrO& zb?gik_x^2IkmYlcb8;SKVDYfQ;Ks6{YSY1^{(O_iXtnH(LBcfD;zQ zI0r^wf|92gD=+~EpqfM7;Fiw!7#+>s{Zi{W3S~<(k=-#&g%25f!bVb;sK z5JNxrgm3Jr^X{c-$zsPR$-R<=fB&J=+`|^rpGBRX3RFR)xqba8_DblI{c|CU99~Ya>PK;T z154Bw!ZlTb{&6)=J&n+7maizzNVF?iqJZEfrl3gUX+4woL*dxEjx4!TTCCEU*V z**q^{-|QaZxgXcT;f1(zMG6HU40ZHiuf88+skn*lJi;uT4eZm z`*hXwaaiUd;>q>ON#GrSixgqau98lxj@L!P6^;|x&0@Ch^FR|XrOWoWT0Ade1wHiz zAfBD8E4cTbsHH$gG0c;cR3lFt-PNee>NijdibyBHvQ%B-<|t+jbFa- z^&&sNidWJ1i+pTSC@#GTieAMN_Vhx(d(zwLJ$U`_chCH_aaDRpcOHohHQvK8Pa#-% z>LL~&)uHRT4J6|kYIGU}RX=x7hW|m1xADD<)wRWWj$ZTG!Jahlgp^K`A6e@L#N43E zdM*t;MpN%IJuZu$oiBR)!y3ntY84qWl(r0O76GLDv>0S`^_f&CFqc3T9Y&{0Mx_8mc@1|Yv-|Imbf9fUccJq|$ z`iu^F>_ag!%I*GKU+bKH{X&~^{eqjVb0*~Pl}(HPh_!tEMB;ao0KKBa;Oy1E_S$F- zq{VQ5FGe`3zI^Ug;Z*3Q9Vi3l-J?$GJl%!9YFIw}lsnoxiu=d|_27Ye{qXkiMs3c^ z!$j{zx85-5EDb$=q&jnA%MrCA;YomTQ}c7k2Z1ZVZ@&Cb=eFLvqmk>+H|+G+tJ?*w z-ObCT%*zGd%k$aeu^AiV7HOdid zp3w$hg&BDfx>`%ORM)Y7qPAP8&R~VEA2r&AZpK=@A*Q=xCKGN<_ZXp>uj<5Gghl5EW~^Lk@vgM4g0!~X^L zPscmn=W5&D-S247cN{+{+dAOdT$EXX_5(!YB4jr6)Tc@%6G}4h9;mTjvNEW5D;g@0 zPc5UWLbYrSwOhm@aHsGIlTpq%ugh};rpFu zhyiTtWP!VD$HVsQy5s=JYc{i)Pz_@3z5f-JPFEb5E6oC#@jq^t-8( zi;@SS%aXu!ceMlT)gOc&*QYQz5UzcUFCu`1f!vZ`2s;+dtzW|Z+h$d9#Rb%3;?b9_ z5+2$wrqFOB9T519Fd~6i(zE;a4mBmoViX*nHaK-M^$#ZMgcJ zEa2n=6xqHgeth~x+S8$X`?Z}5SIO#!Ik-6NsEmCyG=kjEWYo|)tcZ4JoqQ{zI?o@dn=zbW0Af0Rb7`ZW^K$BilFeZ7(&(1C z4LWH7d(Dtyv?Hl46-<6Mgn%PjIn6dpKa`M3Wvj^)cg`TwEvWTob^U2Ia%sT)4)D1^ zZRwXe@SQ9D+c`kb{<<~gFOlfKRY&2!Uk>~*^sIk6u76Adt*Cy>S7j}9Qs|3fLu^IZ z7%V~O{}v5Py61`LQ%@iu9$tHERBM?>%E`@WE7eDw8jYf|NGgk6$W=G`_8s`p9T=J@ z)1`KlevGV45kD*R@Qi4}A|Bg!3cb=e1NH<)(k)Y5J%lKOAR z6>usNCk#uFW>lT5KEHoYhH;`Mr)>#~4gaxT6W1bQ+SJU?IW5PS%9&XPRZXaBg17|S zC1{gq`z!{K_k{PJGVdIY;hPZSFZ=d8KKu9j_CHc1t~=PfpzfF+Z&nkdeDN53 zNa!{c=QIlTK)7ui1BmxxeW^^djmEGcME0xBW&PWM`{!)^x)JRUruggO`VUk5KaAeL z-MRPg5dE)v`#%ZMv;FOO{7)jrpzY%@-uTd)t`&te_F`fUqcQL()OZUj$&gI1>87>2*Kwi=<~ce1YVFf>YL(t!UMjT z)g)KH;GJhez9V1r30Mg(uiGv-1&5X95zPz|aKjqcC#9Djf7{YvTC=>8D+ z-zhyC-Jew@X#a61aW=X?_Idw7>DlQ1Sj>JgD?W`HX*A*QpMwTK z2jXElPv(*FMPdmAZ8T-rLMqCjdX&i3&y;b!9G*7wI$b}{%|95JoJ6Mn(a<^T9ciih zQa1yUJ$HX!pDuCd^2895bnD_uT^67_A7*gE>iK-Resa><)cSJ%{5<&ZK>J7IpylP9 zmLPCsQx8GxMIU!oL{ih;vpinsYaSj_psuisyL{6wnow~_<{EC|#^X}wZn|684gJeY z2mQ+l{XI%L|1InNWqa$mI^eE%H#hs zTB%pKDVJBcc&%5nPu@H{OJChDQ@;21xH(SqzL&c{<-7lKNHEOD<8`@s_9b_7vD838 zW5mlroh+5G@O4FS)Vju;@E+~!?dn`WH8m{jlsy9?1Wc+_PMa9I_;4Ni(>}>tSBdM12ECmu;XR4u9cT}Huk5U%TK0s}N!8<*R^fA#QGkxK27>OA z`5tRe*;i-M1$L@5yWCv`l?Jv`v=N!@7AJtV?b!)=`>rcI8v(kq)>{avQ*v$>&~qzX z=d04Q`Q_9hP))B?+M;JFn70U0%|lGhw`+s+Shj6X6*D);Yd*Uv#&SU9S#oXevBo#l z_9s(~LpKOojGPxz)HWfvC!l-)7=lwpxT|9>4KM^Hjr%HCOzdrNrUYeI2F1lvG>cwh zjJo-vZKz+kTn6oH2X5AfCPN4^hK-EL-Fit99MH8po#yJ50s!mxLp|PrH$8_p(M|JR zi|BpS2K;v=^Fo#jn3y()^|VJWcrzB23+TA|#*Iz8^69%TC)3q4ZcAtnU7V&DowiQj z$=&iE*6Ro#ngjY0s)xQ?JII<~=vr;zz`+V#HB(YDO{ zqkBZOTEU}V&{E%#m7j##A8@~)z}nvjqGxCLPV#(*2Y=7l{4a*+zk^EubsqRTLGJ&o@%MUGUgw1T0NC1jxgHvhN1gX62w#sn=c zWSUX3KN|=wR5@HH?$1 zur{r`(|sBPh5zXi1oS;3xM-^`P1dWqix? z*o{>M{MP8n)qW1okK$lTl-gpb*j2#!3YVPG8_WEZRE|bq?v$~|nDQWN3zr7blN zU)bKljLXBu$wMlu5_7h?@2SFs7nZf<=S35D;Ud&PTOv+j#Om=vp807C6a=gJsL3qs2%;Ftjc%kH9F|V7(sQF2ZFdPiS#kzsl`9MP%K-+;+W7G|7E4*ph@f*tW}= zcTCX1iyy&xHiI;dU4v>NLyDv50QT|2j7Es$wYiNP3wZ%YVpC%NhCI*9kvk3!3pIg_ z@^*?lYeH{wHM-PZ_wsmYylS05C!#Tg9CuP@h8V^uV{e;M$Hlz_Co|c^`zL&>lZpa1 zM`U2lCiBb@eBs+j_8^U~wVE&2Tkieo05hoRx-T!!_mASwo;%RHb0wuE*FLp0_1sUe znhe`i`e0pm^TpG}@pJY32i5U%KbFB9t&wG=1ZCCd?mH`tmk=sKLuS%p#vE<27+ec`1i<3`XSI}hP!*bbyn@vNNKLbq6eWu@^(oR-6}qbrnV z%i(T%LpXQteOmUV7ltS8S|4dQGwmotJf}~-Y-f2gx|jB=H<()3lbWmJ;+BVtolLJ^ zeh$zcoZaqn<06m~BcSITAEYBX1Uh^YexDrL-6JOF8ks#)F{nQ`m$&L=MOS-R3-)xt zsl4Hi6-0Pi=|*4R&EgbWsWgbnZDSK4GlC>RAwr#A%%NWJ3)jP$70K~lZfJ}X@}}%Xi_vGrHiS>3u2z@sVgcMsP*Bz+d!;^N?C!$@{?*wPxuy0$KnU{nx@_r8N?KhR&@8{ z_0BjCq&c|mz)x0`1r9y4pYxtTyL3pFOv1Ka*Dp#jp$nUtNC#Mu)l!@+Oq2u8 zkE9TTZZ{1tb{lji1$xWRhZN`=GW^Rt@jB&|AUgI!@jA~OZJ)YnZg!?}wMT>d-N%A2 zx#Mt2-Hctc1vv+lp^@{qs`v ze8?DbbT_+5X?k*OPlrON`;7mQ7mb6}98Vwk1 zI}?^+o-R)Af6LYvEd4Tb!dQbNPPmgJu3pyA0D&u7>D?ZN162r2g#-&nk_$;TW1YKr zzVtSRT6B=L62~G>cJ!(K@HCjXBxzB;N8zh%&JD1J*{J87j2bfJhIqC`3#xb&hrtMY z=T1m%Mrh&ts40ZVYdj8{ zyJWIE5`I^yuZz#uZ(i(uh1u?vnkCL@9l0XTX*HJEybC7r`SMyek|dK&E;8#bNo%tB z$;0D^jCG7KFEiwU?(h!d%NlI9G z*e6URBo&7Z4ipL-3SlGZ*M(GFkz#TXjf zw?UXTy#bIEje^A5yi1Q=xEe_LfahTX2dSMT3(TAPT)BXs2i^Kd| zoS*-K`TJ3@{B8>q2P4DJqhS6X`1Wbm-{LSbF)*<){n*2gz_&PTzs31^04(43;K2Ui z3u5{qSo`K2VrTjxfpU20yFYCE?jz#m{a5D@(+@e(H|G%ZKiowB;v8cB(cAy-9Af_7 zm8Sdd9Af@C81nTne{&A8e`~&5IvUv%(urE?IT{HY8Q2&aeLdty=g?D?#=9!(iyoXu z=g^~b=+Qa!=p1@<4m~=D9-Tvv&Y?%=(4%wc(K+^5tPuD_yhlr#t ze6cro^2e*U>1!8nq8AAyy}T(dzXu3@+x%Nx*MDsOr?~$V_~i#5cJlqd+^c-u36@)~ zs?H(e(-ywan>+gB>yF-t$%oZHz4KdOSLZ};jers(Bh08mDe(F7Ni;RltG1hd@YEZ$ zfh8hL`|?RWfrAV$=h4);z3DZnj+d*GBPm{4NzJa1a$a4?WeF$kGLVsS@yB(RA($ju z&F>@Ijz&Rku1-m|?7X++lQEfPeRujYhFPd4apE`A@R~2!h8GsO-MvrtZU-yB2dS`qfO%Ip=l5ZT&z;^mFkc&ptdNMg4ZBXyW8#Eb`PiV-rQopy)e;TNb_~`hS>NX z@R~Q#y(8`XRL)IJysh(b^(sCnWSDN^xbWoXqMTA`N#Z5*a3j^95s8Vv8JK)B_ z<_qusy$<{SJ&$P1N(j`ws184Xt$zPn3gVCsyRpUa=q|eLA>a+K!wC2sEu30izkYAH z|NOoYE)5PStXlf0AcPe18eCM_b32jGcueoei1p*D3`S$2Ol)PC1y--ocu!$6&4 zA(Y*>OKnJZ{l>Vvjv4jv^$zG5_^Ye+RiNQCf{xom2mQU40VVIuOdan`2UYJRB?a%y z6N!61Zn)Ek2%Wo=!~5;DyG_2k+tth59=iJm-n-MAYbQ?gXEQdk1D*bc%z!*WGj5WQbdfQz@+>vtny%-iZC_wtH*4k-(3vg1 zWRp&b4de+@;_)5sh=_|l!`M7N!;#W19gMo>MDhOMbvBfAl-Yjw2rrBQ`HEAtS`Pmb%4nLsPD&+2bx9{L8K{dec~ zZ)6@~`TtUjeLc5-H}eq7SI+R~$^EJSU}yQkEdD2Ga2|9ljO?txFOUBwC(B=D9%A_l zbN)+`v;GIko|qWFCi!0?d-`k4LoC1aYq9<($)3Iv$gF>X?CCEv4}FvKJ!JE5Otpmd z1Eg$g^OaF1G}g0pFd~GZ`$JPv$w}YQ&DQ9FWVW$?uoHb~-9XEG=zZ{ya_3_Jgi|r0E47Ap5_brf2+#(?7iU zim-p<>Dhi1zwbOf+xNUp_noI_`>s3q6;IFh1H=Eu)3bf2@E_v+3s2AX9m#(n=)cxh zY(K7O-+6lWpO=fT2lE?G&-RcKzq;f-#QH}of8TSqgr>o6-rc+F2Dr52dYy+K2oyMD zjiJ|{9@XvX+u3kx(7w&wZY+_C$r+7vWDhu@-T*=~%ooGftZGFHnFYOftLVH}P;NOr z5%++e7WbRu>mxt|pH_KQ#FN>lUFXQ|-X7kajJ%4W6VZHva%2|~7(1D95mAH_5vnVh z;Sn4J!*Aw^POj8>?F%E2dDSa)yw?~BnlvP>LkjtlDd86_crPVjjoHg3#L|C(RjOIw}KV3>)&)n3{aO&~0gOBO)$TCc+84$hC zt9;AOYcKA62}i(S!WwE^OS%5Y)1#|PuVxCr4Yqvb=^uIeN1pzXr+?(>A9?ymp8k=i zf8^;OdHP45{*kADA9?ymp8k=if8^;OdHP45 z{*kADA9?ymp8k=if8^;OdHP45{y&1JXNI?i zy}DNFyVhN50Vwqy(vh^ZMBdy99$&-uMOoG31f38Mvmv$~#UC7n6jJth;NemtQZkUdk%T<*1)e0W> z<)vt=_7E%^9zU;I|7Hb^cBJE_pCCj>1bpN6Xw3Vbuyi3i?N99B1>_;TlX;pJs;S=2 zfCU0BckjKu+w#hbo}nLsQhW!Lq%s@(Wx( z@2jJW3!Q~UZ#VDz_1oKo?}1CFMeoZ5B%#eOWr11V3=z9e$!K|7R0m2YMkAnw=rg%_ zDHl#ch$lMbZ4ssIybhL6hMT&s-`;yKzrDY}x(${iy216lT3XzyIh4a{l*dHdNhk&3_V&6vZy8o7 zzo(VE4IA>f4MWhqwF(z{cqY5OKSKM&$Ln=D+;X4meU)|(xQN(H!*97cyaJ4#98Q+! z6`Qtj(4fjiDhsJ~^&Zn$6FXyeoX#lSsK&h_Ot1-)Scb?u!k@%cM_6&>{u|-jFLL+%#(t_HpiB;@iSNvxAY97&G z^1z^$H@E#I**JSqyi==~(ks-|2H@)& zc&^*Ys{>oPO<-C+Im`+4!Vs@Fq&l0}i(bdZSa2VfknDf^#*KCek}aK;^& z*D#We+X>K0uQt6_j-6eAT9$&=^r!%d>)|PeJz9U;Ik?lB$712^kTTTydAd_l5=|%5 zBV@agAI72hy5XkNnXc18OH>w==v}wzPOcYUHsS^5GUwH3*$a=GWADvXzMGC!7q7mB zgO$Tz!*~Wl@5uuq*29pHS{E%$Km)>lwc24YJOk6hf>Yinr>0$bnh~!T2^S6ZdxxBk zS08h|(p={0GF(`0)&|r!0X3G-7E~^vo{KPhK)pt=r>2e)FhiwUdD}Q8rM;r0lWi22 zqO-JVK~Cy&rbQ%T;A)E@3N&rS&NydVFPoNG=`=4bIr7DSH_NkszBW}EXM6beoCt7A zCJ(rWv^o>~@+*@58?y3~4EzHg^^?u~IyL667!|rd@KfK>rU%mSf5c3oUpX6jJ;w(K z%=#M-X3O@#7pS3kR#}8WZmsR#3s`x+D;J+te|3q#6CuVQ{ zHg7ZCw>g}@*SP;&Cx0X9IeuRr|A&+G9AB?)|C;1Kz|a4LB>zUzbNt>Y^KVP?zlNme z_^K)RW0G^wf9Gj`-7xtdmdhWe>SpAi|Gnem-<0Hk9ZCN~81Yw-^u}iPMt_={=b-;V zQUAuxGtxgy_Rhh~!uZusz(UJJ&qmM0rUmo=kfi_5v(WQCJbt6NSsB=W-9Ubb^p6In zXM#)#NgaH^g&RyUq-hvMP_!!?L7S`3Y?AiJkGH;;eg&-c{bg))T$QIn5KsN~_)=9e zFFBg3X0DI$v*Y+$5*F{L`!8Bj7c4AtL)8r2FBO`@w0owz_QvWmLlxXZ_2(@<>K9%G zekM05K34Xa9B<-wR>AX3K(97avl&09zT$MVDlTDFBgj3k>$k)2zEB&Ss@{P?Fl%~A z7sK?XT=lS{2`OrLNxpDYwp{J{0PKUgO;QoHss|L?O9kFlVIqFUg*drGY_B-)`xis^ zSNjSSoi@cF=xL`1$)6+uhK)k<>=%bxo2QH~tb*;!BMIl3dQDh#ag9!vOcwUm?j{uTIGG+NZfM$9A=YDuIDN*>)&a70nYe$ZCm+9WsK#+Enl8y9 zEMZN34N0gfd4lLbV7O~fvEC80*&Fc`_t#1&YQlNKx_o(MKwU3XQ$n@uP>#@pal@+O z0)qp5{IdMt0Bh?!^WS5l#EETn-;Y-&3j=oPZccW?o&r?{r-YJHiuJ0I(i4X0P}rCC z1DCBCZQ`YGM7#5e1Ic^KirP=xGd5x>|B5g3qj&<0$h&j5ZM=-(gbaL=sD5>x5hq=g zw9Zd7_#o%`24)>lX$NOkRFC4Oh$fkK=Qi*HEjs>TS|;a?HW)Sl3vBz zMS-=!Eg32xuUF46>|y7yeLL6?0t0c+l@jJeOH0^mO}6T+AQ;{}`l0lUawo^ZSZmUl z9++~)a5J{2e9X8VTd|X^Y%!jUlJg=VSv!v#Grlm$<^3I-J8?yl?w12PDU@sY5h5Ax z4vh(`On6m&k{LJ6olG>aQ#g*>C zr#@z@`G(3Knv}w}^sMYsn&-j`rC=Toc%y-w?_ZJ`bz@FlLA)=!=VvCz4D_?>r+(r5 zJkk#o&8yji<;XezDefd*Umk7qyRNiL0d^OiI$gnV=J9vy3G@tbIvlZf2V}eiefasF zDTS)YxXowJGt17B-M}I)2Uf>~%xd0zyfv!lwYfTBVdK8a2$zJ7GIYv#TI>a{({3hh zFpYIPUcsf@>7vu6L9~#i_l%Zfo=wzmLWdK4!%G8pnq}*>U==qyVf%0j=0HEvL#;R1 z>s;&Z-7=QNQv4F+kbg{1?{-M&+PSm?Ts5gl@Ewjx#f$U>)A%m|>&(t#nqj_V=?rX! zN1d>C<0}*WDrBst;`2L@=2kDsTOS71I8$IDJ6)jVYO_q%f#8qOhERHP^t6=-MCor8 zjV$W996UEJ(-r_0I~!mHCvlAz04$Bd+8 z$~b@H%rFKJ2A7Urhch^tTcE3|%^I&@C}76@l65xSuczS6BrwYXs&<#GT5FjQb-(Ba zdo!d>P?vXs+FOTeoafLjyM1w!2C=Z8N}ILJQ!18yBeVV<4Yl#@M1ahxJUmCNdiQ6UuwQu24af>gLfaU{!bS$(+SoGuHdB!RVUnR1WHTdM4kzrzGAo z=f@YZMb^Aoc81c2?h1w$Chg)!HDswLnA<~3c~UM61`6n^A1n_0(ju%4TNY9j3o5~W zIEfC(Y?`F!V@#EU_(Cd$EG{iz%UmZ01KWrE$mL>!QRdFeYr?vH}1V*b` zPZ%6}VUSVjo%v4Xt~~>r+eBi$dAm&vBIN8JFWzBoTaP~UX!bZT6=C2?Fp)@I z`F!%1O_*+*0cfZf=)gIefc9D|t;D&i0V^LRN)cRBv7PE<-f6+v1KxZ5?1bG|KzsRu z^tiWxRFT=>u4j?<0qO7^L-MIC3=BPFkRmm>rN^mht$M@ft20>gDCv3!m{;fufqH`O zXK%9eZw%_M`biF3Y{JG_L&1pJKHQa9*+6!X)skf$bU8_#cORx&Xc*NT^=aja%cpVc zy)o31Sn=8wp6(Tt*XB(h1&&xy?tq7urDT^fjCSK#pu?Qec2(kpeF{N>b%rrsnDxx+ zR<-C@!PEVuoT~^|^c>Pz(vDb3Oc$KXVzx`|$uQ@sAm7rAtbtCI2*pkzu`l-FAa<4w z+I4H6-Rg(JRU1p2V#r@*I>sN(^WSGWwuct)pU!kDQcAP*NX;kD9IH&sMdbKC#4V4@ zO2KCBr=Jp9B3m56PN%Oez6f87C6SMAhtsV39PV=Kxmbb^B@F~3#%0>2Z%|&&*6j}j z4;@MgNkWVigJcR_;w(GqS5rd|0;O*WX_YJ$UOD-Z8>%doBU~mrl7Vd~rWBCs?;+H{ zwt$WI8Egp(sWX7=f&b& z$}fuVEpEPmXXD{jUN0dnSlW5I9wo#hy@uY*is%F*W`dOl>9$(> zQWRBhB}_#Vr&(23K;}&J%ucO$f;Rl3c;DP2gcCg_q+ghPZ_l{k^R9jkoQcNkHV{)& z3f`Dy7XpL5Abl!-Y1WE z1Kcs8qMp;_>5R|FN-E4-7>=kW?#kRq-e|&KX8b|agjz3X5OycgW*zC&-yI@Exqpr;lc}cPKX~ByyO|($GP@|RGc31wd#P-1qHuS#+U%b=SQ43QvrgW^ zj@7^h9bRs>2Sq}^;`)Vn`r+4|gNtSSbJoWF99Zno7 zgJg=?1sBvjDXX6W1d`0h3G`}j3FjsjV(L*i8_3n0oXiMfoM?kCi!hCdU_s0-5mWHp z_KOPj5+TUIl6t_ywq9cH&4}`rKO=98D#}Vt>v#54OiT0H=}X+my09k)d##`k^l@}U zYjQ7K)GduC#-(f`CJJ611nonfk5K;{6J*c1*i#FvnFEoN7d?C>>Ml;dEHhun3m&?( z|5Rok3eul0Gs;p9qYq`~;>8vgqH2_3U&I21r~K>fPpnK&C?I6ss@5uFu^; zBKgVGuNk2kj1qe-2SJdmcd2runpvff48VE?ps4D|W=Hj_{=nQpX+nXfyA0{>qr7T) zAe{|L1;ID_hI)}Rt)w`yu)Cn03q}ha*1*uH$pAzr3PnBArwKb zW{PnAK;{l+39YOI_b8V@&@|en%jzp6qnj9OP$AUXtOVMrCC+SV9%UP&3Ek_zbL8XF zrQmK@wOkV;mZ98W7QmJT(}M5Bj7afnJhjr~hmQWRu8{S~NC{1^y^(Neqd(+og;w%| z&LY**^jl~_2)37SR`YekiR~YDXC)RdCQ!`^=3Frv7K+m~@X6wOO!p~#t!OBpsY6k1 z$Q_;bmdzW13I{TY>eYxytZf0x0=!&ioGRX|5{52OY1XmHwY@6x5OO?xadm#BltdlK zquw!u6&?czvZZ@iTpaPH;~K-0n4pZcGM%dmS$<3I6^PiJoLXWX0es5xnvwn7`WLp< zs%OQ&Dk4l@b!>kqBCHH7f4Yct#Y#EM&?EUAUZQi(FjW`jk~&zZzb};_Yh&W6;=z({ zWztnzHWu{qoD^q;k6^8Ox83!u@A{KhgSww_;QM9p=@>K;@Jl>ds1@jrM5#`+j#$!O z97h*B2VKXSP8ekA{A*Qq4}05dKAu`21Re``SrnohmtBv;Jss;iX}5P;ouH}21@xJU z@AnYQsDt>Wv)gAf zx4I$n*~KQZ|xdLVJpiGeRCKX|D3}U-_3xg031@4VieT6ai zo1t}7Co{6QJEu0lmxW={)Y&(1d3!J~CaN8{UfyV}iya($V{WUD1D0)g)$ zTv4IPibf01ca*|_=R8O4@twT5arkp1u`WJ&ZolB$F(7*9b2pJIIC0WwJy5SnBW>jo zQe>&1R;pB8f2ZDXqphEDqmY?)=_bk2ZDA42p= z@ak+<3$Vfiw!?R@pg z!8mNh583a)6npArf0c26da3`ZZfD~7(;0VAMap585UF|dg>4lXG6czKZ}Cv!VAfDa z>UR3RKzyKxfka8b=dDFdIFgzeX1o1&=NYf?RGSYqoRLA4d|IdR)hkuisrTi!1zKUD zLb+kY#RU8Ndqp5O!ZFNo@wNZs>^CfN)1V5n&Wxy54AjYTlTIxa8W` zZJgvg)Atb)r$1{0UFtsjVY99M33y2wFOP$5DCfqFDN#{%rx zDF73*4qw6E2kG-_$Ux?}Kim2WuOJLz_(}^Y>Q)%2wsB)JE6$vi@^0IRZ~67LvEz79 zBh}yW&%AFs)KP!>tiwosGVXgeh5TaiOoKnC(W9D9kXGqOCtmQYFcr`7~{mop&j` zUV*MWzZXpKisZb8c%BkUFn?pp=$mo2>s;(j4iV}XTA zP2fd$8Xvs&Hb3dqcI!i`WvLJk6H0P<^tjYIZ;|LEW^j=u^Mc~u+g8F*QXi2i&A>~& zmbAhx?1u|G&;G8=Gat>$f$UF}>#}9Md8J_ytPSyUoOckD_?m3LC^YO$zaMY@K6)>w zZ?5F{U}cphWT2=2+IO{gaC~^l%Jz?eS4M`1c>umW{`;=&zLu8F!`b$nES>6E^Ih}u zMiT|@vGxFEHq+Y#X<{4qr>YFMMjeUFYrnkUsm!vR4mY5z@EkXe6z9~0cQH0G846B< z&d&@Ngu!z{kwm6f%tL~vNS8hhsQN^!CaCh3f`tfjjp?{OYY7Tmk95I@SY8tJJxS3q zjFk$E1xtRJifY<$ne5c3YB$2P*-ug*bEYVgW9w+3bJ2*%Uol;3<_4T}3%qe??~0vm zJW|9F6aXt0FAX79kAotOY9zaE1Y^ts&B=Z%j^GcRq44r)?DKHWQ`QbB8hY8jlBb8j zDMR!?FJtt;;21CD7Nn<_fV^?C`*MIH)D6VdK7my(09j2)C_bSUI828ZdOl&17`OyY zR>8`jBokjH;<(|+OJnY*RY>$!40+@o({x4PP%={;dJ2aPlduV`1gsTuj{AB(OFEN{ z)9bB|T#25?Auw&x@U~U$3~KR6ct;3b;xO3JH36lDY@?J$fo!9x=nmC(DB-GaZ;|>U*j}k8<#I zKs@^*RkTQgRgo_!i(7;a45ckrg9trq=u>nyGjLG2zknw23XQJtC(#thP5YKqLK&fq zAOryus8JznaW{OU_vKMsnPe%HxrNTyi6241tYlTCf@MCMMMAi{`|qslb6S%Rp6=(K zsBZ~4O?f<#$yvdp5Qc{w_a#w%iA(Y_*61keSSJ4M@mgg-KgtY+|A&NZA~nRNNDxZF zl`wh#!xkNlqzt}+@B~PgGd-0niomwHBT4=6?vJ*LPndL%41pK`8EVpUn;cX$+7NVM z3GGtBAkaEKfiPK$zRYy3;NW@bK;CHYV?aEVeOzEj9D#Ev`MJTT@`3u$2-`s%m3=Z` zj#PowpAkY(LJ2?+XCdP)aY<6Azd}}FUlu`9&?ORj`Wa>bgyy*_V;O}mLn|?1pg=1> zJES!5IpJsYcY(rWvcS6xP@&*Lj2NJ|dYsm>yU7KN7OTS+X+j$`5Fa(ZE^t`%HVihm z1g^U!7J~z@Q@fLIAuC^wu`+$Jw{ndX<>$_p#^J1yn)iOT7%n_EL}x}@pp z(&043f;5xCZGBA}XO&WVT(w)<5&V>@%o_aXdHRwCzg_jO-yd#FiPq(_xwXkO^$8r`vsSFZqD;4EyFAA!^pKX2tlO33Cj zx=Cp>cPD6*&6qWs{+}d#Q#2E3wFG~;xKX64b2na)WoSX4=${z|h&VUe=|ndIwK%)$AR2Q;Vnl>K07lGkSVv znXGG{8L3HC#I5(sloe;6z*I#?GtTVLQE1U*1f91ct7OXo+tq3C9YOU8v)IM`Ds;W1Gdy5->{co~4A>dNMj=<5qt(%ZL%{qPDLcT7*pc^zB#b<8M zdgrGzI1mT!;FW|<>4-c-FN7(1{W=Z+`vy9sVeek%_5ryzZ|+f`C2JGbMp?&3l>kU-2n$_@?8^m!W0TF{Z1669H4OP<%em*+McxFgT)&UEEq&q@rL zzqw*uEp5}g$vkiu+^AHTN!3)k-V~4U zGJ-Ds$j?KGr=?;W>80P!-LU7`fcIU9W?6Pv?A2)38^jLy_0FA~i0!QFVzQCAW=-Xg z;1U$vkumAny^aJj=*f_#DpAJ^ZW2V5mYdVr``%|H=R29h!|>aI!3f)wM3UP0pJQYV z)$uoa(kYzW#3P^;u8!qLm*a?qX8>8Ruk`@SQVLDQbm|O^YDbPLqpTBE#ku>*_-3Cc zrSK+Cj2UnzPYwhq>-L>IIkB5eX@yfQR-Gge(LM_#NGg>Nj})mT(+O?uTQaAlMHrts z-at<{DaVYr^+^_^V!!K(-#m35m7qDB-5s=>xV7BUib*>V)a}hLH#X1WWjv4yV_Cyz zWXU+%s5CoP9w{6*$za=;J$-F-DjL2pnDJuZEaSqf4ljJcmFs2o;=8T!0q>IW@JyGE zEqDu28^E<_saWAtGQw-ys8u$o?NlT zb1CxL2NtIW3&rwxu<5@2B)@3SaD1Dr2o;p8if1jIP8wR6T3ZcvVEAO zJX-a#L!Dk98oUcEBN`+fnh{4v;{})OVLTx+gy5WBk=?+j`?OvQ5a+143PR}3JImIz z={wRBw*JZ@^t4JeWawC^@Cr&rLVB^-T%UKs(_mVVX~A)<%Gw`SnoFchgsA+|RN$Xd z+0s)d-!RsXu2MA)(w@H#8RifQ;HLsBHi$w)%cYP+BjHua9fi&WTh)adxZZ()ozor~ z5RB+Q*0}D}syY%vb!tHvn`-W4w^>I8cHE zkdbuBBY*}hOCl)%Q!$NVliGFmvDjUMpUOzFHc9?{nIIhf8M8BH-QmIle9W9TqJ5?e z7PORj%aiE|myH8+%j2AjT?5yZB9j?3Att;2N%`gXRWaov3nLa;>7BfV64RgjMqIzZ z$hotAqQw=?j#Si#OqJN!0st)X2O;rLkh!PAb-^GLWKYme9n%NP`lW`)j5t1AX=2Vw zpFee$+~?0_^@VWORvs8-Po3OCy#>mC*EMAJEWOuV1O)41*GCbP!r5>2qI&&lgg0<) zhEwk^bK5V56ImZ_hx@aQ&H}S&6m}%afvILPT#YP1=<}~8&@44ln zBCU{&r#hL>ywgz0t0*0xY2=2z(e#+}WcMECrFe%dSxuS5&$D;VxlK-N&mlYZm6Vw5)U-<@yU}=n-?K+nUIU87}LhuaSHndzV_7<%M8kjl3CJYWpuk^ z)M6o80T+5&D2K1dhhU7Q1>3BW#*nS_@2!#$ocdVu)0KV8UMgIeO@i$7D=;4(I?{Xf zAvCWATpM+&wIm+qA%jsx`$T_8Iv7q(KPxISi4G9X|G=$|!#o}UY81z9;*3>CG}g2% z`TVfyV-^`y_V_Aii_Bnm-SC7#47l`_PDoGQeq-({ALA8_Lr|I9xuM$Et}Q%wQWBP` zME$ZDlHDO`Tc@3TJS^Ti%b&GQJ8^NxlCA{2B9Bta1? z8oT#TJ{u-s1>&*NQVHH37FEg?vQ||s`+V4Q?dBS08a{!TPA0;=IPxX6>6^9T^^-Py z5-J~RfzZjcLEW&IvPaT13EM?4}Zm7B8BUq{5%_~}(_)<-FHQ-t3LTOPFvyoQus$AEsnD1y5S}2r# zwrhwa2Uee222=onFZ`Y^eP9e6Lt=YXiE&}!#uN1O7a{c(m`=CZ-bmUPe5DCSl}9D_ z8Detcez9smz(C%GP3KI8=ZHcouhl606*Rt=tYHwO0!G zX|Oa6o0Xr{FvK88-kSL1B3jO-)YTw|fFf^uxUTn4|L>CVcq;G^}U=S0vJYnxI@S@HMQ zOiO9BNSYVFLEzeq+@8ZM^VMP=+@Y7jq`CU2EwsO3CSLzS{<9G&Ou(LSrx8FNC$uvm zY#lG61xPH%Hvd;y>D$B}f6Piu|2NlL8Jn5!S!u8aE#hLdAqiA56Qv+eGEO)DO-{iR z)mE$W?G=@vjGK!RwIqHDW(mZmJ^GH1N$+yqx=n-Wah@!b$FoZ%-!2nlmB;$&gD6P& zenM08ClgEH5}~X4dcnOh(6W7Id&U>V_4R^lPe{4B-vHu`a-GnZW+qpexfW_BOd?Or z-cKg(+xkSI1ehtPg5e6SIls`2Ay}Wv7NDnRsg0>z7s_k0>FyiDG=xO-{?&VUs*(5X zB6bcSi7%(LOEJ4ByO*JkmEX`^x_X3xBVbe(FtaJ2(XgLmw@t1$=9vsR$!Ph%wO!&q zV+TU&3T~)!*TGH(P#rIQ>P?emydHJ58}e~VvJPctIa^jc*IR^)X{X(_4qR$XjN6?# zyzJ)d2umSB>Z|pwNsuT<3zzB#e_qXaUTpL6-8Qz7q9) zwsg`p5)7J3AaKt9`K_D6RSd2sQ{U`jM>`H~S39!3@;sKtwXHWtg@~{SpwR8ufPjak z=Hvbp7s1n49R2U@TkE%9T%LX76aF|JDL!=qydK$RM8*9mk zi5s0T+n^BW8YdO$>5U4d4|Se*3|tIWJfq~*w}8nXv-UyXD=NVxmteH`)U$y>#Ub{Lt;S z`2tWJBwSKs&;va~1+P$_9t5p!hG-yYwo(I(<08u$oO64@VW+OnsjiFY{>3EikT;Dl z4Kb6UJi1f zF-ycaoSQ#pg%3!tzqGw2FaW9`dW|T6U6@yQMze}*&|YJ`>6uQM@xpM` zSV>QqN`kp+i=5E`M$nLEe@fao5`p?|`IuXgQUhS;^#nL%QXtQGOTUJ4mX zOsBa%H{mVd!hfmCF41}WieBVPljfqkkHa#SFD3ud4Um=E9<}p%Z3tncG1vwrXaH)U z1Vj~BjQ@a%h)qo-C>R3*;=W%>>-fE}HtNw6j$u4;QL}4JUz@Il%444WFGuga<1v67 z#OX72*?~C>13?5~0~HZolLC-EgHhY%nN2%YAudWPDwk5Ao`sGNlxvxrt)z9(xyvo^ zWm2|cVT2;{G12PELW?WHK@Yc&5v-C3Q6%y(D<&NCVn53sD8NuL+niJ>bnE@lO?g%c z+O3z!6sZeCX{8Wtm=g*g^wu_T4$)>jeLq@syN2W$`%4~;SR;K99^U;eim6c>lfpg2 z$qd%xFq{|q+EVVhr!tUfujVS$duN^(u%_#pWtDUZp10d7ni*(#(>CrhxFWz#_77!+ z72$b~I<-)}>l9>`Lu#V^ zEc<>#WjX=4V8*ygDQ!=GS(Mk&4en`q6_xAu%-+^3wQyGTTA5pI@qI?#02eoUby-h; z_Y_W=BsUfe;}>r3^$SmRya(CwYF5G=;3zlV`y?-mZ7*mLP6~d&cme@?a0mb^d$K_R zNhxgDR4SqjX~)qb%VBjZkewZlx*=Yt_;mX)2Qe+NyhOh}L*pK)35n<2YTO9RBfyF-eCom&~ z-kg#>p?a*nz5}%z)7;^8VWC&lsoxIP|#N{W91@+~PQ(sEw<-PC%R9VE=o835UhFSg(Yi|M$ zW&8dQD@j=sB5U!KEe*!L7Dbz_Fvu=TWF2E4WG!n8$(~eX8N}EPicyxCWEuNljKN@H zVlb9>sOSAX&-?wp$NM{u_kSGc@$os&>vYX^U-x-m=e=CleQy?wx5$J$s&}b=lkI~C-uY&MkkZcky>j%C7LAY6~0B8}h&g}ErSD3Hz zo4>v46YuctF?iXhal(_UkT=fpwOXrGqm^mZ?MvQ9X}C~%z@6QaYHSp}E%!L>@;bM^ zgnucv{axEFjWcxDDraCz0TuEc?Z&KZV+i8dCmHUOd&-YK^iseG87N(WmEyQ<>+$0af^MxuDVocoh>{!)Ghb~^`XRD@f;_#oL1(cEb^M%rXWqR6k-T(EFnriKpCBqdex+9E3 z{K!$~{l{S;oDQY%bGJ@f+*T82J^e0suB4ijixX)!pX2~Rov+LUc*4~z7 z26Id}CiVvLfR!*GZ%CA_TZf0l5p8r(bQj-PuvK|*TUt2xx?2AIwq!MjG}+FMd=-T$fmN1_Pdo*?~@l^L}*`YC>QQ6R*gTY zH@*3aX=uV0q?;u^XO>pt{8pdXUvS;N_{q(dntu|!pQ^2AESAeN(Tqf?NjM|VKQaN7#bWSapO(;Wof zmEc;|6JpP9viy+PqnI~ zg6LhDTVi=i9ctV94DNFnaES-6PjsY@Pl?CE;1^TpEP~D87*Dyz;Lx2% z_qLSsuU)lw?mROM%Lz>9c3<9q3op4pYZm`GoGH@2Y5Bh%&P=Uo;l%|dfC3F~ zzw20c$^LnQtLCB3QPup1OKtiSf4xmo6LZ32(QO8g@4A+VEMM4rLR#18Bupk;VLPR) zc123GMzjVe+!#fdbn=ckT0Tw!a#_7e=BzHdj3Dd)~_73sLFbV&vzh?+Wem}HI-0!U0^mb%O-`@VI(6Q7tQGC zwDH$9yRUZ}2BW-YappttQe9n`Q~Qu<&({6K`7YpHrO~hB07;FzhTrP1KDm>cK9D<= z(Q8v#&gbB=xivYI#|bxQpNzF*M;r+&%5tzilWHo)Q=l3=_a*oukZ4~rT2rs}NWD*Z zbL9zV3D2b~ObngflXVcrMOA%JUpZ-QO;C4CXUt6jY7d+Rs52#^K8?QZkjVS zmuwdEJ_IGilk2vJn<6B_tNA(Nx)qet!%AB!IlqxJtd{Kn!n58 zO8Af=xDkAv2z__PD66TK>t})SY?%m~1erD6A;1{T%CbD5`l%XvT z{Lkwm+K1);_ffBZFvqr;HpkW#Jq0%tel@`F@#83c&cm#;vH1dbh!@Yg3Z$k!4o6$Q z7<+ef`v~LZyNzL!(6C18=aJVw{!N|2<2RIk>_&-Xf4dctmU&W??s`Y)7Z}Ar$tHM} zHP+`!VqD>r<{iTjIA^5gYsR$(AgT9N~u2`gY+N52A`LkK+l{h<-TcPHF zGwVxTn4t6UubS0WK5FOi?h+VLN(Wu(9FF-{zG9Np?sgGXMPxh z^Q-bEj9YGbxbKv1+v@#_*jW$#c5SDoxB1PR=}~?=^mJMx}vvE=~gwxATzkoniuJ?T_)_V&Og?VHP&h*VJPXv4Acv$GesI%f!0 zNrqUYi`}Y<;nL{$;a?t)j-SaQx33iNXCab$TOGi;!*s8c5Jz#$)yE<)UGH*y`(gUK zDN~g}-}_5tOSjmpKgvjPTXzZBgM8<2#aMitU%b;^BXQx^o_LS+T`mWqA8LD-D)6RN zBD_)C$DH1*-={ad>8hH1{pquK!}w!w2fq7%s}vVj3^~ENCGdo@<){sIMq4`Y$v5Sp z>6Am*=uej^xu$)3twk@<;<>8F%VGBXw9DgmzTUDGZM~9Au$f%4->s9k0ei=yH5w*g zGo((&w9o@RU~^~u)ii9D$ItiQc=}1);-N*U`K#XQS?5>u9PiFdBpl&b zc39DtEB$A#puKnCf1fMvADkhD(H71z-xZNgP61T*I!aXNvwZyiFcT^CNio&U{ivr> zTMPDP_U+pzQ&%f^8a1|dw#fBza$MJa<#Xso88c<&l>$f}okrGQ(+q(zWaAO}YAuv62^0 zroWQQ|Mox^!C)pBjTIBdaY`sY*EW86PCq8Y#XV)jS%;)Ogw{z-%0KlO5ew@ zyP?wam#kg3{CY?_px;z+XqDR^!%|N@xFi{?^R>v$QEZhss|1 z=_WC0O~P?4weQi-%rZdhj@aezl;eZq{U0C8+-+5f{Cwl0`p56je_ags_EtZeig11n z{$YfC96>iL((hy%6_Gs{U}nkZYT{VHHa>TqAetO};fSaBjq-U{zZqOm2bWqagAJE# z82c7n80T_S@3mimvP$K9zr6|5_j-$nC-a>L#c}KCiyIKd|p+`%#cn!+MmKR}W$5UH})(xTvnxb?~g7fJdw09t!6Pg znQ30!ceD4#NTZJuYr{!*)1{kdO-nVtu(aK6H#Tji1lE7uRWmG)ezi{Oj_DQ{y6D(; zeN`0f?xks?KOr(Jxq0vMLZj-4Tza8rO-902=$OU6I=JR;ozHF4`Q5O^v!KRFI>(P4 znKCA>mHc~OWKOq6g7?e)+aA7hxoi!HAH7HDz;Bi=?+Di7<@;(D7LEW?k>~+sT6ZKLH{o8{XqXnG0KWS71{sKS;X1Z&26Yz^%s8y zq6@!@6{XF48myf>Zf*z2>D11vVGQ}GzO-a-6RvYw;;FMuM!GAPQMkBf;RT832I&u+ zSNCa?$SU{8llPPM_pmMDJHq?M;d@&9SoWPAtk#n7GGTumw?jqmZwhPK?H1ya(BP-#CF4&MWt#I4lp^2_(0)?QC`X$RNDlw~SfE?FUnc zn*&Q%8}17*!fVkK?kZ9XflwD5A~@kOHyyS^E!%blhw(`#qXTvz-nx`wQn+KNkTk5I zu~%LF{&JQ_LEpMhwF>*nMVxE3Yu$c+kaw*ryX`V^bg2X+LV1Ky0CP$5|sfJpjaDAT;&i%@D_lF>gy|f}Mi3kbHE~C}b3z4_1)7T$Uehu1E z4TU!*mrGgutK+g5aajJifNtvMj?(Rq%MVr9oV$rXAF8C3zd8d>wi0$J!A(5`3tCH$ z&k59PqR!A-H>1iYZ5bY{#I|Bam@b)6*1W&BZEUw%Ey!54OzVZ5PE1R@rLDBPwdGJl zO=)?MnL{{iO8vET`Ikbxx{$PB`72CY-3IRG;F>A|wp*@-Nr$TGO}nJ;VfJ@+7V@;Z z#biCT_Q_TEcQGlBG5aK8>UiU=kumh-DDT&i9HRG^iA@T4RP;&f8 z{iQVXfU4!RGZSM{_#-4g|D>PF#liy(DgN&<=;tKN^EA=H4)ry3^+(7Xa{*eElEGx6 zpNGrL*wSX`MtAo{_ScE!s7b|;!p`MeuY9a$JuadZYl@gF^YSRbtDei7R=N$B92?bT zWor}r^fq6zU_Wv#Z>zuE4)VLu54|)&EXp4HrhL!mLYJ}@wO$apnULb7c2CZreZ$~; zh_D`HsbdV{=c$WZ>KrNeO$Kh)S0;gNDeJD6ddN!{-x|r=zAY)qRi>z_d*~`zE%s=i z51KqdDtrl)Q7$*AW^LuiBrqt%I(bZSk9H@#DFqhkklh>G7ZoJnxQa|mbX4K1#D!Ao z;WnKu^I2%iv6*!Wx=$rC_#)9`M-4Z>t$uoI603(-7Xxhr3K%iZt;5gyU|I%sZ6`ZB zoljNapTID4eqo*@bh+>JFyG`iO1pGw@^X$i`b5FN0;$?xSNVeKBem<7umT)1$#m~W zlJ?W^S=dyYeTZ|flx^vDPklTt=_Tgv&ouY%WQHWAJ@ple)#9x)XoCw1 za^y)@%#7rP^$K<^w$`y}?Y78n2ZbRo`d>?}!cbrv?kn!^4HL;S8~g>S`l{L)F zmIixBGvRemi_ECS-TPygqs@?5Jtrfmh?Q+<%`T%TY{5H~y%YMQ#`>9y!m9faCj|A2 zT;YLMuQk()0_RdSr;+M;3SY(A*rFR<>tsX8eMLDOXXrmAwFsx(Zr;nsRz0iV%U|`f z!u%5VL^j)WltRKL22skp<&ABhG0_O8boB`@X1$mve1aSI z`bSIN=}+p!W1@^UPIwNW?^G!;Jn0r0c;DGDblhuVSG?+*ik__5Xj9sD=;QYqSC-2F z%S7Gfl&n?|H7G8ywzH<%OATJ`PVHKD^uX3b`IkE_)R`^Da>3@L4U9_SvThyPUQ2e4 zslLlMWQcLJz3$Y;Q<*&>{>f$Z7dX^*G(BmQgu6Va%d151mFWINDOSU}K_=e%1Z0O_ z5BAB0J>KK;yGq8Gi3qZ~73D1G%#H?oxv%{%u)&P-{tDz=`zAHW>yt+nJ0U-iV*T6aI?BOjqdXGO;RVg!ZbgE9Hn8E|< z3EHn7X;)@v1tiwj%mFJ@L7)~{q%}qnJh}5ZH#;CN)_1OncdQFixZyro;!&ko$F}^D zRpgN(@9wpJrlY9gbvYDJnwvHzl#XaiQOj3U>s7mxhD$mcDDgdsYjfX|Zux~Z7aoWR7g3KJU znA(uET#(qA&s$MoP`{F2TQ6)Kx3Q$B7o^0O7`E9YM+x(r2-4!kG(a7XIhu61Vr(>Y zeT7D=@-zy6j-w^#Dv)9R6F4nef4_&`9}Do*LgB~R2|OE1af2)2eu<)UBTbYqxH-3u zv$mI%bG#QXD-*y^8S(0&j+@jxP1zX+RT-pJPU9G@FLsyfLYgvjsAEOko%d33B>1Hh zgy|oeE5~sof!1RfIQ0ESC15!ue*?GBsu(c56{8ihBwO0&nw_8t*l6xV#ccqxC6$2; zhS{PNIRnC;-?AYqvTx6C#SpV6zkd2zR?=3^jFVfonA4ra$kM5S16zAsxni&vG|(>Khw?XE(34VP?A zeAoQ-o*i*d7)1yjD}4;p33q!_gWh!-xYA45^Tk{tbN4ahw;kFZmOJb9T=K;#L$5DH z8z*ibO-Iy8^Ae^bjn5WH=)PY~1WYQ|^ap-^pgw%kCA4xX!l!s9!siXGw^nv`J})Hp zGjt~ToKwavkTgpsX6gRqk--iv-1=U-o8&EcdAahJy{2T~D0MV$t0S`Sm1b%Z z^}AWLF70Iq+cJ5n0KeXot=C>BK(X z0x4ZXP8$tG^n7TCuHU!eT z+-J;H9hbn+`B0sr-^1L=+sRcZX8_7JH;$B9ad9MH*x&VAis`EZ=x^Wc{*lg}eA{+g zbzcp=&$N<&+DD-FQREgy~>+HGm^EicH4+jF(n_@MUn_?3&-wQ*ik$3%(Qwk4grliE}yUMkp-jb9U zaChNZ-Z+YxWtd(fd2;*V&_UmYVr&IN`* zZH`0($D<^@JY7gfQM56wV(50$qXEvzLUeaaGGmirUb;tzk4*{zFD77}f`I7-Ag9(( z95TYXYm<-;rl1^*3PPPl*MC=G%msf}aZx8|69fWLH_L8!Z?^ZTFuDkUvUQbjACd76 z6s9B5=W!ybR|cVU+2l7WXcdBKZ&2l2(^NJgoBYmG^D;KxKJnnVL#k#ztNfYi+3=x! zG~_1{nUCFRKucu0H`tsY{~8!UlrO8**20_bQC~`IRhO&Pc8+S+HJ2?X9gIV`4fC<6 zG0OX0YtQjz3>mbw(-FL1r9Z$)<`dtIxPaIH8o!2h*Dak0yG(|QCF+*0!!xTHcgVwMdaRi zoI0<$tfV8a<7hma}Xt~Zc zJM|=kM1LJN78e#!VvXH6`iEDdIY;CuX-qCT%L80nJ{~6t9j3t9k|V zh{l8^l~F2KpERq0KS$x*)dM(C6f(qdnN2>Ey$0DEM}?FTZ|$S zgpDY{-DH#RYI&bgf0NN0=)ypH<8bKo0QdXTvC9ML;-l$E=))g8QsX@72)p}6s4om( z>H*IXERyZaP8dW4^)4Jx^Oo1qWaV~0LYdM52PAFZRa)+D5Nad#1!^W-&%IG-S$pj{AXwh>7>g>mpRfU<(FYT zt-=%6E&UO%mJzSka~oZRfA)OLYEgx9t%&TKy$a(i6-V)sE{f@fKW1ZDeEO@PoELx5 z8X*(e$tjoHP==GBynM=IaNn5Ek!vO4p{*+Ay}NB9_2|NF>hAAg`uVkh07?g@%<@G3#olp`6Bz8eR{z$I@+uou6;4PFe zuorO2_GQxYOeK1^c?)p{-f_}Q2r}|tW%=WdNLTTMnwWOz3nG^7}^z9=9zBw`Gx22i7iC z+xS1euJUqcP|~pa_dl&9R6+i^QZVp)6Xf$<*9oM7z(|T_x5M@6txx1opBzBV%JmxA zObRxMW+(;X_` z8tvX?!T_Fazc;6)KgXp+V=l*DL*&*+@36?Z!f%{GM(-xAYuh;W7AI!13#`B<(*g{= z#we981wC$*@pl2dd$KReI0nomueX(1ko~9Jpx}9>cQRA2F#@GT*m73KY7?@+VZH|y zOUP>lISPDCPw;6Lumq@~)i6OW>LhJ~VBq9cLe6Rvb54M`)Gd1!1e&QHEopu*_8(@0 zI0))7A$v8OIS2d(C_;!LSPiQDwvn?-R0*wMHdR9Qf$=bH5Y!39D3zbtQ79FH3J8K? zI7ldm#`-BMo=jpk*m}^4rwJXqQiY;E8iXni)$^!RvT0Ky>Ujn@7Z}maAHaY^TPwJH zVLSm6&N^w^Ms@GsRT$b;2n=T+mFrV5=EVA`U^XkXLK$Jv5^V}2w60tA2g6|NR`_7g zkspREG<&9~6yb(<@}o>q;{Q-7jE^Z%*;^0;Pc8{?TG-FFc*^SqQL^g%q z5;d;jLoF0+j}y9KTc3OprI~;zS|EmQsS{z8U>*Tfx;5De7dj&U$HNEl=#R%YG&(_3 z3$U}(G*2e~*hIWrfZqHGy@{c|K$7bhLfJCWH4CAh>Umix!hB)@IU}!=2P$N{8Pv2u z-uw}$sg#3;xCrE+lL+AcEh}c+eCV7D^?KeiPgsrD_M?`cRl9G|8_Zf`O3<3{cc(x1 zZCSM`tLCYp2{3Z~ahmsvyXQ)FmK5H3OkRlskDa&D89?${>iF>`CC0d&7=y=}V`aI* zI*m33qZZU+`yZ_(wJBU1JFDaV1Tl0f$Nh;J@BdAm6VEF|myyI0v4&h>TK3yvpKG8U zQ+#h9%f5@V^Rsg*C=2xwfZJ4bJ}GCTdi0t}C9|jR~`! zW39@Wjr@cak@~Ss>!%BiFFuoQ-NB{}o1N7I2N1@s{|Xoz;{BTnKaBL24+ua_T=%7j znO+iCE001E-^{BHV;~h|)%hm2cvuwFn(=S5Id+VgNaz+o1$oaAcZrv?8`#;9e4IRf9k`f1 zg1%;zPsW;_*!UMN;3ksv;tuwLg#{segg1)Nvakan?f}#rf9@#d>^tS`zn3|V4)5Qx zEn3O2J;jy-`WRCB)5holpdyKKw7>byPgU_xY(p;=p7>ZZ#$c{Khg7`M7fXgkot9!6 zyix;ZoxMvB{eg-%J{#qJE}ie|t^2fG@6B4R9?j2794Am5kfe?~*aVAdjdx##KE1LP zOI|szyS~5U&^En|eZQx5muLFMZp$lsvE+e$Bx&Rhw(4w)3lNIlxM?jFPaBKGVAQ8& z)Tb(rKf`7k@_3VUk)PMK-tB4qI8!jMGOcjTS_c{Obiw9sAmH)Jg?~_@nilQjBuLWE z9qd*{nftduX>Oa_-{G@F&6%bYu1UQ&)Dta0d8mu)4(j`_ocvWao&JDWB#A{Idp47- z>T9hRgW>QKEF%deVKw+#Lgb+oS7M_cE+7R-64J+NWcIs0xYU&VYXbLtkM}zIWO>1N z$ZS)x73TS>DwDMyVnq){eZCsT)gZjp5Sxv8w#vt3t%HD_Cmft3i&*G12`{J_;R4=# zAYDnqKF&nYD}*t+ZL|G)xo5@&BeJMpEF%t4ijXAZBy2$@LJz*KQM?*rf}<3DAQ`h- z^lM`<{ua`%q%p|JdkQ6y`1BC44=nbXCm)7x3u=>4DZmua2p8TvJ#v zOgOCEecJ}J*$i64!OL5%%^)|QbPldu8&EhI%K)+6npsV8g_^f3;2 zxH;r+cQvK30MDJ3@m~}5Wh7J*Hiy4OO$i#{nMUa-riujGK5780sRi~2{6vzb^s#OC zFL1R@K`V&}a}3-(Ncwnr2h9CBb~+33MJX)KYnu(bDTr853&jO&ejxoUgDJS-`4sAO zt%bta6Cu)OHnf&jin%{`H^I~Kg6Zz4(B+vly^*)+Z*y-TW_r3qN9#1LZ{av~i1+4B zz4kqksB-Lsz)?rG#}aX^uXXIY&R5jH7Le|$f%*Z~{Uyn0^G=si9B^>;EcnzNl@myT zV<5IjS;n^1D7&7k-uQFo_c4Ar1?z|U)DP~NK`bBCk2?xQNu{*C?zHQ2l$n#QTjPB+ zD8@(ROj>^m+io|Mw2=+e2RX7>_xD7};IHzM&shbXLaLv*CloEq{yB}&9%_xr!9W;N zZekR`5_jskkXB5f%Q3R)pHpw!_q_MU-yQCHFEe+S7c5~_&sF0qk@&YurE|YY)x**e zzrjbAVq9%+prdIo?WM%NynbmwMK7;r)5R zYKirNuyHoW-H#vl2F$}3i?!gW!|rPO5Ma@dSi6=TB!X1u0OfwIl#Vc}24wU2e`7`k zn}ak;D}{zk*@;qw_6)E?kBSdITiM;sS^6D$r)vfu25(FyUljpNVnd#L4O+4CtqF39@AJFZpQes0rLqA-uN&QZa<;C+c0^plo=dfS1%*8awtUU7o$Ugw zrPemvo*H>V{0WQsrC6g1N+!sK@ZyANNUH5#4dK%s4aumq0%pe!o3n|dI zjFQ2o&QfYI*&}5?HMM z@ZKumx?~TS%yEj-x}x{SpS9l!wZ@Xl4S1d(%?<9~sLF^#WqZ%d^v=;x+hC!7rasFQfaB1OaHue zLB2&f|HN_3)viIc8dcpsgm>~?SZ;ZkDC$sPGz`@OA@YD&bQ+1Ubbn^?{>*QbBA_$K zgq|%hen%xFuP!)G`4Bg|1pVgNRKbka^--wttDu!Pz<}>*YV+n~E@i{Bgpc3VJ9czH zd-=fq?`h%lQ&tSUrpS6pc~F_aH5azGK*qkbsDE0mbX_hN0Mq-@y61bG{P1$B;Ir2C ziHP8C<&XoZqmd%9AMB`mU5{J zOc#}X4}|&%Bn+g17o`XT8Q{ep6$m~%*c-vz8!#1$k;j&eo4TwN0|N%r8W(%4A$XW7 z7-U^vg4mWwc?RU!R=%I+T?a=rRn*gGoyu z_H;n-Gr`uxhAxO;9n9SlBb$dwLlb)l5Ii~fAXA2Z47G8wy$rIw{2Oh9+E7h)E;bcX zfZ+_Dr7mXwIflly$ef@y*xzQ5O$G4p!VO07IwSZH$!WGrJplhXp2oF=oUIPnj)O~B zrBur>D6A6LGMr(%)CKV0kN~esfDe(JR=Cu2&woy$aV<3`s0*g<7jvcFlmfM8WX%t#t>NeVNPL0syA_~TX8LSXg5FqK2x>dNq+yQ2pFV6D=R%6eP>+H2qj9Yo8G0*Sq5*Tyb%JIQYhQDMW>MKF;?m6#q;O{53~q)`+d1?6qIFw~<2ob0wVG3A)?>vxVA` zK?A!%g9tb$>cDWcG$+DMEE~>gwA@bd9@^=hEJjTh8+i>D2;?JN_nZY8JZGBP(XR*I_UdXfFb;Wwgw0PNg6GL(LAfDot%Z-XH1Zc0U9C*oTAIy=l8q@U(f{v7z&VyyHAW z=dVI;*a@CCiHkNpusw#{Fgh$A{7rupmRcAG{`p7q?qh>;kKuQWq&dx`IceIE+*SA; z+s{+0^O~Q7#fyZPN`#n7BmU7-*hoVnW*`B^iqW)b8+v{kYpW=&bC~f5!$De4^V+*E?tduYii{K z6#bzUhZ?P*c=f1z)0;z|;?>WG+MyfqHm|(Ux-lcQNC!Glx!Btp46K-BDORE<_P+T; zzZ`0`f}%;5Ql+Rv9~vz=&<@?I0QR)56SnW=GpULlyf3sQ&A#y}F1R}i;$<|!Z%&*1 z*xYvVx=f(3@x++1rEL60425H`8OrW5kz%gJIE22s4z}ABF!@8xch}m&w(MF$i)=N` zqZkLL9xDVIu?m^73emKosjCWscC11se<=2g1x0jd?J+#mNLtvun{n_DH9ORX)~>=s z?WBcGx)~3tdH8L*o%=_pu%{#TUbUvn1gbX(SAIBEEYV&pam<~mEmOPb!>Lkon!(SZIr=|zmq1)`A=1rb1 zu5I7G&pU zd9Zi*+@st0?2B}HOF3fQ{?L*G?YMh%KHv0VxY|C*ku`BiG<9JaIvWK+8s*5EyRZ!Y zp^~)2k@T<_xOe(^iXP?qkfaX0%N*WiS0-m(!ZIis1@AKYL&IrN%r8YsY7241G(U&* z8%@ZYE3pphI}YkcLHg|`s!Q6*nJuFVFu&_xMo7 z)5qQG+W0(+V);v_W8MDHk^_xakk7aBr_qASCXC6ZjBG=Xqaag8g39KMY=gh)CM|C? zKVP4<(@-%nWE*;^^M@vz9%xbPvql7s_o%jAQTn-IsMi-M&$7Z^?54}O zsuvG3y07cNx6R?(c4eC8CBnsn`-lAv+MB5Rj!pWq$WOPyN=H2&y?s0aO8*9N#10!_ zgpHu>VX73BJz|$pdzZ0wkKSni2<>A%Mf-GS2ZU}o{MWTHMt&34~8&~P5=c2dIMLpAJ!Wx;_of)DY3u z5Q#j*Rw0gjAr9=9O70lS!;Q=n>zOAGkuF3(I#@rHy%WSWSu#>3GEgNle1J!nEI1Y| zIQS33w`$R1^)T`VmqIueLpVxE*DFX2!xWJL%FJQ!6ppBg4ycKmkrM4lEENH|MFGge z_|U7`*Dc!DE#2d9+vB&}Pcqt1It;!%7xok*_7rms^+*l%Rw1E$A)&TIv^%tyPnX)9 zYqL3L2Y6-#cy@@VDtK-b@qDF4)o!lF_10XG{9KW?L$ot|Ze;lUptChXUPd(E)NZ~R zsc~KVZ>NJ{J!IqJk&u_s!7l}zG}f=vHvi(&x71&l!@3Mwg~S+X_dF;e>&iz$vZI5u zL)qgF_HyX@t&)tp5wQgiw}x73p_qQba?>J4KAYu?ORA2FS2G6r+D5Z37|4LVnOBI{05mYgn1+ z@YqF~4Ezh{LX_PF+k{kTlK*d{HH>&-WAr3V)@k_l4*>Oh!5z@AH+!6`QbS6fjDt9_Ix|`{PnbN zttEIu@$G%v_Uq@FHV#BprVfB@d$U@UZd{RWOv6$e-L^x?x6wUF39b{Z zVK?%_Zd7icXP_QP%=UTcNm^A3^dXWl!IHGofijI@kOWNz{)G#)9$9YNyF-)we|WcU?u4#U*=|PXPZ6KIvvi>jJ=0h!pb1xmrZ}K;;(|Uc+PPmLF zM#5zWhfQ^?Jpg6|fSEVfMIMTFbKT)EF&eeoq`lj8&|I0N1#X%w{tFMPinaHuu=A=g z`ZtoMX%FwcSqp?54_mu?w=T>$TvqKpW!Ir%KevHS;>GGL}#!UWDFcyFSE#E`q!2;Go`gxUkdg*d4pHT(36HIY#m^?JW>%)LDM{HF{5_yRQFlJc}tj!Am zqx&lN2UU@0;@sQ8eiCop%gA*tDQpV2H9EvQ``QL!9@%NZ%~^rTDTN;J6rgnqctf?p zff_VN#4F0D7<9f|7O)r0UJLRw4aS&y;WDOZ4;jTC5$4A-LqsP#d|_z~ z2hIaHcJ^5e<&fXo)^6d*&kMWiR-l`1NjTeIy)N-yI@}5(nw=oLHLS#DqhE}q(y$0W zjZ?PKYk7rZ_s^e~8y`m=z5HJKU~0A_oGppy{;j2D>)Pg50mJsS-pVJ8T5C_u5h^0F z_b^g3yS>jt6!$={yll=cC2tbGihqfN?4<6HgukS;mXCFa`s!L?Y4^bsMBmz!lVW@3 zUWQ*znyG*U>-}xE9`m=l8-vvv?MUG_teE7$C>gd7&ODjNnyW@-u&!+HFBu02wpN{(GG86rO>x^`qfW`LNAzbsK?h z!YOVW2^+!Jl3Wz15S5`KVq?I-;7UASnxll1E~_toGT@J^l$+7#t_$Bbuca9WrV}kD z_#jY9a>Hnju~TZ7KLwF!ITHWSq;d;@D#Fm_+`xLu=SAI~C6{GgOCs4A7ff&~%+i0! z-R5+{9og7C55M3RN{Q!NMv3#6o5am7JmDjm#2I7w@Kv?}CeUrCf_8pGmy{x7ToPlQ z`+z2TQ4o*Lu2@Yi^(4EEowB*64u9KKJXcoa8s$7aOqhmh(m8tp!2Vtku^)wB>QJeXm7UK zVr~qr^*K+^`vh0arTASk2QDHT3MS2?PTwEv`QCr5X`5Jz63+w8C%YLY=W0#d8?$=Y zf3A9FQXyA7^{GO^Xq6kmP;fvIy(rIK5}|8vv#eIE0dloeYpFmMTUT^N?k5L3Ce@Mv zrRPI!Dx3$R6lj&>zLA;TpJbdVJ-cq#Tcl)m!pyKjyCOK!^sM`f@-wAf<^cozB`1e+ z?G)NZftNHX(sZ6q8}YCc+K%x-oGTKD$&7%s*%U>TDbOlw=@ z;IR@hbNz}2hY4Knpiz$?aD&lZw?nhi*(6-Dgx5?SPJV{}pQwjJ=Ra*3E-|8MH|Y$w{nb zbmxsJHP5O1kn@$_UGDBiuw$0aThIMUYN_08*ud-W5SaDbhij5I}kn1f(e-B}kPTg{TCSqClieq=p)L z=i9;eJ;!@I=iK{`@sF{_vsa!qSDSmzx#kWb2|dwl{UrOr zuUl9;|DzYOsP{fpvBD{Y{QYYxqdTSbUV?zC?hCwT9{95AUy%dn!9NWrcGRhOZSDCX zBy%q{)33eW6;mJaKdRY8b{SJ|HG?@nMN}ng=Xk(5y>90vg!oK=pUsztb*%F~o_==C zrQd{0<-#;T1O6co>^9Oe=ia;FjmL8iUTYuVMWot8|6z*F_e?1UMmWad?m_+)men{) z&{CyM|D1?#9$S=qXs-=Yq=^xu(E|MHb zKGjrl^Udu(P$yXMd_KS3h(kP3*XBbb9nb5(wU*I=qjb(-L;)iLQGiL1K@bAxgTnyNKeh#MX&2m6 zr$XAU-{MWvN@me3_f}9h!bzI{0NlNLn=54ImkG zfy|V2?p(&~;N4m@+*%qkk%|AF=AN0qHe)ZFQTmA=|6bH2?!`ruIKFuT!q*1lyAQ?q zikZae^no-7e)7N8KtY0J^+W_QR!ypL7t>fCWA|?0pVlz5=WDjiY#hd#R+#Vd?qmb3 z(|h2TK@N@wIrJ{qW8tw6^3P)zY(LyiM>Sfj%Mzf?6$RPb(DQL;^mSx_A&dFt^eSt) zocDuQTF-(p7f&xq_-y!FwR~A#4`V*Hdx$Wt zV6iLnY-ic9E))O4I8{k!I2e&##GJaI{Nf^}L>yBh>{G+%ld{Yxr>AZ?^j7E~3<2w&@yq569HgNo~nWZE?-C@XyFij%-bi0FIlTxfky~p5)Hqw&drw z1Pr3n74V>IunsaqHj^2k>DJ|6>vHfhL#j{?e$A;wa^SPnLAW7VCqpSWJlne7S|wzP z=rpH{G>=WV#@|bI!>dsoAKpI>oGh;n_Cr18tNd-g6j9Cx9`1a+9O6J_bVg9KBBmRA zu)p@y!M|ncPO+=tDI={4PPjO6(+t3-W#8ldTRKuRkzF$-_k3HX8%vpu^nio1^)gjz zX>MX^uCQ|v#JQ-GNml*fv@#$vVAbrbR#Az=uzXehdf&_CR!gO}E^;!cF;>@C?w_URKxBDYKCNbDfeO zhIpA9rdt8wm-X?hKhLL_f3hgg=f^%wGoQ@>UBb2iPFx?G{SS727UMZGCGG3R=4BFB zK2HFSd!}ZPcMpyluk8Xqh5aG z+y??J%f(!Tp`5;o5CM7lz)2nTdcB1AzzGPSlQ!>x%lVCut55elt7NUwy3PV{^(7CM@z;cL&$ik-Xy6rqWr$1{7TbMooQ%$<}4=j zR62ufI>YbL?K2|#GvYVlkTvLFqRg30{w3h(oRZP2&9f^dz95gD0UD(Ae6&aOKuq0; zN?!N8)y%iR4IR7Dk-ET^vK0%&3tV&lJH|Z-HGuokvviZ$N+g z;(%cDHv6KVzK&S=@f^;dEBVE5|72MsHhdKH)3=i-zq$-e{(HmqnPgdv)Km8^wi@e) zU6=e4-C1TbfyomyZ`A^p*%jk!xAF87JSz5$tIS7zkCmUKhYfWzF}`(O23& zZ1z+}d51%hIh zl|#~wgEVRh2w`2wO3c1!mX#L}i)V}n?E}-hkVJ1;i{AXq(@{sJxtiu0Rnxh@Y9F{L zijqmUYFvmb-{Vy8Jn>Wc+Ood%SVG87F(Z) z1Mb-kzC3g*JDzmF${}qRWEwQ8N5@oscv%H6;&|Yx)?5M9!-ceC`|NAa)=J2 zFHN<^{0|vk_kM@+TKjUPX(!F;%l5>o_M=Hq2?X9~okCV}DwP+mQX%+W6quqDi1mWZ zK$ap5WGS5R1YlV1_lXxq6EDzUdWA5(@&ByCTW;j-ilz+|QI?3Txj{YO4>6Pq!y9cs z@WEBy*fNwRTC2w{smIb{dSx-aTv84EQqmB$Er?nKl~H1T8=1iWBqwLHCuf1tlP<6& z=KCe)E4z8UY)?#Y1>!0@F;pYEm14`Aj

    P!7vi%0XnQv7S_vpvcAEkD7JunjA<#pDkcSos`9XR!2 z19l0rG?;87dmZJ+ti^9BX{u+=%)8 z#d-S}^=7B|t9%=;o7(Co*;+6+{58iWp8x*hmaM-j@5XEOW)?tHA30E9DPC;stdFGT zcn6kyO!cpLqQC8qK_$DzfSuMr{sWNU1kTT9aW}lVM6?B{) z$Ft<{i$8wgBs0<{cYXp2m|YShKh!t0~7EtS3Ee)A73b<186!Z4()p^2%@Kk6!Q znU4^iQ`k=oz@Nu|L&M|2@_uz{WnB%EwEsUNbc>|?958ulPwW`Z;Q4>U=V zdBg9Mr=I;iNruaxPiOlk-`_Y+WM18fs_>4%1gQPoBW8bzze$f=)OoANcZ?oZ?y9^} zh3Z{{NtxduIt%LAj*0x6z=paz7_w8Sj!_&V1>|uVlbJwf*IKn2cE{ltYPoe~PiFE- z-O+K2eNZbiaWDN3?3MirDE1LXiWlg5v>JBg@CT}F!FV)2U6d+>i>hLzsM0=%X-@xV zj9IGdDuT>-9FJ(>rmgO#otAkkF_WiBOvn2!-!XciJc)bK?7F1hHTTa%^1{ShpVo)h z{wwD1m7V!uSKwC%M8StBv6;6kQ!*2sz0JdsUjx;%>`Z5R4hGJ@l!{myJvP0*%%82z zYhivf{{hvu?%zqCzR*B-9GP8HR<_N({j*oL{gd_`GLG}VX%S}j7yL4Ezp%lJ74U=l zI??7jw+S-eRw|EUEZBQ@=H)>mv5$X}p8(dcS`(vLi4dI|iHxn?R1szvG;?Kc#*M9?R!%Qe!^G zhQbSaLn0Wf>`9RcUEkJRkN=7VejWdqK5gZy?1WvzG42X)FjpV0S`c&Gsn$>HVR3WE zsJ@lVqwx_A3F5+7wJxrQ4bL5;`c@&2#vbnmbKDsNf$V5{ z=Vh-zEsk;Sa6RVho>~Kzn0F_F7`lo!}}_E_;suiWO-Ov}GqUzaGp1 zcNBBLvwqkcj>1y~_5Xn>OP<|D5N0M!ILyr^VV_a`@Ny!G8(3lZMi^-R57gXh;L+H1 zNCfdey58;CEAbY`ILE#pqv4jTDO?JSsa?gNd7JqU zY@p;I+D3^0|3oYyEl6!-=YaCL$GuwSgxV{zJzluQppefi55y=vB z375uSxIN~B^P2$*VmS*$Il@5u_D@t^b<$kD3_;dHkkl_m806|fe_(Xo3;wY{;jzGM z@4fm5-()9VHU8hxo7NX6H47BPOb)1flp(wE54<6J=X!o(6E&tp2vgFUz7=+D`480T zKCha*sfq7T?JH?TZG{Cb|B1M*S;TmL^msmhV4Sddpw8R<{|_jaoV~5vu&wKhQ=ZEM ztw5Q7{CC8~%^~DpMa#e9KYS+4LaHN1@h7f-wk4V@@nI<1@;yUy$iG3#B7XK9VfLJC z@5c>}95TIfZ~w-4M-KC9I#@N``o0}7%yl(8O}FaVi}AA;%{|V-JkAPBQ$wVwnc2v} zY~j(dB#78n6}4cfnqs#;pef+n(C(?T31ysyWSnN!q5x|>iRL3k@U^KV1w)f2aHuGB zQ2&P@M#RzU=oV5$OPk7gFm!w(Z&@L4`9ZH2XRlXJRWcA|asF{an5{fU#XQD`y-}RK zQEwep;vH4YtGQv--0Ol>Cck0OjQy}(0Z$>c2XESYDcm}m2_w}P{`;;kb*-VtstCI}M~6lP(9urM*x zfWR~$*)*wq;Hed&wyYk@Bzt-jP&Dvn$gV3Ica?9)vRWKgEiT;B2J?@w@Q+B?rfr<{ zh@bT^_mGBpNDE7|L8RH3vuMFtvC-O;2<=ZQg`v>GpSXw^G~M6_y7LH*%IIlI#PlbX zwNU8V&%7PQyq$-=`<%V|Zyf{U9Rtn9#G7uJ-ND4Xx1zp~I<-GTyjw|twE1dsiN7v+*PwaV!e&n=%%0|wR)$C`M|RO8 zy6AtS=S)V4$Fp4W>}k|fAj99x9kq|a$U$~L5i^3lc>cZkS&oER4z67_$gW!C;Tgo? znYGT$SU<*EI8UmU|)$73B>!5T@$B&OFtUhP`>q7sOAN-Ub`V#^DN!9Dk-RrF+mJJij z{*B%NY~~xd`65MxXqV{rz85+M2O(woiQo2^t`2&*onU%Uifyae@&g8EVa@AUXb zz`6Z0_8(Cvj%x=y+9o*Ka%I3F8SqFxCIlZ-9zrD#5&pl@-~Za~dJSy7CVo6aan8O#<|>%xDpWZJs(ku4di+D;!PQep*%bSaE+)em5^pOM;@Lccwf#U>1{sj7e$9HvafM-oh0ZUR?69wmQI9tDZK4qb1 z{uYK|_vOU@0auP~$Thl~ z6#RlR^50{`vMq-A4#o}p@g+=)&>;hCpP%y&{Cnm~1)Rf4!oNoX5D@AZtWHOYP=Nm< z#vHq5fSHU$y!SnY|A79?nwyJgBq#qp33&LGfgWH=r$BCefy zSJi1avmpuIi3&36+yqFlcOn$0PC|en&`D%CbufY-weIO;^5a{TcM!3EXq(zS2>IKX{fU`v|VS87>KY*LC zu_K(?$AD0yNAp|+$8kog=|b2Q>Em)>G9fL|ycB{;Hj1Yr2uGnCPvI=iBD~I^8!v*F^Zr_|e>^uqF=U%l1s6(2P>e!T z&i%DsotH3~6wYjo1nOJF2_B=#1>QimQ{2y4m)mRqBaV%63ins|mA=|1de@o#3tvrXY8_?6ehRGChvKu7)Ek&G$5AlK#-F+D>FA({{ z5E5uaFJA)NFa0&mQ*y$`C^Rbw_mmMK$%JMV5OpmTu?^q8r-G|u1PY?tD6-oKB4@@W zXO^&iFMwIoDG6OA02FX{Iem9IOr}vurjeVl@N1$Y%R|0}RpPi2tarZ(&QNXn!|_vUCfaK0*l@ZAwLU)UlfoH#0f~7* z7onhQN0ewc?&vLH@OUHrcq7bzS;>Eyo6x*>Y*6lKWf3r4Gd*21OlDn4W}TbR^LIm> z2w1)aP|TO)Z9@1qK?V1T87K%2t4IzjNT5HUn2bw=O%P!-8a*rm6tF9b-W3G{ehe>~ zSNs-^;T%v9I@Xao))2X1F1g@@ZL&Z{O&Lla!iCd>3o&T-mE$Gf26w-Q$xtf)n}(xS z*gi;kAH+itIZY6WL8JceA%ccA(F18PFipuhpdgU8kw{xeOB7d2RKoViuI)qtM?(!8)3a_=!geEOLsE^!$cjnp@bGBQ38Q=krVh z-;%xQJ|1{D)4ezobg=EezrQ7a_$f|*bF)fy@6+JIgJ++v?_=rUNA-=%FHn6t?|0|0 z50U=+FAb0Cv1OT*2jAwp$MJW@E=26z=2#!v-yeB!Shn@ku`d6^SS=`Myo4=Zo~Lsl zuKSMp&i->hfvJ7-x}Q}RLK?_V307)Gn_CHc4?O}u?p=Ej*pgRHhqSvv__^;-J0VBS zs>W04+S$7!()ZJSd}z%_e$N0|)Ka(A+duv&uy)sfb8$EAqtD#MW#Xr&XOvt>=l1tz z9M{*c`#H$#w7Z|3nGtZKlR5tEw9{R?{jKpd*H|Az0pP2r{kcaJ&vZ(Df($>3B7R=l z`U2r_8h(-WNT5^l=bJ7tq5JAaAw#WIV>R2+`cBZ%d=UGc-I=4E?5(X&q&9o|WwCXU zc8h#vX)n12W|Z#Q=|n|OW#lv&eP8yhw>T9bQ}Y^otDVfoBo*b8VtH{-f<2;NGcn_x zOy|y4Wi|i1p4$V_h1n!BQa>ae!cJDkMeuEKH#l%=;v6>SFH$hS2U=|Q=d@1=L2@1xRgN}il9Yu~WFOzy3ZbJd7vuzxLIE-8Ph zJxM+2mL(gfgjMsQUp(;7cUp7aA)j|~zOKn3pUn^aFcS>ca;Cea?^4jhk9T%XKBJzK zKT(}yN*s= z@yY<JYa=eoe{YqNUcfb;xV^ZP!xOmS<01KOEbDN($cilgq-;O(Ehb&oJdpMcu11A~ zp%k<8Dap3yD&wB+;TPi~OE5@;XC>Iu$YO!Pdvv7A&cl2p#0RDR&u(zhsU zMchUodY=lCn$&m!_4rV_paB)JF5RGrwmP^)wdGLGtz5{Mc_vH%!cfPLLSoY!OJsF3|^_h&rHIyCBQC zy?2^6<9))HA5kc)r3Uk*4D+S$N3{CP@fnZNRuO$2(gi>VgDn)PA<64YJ>!0T#cHyP zdV79x(i=sEvb#t1d+vgRJ`T?Geajb@PK~+2LvNE6--)W%@U1!2Kh(kOfX-|4&yBDG zKY1HjnEWX7di6U#YnswF!8>AB*Lk)Nc&j@Y_oVzt(yc!j)qCCcTgv)`eBSP#a>GYr z1hcZISTtF3NvFkk-Oc(YDbm%Fc;pYHA&rHV}|sK2CrM1F+X%V6g_gv-)6s(I}X+*e->Mh z@Xy`Xn9SH$nI`Px>tu1Ba_AtN8zg5tYp@3LN`(4V6tvE#Ac^4fM$e_?|Ps=e|<%dsyk`P5zL ztgxBZDNpV`WhGMvQ>bHjn6LUN(ieV?>yTOTpmh2NL1}g4W@T6|F@kHYWv2A2Z$-I$%;q zF>0V1dCZg?Po^`{6Ko|`8xpz8ljDfD1V6mr6Em5*7A&>OT(Ast}+HeW9G(YAJ zC7!luflyywqqIU@zty^~U2BVa5okHDVE?m_gPT$Qph<#C|DBF}*yTXqR}>HPdbB2= z%by#T=#I$?x`>+Pt90U~h5GZa7QNm}Y4?wR#(GlVPA+mrkZ3)=TF}RlWKbh2l@|~R zlDMeHR#Y*R!Ees=uzVyr=Nv(3mpptLS;L>OjHFC3QQEn_pacF$#y)Bq$lJp~wyT;m z2H*S+uXPbDlT2;8xB1NliBw9~c|ENofitAswG2MVZbupgqzUZw2^sBV+}Aj9 zQyu=FC+HCK<8&nXd^vO^4QGm^YUCBxX+p4>LmZhylG*`h3Hut>vZqR)Djb~o^phuc zk;nIs%H}Rl>?gGg!)gl~Y8T?-uGhwWpO3rF!SV1u#~UoiLpeFzh@36b#E-axrJ}YIbTz7iz}= zYDd|#Jws=EN^5pVTv|w6^;+|<3LTZ1a9t%IL^ zB`ECg@pErzTq;eb5a0!_Wywzj!o}OK=91eRDWE$B%?XI;&w%&qHtVYjI811$H|tXf zIP_|i`ATS45ga9k@Pns0uaR&A&inP=?dz-pcYY%I(*fH!BXY;x;ns+~>GkJ&-KxPc z6wuqUtoeg*G1ijwZ^2Ts*4n@oAth^1y#DpNioty|Uh2(Ly_>MdF=S9xS=N_>j@O?X zc2i);pcOwgZWesI=PSl~j|0q*p>Uf5>Qv@K{^`DG?!daKGi^@>PfvzrCr+`_JFN1% zvx$rXQ=9^mpHMU<26v_d2eh25^d_r(i|v%Pu2-uV`P-S7Hr#aJOXmf>kZFEj-MSyt z`!$a+r20{Gjyf-8Ur)2<%b#9SACXmFV*g8Ut0?XHHq;5`}X^sf} ztN{INKGSS8*)BEtZjt9UH(QGmo18OSi$VlaA)?zfLged&K;J}_#4uC3i-6eh?Yp&@ z`Mb5UfGH&3ey*$7`~Y(>Z=0DIPoJx6{#oC=z4P%+PT|{^geSw@scu(lJmf-Z$16R2 zL#$BQlK_?BKeQQ;)d_I*pQ^qh-8V_*2_!rRG$wFm(wZyUXlCV zPGJfcUSah5EVf&|n^^AXAvkk&4oIt02j8J^q&x}*;(yWu{?eU@6NI6O7Dr&7VO zzx?J&<5y(mpE+)qA%KO&4zPAx|1_x}R5QUEk;_B;BQb z*(O}wrD547Z+zFJT;%8^U-UokzPsl0cE?E)8UNf^NfHScI*?XJ5#zThxtIQXS%ddR zuC27sD=42=Y%+r+szLi7a2tFJ6;yr|RLw@sYzD4$2Cj<_m>yi${PBPZ>C!?gVMTXO z4yc@z7(aEdWyntG$D7o5c0!iXUryS(li7ZAej}xDFIM56ugg45<%X)`eE)q{uDZIg z`>t~v!FD~tc43sUmeIOS^A|_937&*N^+@RKDHX>>HRjcP%~`cH%jh0;ZjUG2)mZLz zC-p}R)IeJ@vs;JeY;v0A3tPS{+uPnza~oaR)m3-iR{1qo@h>i%Us@RI6q%e#>**B9 z9~(@1w0YWVv&d_+AWOC_%Oc|RTMT~S$%ZG@^CS4u|3#>rSfqcupwQ_6aZWJ&TvhdzbzTKX#g*Ijb{j7hAm86qot@oP3Z_MI zglPnqi|{DrD!h29V2rOS9YO4Ps^=x@@&lCBO9d>J^Y04e?+Q1uBCaWBjbN%kzc$G` zsagG)*XRqF26%^CP){xVY@QMeG`t{|`Vur;ERq`YdNB9Qjp}$d{7Ry}w|d)3;=ly& z%az0@6TAWa3q6r+rfAyTUow$w)v<=a*PVz(8qSs6CO>HupT)RtSQT`~|Ee$i=1EhgqV=EU`cuodupk zQcgl2@u-{Kg%sc9tYlR;jTk$t05Kx0mgWpa>UtRU zNT(K_?fiBnwXn?S8nu(Emw3MCna4_J9#g2C80x4Bxl9uEqi??et;4dK)OT4`{exqX zExwZMWhEI+C%8IR@G_K1JW|lfVmL>4I7iVXRHMxDbYC<%{w1x}<#0an(^^h!83xo^ zPUkZE8onwOe^qMJ0F~KgQeV}kvCTC7be+*QlLdW!99IendCYxXTu1Lq#1nCj*Wx*8(s8q`mcCUtZ@N(Ea@l%5>h~)9`1-X`Ma}a~!00V=38@;Ck1S?Mn1AXyN6g9z$ z28VJrfrC$4u0Bq~b5`opo3wFO4k+5cYuR!e~LMf+bZkR?AJv z>tRvNt%+3Ap?Mb+sZ+|`+BSrGDbd4f;l|t+@Ymc<+V`S)vaEuI9|0}`1vAeo{ zh5ry@pi2hRiQSa()|_>cV7Ts2alz8~$wuGJTFN5QjnIW>UuRmwc~m?kEw8gs=Qt;tZaB$xxeDH;k*aE1(1^K z7lvLe2z897&8wPTQMu5fM2lS0IJ>GL)-KR1jf8R`p`lISvJ$71*G}T4ulr5hx4CJp zxFWFXmnqaQGeL@*5NE4)d}wZy5(5dXi5=b*EZ8>#9c9n=78vW!E&|Z0%&Yye`z$4%C|~ zN2>Gttoi$_pf%TO;UbBPMYTCOrt=W?dB9)xYu=#cF z{B>^7x9Dns(h#Y<(%f!Y)9%PAIwUMw+NCGjp;viDZLTb=1IXU0%+48Mds+K>&2-gV zJrk4k5|hH!wT<|t&O@Y3;wS9^N-;5s9H5LhSPeJK;Qg+iwaJRL$>f9jMs*ZdoM^0V zoKKWodle)4O7Qcu%7#ym72{5Vd{4u(9yugGaHk7~I)f43Q~C~no1E`@nj>FL zX>OAcXsx!iYgn{>xRTSg6F)$uTE-xFFU#6 z;Ev};oviJARh-X1<5g)Xo?Z}ioV51jOV{H|4^Ou@@(Q~$d&)*p?NrIP-ka)U#5mZ$ z`s8b`;7zqEX|^w%Y+ph=#7g#Vo!cm^sE`lu_i>@{abcRQF&Uj~Ey9F{YYCTjxm@dT zsk&141%LlM#i*#@Y^sfCNTyy$W;m6bQQhbj$3`2)VVaVppQjUl3c_Oj7%p)oH1+C^ z^_e`PFnPpeKWH*ahAyIt4A)X9)y7_fVXHVTmdlzoxH(+~<0U;`XY0Mr4lnj~T{P^X z=(<(=qOi1U>srTF)s^vXyuW;?zdUI5;HFcq1EgB;tf_t{E02#|Zd1aLt|)|o;nE#t zC4rml)eYaG6bl(a(q-_hV8`TOM;i*98BJA;Zg}kbz2fn%Puy4t|e>S zG^^Y~?a^Xo;b}=LtGeF(RH+nHsZ0>KX_ocfWb3;&Aus#Cc%IIfhxeF&!cS_rXKIQi znLd!B5~d?J&U$$_{^ec8)K?}#Z!^i#B0@^Ex5Qvu)tsZ>@E$t(9y*|JvR|C$W;hRI z;sZUqiuAgQ!lm+!B-ursWbAEza+R#9(yXcqwX@bpyY^jl?Q3n)s~Yl{w{F;Y=TVZR z^E6RM=%!qa^iCh=PG896t&+Wq=Qs2!E8-ISO-dLm2Jq^99+isHA+pbR6EtW4+ROlKRn@_tM`1*V<}GGhu*@tMww$CN5S@y(cys&?i) zO(l1!F6~+o?^vn1(uT#KwhBFM1rqfyYkAT-%R&u8=2l1>e&;m&9%5iqax46)ez?$0 z#@b!|)1jJI1>c@+!~5Ii``dxmo|bh<)&|?#a!=iZg*|ERDAhKXfSK2FJ{-iOfiGZi z05PPM0hES$?UiFH6rjLqWlI^i`^3MrmftnHqrhsfU>1MU#gn31kD@yKe9v#xkwpHX z3)7}+m2}DwXUb5Bfm6w?;-~t>LN{LqI&Zp3aH`(nRGs&~m+yZMwDzW~>yt$Lr&>;q zVf-Tx)x}xCdun$)ZR-?m>&OwKM*NRhc^{cQ`|h$)CNA+y$%x)7H%9Oa4?-6nfGXR{ zx@aXkXzQ-r*mvPht~#mdL6Pd1WqUu__P$M2egCCtic8Z>1<%YzXS$2JUxWu7mUbCR zwj0)Q8js@5J@d^yLGJzId`jZa$t%6dE8l8+OKN!6U6~lghk1pDd4a%VWi4~G z?n_rn4~||O9BsAtDoGlpNgNe|J*wLs4p>q++va*<@vBXYYEtgx+!qji{k9!b)84lknCZ zw*Dt&^<`S*I4=AYd#;;oB3165jt0D&Q!q?ZAtDBRweQonkO7gy^;|N~y zr%}ngY$je-rgW>KVXQ58tS!`+?jO{)vQmw1M0Pd%dO=OY?&OSkhStTtc|1b|o`LSQ zPHDN^!`E_zirq<4Q9M8vVIz5{j~9n z#r8|l{wt-Gz?Q-7*K>Ao9?Ve)=AhH`ZxSXvyhtGApg;XPYV))9V!G_T?)?a00?uDH zQ>_g5nDp#TQ0`5jR8g~JW|LxM^C42$yAkEz*gdi~8{9C(ZkV#Bm z7ZTKefx2JjqQP2&?w4ZSFKtTV|Bc$a#?1(E(q6W4_eFM2U+9>Yx%hmo;a*qqy{@)O zssBa+J$WJeA~uUzSgk#_j7`6u>hXCJxk3^-I?(pmrm+<3uTv1uEBIsYhLR_5jxui! zWy)hqV-jgY5??sgw!~z|;A3B^C2nuxX$i>juQz1&!Q!T9`Cp@^GL@?WWTU5=({)*-w!o;5ksTBzydR#nQ&)NPq zkJBl{>Ci>XH~$xEtvfO~9;Oq{SYSCWje9U3Nm&=`ZSe$e@C0vj{x#O2h}NNqJvsOA zd;&GNztR`piT4yLQ5GtptSPm`R!aX1b!;Xb!h(?-4V(kHoCBdDa3sh!i`rHepmqb# zMeNzgyyciap0gMDmw3yxXCUF%E_?CI!SO9~vk5?AH=1cTn%Vod zd@aW34aVnxr+`I)!I$bQVBhDtZ6dgB=%T{Lp&f(qiGGKNFE|YZq%WFn=G+^cuXHG^ zbfD`@Z5B3r^e@y=yl&Y-&f#F_?j7X(i!A&L+0vlRhQq;JA~kb-gPxve((|)`F6u%T z70=XQRr<75`q+O_q?mm=Fp#Q!JT361xg7nd2)&sD9-h~@SEzB1PT&o3aB)hl!|T zVn5xNOP(nWw^AA+4Dpu6#W#+r!(+F;+NSS?)Es5g7?r)~xz*4&THH6ux@ zO5e)4JvN`=Q<&jH=RDn9p6+!_9Ud!w<4O3ICG*%G^q1nr+gkTfJO;)qHw;$%bl)#~ zlA~^sqaqmhE&ryDkD~(LHi;9KbtfMkKP7FCJqL z$TD}Syua(bn-3(RJs^{r^gSAVL{LMP~~09#v{B4iAeEf;8Rdn&?q#4P^o!Pq2GqL3zTHBZ@ZQqHj+Gt~>H< zytH`Ltj#qL^0|qJ(hyx83mgFso>M8rf*;fsg8KD?b+m zE9#qI8**OHX?}uT6ql~S&f54r1#S?YKpP#<&;6M+qo-Ua=#CMiYg z4e!x~eC4V*cCo!}z)T8&H)z=`y-v^dTrHqvQ$CD=QQf64&<(=6s7Y6|%_$Bi5EYt1 zc1er`KgP@Eo3@_gg}^pzN^c0y*(@glGtNJ74EY+$chOQ(ajuW-WrUV4uw<9h3X&=8 z9=8Y$&ov6~UzS~XwF;a;b|;1^*K>rTv7-jkp10;~BvXL?tfW1uFDYG2n(lY5uCaXK z>ze=qjRZvwN|SE4(R+0K<*lGJ_D!!HK;4Qx@yGe_d9sK3&rsZb^Rd_1q`TI0e%?gh z=<>i{|JD|J4bY6l=^RfjI#cX=gQr&EfVk{Ei#1^KpC^2OtmjZ_BmI7O;Df)lv0n#7 zYejR?wdpeE)*C3b3)!#BE(8-r1xNt~Xh1%n^Kg3gt?jn-FHr#Y3a zRKQ-VunXuTI}PqB(N$6cPf_pbGn@1+A`{4!zg9;Z{P@jOYB?%NX& zh#ABemE59hl-_74xfM~aEjx=pKF941j~_gZ$g7{=6`hNYT_~D+L1Y71^*1u#n;SWw z43K^|J@Hrj+t_abtCrBpF)^geFx+S`F)X}oD0|Q7SQPpzlQubPgDnBvzOEbJBUeJX zSVgod#OK5cPa~w+9Z$!s{?GxFV^`o){~lC=J*bmjAIB>ml^su<1i6PJj#fq15WJDY z3P&~ud*Ueu+U{HbnwSSpCmpiUzymLgwU%8twF!u>k(ows7(=RJce zX%8^IJueoHbt6XgJQGM1hCT+X-jQ|m7?@YRlf{y?QPDdHL>QL~v(E-XWA8REJsT*t zGo`!n>R9wDWKA9hWG0(h-ydno%Tj(UjFHL9SBnmQc=qX0sQkFW;c^hF`71K$DCqED zck5_N`PR_B*Vfum(0!ln{r&MHU#|>*?771=B;l^#OZktBM~7Jdw2~HOwWB?&`EN=2 z96{4TM@EuQ#@_my_-@}F@&9s^7m|NC(+#^J~J#a;&DM7BunjLK1b3{ zP0ueJ$+^i7dmow6>3HnjteJbmKP-J1Q0?saLI=A5YitOzxW9rW%-hZQ9|m}4`(_=j zIq~(xS{XZhN4WS$F)d^DJU?|%E1)N`r>l-R$Ur4 zg~H=dnm))#-!d(3>oDN{)Xt7L>Zs)c<=XxWEN1oaz$SPLWrjLB2$BsvSTK?Dvu!>~ zlewXfcrZaJ=d(tc)`ClVab)v3a(nX2waoRmR!kqiplUa*&0c-a)~p4EZMLD0x{sEv z?vM^v`JM}FJ=(=yHyfFoxuBW9R%#$m`bn&zi(U4B$J4R8S=;N@QNfdYZFlMidsY@7 zNwa?}tn_D<6WIM!_{xb@?pFFo{?3euDY4>@{O?^@<%Vy@=m>X6_&XG!@`iA?6M;HyB~?hMu&{ZrQ{l$i5*rKrs z{)WRXt&0!Fb9OpcQZ6ymjn~ERi~9S#2|VAD24NrYaPo4_vU=htC$lh2tFcH9YcQ2yAqrjfhr@_nt&cz2Ugc-O`Im8(_k>+vUQ(xr21S;ox6<4@eJ zjn_UBnT4G`nHL!|x8`?@=f{yu74MszrsdrNI9iz2(f0j^q+k~4p!1u4*Ew4(t#G|7jFCq!*ZBj(;{avQR9Za|Dd88(#V($RD&68> z*zu%Oa~&^x8+3kYXGJ4oIkf_H8c@@>iN?ksB5hJvx`Riv%5f9fq>YWU`=bAkudjfL zs_Xui?h>R!MF$j+7`j71loS<^uAyZFB%~QakWdL3dPE69S_Ekj5EzD(uAxSx86+Iy zyEDGe|9$@JTi>_%t$p{|d!K#co_iWl97Z=(YWeS&`te6wM=ON}7IgS2ZHsnfv}_(v zAJ1C>m~Y_;{`~uN8oi@Cmo~nh%5YEp#0e;`_Sr$_?V%fwto+9MMLT?3c$ixFaV@l= zJef?p+TX;u&&Z?OZ3kkU?w&lYzbz|#T=5|kH}poCJ7;YtpUxjICUrJLL}OR( z*&V+zZN8Q!0j++pUt>WdZLku6ec&uTP=C$jO+U72_1Fpt*1i+%{3taRkl1*~_%wvV->mFIKnKBzlWZ%qf}h) z$y9+p^mapU8cP)iDMgPYl;O_!)g+sKWWG z&UF-!H1@sz3PBvX%d3AYUnLqFoHKJALW`MKtiN=M*LZmziD&htEkicFWlyK;-FpUZ zXXM68*55qlMxFVFI1DdmEZECB!A@>}IF7xWybei12kGpQyaj!Ee^%ZQ`Ewk7qF8Vo zpqnhDK+r5@taeN3l?5wCW3TrZcxU9UO4iHou%q5ytGCz&-nXwGz0)^rbsmVVhNt8B z&9b(p-YpQ$I(MC}DK~aGFJyeD)Iq{o{*@&@tckmJL?09z5|c(+OR(mj$@}G986w0tYQW zMq6P!nyxo_;Nzueh`4kZtVKU0HhGo8rsq z;Mkqnw$Yhxv6pqU>6^Wn=JQb@8v9#+sv;X05Q3V#3!_)`>H4xc(|r2n@rn#%piZ6( zSiZ%VI;+L|?ThQPfk5t?l0kAnad_TriDIC46;m;3ICJ5{FQ&sbK*`4y{JKrI62<$! zXl#8F@1ImT97|uFzT&rPx`iYN*Z)PSt7a}aWZa9vQ_q+gV}~?=zILeR?-8CCsn6}% z8*E$&0rj2gLh5(E&l;vRAcT`}=35^m`uy%~eW+4&YxNRHThSNB27OspzSS3Okyd!k zbc?uph73|qgY;rcU!kH)3;Zs8_zI3`xbBx{wxtRlaJ;u=T|LtR2`GzN*^=p-^-OD+ z7xrs0%PF?4_d|JYXRXZ1^>(l~lCCYt*OoE)BzCwk7s?#@4mI zV{|Y6THk4L8qQecu<)^$_NrV~Q+9*7h~JmTUf3nMtmf?P&of+ZJs)1++YjKx>C;N_ zqcohC$l=Q4tv-<$?5Fg=2$4fl^DU~{W#3wF*??(p?Mh6d-2hK#4(3(BmiEC+(ndYs zWO7OASu!woJl~2sn4#IMXPd(AOAlm^<|q^^`P~oPdVioOSH`XH_YrgJ$$;fdPD7p2 zKqGdBWUHQH#+%`&LC^h-Ds_V{QEzX1*?>=hZhPAKrX&Bau5 z4%kZ(l6HbArYr?0?}ds1<(s_BKpMbH`G+Cecu|gP`RUbxrQ3h4NCqbJI8lIJJ%BfI zPm%H=J;wc2cadU}(J9_#7Tq3W8s|TfzI%?(fTU8AGeJW%;3bQxR9sjK zXvGqo={{fpk^%L0d{}{^>;oh}a|2x(LoHyOv{Gq0U|$Ki(NbjiaYiUrH@@|v?0*Aq z4e&y5L61>Pi;3++XOUqAz2vg0ZFn_r#dxzKVMxGRL;&qqZj@OCr4gn>DaqzgF~X9* zP|qj3(3>82TUcTQ3Sb$w5>%m>Vs=0^A5fqr zmxc9H%3@S$;C}XUOZiXB_WHoQpWu1!c{hfB-|zC?Q;I(r48Sfm|H56|Uw{5k|n{=I_v+&_P>w%jdiw?}2ZY_hc2II?OL^lHKGK-)4F^9k1#39Z*f=SKC|Wy36cH@IQ;YM>=W)#JbAkzHy}jNTCh3vkh{s!s=Gl9BNO-R zcqEByY1?}HBs;W4bhg1{3G?}7vP#Pt&f4>=(PT*}1o(68bIl>AhQKO0IP`SmLulyy z341f!%0PMUdGPs)_esvm?twkZlXmm>k@2}=2rt&TyVLRTT4+c!FZ&cuUM4u+s%!6f z>o@kuI4O5KU}igK3>UK(g+6N-7Yrgw#}d7>+=^j%fy2nX{*t>P-oIACvKfpR3yMD^ z%U$>r&|ViBQsC7bsJH+Al+5dF)B8kWXlWDEsG?d{lg9j_U*OdtnLNYg?aZ(X-*NZz zDPG}1K43T3F%;hqF-|uz4db^Bret2Nds;6Y-d6EcSv@84I(}zxd3?b8=5|H5{W}dJ ztuL5bSLFr%BX0_okPr|)EpNdv+4C)_=LUP&EqfHj3!HK!K8H?MyOkK`U3%S=)Ec)p z{UhqQ+XP;$W2hF-0vdgq0`;*P$K+2>XWjO5mNB#4St^$sNho9VcAvaICw-dEZVj}~ z1tRrZu!A6Ac}}!@dJO-5yd~8S+hhB7>{o6S(|?qOrTEq;cV@^wPqFRuJ(sQPMxnCt zk*Rhr-?qw_f!wo1t70uoLr7oo`JWTN^SdAU((2}vd8qiN^vVq+pXfY`N0qf3kn>-a_F> zG!@k9d9w^1ln_NV0x2?W6e$hx--qA}Dci6>c?LngDQm&13vs?-#Mm>{T}{I>3XIQO z@zbQ93?i0iVP4tLvH>xwINdO>=3u>pywfPJvlX{dHr4Qe&^!yGb*|pu3t1?IfJO1i zrE5D;dmYaW1WgK-@$DkoOGUPDgy^nc7(U8=&QFYG`XSNElL23~dcLfYfWH22hr&~~ z2#zzO7i^MBcIRJWii$&-7U#Vb6xeJ3pKGq-YQ4BKYxlIWS2Fu zv#z0;q{}%wu7;(W9az8_Hi4|XEgvH1BgUMDdpUle2TCH4a;SzQ(zL3R*jACv zHKbGi)(3TLWcF0aV1iA8}UlA2!tS zc=>Me1&Yh{ij+2))dS_^}?zE zeU(<(!%Gps%WBzpu6{gtrY?8B2Ye#?BxI|n;qC2{MzRXjPEP0z!7QGr>T0Mj3o5aF z(hM)uMsGAgefeX3Rb&MmE)QAgysHnp-O%U3w@wXxjM>IT=3g6{QGHh*e!Byxhl=7g zXIJ@*jKqS1d;**KUzQ-MoHXH*yq*q3djW&^Xr&3j9wYW4u@^FFrTWvPS|W1rox6m)tO{%o0*j_AQk@XkBYc09=vB>J#4GjTZjxW zI&TM*Ap*Dn^DoR06M5S?27Os-0VLm_3k7XdSpAW&(t_DyEexmxVgV$>rYK7k^QzxF zft1b2$?`vgf4|3utRr!=OJRH1l^jD(cGbfHuDc}s%g=E+r594LqSpC9m$}^z)J#_6 z+d~))wZCZSPZAcg?Un2ysE6U6RR~{}HEZKrz9|O5g{BkzeQcTMT;E*6(T63Uxve9C z6rGcI>ph~DWM2e$o%k5^#b}OJ-k(L`n`Prt;m_LLJ{yFhp`agQ@2r|&%iG7cvkS)T zR4YJtldovfWhCgw(n}JxHxadGN=t_9Rcfrq{a=}}Yi#d03~DhQ}4IP}iePp5Tng=>e7H4-%R54KHm zgutv}9HORh`mH3ONff|n7N6sAn@qhxKLLH!0ra8d)Al5rm5B$Y+JU9{N@GL3>+VU< zYP#j8?0N9w3DrRNje`k)y=dZ(d;TlplTjbN-hJe*Q==&9Rm&uOxI+9e;B zUN0vqZ5b4^biSa>n`P6L{9E*wHPGF)bdfd6${sS)drGwFfhu~mV0zM4bv=U*C)hkC ze8w$3=jVB4;0qw;8HXy*s*-#Z-O6*Q8oWZn1Kk^c@VpFJcT=EDB+ja|8|GcoXyd5= zi$Rw8(Q3{H#v>g^kyv>R{K`R_c+~#uFca;asv)a79i2D9d|5WCZ-Sje5rTImG;|;h z*X-{F+2Tq(Gdl@=Vf~S4=Vn}{}paLX&!?AR;X&`U+1cBzOpVVu_En8Rim7PAsdi_Fo_JR+IEJ;KZzP=o7XBckD zzKRl;cd%`g>G00yC@YooknAX5e-*WhI1M8vOkUV77`8K|+$i#^Hd>dZDbOGws z*oc6whybIolMtxd(?|(MYSQo80wMVqjsZV}ZsxM;S@uuN>}Rs?-5E7KtkmOV==XDl={^?PzoM2Z8QndUO4?LwZ!Od z7&Gd&EDWt0cA_wuq#No%w0E3AOYz958TyR19QEzT6*F1?XLmq)7TKC5-lxC00BhVY zNvrGvN(vLF-Cw#EJhXQcdP-nzi1ke_l#OhiJe^75X32>EGtM%7*blg1PJMcM7-ybiC4*;MCGETpJl#Y1rg< z>Z9Y70X=DJ8?qS{QL%Xn0rm>wTR>a2Aq&FydNM*bUTMIs=Z}Y2Os@^V2~WnFRV7zD z2ta!Dk#DlouLlC3A2oD(rrM$K^-2&h%gDEpYf-sWrn_DzL1O~h?G0NAY6^y3={x?j zK3+%Ef}SyuU6yI!vw*gGN?$sG7y}Qkqkaf~%cT2)OeS$ib+Kq9K(}vi!&u7Wjk&$; zsM{N$oAnZRpCS*tgUV<@1^Ra{1S`t6sd8iAokiI*c4wuZi3Pv3*B5wu40HfssAH?6 z@+FH^W5X5ddL+<02cNg6no*Kjtm0dq^xNb89>bk!`ML|C%9qr|fmYLN0}M4`G&>qN znochDHmTqJWU>leVD|WQ`Yt5S7!5KOgA_#bk379Mm8M`bxn6n_1l&OYh*I|Jba| zL@$>;cYlQn<2rnr8bgT*f%aVst7Zq9Q;~1XHk7p^yz%YvlfvWlCnnMMloX#7ygn%N z&Umd+Vg7dfTqt!}H&}K!KxyeqT;{nv%Fkpx5JrZ#5gSE|bZB6}o*nfsYTC zUtqrx@c&_E_)*@Kg00m(S%TE$FC!A)T~HbyF=NT2IDU?6<07TdB+7ZYI;BZOF(^R( zUzj;Py^#Hz{9h6buWIhgPee%e!2D2kxHBDX4Y{dxrIf0?eV&xq5T~g#olU`%MW$4R zm5(maL=1P*rH|94chaMaJG^(q>5To$zj%rT>6$}zary`TT$qq{L`N&|%3(3#Q8D4M zG2!7c;cWy8@PLFYCVcz0f#9^QO%u=ul859|2u2%nBl2P}e~zOftkTvf$AU*92V6{+0AyO@7FZQRx!v1eb&>| zS|Pd+0<97|B37>9Gi+t6sGzj_+|O1Kshgo3&u7MY9%Ew{QMPS2WXErT zPMI{?tmn@{K^Ic$_oLcj`f#8}%?gLgceEKpv{R=KjX{OOz#Uxk^t)eVQ=i!0wy5gC?REfd5h4S2_7@5yDK9sVD3%U3mau zerfrWhJb%F_jHiHkxR4`ClEmA=7%WXouNNhuFYdA_5k* z;DYHCG^>dbldq?<$f}phwh3Wi_+JENH`rJ`c-mZ1;nXBr^1S_u7>^7m$L*IgoSfHr zZlY9xuaQNXla=Mu=Z9J4o$3MTM{vOu3hI?ab$C1ir4FaNNSFfOMl?cSmRSml)@F%& zy6e?s37DfuL@`74TpUODb^1~pmYP9C3Ty{z2jL}vtPL@+&RSXI1!X3}fR zS&o4a4G>3V`c$q6i+=oZqFlG28a2}XxIgN12928(+qmnk(jOM4CG{1LywyIf+P~ZO zbD0xhDV0B0uFIpffcFTIJjA%YN_+PayA3nnZR^#wf;;^t%>y4Cd^X~n>Q>%t=f`T7n4`NC9hti>lD!22mxmOuO1~rxuwmRCma$CGWJ}x zghpshAPc>!gD0Qra)e-$JTD~#c^RI3rVy%T1Saz?PTKj>*REzXqV&i9lY5C_9Tk1dF3=wW}kCq+EpoF z_5EpBgyP66rzsS;U6KDg*sv^^lJPOeGDp>~I*Y*SG9WruS0jgM8UD!vhhf6TUmmCl z7s4(B#r+PZ34n+X2uH0o0-Frq!E^yyubdn(9JYWphZ;V;n4`#4wHz}fxX)HybQ#`- zPar~(Utxd}?}u_v7fcFMgppahi4Uj_{Wv`^vAV*7kNP^>DP>dQJM2^#m|1BH8Z>N7 zNaf`Z-U?KdMbJhL<2#=?U-*_Uyvnj5I@5gtl-bym<2$MCn7kQgLn<@bt|uLkjIbvgPp|K9>suhC@`<8gz$lP1|LtB(atwBi4#q zdtVIqN_M1j)JechAgz%ZZFoV^La(p|{8U&YN?@LXjax$&1(k2V!v9R1`+g7)TDC(x zj3i1x@{l=kSPQnXJP@Ib)+MdB$$t&MTd?rt=B*iLW`xg#^Q%jGSY?Ed6+BU>+QxBT zQ;47LQFQzR333^GBhJ$JW`9T4GTrV}TfWwT{2nN%HQcJYTMHx`2Q>^c|#N+hg;P6pTF={>e-qzE(G67+KTFMK@_G?=E>=keZ9`?k>Ke+X@zm zTwXlEV#w9u7c>on48I-kF8p2YCmI^w^I*c{YU^hrjZ7xK>D4+XuhB@u^LFy$E4pFE zjm^+xkvRuuX?T8)*SrkJfA%a~++9Cj=GF%4U~u$-q*Q{Qp0@GG(CGf`sE@Q1&*!N8 zVi#vu^`$g>OsiIAr*P9s`y#)pD@GK`@ z3eh&M-Y$SRrA|H_SNMn@zKZZ;RaNhU2k^L?BZiLhACZYOW6xsRZ&v5``aFQ6@WPuP zbsh1RbPo%v@j{-5kokuMCj)-}F?rMfsZ^rpKnfoOVs3o*G^Y=1?0UICJ9B8slqe3A zh#9RL4Q5K@=eC!nhLZ2iEV#GkYHuJo>JAm2J2!%}h@kNsF>Gz(qf61eoK6gS+6?`w z&0GyJkeyiXh1lw)*pcIJF8+&>RacI_xfJ!$8DyaZP>BMlZ~;_ht}F$Btur8)D4^fX zj7hECk$PeHahBmp$MTII@;R~!IkFU9vuR^HSZ4{AndAH`ESkXVX)vOq&G61kE_I_Y z2~KsjL@tZTYvnzUu-_~hWSpC1#MRYGCI?-mYcuFRL9|Qim&jpUHN4EHjSaJTzp*bq zt;Q;Z z`};u<)TUNosfmA@fv_F)dJ}^>csUtzW!k_27w!&3zfzg$bs)kYrB zOom*=$4bOoDO3Zg0q#ifLSSdnd`i~JI!`c7N3R~6bqi*4ZTX0}B$;)d~nOxv= z-tjwO%%(fjU!~wYNu~>_bJzoReK%_@C62Lo*y%Y>4AX*N_(Z_S&o7U}(4B=>ITPZ= zRBd!S7|3R}&CC8SY#Lm!cHS|NJ_208kbJAY)FmySepGpeiwKx~=HcgUZ!lL$4FZ@0(!AYdsZ#FahIHBj0( zf4!iY;g;afKjuIGWC9Rm5@p9qTnxVgN7{uD4TQq% z?quMooW!^Xm+6?Rr(PT2r9Fo0>K|ir`&E@G+i}jMroX6Ojc)Z1zuz zICl(OE8%eqP{>5X9Yx>}7mp)6B}sT}0PIyI8j>OaBar)GYm`-P@Nr~2dA~X=n%?&% z9jCI5$c#g>38UP?@wNp{(RSY=!5-Rb}!|B<`Nq zpZ$?4yQ~b|65w_OMhp3N4qD740&PPq7Bd*}T(NG`Dh$jHY#_x!>ohtB`1b}SE^0T%g;re~7w5+{rgsQ3J#)6D~V zpdd+O#f%$q4B68l@WHTZa@s(1P`h~a5~b7CEMS;xe;R2|OVK15ZI$s!r*D8?Ifp|+ z+(PB|stzehclFqg@!)UcB#JL9G+cB^PI28}4RocY3edHEfM1~zx(l{-88gfnlKWgK zxrDun4;Bda({^@`d9GrZ_=dzvr+lt*%fFKfxWcViG7N_*fO~1sJ4|}JFQTtlX5pw} zu4i1~7rHB{84D5|`dKq&`fe!J$nf0_yaXbsT6-X;l4SbM_6ek82H8~)r}GALtwN+x z{qE_RlVUQ}PYH_Xdbr0xzkAmK91#q0&b=|^G)VW;hQt(@T*5|}Y6e&~!5TQ^AotW) zA|3BENTRO0U_Z+Tc%CG43Z#8l*D!1V_J7e+PJ1a68WIEKT=n-rk@2bL=H($bFQ5$ zE+!W&>5S~WcL^GfRMv~3k4Y7`;*en7#S0`AUF3N;YnAnY;$_HHRpd*8(;#ufy59{Q zT|f?E@9@FIVWd&e(XD=2w_4jV_m0xZXtQd%Y6uskUmBI+kuEhY_AiCUK!!)QK_>f! z&}}_a4rLG5?o@>R;bLkV)r}nK1cS`PLOt5%FU`5q3OJPf9~5`6lQbjk5$b3`FJ}65 z=VdckV;-KrT?$~kxf<16o!AW4p68fV4o&ACNHscP^ue6~Ga&L{r!Kt0OnZLP7k4ti zk4b%M0jCmL61`wgXF{$*mik4BcP9G8+wmmI5L5=t^`L!gx!T-Rt?41_>{NLTlJrER zLNLCFtzmy)N6Y3~tK7vw@rz-{q#h0TmM}xhscl$0&pL@X8(P3y6ulKkRw74P{8ixZ z_`oou&4n^hW$%ul)#zhn0v0|`O!2oze@o}jJ8fWNdAtg6zK5YBpl zY0a{Rn6%U}cM|^eXL4wi+j%l!c9h%QmAvs-;EI8IoyT;{|^8f^;#)=9}U zYSLZi4s@~7a@(|E5zd*}pcib!BmquzG!MBhMdJ7T$;)(sw`R(L+;g6u?N>=kF(Ky( z$Y1K!B_+`j*yg89FHZ5<3x?+E*f@%SU|JwUQoyKadZzhAsNF38j#V= z@%$gfG$4BBa-u9-2p*yko1hpRqF6Y(k`;U*k@?q867~&}^q(YQ`s%=}o*s7r#2YN| z=K}ek3-W(1Oz^ZTU+~iL*(ajiC(;F==ru4)Q87Ugro->?j=`paAupdHEc?m^$>qY^ z+I+1xe66?nE`UmFHpxE$(@B!nn%B|4FVL+MagLExC`7IkNxvoibD@Ga&sIsb!zZmIN!=h3VS-6{!3B&Rt89t z18Yss8mMmDrf4XJpX`u%cT>@^Ab|q`^)}sl8Nk^~GBBi-+x;LChR;dY-qx6zn0@T; z-v@N$1S7bN8#8k6>Ps^#XTe)F=>nf<9wT`~R#B|p0wla5t2!mbtktcb7bUlusm+iP zsho5|Qk*8PlBJ{0uta)yar+Ni9d{GD2y#*(DTngWS8w-v^AsNwjvm4z0tV6HWZ*|} z)}Enymm-IsI_u+Cw$e^=W5_kY$Lg+q--Z&DNw$x_}DGly$xDlr&oTC?-cCA z6_)-0>-cak4{xXMZonq{ZTX1}s;F5G=2?!7aa%v~V-wI`ovLZ{-swv0)`A763qj zr);Fe_}v@O6F^-{MjUl7f|P*Bdl8&zq*B6Et`-+ZE3OsU>b!#Lys{x+;uAn z7iT*f*4hrcQ2!CcNBZ5dh6PR8;esFJH!okFdH%TKca6=uO8{EU2CWvB{V<5}atu># z4y(J8$OJ*T@u@JBk`XvF0j82QxBMAfe-(87(4#BKCm7cRXt_89m`MvfUcJC`aWyUaQD<0Ui%7FUq(KQ3U^b#2x1aWt;WAq$X%{4;Vb39m9J5lV zik5ntP;d0v>NviK%9+GvzSNy_w!y`zw)Z5xP!mfBcCpb8PuqLi*BURQmo;!iAJAHv zbwjn0%uHkA5%T2gC{hBXTe#NQ_k*d%vi~Aj;JNzbGurWNs)8201YpLpJ*;FBiSrKc zRcz_jZRrA3?6>~GSFq6-c!I*1^tbLhEyX@grKFyv-Jug7yFpYxaolpvOvGp!d0!(E#Ny4qK%W&L_ZJP;^Nzn%T9;De`xGUXIZy`0F}{qY`W~=pA09 z%N(geq2MIz)2gn-U+Tp2n-+5MZ+2{y=gnOeWis+|T%x(?R65;uwDOlO;q#bZVd?z3^}Opy80PVaA$B)X-Mo~a#p}wg=!hqc z(M}u)I)J!u->l7bjDHr7uz5Ht-Y#E&NObWjvga9rs?$A-uShf+6^~Y*_2ud4Oo)h$ zjp$5h2bj);4b|nvuKw3DO!T<^iaH~)8}|=i?X_`-W#ksbptcQKCw zH4IdT&E5ACWlr(Ikmz?0hnxyTBZnEOzcTb_eyQIf4Ti)igEe#Eh&x|qow}qlBK|kp z|9243R*gGT0~jOV|IPGT<=^Pq;{Uh85`lmPav*o$0YXq(nMv}kBhmzXl_INL5T zs7p?Hi9J_bQ??7rjn3N~1a%;)-|=%N4zPDQaW8?JyPfJb9#s4n`?6Ik{SV>>g7{{f z{1>?52W%#b0c_ynmVj9u*o{qKL9)+6Tg7Y zQ#*dgdZ4|iDbfzetVXY8ov(5z5DKG3lv`vfKXWJAElrJD9b6lHA^ zYonjm(HuuxpcCnKHdC{o)(#;M2?PL5#k0>Fho~3WA*4~GJa0d35+qI=d=R}i6tDOO z;5zc*OMt2r7b3Z2XVZ3K(gx6ffc}U1kEGFj@@4o3>`>`a?6+NKNKNOCGsszqlCPgs zs%~)z=?p^yDxIQjZE!Q)ogL}RZPQ_-o+K9=2?6xK1AjGdPNgre1qpX_&BfICtE2Jt zMC-Z0vSQCM7a0H?_5zZnO4`i0d-F+-7UROE1pI%PK+9^MN15qJTpIg@m>&g*scT=# zs-~_Tend=3KFUmVWoC~3u?RK%TTxX{lgvMo%ZoAoy-_8*Ax%Sjo>cIg#EZ2yagQaez5;z(LG`~KZ2>#HLv(D0=+k? zdaq$_rn%7kgFdSQk?e=Sxy_^zu*>&%>o4_T!Mk3`2k=C~o?Vdyu1tcWL>H+WLZcd{ zJ`-`1dHd5PVCT>0r)KKfcOjmKAjs{$iH9JQOqxgk#mgbv%!i@lEmB%d$k6We$ z{AIMXJs!dTEdcny&-FW+HW6&$R92**Ag1&MO&dF(8AxjEza@aWCxj`T_7R)}pZ&E` z2_PeL0>WKD_I@|bg_w4dQaoH$O_lRa?IGKba2bmr+iwRLvi*$@tHjR_SnY|LphQhJ z0OG!EknKwxy_YjIp;dJ8Rd$ijk?b+{2pYbYRJo*6jn(m9(DBa8;l$}Mmt8%=>;h-8 z`co+V$JzoS0VN69HOo@IKEuAg!}LDGi&9kTl^TYv>Sdc-`gj}c9Mw>F*n{e*tw|G zc5grO-vLq}fHZ!4dQk~oOCI4tM>@?(Su4fp?sj=%OttP)xQ#hU+rJdAnm&c^1cyZ& z5>d}l2>SEoEd+-xE~_k<7L0K4+Qa_}0BvswU!HEFqumtF{HGFvHr~-U-ckOTUN&vb zC#2hSwG|Ig!F1n@J$xoxO>D)oLIGyuN8YwYyYU1AkiD)g+K5>W(grYP!BpQ|wi<{p zWmi2(18}yWR==bMx7b8cIC}Z{DGD+u3K}R1E@@tsID|>e4-5L=%U=*li1;E&JvUre zKY5&|TlS>!gV9c!R+~8|nWsz2X_}T9cZWq07pO~&qFYR%OKh?SC9dn`>lbfJpJ=Ne zZ+mO>o?DWwS3Xsn7IQ=bD3VK$QaWRTd-ElFaE-@Uw|*$nhM=pG$#~Vdrjp)rj{jyy zLgfq2UsX4G|6x#Q5xHlM}zTlC!WPb(4)bb-9cUYLsSgJH)shF zu!9I#M8JPhjDFFu=H#du2jJqarjKdQRJR#u0G}j{K|G$h{JHPHPtA+=a7uSVRQuAp#Z<_4#t6 z$AdFN!W{n2IYG`j{?1(uZVsCq@pj$y7dH18+tMz#i>Q&BM^M(1G66b3Q6y~VNpc7GJ^Rml9o zm1e`|>de~hiV>=A=DLxd)p6~TFokSNUwNa_{lTV@*ya>;-opw)JlYy+!2+>~n>O>x zkI9lhMf_k&yqeX2)3DjjWH-*TO~^N@eBx50oe8;|_QcIrAzv~e2NQL`f8C6u6u>o@oDoO?IZs972C(gw?lUKNSx zH+OiI9Qi3i4Mkl;T}Kdiu8Mq>@f;erk+r$R-M&K=^C=?sQQKv0DswUzH>>j{;VNqU z(uIT4shT=PRP~YYHKWE0W=F&hZ8WbOUsdCs>C@Cu1ApvvgX~x^#<7rEij}Uq0@CFl;Pdss7yW&Hl%{`vZH2Jtx*{@$lhd{KNjMQ3WtXgCs z00F_WH^qjq65=;2$km@lUZr$=N$qTm-^|V@_V1`&pqrNHS?Vw%+GrB~8;p~255-Td z-w{v6BiPm3idx$VxaP^A4Y;!qyIH{sT%zq{>}9=VxJCVb;?kW;p;vY$m)puzC3;3W zjKX#1SYJ>J`jXw>AZQQERHx)M)+imXu*6df$5Y$jToJ58z^0}-L!M-06(exQ36yTy zMi9EM6gkKIpR5P?1NrXh1M>Nf7=LGmHnK{StfsQIJ0b_)Ipx(_7i|i-;(De+-o$h= zQoG`!r+8^%Yc{8H%Ac4tezn~F<-1ZcO;-M7{;JXjD(?l2)ofYNvxdbVn{g&z)`zqdFTvE=?6%VkmXZ_}oYaj&w~HI&*Cxt!>a3G(T0m_fdcA-SP&~S` zHdn3#te5=<=FKUIxqY34eFz{hrLj=*4mCgWIq{;Z25{sohaIKU<-ayIg+68*sMf@l z@#!RQ>NYjM=sX1tU%%)I1r2VrZluOm{NZcXg**k=*EcG>GtD}{#Vz`;;BQQ*Efk}) zYsJQ|SDOs7n^87{MTngrcKMLk)szVt2X^?Y&XMi%+7m@>3heVFb{`e?x`;3u87yLwbR|vToJ`={ zdjDZU=U!!Unw@}1r~YH}?{Ntkn)FvCT`T?(ef1l@Z_5^)M?<3Ea>IA{{>J;yQ6&>m z;aB(p`?%~H76li=a?X;ymz-`aiN}jOuYyGb20^G*Pvn^`^QyxND%JR%2W>Vpemxn4 z+KY8|*~BHZrEtM+NRuzia*gDlyK=c~DZ?nUs!G6Q<<{)0)g{ zD^Z?TXI#*Yu4bgKFOEd#HT;Ys*RzLd4d%7EX+89VMF(czVEuOEK;C%cS;545{8dlx z*{OHd6YIK_<8ZrjaHqQBY+!bAl{oA$jaTAS+)T~BKq@k#~NT!OUe}O_kB-*TiP{) zpF8feUbKdln51iD0;gs^c?r!A-~6tLB5_GqmIO}Q{DNnZ8oRZf(7_@XpyhB$#c3rV zjO-hX?73ar-*jr^sGxmFNf029<>9we{L3t?BwYxQu!-XGF*D&F z{;Taz;w&ds9#>gtrEWxLROsIKV31O~v4}rr11|G}fSck`Cr{c92Oqf8AZ&_s#785q zzqxxog@Q%ep+eWF5}soRZaQpZ&3iSFKnK?f5tVePz{`|6_wLMQt`%1%_ZY&2#Cs6A3I2>#}3 zIvB?^Pnc6i9k=Eb!MH|IVqi7;uFv$4+$!eJ$GVf=SwwYXORNr=14k zdA)|@_}^Y&CfR^WjH09I1vF!lW!2jrewe-k+>W6TQdNsdMs)NH`c}-Mmw{Zf-R0Xm zp^B;nE^D*sTF{c|X|7R5Nv9LDG=6^^JOF=M+gA~}FES8rJ#mYgem&I(yJw|#%y(BnDRFv&a-6*Yxf!b`mp4GUAk^E(N;Y zJRE(nQCvJ>Y+MQG0ELA8>|d$y?}z_Zto%=m140Z_yV5`dJ-pPh8F2N(`6a>wC$|UF~8~3YL77^ zn8FmKs}}ywqoA&=w-&y5_+OjfgLs>HTA?(C-}{lU5U^$oN0fi+DTEuM*#f8g`&%*7 zTJ{aJC8_ftsq*shmy3-2O(t(GF$xi`LgrgWKODaMaFl`tXjJ!)Kc!tDT#@96@=e{8 zpf2b9$LP}VlwU)FhJ^@){+&+zheoNH382 zC+kb;AXW<@X^)5QQy(X49;P-TxJMrB-LcbU&aAx&h=upZnp{e}MjmzAxpfwNiqkW{ z^jGm@>f_zHJ2gEOE+uw=_NwP>X00p6AEIsl-d=G;F2{v^U|CkG8+^mcoqfP3(aAU7 z$yYM+5AOgs_W(Eh?_UHVXBYU=_(Qpz;^m}o{srEO)%J?sHs3rpc6GNjN=#+SCSo3C zx8}inUb{+zZ#<36D4srlPvTSZFw#aa(Fj;rz*UW#7`zss@*vm{-1kmllkhIGPkOMp}R{gX91Lf8-A! z687Nnr;94(*HzJQ;Q)|vw0tngJ1yO*3g%Rm>?Cneto<7d*ZxILKs15Mt8BjhDq^7f zYk>b5jDY;4Q91yL1Q3{KiBtT~%*)cBL3oR~xCsb;|0E>|?j9W4n6U-*M=JUwbzgr~ zh7`Pb$O}$#6x0NMJP`0R`)SmdY z6(FG?AcjB{R~WCwt~Y2hlL%71%T%IU0z5(yEjzw{#=nm zR+d9{0?HRGu`}>NBI_!*up}>-fftxP#b_<66*TO&eXTtBij+AD=Jmh#Q-o zBzGhC#IcLw$;rHnzq)k|#^_Pzl=@@z1o)nY3Aic54D?L3{e>LEkbql^fE$IA2q{1b z_%cNVG=dh4!{)+Y#K-(h{=6iS8SonW^*bbO5}EA2s+P+O0W*kqI)MA!S2d-vSLc17 zNsqwVVFYv#sQF4*QbzBBx1qnkp+A&>eKm9?65{3lZGgfKK}9=>gykq9A-s!mJ&;GR z`;qq}7o%!}kjvj+beF8rM|C5C(in4p23lLoB)~2b3YLG<4ybTUHU$AO1lqvZjzyWP z5i_sm`0-{D5Ih&)KNkQc;4hP9R~$UL{C^nx5_l-T?_m-u(k6^7Eg~h`jD1TYBTJ#h z5-Mga$yW9)!nbVMVg`c@BBdHB*^@0Z#ug1_2_s9E#*+QL&kX&(zxVV1zn}MGdU~FF z&pr2?bI(2Z+;i?TQ%)Nwr_Io>;N~Z-g{9;4df9dF+M2Vs+E;DcEpztfB~T^L+q9QU zYKfl}KkL9jY9Q7fYl750#SF}ZANc`9)w+W;=)p=AB`FkkMFZt~+s}1D+x51eH@LZ7 z#&JZog}kmUAofg|7d}lzqBlycoh6m zVPZty160PR?m?;E5z{-ZpZ7i5NsFX^>K-hO@ANRr*c0=6hhfGZaATMeYx1DXh?w_} z3ob=1KwU9F9if8<6%Y{ZFOb)f2YKYO!}mKzYdc0mJ4Us#&n?d_T~n9y$ZQxg@QbK5 z@tE!OZztp#k@DCo=%2#znBVzk2YGmnNZ|8) z$MKyx>DZ1pZ23n{CCcq+=HG6&JLC=94YSb9Ld}a^hb5f$Cd%n@c{fRdljL%`yUnu- zHLrCYKH&sNY36@l{}tM^B9RV6808u;X|3AA6Wy#B`k_MNwfKOCA7 z?L6ibxT5v(gZv+N?bZxqOD?#URdf89sr`;q2$6&Q@w;|Y4)V9}+Kmhg$Dh@@mUZM= z>t1^0_JjN(yLR887aM0CDLboWo^?b?PBfohe-crA^I%5WW$CkF;hAT(0D#g9(M=ec zzc2s?y;lh2V%CxT*2ih43D>iZL>RTC@zT7Tw>{#88MR1Wo^3KaevH?sz~E zE3h_vyXGN&;GD7R(I?f9opJ}xU2{FEr>|a0{gMeSEC}+SPJKGWMc1Pz6bEk}oB>FzSL0+6awTtg$IzGuTUQev4MwgOg=&rb9!24-K?*dnZX7$azt};8`OG+V* zi*iX8BOqhJEmb^r*hY2-pC(yxN2dLSQzGtrGed+PmEg54th%hLGB~%P_H2{riRX4k z(hEbLp4M!8^2+{#rJhmR0}no~F^@+jw!F?wV`qXBo&>7z<%qstee-ap@zaqr)g!8P zVV?YY`@o-tJ=b!s$XRlLu9 z`5)%#5#eKFx!@xN@RR~PrtH3Em74UWtcFSKh8h=F@J+Hb-^GAVcj;G&&Nrl`1vmkc zw2w*H_W9r;8yi`^6izlBKCaOFbv8CieAiY3tN1uM*;x{5s%@pE{iLM@A$V?8y_y>ajyet!{T@GX$$aL7xOeAxwg9JuodqA~HRv&sTlKS~ zcOs9fo?$IOl0$F$Lg#Z$wQ+q|O)&kj328}TjSZAc8sr|d$x7cIYIEkY@ym1A7sd~3 zsued^1O$-FR8r?1Jtu|ZZ&QC?zzDIjAb;iJJx$EZ#Ph!=3P?P;UN$yr3^UxvrE0R> zqYZ9}KUsi%@pJqs`ZL|$W6=UTT+6%3HOvyTnYr3m1(%Wpclw)bc|LFH=&TS_)%k7dgKfCU&R}eu$tb`(ei(L?-jTw!O*E9LMYs7U_<5_h@sG@7wQ2=h4yPc=C!Ftnh3g3# z_@eme8cd5Cg2i0-6X0X2!(ry4;;%%gWe@Kg!i;%~@{wJKEp%ehA2rWdKBzrhU0|-k ze!V)&`bEJ={PP;<8F~4|qVURtj?iFNOgnP$@T@P|tKmNYZbgUlE13eu-Uunm?V}(A`Sjf^i7`s~bhqukROXL5{ z67}h>)oXP7am}XCALOh-F6}_2oncmM=HX9^+mI)I>oMv54#rl9G%BN;#NCnUgyI%6 z0@GjFsT;S{Q#gE&lyU;vJ7)*qmPTHNGL3-n-*D zz47hNl$>5!L9*+KzM)p86APR}u*)xZH^5&WzNHEmByS&raSb<5&PFBujK4J-uXh)D z{6j{zq-yqL>JTQ26QDWSb{y0V{dse$%}yDI6ygb;)tAO$qR^&g@&e>%fwyIGJL};! z-l9IbBq8#(FiEAoQu$|-uVh^)Xgz-UXZy*!$b%p7yRMsuNrGa5`sC|jQ=5uk>y47d zU4r5CzUN*T6dl6wFy76@C+>`|}JSm^&uK7XW}l_YXFn znicvD@TLS8z(fN)VKyof0^z$ue{2Fgjkf@vgr${UN$2lL>15X*XDN|YZGfK)%T~8B z7KRE15>u`VOYa#)E54j@TW99>qh_MtpKGuqyXNat(I1yEwt?Z<`)NOyU{2db&+~}N zZR_B_kBqLq@?bPYr_Qx=hdwBm+m*8Xn^iFSC1ui_k1c9bDxcl~Qlf^im{} z0STs;6w@=@E(_D(m;NJP;|OGaExr@{3hS;DpFb$!++YGgV+2KWxDt#bC^=j-SJm3F z$XG2FunU#JVLq2C;V`Rr#D*}gstHkO#U+_oAeT}Zr68I7Zz-mC^iL{$z_xyle)%)o z{g!blRG7Asa=lb0wiY+oq+sU3a{>2I%2!AH(<^l1=UXHSt;5Cjn#aOQgZiMrcQ_YW zQBPL<9ESU;{;o>^(b+_RXs?~|KTx5-4b1g_WcM_{*~t}PNMMl8Ufy3|?(zXE#YYwy z!q}>M%#;VrdDnxle$k9a?)zN4!wz_;_a5+M-BlCTKGAVB5fl#ZZJs=u=<~iWDqAE- zeJ}1th1qtsY>^)hwd| zb$94bIEd!m6rD#T&>^pIkG1NDJ*3w{g&m572?y$6YZP2Y7%hAT_)geTk@hT%-ht38 zGi8JdAJ$C>Eu@A}0h3aaO3q?-6#y(@kX42aaFcx1dia<()kd`zljgJFUB5r8sVN2d zuvP#5jSmh5C)&qy^Un!&7*Oc$s&|&zQH1zDY~qeJrFwa3UZ4mJW#A&6fJ#Y{`>=Uh zaIPi)wEI)8d{|a3_(AP(EjX{JETWmAP+*zCx_v?$|3bX*#G0y*F6wk+8uX?qa6lgcROnC9ylLGrF0lvQ8nON z)<208J!q8hC{OZH@ehYn`nKLWbshL04(`?Vo^>6nf;czg=n&_2V25hqN$0|A;mM-1 zsuv>A?6vS1J`y1U&EsmY>%AzeWx}?XNak+Nk#mB$u;1~VuSL9UNr9s zfa!o>u3q&vul|zs1k{3Z(C~l>f#W@OY$nR%g79c&Z-$?=>VJ$N2x^GNx8?TKARPHi9BS>1rkvds#nEJe~2c@F!gcF*XKz6VxMB(yAWOdA0B_X2#|UdwjwMVdtw* z$z3FO?<<^S!*Fy&Ey32Cy2}WNt{8|8JSGg9$*4XT!kLLHDjCS#m*0jhQ)S3u(x;%&HubV7$e(W zOmC$0M4@cP?dG3fLGL(R6lXY(k!mvtOEunUhQZu8^`urqkx}<;_A5M@95{5u? zDu3_F0~6q*dsy3dx*3iumf3z$Zjn5c6XRjrpp-w9Ch$4+dV|u7p)`7J-o3O0P<`!f z41wc3sO^H9h}}ygOemt2V2w&uvG7(wu7vyS3HO_{u@P#uVeZl}Z!SiB2j_-w60brc z$BRYo8OQg`zZ=tqC)wNK9gyRAk$dhRT|GCel*N(hiFiXjK)31gx7g}DvN*~cp(25jpP=f54gJ`n7a=ZRWG|T}PgNTe1Wfw)y>vo*%ZK|n5 zCjBb@>}hOQ_N8AL_DuO&!R@@uB?+J^tBG>Cgyvq{)K(Yk(JB~IE!}gM^<_5bNhnI5 z%mzhLAn$w-!cj9*Y~yV#T@G;cmypg2Lg};mMFehng8YRI4h^hvVk-VtvV4 zYjIE_+hA9?7;9}p$RLHa7V1Wc7&|18`4t`|zh~sRptF$WN%m|~M;l6}XPEP6xo@$< z8f{pFieL9J-cZdCn!0&&BI8|%l}>7>hS7M2nAjO~w}#O~hS)qgVR;n5;@3+rJbV$< zr{@cEHiuf^IyJ~IgK&KOYe2k*xKwNHX*R|AH-FT&<#GTR++QoxGpsv?PxLeYtR_A( zWqk8O>AQH)%@cPcy;89TGjy`M(S=g62tBc!ZwbazNbyD0M1LNb6a9=of6w{!#N7)iMK1@1 z!zU&tji-E++K11KW$bwXh7lKqxU63o@_j6%FCh-K`>)<1FE8Uy2AC(Q=j%-y-+bO) zhEFb-bD$R*C#jdwtCS9@+LvGq zay~_=dadW|EzS4gqm3FdcfAxj(*WYn^p4&Fblr3%03mGlmb9ZAiY?5K)M~4jOb^~? z88xB!(+R1oHajpWH@Lnt4+_8HZVXs*rd@wMRc&^82z0V*Yf^yD5+vviZVpWP-eYem zI3%^%-bY5rT+P)A@Vb9vlw}ac)>2nZIXJ64z%Vn!hUg>$u!uS%4E6Sh-=^jCp}v31HQdK{A#2?wH;SxBlEM>N+R=n zP8{@Tb5Jc|PJf6grl=UrXLH(}iB~B&QXqKOOtV1nqX8**rtVGs#MAS8;1HBKYp=d{jS;uz`12A z#kDlg{RVa;OBymJ&;L{kAf7X=-)t@4i>Q*=fU-22G-mOTjXPjA@j+&WHx!lB2W&-B zHJJ3tA=Kn~YeimOGY)JJJ)Q)7KdclRNwU(bwQ$>?NKM+7`k5^dpQ5)gB=-RWwR5#D z(gZkj@2N28Eaq8z1EV?4YRx7B7+>K3`MmzjcqdD~RHs8FiRPXOGkNvq2&V?ilco$2!ToBJh|juoBItq`KL)`(0Wc@G=3%R92<}E}Io)c0(RNj`_mtBJrCtUR zN@`7}&s?UDqJ1Dpo81S}0wVr$9)dUxAnwt%_j5fwi0#o(&}YBZH2v3&0vpy*8(;Ri zDXn|m+BURt&nHf1J+HV?#&=aiV8di!$gQ=q_Qq-z-^TOfKipS~N*>hx2|B$+$*Pf0 zY{QX57l$!*f2?=!b5u>aqkk=Gqx%h-Z^OiV`0-pLeQ|3c!TV?T*GR8lz3^$|kG1no zj@gYWGTY|T(y%dvNAKO(cn}y-W4YaAy9pbJ1~Nyf)&2>RUKdtd7mnG;zx-R#zJE}9 z9ndOOztMez3~m!}u+0st$pYumI*5)*SQpc?sv-B?!OId|c(f_Y%$s$Nyq}mWEUug# zu+Eb{0>#s=x@d`Z*!awQee|>Do2+VZM!eFe{w`aRo>0VX;N9t>0TS8tEcM8Pb5Uba zn#!Rk#Uo5jaju_TAGr>|+F_A*!&Ox2?T@P+*d*eX@~y`$dJ-4I(IAzseEg@8o&gq zgFy8>R4tP(ql?yWhY>np9e3+R(q%$$`}o>nQ!~=(S(1_W+TmO3ImY?urK({rSoR+O zZ4S``nqQn5Nl9->$%TuKMa9i=jzwuJYY7T9-wiL5c!X2>j|Ajwg~UuYC2$MV;+mn| zM(2QYyjy_YKig$np}Y2KP_s4-5*#w`*q1~tg052{B-Zjw+% z1tbLP5jS@!O2OJ(X8;WX!DSLWY93n{l$icvV7YeEM27uUBXglPIfaF9nCY3d2eE}& z--9VZp!$R_n?SXZDl7Tf#X5m%wgWlO2J20&UX3=}MIDlxq+ zknmu-FmiO5DO@QS$u&UFY6(>LheG?Y&@i6uT6(n=3b}}{8xS2OThU;B2YqAygv9zC ze&LDXDlYmC5(jCI+xc=4qT-1NCYQld*FZA<;*xCg_!+k_;^0O%Wuki680J4=$09|;E(Yc^L zMVp>OOv3I}Z^~h}qdMSX_lZ+$US%`kEM&{=grBgaeFlCyYf^Yb{gyA6i+ENxr)bae zNDWjUgsKIl@rZCpjGV;f+*>i zLD}!ja9syZ6KII0q42(VbQL?~iH%maio&om?^{jv60Ph{jvmp1S20xlGy;w={p2f9 z40H>m4|hFm$6eCg1H(FmqvEr&_`CO|XYGU|Isrt)o zH-8OAV*LczR*OeF=mE2peHNg~(HpdB z3mEz>*EXd+v$}gIbN7h_{dV|xujB9i=!x!*?E)08EOY24P zF%_)@l>M`73v@QJV7B(1Kjnz6?w5$2oqK{kPlN;V7#uV-X(S?!=G-=zt1!@Evr3&^lmi ze`3Yc7H!|oxx21gDB_ojfGi?`lXTH85r)kg7m-CU%rC<=pkN>keFN{9B#NlO{}e~h z933jiutn!mFo#uWP`LW8rzojKM63U>$^l!nCMQfjxfO19^7q^BscMT7!7`BjiY!5~z$1WOwV&1zO8vO3JVdt zgFZ48Zz}nWOxroe_4rw_*iV^apX zBF=S)v<>6r4j7CdN)^E#r7x~^I3*(SV(;`mDM%uydO;@?s#8h6iTD765rJ!6uNnGD zB;G)UGfSiKw_$X+3p_w>ReKL$nRcEABUN z+p>TUMNdkp-(-Wl3`9P&3)bHKn83qa>9#}>?6YNWfpmLiV#`Ip*?kJ%1|O&I1fy1y z3Pz2M7ih*73NZe36mjT~$teDr&Y$w%cYykjllt-LS>r=TE;rJnd1+H^Vr_p$xc;E^Nuo3}!f5HD^DSrpj4IaUgW^S{(n zjrdnRc|Z@p9)cbW5Q0Fabv}?x^%0l$(e}ZCOzn5=H<%JZ0Cp-5wo66|dYGHvuCRYI5d-m| z44V^zm^XQBj~xdn5SLeVHmNXV`-T?7t_#tFtP+UdD9t|o=(rnwMAE}y(r<=(f>UjX zOZjvA)}cA_6zLpy<7v~chg;G-ncqNpnA>sgz+1ilj7WW>blWiX+vZ+VaB4kYP;uiXHvi3qln z2PTUBhSS}WWxQ`%y8W^reIxLywK4U$4}9Jy99+yreF&Be8hEfi@LfgfXAhr=L&uk6 zKB#^%Q2OqS878%tQ#AXco)$%%yOBZ1Fojdnl|SAj3Q&NHxoA`FUk6lQ{*w3nJ_Se; zZ;;nKS913lcwB#eEaFo2{+F-V+hK*u`l#B>5Vv2K3~R|6wyI?2!I$lWQLCS zMe)Ch-Ma(mcw=gQEu5H|-yz$SDo7<6{zi2cskOAErc+7Jj;`zoopNQc;|;N62H3f^ z<$3wQ9UB=F_J72IcVQ$1SjdlW>%|*P%_1mx^=1*u-3Ob|tCZVM!zUREZkwQ@3Q{H= zvPgMB(Nx2D1BeDg`L(U}dAKG1o7oH|vYEpm?BQ@r3?pzPRV?eJgZy@W2b44`C0wj6 z02ejkQbO%F3UVsSz5M*WsX}7OW^0D0Hib|Bw8gb=(Lo30TDhd^u29`kxK+|v05OKtfkuQxUM_dJUS+VoGr zgEJ5Y6_Z*=tcu6bi7gVwKW>sRL?_{~$_00{qnUvR`p%)_UY?0tf>6o+IDKsUHefry zVfe3fe8U_%-;^#$Z83C5oARm`c%WNn)WZD_4;IT)-hfrHiLH0$RZ90FiuaKB}>E$0t6ps~Dz>uxTlT!0p77n|3{`ECn zbYA~}#QB>D=3&LVakuoT`)ZAwdcm!yE`ncWBzYEz$iB(LF1b^^2$x*0uc76XCB{l{ zh`b6rk;^20Y;6a~ZAC_LXZpHyfQ!u@ICk?#|vY}xot2C*^lRrZU0bv#KrTm z!Uc5~pRaIB8oLj{V{4iBfq&N3_y}c*8&h-ij*`ITKog{vkIG>Xj&igA#$mDucs605 z)a;vNWULvQzU%R$ud%J{kTqv6h*mUUE=XTI%<7HZCSe?GI;4*8TBCCWv~-)QF7t=D zuiTm77wC4b$VZ#~qcYL^z7pk({ox> z?k!IP5TEJue>@_NNdpjF00OX#RT02BFc2=o$ynM~#l(rrPbAIa=i&2h9M0#p^l1((nghX{TeE#Mtd}jf;P; z%lw2+=b>^iXWEuUSg++WNf`%6-fbM`9*|{yud8Q?XS!em=1g5LcVER4%qZ zG77a75S3y518p}TR(QnEy#4;XBH+VX1zo_A+yjiwef8hXy`(HwTgN1N5l|~v1qhvB zY@QhGyaen>!65)=2;eOQ0NB$86j034+bmHC-le2SsDRLDUodM$`qe?2*4Cjh&ZaX= zqP$1kbu(MI6ak|xZ*pL}AyAQFsW+Hp3Q-$W0W>5_6da&|UK2?LfO1*`h}3-b^`ogi z23xz*)Fp@`d73N)@WnF-OEO*YizAg2Q9$>qf+i0bqT&A<9&MctkL^VJg5;`3d#f8; zuTHgD+Fk=PYmP$2wasxe!?EL3DOqeX7#qOO_f2+`o&fTXW}Dd})XrB&<@zoG?vl3L zb>aK&fe+KxDgZ6+3$jY!O$W8THN%B$2e_Lk&BK%1lvdVn34768Ho~A-7z=p^C(MAn zS2`QwCfi4jP6!EJi#t;G1`viqL`LO`?MP`e6$^@MD<|5&#G~2NI`~K$;3zWv4TSB^ zahYFqAING>yxuNiU$k}fEOmhs29YTXktw$~i)imF%}gH{<)0WN8KFblJlCfM4U1#= z8BE(IwMT6}QSX82x@rr!g%y}BjMPU#1-*<)GT>B{o_CkBt^&t77uhc|7q;xa3A zTOB`WVKTow2#ehQ>n+2@JzWgsP|J`57zX}-GHX~mLU#gn1S4{<4FpkuBr+~Q5fd*m zAb}TV5Pj|h9Ls;fHLlI_Uppvw-?%sla}hLP1-x{EQb}wwBVBv1+aj4jaB_=F|8HK( zfjmBhik{Fny7s=&{v|^<=quHTHrvym`%<7+761az6A1+DYuC86>qpVnT|tA~yk^JH zTe%_n3oh8Hi=t?`8-quc$`~Oa1le){MEo8@>J0Q7`|Be3?&Mp8M^j64)!;udkvNCj zRAKt+9~!3PzHn4&;>JOMLHY;4z_6%2XDy)Q5uJ42CNr{^w9<1W4&Elp!3827&7;=Q zNMQ(Mh7(4DbVoI%turwUXsF)SF0AMbOcdR~3wWT|(fhar^&t!O(HV>H+*<wW&+?qK{#Z}xTIwF z6GA^t{`@p44M5biZhFS0ROk{NuhrSz>|!~lOMJO?oK2q?gCsvrxh{&5+E3uW?1o91 zZ``q;Fj0)wC35X2WFH{>U7#2P=VB>}R@(>}p4?0^agc^5cR*CiD*45weR=<=dAP7a z=W*I~JM!Z+K@s$MG4$Ul?@r<^MUnd76XpEa*h;sQ)WTjAeZC#Or5d^P9#}(%CqGQW z;tAmYpTm>VN-FWVBT8jJ=l^Z7Q3ulzJyC=h#GK4{f-VZs8^TD94hB0yhS|*aY zc{UQiiB3Loap?86TN$p(WK|&3P#m+8Um(yK5wu*;kgU>k7$3**B60BToS;i3?NevO5lc?tg+oKmXxOG@@RqMTD&!@mx96Xo`} zlWw)csaPQSJ^N+43-1e^8iRR|LM>^ByH%CDR~HAMQ*>bdyI2jUs=?~~3AqV{p&X|f zp(qY#tP5^9^?WOwn##L`+H*jrzc5Q^A`?wi*z=o|;7^^D=8kAhzd^XP0FQ>|3=ZT+N2PRM>i@+{U%|f-Vhc1 zl#y+4M%07hIym8mu?;oasFyx*PFL8urpAF7*s9798X*kRBM&ype|iK?{2WYs1(xdm=SBNoxm#raUR zab_l$p7@}QM9t=i|3Z>W6ceXivb4=5@``&zdzs}D)lhbBaTr-)JXAvwr#aw!;?Y9d zswR%{`jIM) zk*EO&=Y}F}8s(fCn`OJpO&g3}`uH;fTNd_ItXL^k6BJP3!&o`MjgwWuuvoV$eawL< zCM`FSgoerQ2=6QnFSmdExid4V`+JoQLr;stfH>pnl6{2+oqVEqLIRznK!pH3rIfm* zr_TF1^F2s~X1OiN<_C1sV;S2A5ae@$m^sp|nyaSu((IPilTvEVqd<33ttCyQdzBsn zez~-@U*-roa&M|s4&dm4aBO9rh;l~m(CC4zlO-XqE5*sm@gh*qt>S-i@?^W#_%{zH z{d5mc;>47-G=mB&`y1n`y6Hy7qsM;1j7M?ix5oYRHSc#WN#9dPrnBeMes(TxWxhnE z@np5|hB>A4gXL4}tR3{M6OhERs&0l+`{>Xsv~GrC9HSM-4-FP=_M4b_Hx6h33JE&m9g^M`p!#;F!Z+YN`r(!+XyN82_y0UKR-x z!nbCd{MWJmKzg07?$g%h;KW;HKe(1p@?OXX!XxHpd9mloPIhiZo1ifI({Y~ zd>}28&0M)c+o5GWC6|mw|5w=jkPUb=HJBaBUX_jK^wC zmqn6<@Z8xZV_PKf!&!zRISd4a0SzxXP;B*#!y+KAmQy8Jp7~f$IJX@buv#%gxPLBs zm2(rxI(IPkmX@6JI`(u8+A)9^mEwr=ME>S8|1`-T+1{Vn$94A z6sxz#cuZ4IMmcGH%X-Pcr9(Ijq9yWpu~=jZEM?0FgD0&+ivrX}Sd;uLdZZZLX-Izr zDCiz(Ui;tW3B{)4p5xFo0)1*<^%~ueY%O7Xl>N{&xGDfAN9TlTrCEQKZ0H1)dEO zgV8cTE=F4$T2tTnE)Iz9<-GXqq#9j8!zPMhguFXj~n9{OqJ7F8r6XAE|aQZ>rc;A}BYTGL| zvZtgwGlmMQ2e28$UH`VjEj!AAo=P8+PT!Y8+`*~te5}0j{kRx>TLdoD|}l`RJEkm8*3eSBbvY;x2d(BiX5(w|5qG}jp0IS95Y)pa3^O1Kdxm2A1-QZAS(Bi5uf59 znFWVN*~)V4ZP^BBQB7?&V-Le7$L893W>RP&R+x z=JLm z-Si+lJla4Ep*j<}Gy24q+f6>>COdTa7)BrUAOV)p#2L+>YKZb4=1qVN+5+ruk9Vv2 z$_}}*fpZiftO|Z0LzX4;#;pz*)1K9vY=;>(mZ35KA859gyjy3FrL?wA7LPp$rzW!= z;D5cju|kL;te{h)5KkdHcSj%UxK=dw+Pda}j$&4vzCAr9u9h{+kncBMb083XNBh8@ zyT)2@VhA#Nb!%3pbt*RMgJB!P>qzHkjX886cN@rXh|0Aiqiv0c4xjR!!`J_vm(Y7~ zSxXMsOY&;95-DFB8C$E=umyCc;(3q9wrVNa$Wi+cCH~zZsV!~xhb^SfC$zK)5ZeSq zykl|MN@-se8!rgy-xfJ=sOD2RD$hVn9-Q3+i2fB#G<2lT%=|b*$L$IH{M!`LJ6oko zY>bbkcPgfI{((GkU*n;_@`({m$)4p?9JNP0I-Qc;v}ODOTe`1=^d0dD{5AOSh-#($ ztQ)s$@H)!*ZqoT~kH4w?KX7cN0y>b<35CP-MnHJpJJJ9-^*nT(>^3mX9tHhdB zA~Iz0_7dig*df2+`8}kG(di-bwf>B~^R)X7OaFMI(=--v8Ud-1L!;!SwO>^dGb??g zn{z!^=m{Gop=6`-Th-U zZ=#=9ZDKTUw(x|{y6Nnn#i|V@;Vj~`(fpspiP8SqpRa<}S6+LNgM#`NZ|+!~i!H!S z%yzg9KPvgRZ;S5|i$G!P`q=b|d)tKO*Sa?(Mv@K+LQ(*ka2ti`MMX|)p)&PO4=B?I`|iG5?AyKG(Kl1P*mETCSM=3~ zJ-vO;TP6co6~0e?Ur603UMZjaLStQ;E)$S499$u61b7VP;O8sd%SP@@RHUxuRs3>r zs^sRym00cHRh6M?E%0sS^RFkVFM^V-OYUe?I9KTA1(i@EwS9wryY+PadQ$dcv2r!T zb1eCVZ~Vs%Re2XmbkI6RVWfF9srR&(MbY&QjdEryPb=kVBNc_gg`f=ncQKf}bWo=f z+iav#6tvOvu)8=V$n%H%`iR4*eCLSIh-WjYWjb|2qrA?_b6s0;wBx)RhuON1$esI* zG(b#Q`l7|GM#VAf5+RqOcP}iozta+mq7l zxn&ijQh}%Yf&zP2uNKWX&0YzfSzWa-tC?_l_M+lh+1o`U7YlMiYj2Npg@(q;ocV}> zmtT>`m*yX9qwh!rTiTUKTCr<_e9+p#`5G#Xw@Q9mqsrMzOP*XSf7Rmr`>{K;rAX`4 z#f*M=-qTMqYH$5fD(`oH_s+)oo<)PkuN-R&1(}?@7Z&cbbcu9THA`8%%jhdv)ff1M zQS5=c`TL4;sU2uoz$l)bnB%j`JMWwRJGYE9pj=0GN&QBMEkO%Alhqge7VfL9e4V5; zXx?q>((`%o&84(gIe7BxfU?n7<#LUUv<15f&*tx4L%)k&KrCrnpb2lWFM4`Uel3W8 z5n1xNWJ=4*T6eKT^6Llr5+3L4q%QlCuD-627hjy!>~#A}%H^kWLZ$G%Z)c}}H+TKY zd-o!1aVa2ol}5$JYvS2JM9v&os+(E1uqd>37q#pyZ$zq;>V61%NyQ<{Q!F^;S^;ND9Krl(xUKZ0CcSYqT2`$5SH_&5 z-@WqnPky?RPseww*}~uq7kOR@occyu^Yqu1)34~l|0YH*F}l(#MqX3*xtXD=urgfw z=XP?{yJbi6LXSo-2YF$f>=`iYQ&!&R^fh+T;!er>^+3vpwY!9Sj?og+HF5!LLk6$B zZblCPJ*b&}lYZ4{xeOXwg{l6LUwNr7wEgEtXt%!WY_BSOvF8u2%G<(H#s9#>8y$<} zv3ovMBX?Z-x&h$3)0ON670}0VL+C^~yCY5LSvAFVcBXNSN(V#Hzc@mVLhrGtaq|o zsLw|{n%8)~p8Pugt)9$VH~sr|p!u(*_v)XbimX@7%ROa=$XB&fe{tRoSo+?QYD2K~ zXmDQjw|nD|)_t|MRDIC$V`+(EvRg^YtXP#}YKE)ipruM$ce0z+?onyOzPp5_<+^6k zz)H%n?{%x9?m6Fz{%wA&P5~8Gq2$5e9^M8T5zvswWA<{ZBbtvxBL@aaGAqVfH7~Jo&YT!}Kl07%gypRgqu7oiF$Gnf9ve^Ij^5vG$V+>T?NE z>okA=VaSfg*;|P6pooIzs-g1auRRhJ)o^F4w%c7|smD{_5|*CA`s8C#gxd!czB_ki zlK3rBBb+6BEwd@A>J(L5+SeY-SKcMlv&nl(m%LnDYI?>?US_^nSX*-d z^}HzkTd&^N&(Wtff|4_;073!Y=*h}lYYJU7Sx9sp+0xDHz^J~0>t*ZG;WizF+`Spe*JGd@MMpQK~ z=oi`dkNlat&J~b+YvnqZfAU(XRolN{Mgc?Dbyg%t*UQrWNRCp=(v~H=udYZE0+MMR zUP|-VTYiCSVNn}yevZJ<%9TR)s*bkGj@$hXlT{tnUi_)ki1?D8N=%=^^t;C+x4Qg5WHbG)oY zYxZqVJ(5~R7$6&GlI*AF32GZlgB9z`b-mQ7ib^Zf@m^G~QA;ICBaL8P<=y)&onW2R zp^*9urr6t4XW*4uSUZ)}V+2O91f8|azwWwj*#OYdMwQ=tp=sCOPA`9*{?5KIb&KGY z@eTcEsc_k=ydP~i2_HpeD3y|JX_wzlFMOMZi!ES02;{VH=oo7D^I!1Mzzn6=Kwrpu`x&JSsF7_oR>)JMQ5!_2#}1fZUkzmapa)0O2}uMZuT}@>Gc{9RWt9U{D8ME z7JaE4>d{~cLubm9t49_;QTh%%uMm4_H2v_x^h2i=-1}9WVz1xLx6_NubGY~5Q!@Q9 z=;54oWR6Gs>ayb~w)gZaua7;YukY=&9`ji#>AI=;ZM$Fc%ykw2NI#4Z&L#2}%xtCN z_6;eE)QYIrRQJLq=jXrdR<3y*>9S0{MnliemX%koUXNM#_xG)ms_5@tSgYhY9X=bq z9(7ykaZqx97eD*&Yn~sy5dLq?o~!s*Re9eN3@Cj!=8&*Xvs!X?o1g#iF8Nj0>f$xe zPon|ufuvHi=fX4TAK%UPlYeK|Q8hBc+@KlW`^V*L(DNl1`Hg6!^+Uh=zb?D9Za!CR zu&pY{uOC_rpsk#;UqMBooZh*pOI10)1qJ+zBo`;={;1piBZ2*^YjwRpQ2ndx1#G8F z0y;)-e{+B5727`zEK%6(<=S^xsm1Aveqf01^!fE)-P3#9>DYNfsYdO_`VVIhkMNC3 z-sxjHbzA*ASnGmjon+)klc%3|fFI$TU9wWB zp(c_@OSF{&iIRKn#Q}2aU$ft)zX&-^mNV(R$5;L>Fgk zr=|LM6lQC0)ik4eA*W$9Pfg`5deoELg0Cx4PwTBY{VGCDMZwS0oh)CaT-5>~0?CGx zlu`;If$Uq1Uc0?cTqEGTyF6%x!hv1cY7=O`u2>`Tau#~+tNKJl#{9av^z_qI8x!(! zjMq{nw#0{minWeWBd@GPz9a1>uLR5|l5Vdc<@$v(S{x!;92yqVJpTk_I9t25=quFZ z_ANFn1O)vKaA_Isy}3BO9uV{+pkFB?Bge?X*(jgd?UCH?Zxz_GbC> zqI-&>KlVH$^_+MayuG(v5m0G*x@NJugV(&{5#dG$y-~S=(J)oLgqJL2E)mzAT{(B6$F*4Ac%l~0YV8iw9ulWVxfpgFQF)ifC!P^6eLJV0#XB^LqczXgb)Jn z!*l-k-TT&E>#=6R%zS(Hw`XSW-`+DJGYI3@9$cjdveNF~Ds}eST|x`OXY^R;o5&UL z{;;5ZY$QKT4M;k^ak|9mA-}lkPQl;K>`vc@l2m`X{3gX7<+Cpz0%AEP`Cq_b;I|Nf z&NZUL_W|6m>>o#hITYh7f)-Q8dV{%^>~>^>LWgu`svevCb@s3~i0DE2MN^DUy;I7mAdtvZ7_zBhJK2|WY&?H|~Ni1o_qX;Or+>yRKW zG<;-J{S6>XJ1IYlOn#c*N~O!hHUVM7>46<}&v$sC7`%{7gh;4P&=b6nfDVm(cOZzM zqq(y~U;7%)obvRgeHHq0I8-aYe4bx^^jNwifVaab!Q|K;9qV8FGgC8v z5E_c&7)%G|qIZYbpRO(JMu4r3VYt>V580O2gwt3C-9oE42CF9lNBKizS=kGoQYswt zH=(u{#2Q0j^o6IjwE*5x?5v_}95@)Rr9}+HN5{^J8hAAr=sV8<6gB`24#!amF?kcl z-wL+)Mz;8fU?^iZZy8lK4nE3&!l-0gIdJB7xn;g{}FWY47xK zX4pei;a2L%)@_{#rN3#3zI|9H0=B&!AGKbA_tH8E1Q!itZR<@pE^;?keF_F`C8BhJ zJTXJpoZQX1jK&ADV@=83edBe!hv0$1=%+4Gdb7ga z@j6wZRCTwq@Q8|(C1RVC#N%=}S3+Ui8kEa@`=QZ(PTLv{2rO)H6CV!L0HsK!bK|}X zr-yZ@wMNAzb&6z$YJk^r{)U0u-K)!yK+l5q=81kbKulc{;N|gIf7|zlVq@SQ(@cC9 z0IAkxdRk3JkDq$ptRF@v8T77`FWnY*1!Zp=r)5x7CLpp9k3<66sNKYkmt%(cSAg`F z@p3OHhMqXNS&AW8ARuc|S7hM;X{*Q=NbxGY+Q$?1;w}D0Q5$cjRUH-I`~o@&1nbG&^alB+oiXNNf%s(~dPDby6MD8CQ=mmK z%YwluPU8aSWp*fJtMNM8|7wCdPNRm|EHbDC(CfozTNXI?VHy&Hct`Z?45lE1XlCLC zgZqu!95jR$9X*K5)uc>t_rI=+~#tv zeI6Ig@p72HWH6GwtpQkXQGxZAbsZ4-&!*JQ3PU@!ai%qGg~VwhNtm2GZoJHGaq2ilapbggWRr5Bb$ zzLY||7#gGtYo6blz?G}{2voe!{=CcE_0UDJ)R+sI4B_{$h2PiAi>2ZUW0TA? zWePOFvlaz@U*PHHnJswxMVr(TZ|8^wn^Yi;G$yM5b}OOM(M_tA8Nf2$+at4gXH3wo zNINJd5*R<5;1vw11}5*oa>V;h6=jISJ~4EkZBPqQU)vaCZGDQ^#Bgv({ zjrAv0{w*Jb`mpv=Uc=R!!)3ATb3+b@c2FuQfrsI{{GAoU`;Gn$l zN+{190C;fKDtsn5|Rd{PifW>p6~J6Zr#r3dX3o;jmikujYl z<8OTBHE;J_K6+M$&$zBzhrQZ=bl?hGkqPSi1iwA>>@Hb{434Lu(lhp*z(hRB-9|=b zgw|rb*@86&6WJOe48B@lGT=B)uMQ2>1Lwe3se@I=!Xg$L(t$KGRyV)%469z-f1%5C z>$v&Wak!1W{OGExP187xd4XcyG;Yx}PNXuhGj)}yPjS@fnLWGo;6W0}uJhqbf;*qf z^dh-2$uT#{(F-U5BNht$-$Rs0qd~;my4831;6+GANu2KrgI8jQmz*Exn?GJwQW{>l zcMe#hhP08WLW{Mp2@989iqcb13zzd3E|V&~9_ORz5iZ{Jr*y}_e!vn`s_^v;6;&v0 z0FZsl(`3sN=Q&QIB^d#pLmSTW*GJ-NOa|OxxaAT{$cl&ZWp`y#z9mFBY``XbUTXv$ zv4q+>ir*O*e1jjZvHC4|agXgpGEx zIU~5?Z0X?TM^GXBW#M`CjBp{mo)Dhcx860Cn$sp$VznFr*g=Q4^g(}wo=x%usUM8j*!$T^$c4{%Q0sA7$_x}=r9G2(*M2WMWA&Ab$dmJ})FC%{6j@iulS+__}jxk2jH z$+SX(d%g?aKKx5+8jwcP3K6LiOY85TJ`0zJxJ|3mf6{}Gx98JxT+u9~0_&sZz@NZ@ zANZnMDh(X1R^X#y!%?!!x`TltexsIg3AtpPPQRydzbDpnbfCVTqas)`gnfDEJBQtH z)YoO5nbcEgti>x8bH|9ZLV0C#M=z+9(O@*z62w#D0*m;*=9CmI|3Dyxm5r1{uA@D~vmoAQ>N%~No5 z(fhAwVJ*R`zk*AJgzIt|Px!Vl{Q#serX@VGA&oxv zr&aHsR#mO=8J7bOZ;bKfp>9&wdvEN1S6SyGdv^^S=vxYv$2H9){xLNAoyWT^pxPc`ZQg>AhsT`&OUl#$@G8O$pGDt$ z%bGW^95c1)$Zs$v`TPy_)BDE_-x2^D~LZ&rhb+0usa*(bZQUt`(Q z95S8aRP*|8V;W5q%_R8JHQHAP`8_K@J+ROpLs_o@4?MB}%{_?V1?ybZ$F{SNQyFj5 zTbDyNvj*HjdHpV!g5fSRPZyX6sHGyc=l@#;56{JJy;d2N(7|q<1aix^sI_{kD`hxu zYqqTbv7CcgF3TJgEkmp zOCK%zz($~?Qsp5|i&|0fba;5EZvfNB_pPm~$Hiv-@^CLdA?t8SdpCsaO8I9h;j-?n z1hL9AHn5y8VDRutxJB4R=U*4N?mW3OW_)$jZ*#q{QPpBxU}R@(HCatY#fX5nV4xi* zV7%#QF=+73#hAA$Ez(p_{Si?8V^E9qjd7T3@G`;aDCFY5?&Ta zm6WA_8jugkv=J9DI(!&x&LEqRY2+W*-kvcps(Zy`Yxu#|Fx1t3dSMQ>{nXN%GgK(^ zNvsLX-@nm*Ub;jo^t}xW!KUIHUmMTsU*UK(>`Drjag8^E34O*#DpRP4^XhD3}dAi*v zadv_0l_%<2wW;Vs)V0l>1k>;%IXX{=s3*fjI1jo`NnHWrKJQ~^EQN9&X*f|fe{)+sRp=6az-T)^fq zux-mn>*J#lvwR7xoFyFpJQUGeVu&6IKU+2*d4hT!wjDdb%E{1qbxlMMwj&x5D;`xs zuUmq4n}%)`HtY~r`U_|a19?IXE2Q1;R;b}3{PH8LaP*m~KOypu$0IrCe!ep1&Oi97gUE~$DPLqb(Z@-HPlvy1|UjTcJGwZ3r#}<+)BR!Z1&>L zwEbC(pfW|C?!^slB9Ae^D#SabGy)BIYzO?fcYhszR^xyPI5I-RDjC;bp>0)1c4{g5 zo|UlO2S2x<{@N3N`@>ZgqlU`QfA{HRR{EhWe>~o}H(6bvE(|aAuXqrA)JsY)>1{{1A-3HDvQ zr2!-$TQDdazL0rx3-_xsh{U+2_jZ}tO==hgV6<*6qFQB@6?b85P2IE6XNi28m2|qz zrO~GvEb$O&vKdln%2dzU%NU}PpEKYpwkD0&4rL;!9&EdiZ7T0S> zl~nk%f707~ND>C6sl#|v_Ab*{?Cy*YhZ#ApeCtqafpE4NhZ!vNNwfB~o{%R%6?4Be zQ@b4A7Oxjx@=V(7>|9p}hxEG=LQBeYG-w2M`X0+hfi3af*6U-^wQ`Y6D+G?9c&$zG zT7k=xuV>;dqBSo%AqTweMIxNTw`CS1$uS#yC*oB#Y{upujLr4c_pI079TOJ|MOW7M zl-2hXBJ%QJ3tTYwW9d8oDqEZ?TavH^58aOyVOLM+PmoPNCKYouIft(q^}aUZDi?uu zDhYKeWu^f)umA5>)iHWg#wLn0P# zMJ#;S?eonK9v4)T9xBwT4Ed^I5|tvwRDVdAv07QJ8Tm8$jNGKX?PkY~%s$Hd+SY0M)4R|=Cn zxU}{U+6do((ZLV)IF$EU@%yuOLb=IjZT2{l_I0uQ*GG>d?4uk?bL&ovt{mYGI;`ap z{Ex@0Is0Ep%Fmt8+(o}!D|Q^~7b|}`RQ~c?v6%b7*)(OXcxAm!`CRB3F>Boq#bU&s zceKb821iv4j&}7tS#W)#$-jYP?`e94?KuQj%GTh|R&V1{H_*dzYLid2tLM%Lj@w)d zQ5Lb^qlMYz30LZCFYs@zDKDI#Mvxkj|Es23S!(6f_<0BiVX>Wm>x#z*=v7MA+4!V>0S#&0p%Dj~3QCap+C9W0<<*Ovi2E?a z{RfZEE0>AMKRvrb8f2dKeBD-UYQOjlJvDxEEYPyLXzd@-&u)dj#yon#bu~Bt} zZd1K@c@@n0RRH!?AZ3xIKj3K4=#2Iiphfy33#s;c!00t}6XL>~-+Q@Gq!_{e!_sP~ zu3;%@x)a`2xu@;P3?0}qrC?swE9BC6w7uEd1@dNMa%55Ur*Cc&bL+xHWktA?IkceB zzxl*>Jj-UI9n~Ry847(OA821su&dRAPfT&#SZDnS!p`E(*I2?9QO;?1LD)4T&_BJ= zb6c%RZZH2OJ(f3VD**%MY0VzfM+5?GRK|b3? zneCdcEvfud7xUW-(&^PwKJuC1`5FF&xULTd)xu9rW!&&JxegkcZB$kqnM?J&*QQAxv{#Ja{{gmB(a`r$frk{*GYI~@6IH&4xZFS_>yIl{8fjcjh)uiQr1Jft z0+pjjlL;uM1PyhChRQ-3%#3r=gJATa2YW)w`|Q}JWXAMduRgv>cVqPmokpuneS~dG zCZjz|UX)aP_K*ohZyyg#$+|Het%dpJN>porJOcYPW!f` z?M@Y5aFnLC^$5hSI7S8!nQ6h+GQj_k+N3ZK4tM_iX52tc% zbrmA^{g8s%Q*#L9tuc{Hs~ohh#JcG@jy6(iB!Xn74L8FadZzHifh`-vA{u>|8*?Z_ z!EB`{PeMolatOnF&6&+M-L-_5av^*k1*R7pSi`LcY{`5d7z-184%2);f>}OmMbfCi z@;EqG!tS6G%g%P8i5_MvUn4!9;FO>EoH46rSzQJ-q{Yb%Jo568`|x?`eHd&e{m#z9s~G z(o|Z5uxBO!gNXf9Qd8{l)lc9ok;SPgoUC%K`pgyLOIlLq!6-wU|A(ObpAK!rw|}~= zInP=iJ0*Pt_vT8_3}L*f>>r2X6Bd@gDq;rSC?E;b_{K)_fuN+V(Hia(vd5npK8-Ov zJbf?QPjbSm-OnJ4$xOF7M@rHQFuXzMp3Tw<-PJ@LX)d@nY5oH!$7*eJ4{dYH>l~Lt zO%3aNw5Bw5aT$Sa;xbAKGDbzj0(c*o94 z1kO(mMSp?CpQONZchqxsWBgQ6d@ph1Pu5h;wgpzF4<8I7K4)Y{r?S!1ZalN)fMeS? zUo{6ob_;e^j1(qCv9nwIBX5bN2Yvf-CSI@wv-?B=Y?dlwMlz^L=OD3aP>we5UUQ77 z=Qz3PuG6R$<+ZpwqyY}dw8Gs&u>RiFBS&9T6TgzdsRsR6fA|>mm;m$`hVS}p^fjT< zSs_t0|LFQD-}+p&N0UYg8!YeCV`AKnK+>`mjkAroj`bc(?VmH^I?;RVh1(J5v=2c~ zx?KJ9Pd;~h)~xgtWZWTejRaE3KN;=ztV8K(Ev!@Xnu}6xC(l&*OiaHdb!%+0nX|Lgt$4dofWU$(_8_`2Ewll10DWu5QhIe|X@ zf^Y;{`5`FEq0#|T`6ET`M zBgj>&k`d0P>o!zw9R0da#5+P}4CUzbZnj@Ub_QxA|2;huM}O)QVWtN5AqOE$Pm)zt z$f{lRn1$V!CL*n zUiXTmI6OHvm1|f{Up|&os_jIF!VRBjUO{pHSkC8==gkVw;L#grqEe0jhhR?Qz3WXB z*hOc)YTR_UgZaz52Ib>&uW?cyeOmx@5@U43`SSJD+w|BLhs!yj1ktXG+%D&ctSE1_ zF0DRNWE6ekZupv+iFxC+Jm_v_@3Bdx9G|p_jQp?`M^cW830HLQ^A5M#*ozN)$Z@H! zL$;WmhE%!Ia-{EN?q?@k9d0;6Zv0F!`)qXO3YXM)bPBx)_xzcBj#-M?;8Q&h`hyhf z&sO7x^-gl@QlTfI*Jnr0fLJTavK_8ovEbqUa6EBUm5qm6HIS#8Q8y+{f6~qAfh}E+Ja;8|k*5;DFOu&^H|YI+F88mA z%5gT{WX2Dm*ZUiuE0%7Qyh`0#=#oA`IrRc@9QtThlM_U)P$+filC~h7|A0vJzS&i5 z1$}fq#p+5|5v?rhFUZk7<<`p^eif};`hW%~*l;`=(9_L?8TV8Bw(n=huZ&D#6+m7-Pyi(xk4vx+sN&TdlOcDLb zsIs+|x!rGJ36IxWs@GdwcjYZ3hW_R8nn(m9wlUo=vyCrsQk_Ba`Yy2oMbQ{3h;!my zYiBwS<~Ozs-EpN@k;jrR^M2B*Lv)v*swH2{eN2Z`U99#)1(KW}90-I$48F`hdX2jY zuwc0mBXA)Ga}zR~d$-2*fW=%HyyuFo5|1o@=Gy}nVZy4i{4sAa9XJ1Dp%`+&;$g|a z#(FDJn=GMaqmfkDZ@}4J^i3bT*vJ{CUvcNK}H2^rajc@nG2kl9T;16klbv@Xr}jnI(aS@UCE_fntG z2ikrIl!FdS8eQYLJi!PyIEY0x-+JOVziId8t)za?P4Nzoww2I~devZ z)R4Rx-wT#|vjR}mFn7Q?|1OEx(_3iQS+=IS;R3s=ZtA-v3XH^K0-c;S?-63zD#at0 zf8zo_eiO1DiuJFAG(r{q%85g)9U8=_VmPwh*w;VOgzX^>S+zC-;Kn+YR zksr5UVF7r5L*pXe@v9p(|F4G9-oRv4UtWrFZ14E?QSmB8C@~)I41I8qH|Z*yp+<}1 zxEUY8){D)MzvX?RBSJ`~;&GS#3>=L7XUhpiy~T|O^ByK~oeZ>y3CGk&->=wwRzd zU1fW>774Zk%+!r*2U2Ldke}WQ&c3Q;roo{ENRbNh(lX=c_>jnYXZ9&cQ%XFj3wQL> z+BNIoY=2=_gzn81xk_g0`Za4r_F()yzzD=>yy3_|CuCs9UKb&6_KfmS9&sp7iF!pk z^h1ZR%Q1BqConxqe`~t~|F^105NviX|KcmsUk}z8ym6iWy^Qx9AyIf35XUAkiY{^4~#``mqe|1Lg zRrv*fk~bnM7N8)>#n3xDb}tnl=+q=3wdwhP1Nn1z7PI?F0coAu1Rx0$+K4n5LuG=D zCfU$FFXuBRH>g6^NUsb>erQS}C`>5vuTnDq*9)Gn9;Ym8mhbI|mq4eBLa#gXC(~Ac zGti(INh1hPzCxy(?O3DuB0k2=2*Qt6j9D!#WZ=W#9GF9z2C2<=T_&&es&~vbXm1}O zs&y#EDoPuqcHEWqUir!EK)zzG)^SzPS;L^FzKYfUiGV>W=B~@^6?+4h1JI0q`WH00 z%9lsW>8_mD5Rj=o`g}GYlC?#^(jSWXaf8e6>*K(}4yZv?i5m1h#!>T$;F&x;A zsQitbPMgpTHVu)q<|vm*-Clb4Y^Js~i-1TPCdy@2cih~ZmP2nuvAw{3%$F~;PU%}M zI&@&*65yvJIv*-IoJXVnNMUv_>E^({-Tn_Q-=n_yesdFqS+Y~Ll>02tC&tIuq99a(DcLxV`uMV8goX)pQ`er0oy#5kFM$*iBJ?!p{m3*U^~Y0 z%d0vW5q<(1q3O+IE{@*Ff7NM57nb48PfkyygbVdnJPs>z()+dwmSmVFF$+Mgh9cKD z#8mRtVkB`L+y#oQhH}^CTM4OC-1%y!&38L1!epm4FYP~`PVU{FE#CE$YO3EnckyT* zrBia(k0(Ms)Be%UiTB8|^-i~4Kg$SufY!kprTs@r?WJSk9|FdV<}_hIuB zsN)Y{5U|cvgNuWZX>4yWrMMm;<=wb>>*7crg(O*z;2G1(RJGp`f4^9^PI9Y9SdM8W z0_F4XmwONt?lG;?-h2Ozfvyu|q<4r~3=5SSY24JmXz&reEC~zcsbn(Jo*sl%w1APZ zK$tg!P7d{uYH8YpT&(*D+LdHO^1K9RPTGekytgS=*mYw=TD}A)PTKD%ytn(qx5xbw ze7XgNTa#mQw#yKB_mp0OrCas^_!-1DM$dfm_de7r@MG#scIeSNruyagRJ;#i1%51? z$qqSs$6kNqUajhrsWT4iEMfo6bvZ2dNLt>L{=3%#xIYNLb3*$Y9B#e)W9mw_<|%-I zpS6m?VeH)>3s)xM?nl!NRXXwaOp8Vz{j~)}2NjVc*r*>1y4gEt?{M7mbExHbI;HEd zF4i4>;?ur3pL{yUQ zcLOLtxfq(y5WdpL$}`^bFY?^MU`a{YHJ2WYp0lXZn^(P!GY&E|Bc8kJb+XnbcQftc zv$Q#h7kut!`bC=p#?>o2r+HAvN1=B^jNccb=~rEKPFtdm_e1aQ7{7=2 zhVyWvj=#lE{WnvlP~ZqYB46z_=+4lAMM)o(Qk*$N*X#pShlAN|-jqGWqk^O_$w*o#0C(msA+q1R~{+wFe_LD&w z?wcgkXJgOYfJc6-y}s>no@ryO7+EXuyy!ZM?2!JfG5W^hI@#N)U8G?U#p%5=yj_MT{9hTMFXFGH+kLM=LQ4 zlfK$`zSjFvs2gyRVY>GVl8xh5iCMTb!4%Z4x6pY0jrWVzs*Tx)I>~#PmkEaHBQHpS zjsbOMqq2lLP`mwt*M&DDFIt!XheF-7)KhN1ykWO!Wwzfgp+PgDxM1aLPPNAaqOyOG zF?HF1^N2yp8K6b>`6h9)zn~*qcz- zjLNfW<)WrK9oJ|7>h02Of@DPv!qrRIQkBErQh~bBp19y8-1vQX8NeS12Ws~V_NX4^ zP+7>6&%)VD7t)*_1aO>fJ^E|vaBk?6ax2&O_7#XHuEL_09NoZ_%86*-Ngx)l2rw6j?4Ukk#u1^HPbxmIrPQT;-C+^n2$BVVnEcIbS%9XLP|%~gN( zKuFJm^)6M)cmrJ<`D#k^vG3Wx%c2Z{_q`SLSl32z%kiGit5-r3FF&yB4L1;P%#&=) z`x~Obb>)A$z@=kq67y>l^+)dz@|1oaPhYX*_mwvGm5!-PEC;(i>s3y-aqB8k>M!v( zHP!~}+4mh2fz{&Oevy@0$x18mj;zloRfb?X1q!HM3skSR^49Lz@Vi__<@4-?oKbz; zQGM0AQlYt*gPqXoA2EXW%!Td&UKp;o`PkT}J3q8Yzy7{?{r%~&FH13L4%t{z2|vZs zc*_!tvIJl?#i_U9KBd62uHi2%L&xOg$gdO(1}qE)K8s6-mI3RZ*rJ1v709pT2Fq)r zb&5~ohG9Bi6+{LtL{0VJ0nc=U$bitBup)cN{fU}jWBAlgG#N()y?@6xQO4#qyC z`E^bDM0<0hz5Ul&IN!KriWeGz!DvCuwIO*~WlOZQiCW-vx0ql|elP~34IvP##mw@l{s7$G(PpJq5r90yXj~RHWR1s1}U|&X-veH6aUN@GW zj2QJt4Zkw=d}HcKEJ)I}=hCVngtDhhQfLfscqFNI()s|EH7d5N=ENwQb@q8?Hs zjOCYHD1|ZfzWklOmBK=3(wus_1KBvJI!29{uSUcOc@ex-@bx2OI1Z9e`hrg#pflFF zb+lGTYHNcpK=TuujulWP#iTF905tcby?N>z=fBn>Tq_=Swp|#Peh`kX zS-{u^nA-)=`aXb+sCCBjM+zA0`n$pAyTQ{D^-BTi6Gw5RHUY}C@z(UHImJL4qk39@ z!e3(iRf6}M1aD${a)TFF*bhQR7{sKp(4;Zceb2ph+vVq_jFrQJ>xWF%55$7oL>34gifCj!;ypq;T$Fb9AoB`ob%J^$D@2}SABj3skH`eHQ9FZY?&JALB_&^`T|nV zn|16nrrPMD+EhTsRDd8&!=-fm7|mCubUJ0w_sigVR$BLeB$w2u-e*j`|G$v{j^BFi z@7@yabeD6-$>c z*pUWeN%H48^$Z6)lOUH^HBf;Xs4X*<;H~zvCIg$QPU^~7=&A=MJ1>{)^Q=^Tv{!v< zK4WTr7r_0_?I7`?G_?Blwv24^%&y}gog>uKQ>sSAXuZx_OBQ9(b_V2h$oe2 zrT3jo3y=9HM@mYDn31)ho}!}fX<_UA12=RPBq82l0svU-_$;(I-kd;hI; zo)h8T_ib{YN3ogA!y@_>niedY761@2O49!D(;#!jU&y!C#J4t9)6Q_;Y3&Xa zUK^`!SD<0HTIhB#)e-@<27$4E1O4@eXYm^827z7Tn*HLT09GY9kGp)cE~xV`AXbe>!Jktu;x-nG3~20Ru^mSO>I8&_Jx3M}eBhe`6x=0HsXF(tQhdd<~e@ zpS(dS#l6gG@d%=11o1xzSsEnR)D!G=`nP z;z;{Klzo$}{jq!I+CM%)l~T~X+CRjFCnSX@d^vpPFPs@$f(cJ3aI9HytO0$7C28mV ztjSyv7WU;Z_2u{*5bxG;MvoA*+8|leg;~>g@xJrt&)}B*@$0Y1!Eeah|HcrM7k&Xrh!X^24`gMoaAl5?Y<+yN znNn>Tzv!)r95Nfv-c-=v3lFP$Qc6><$cP9yJE8l`xP4Y4Xd>X0vzHUx-_P06^C0K_*!>hpUP(<< zUKGfRYH6L4GjjHV`n!s%C@YBm`*TW8-wo#P>?bOx4|DW))^mn_cSV4IfMr;yQACSXb^n zx-KLn3Hh#Rib_f4U-l^$B=c1pY7yN|&Uwgs8~X_78Q6%I-PE zF)%TFYaC|PAhR|6UGB2S$4QpJKPOk9Ds$8)jJI^f-^k#c;*~}`>Hb~cNJGBNB=DOr z?32uXXXUtdy{0s={j<5#xerPAgI<%%5;zxYBnRv@m-R(9%fFY-I%htTpZ8SmMywGZ zuz$EeLTeC^IOXgw7!hzzkf$@ZV-Z1+46x106f7Bq|DYaA-D;2<>)TrPN*hy}Lr)2J zENB4N%YVBvZ&`LhaboTRic9QY;mi2LRk^HZvnIqKMB*61AU^f55?6#MSx1JlsUlb&- ztO&?-@08q)8{Wad*)2dpQB6ryQ9;G-l-xaMxOadb#2NnA8qNH?A?D8hqBf#(W_tRf z!1J5I{s!j$fE<6H-%~wcchJRqfJp*I`9Jon3{q7B-u(Y#x*6ZYvE@odUx{Jbt+Zn! z$8R0Un$TBkPN<7g)za8Y%@E!WnHUTTI&bFm=8@6Duh=1bbZxu-{VNGaZZna4g2)%( zHgXen75oUiKRZrA?K6?cP5eINHZl>szf2C>$2aYd#O3cuxb0GQdct-;kr$DByWxAI z7n}C~jMo4+j*b_;$BctZOPgM%boAvYkA$YpM38%3k#c3Y@UJ8=**E-AqQ7{IFiQXH zER$9ozErw5{I%y%Nl$@l3z=bYdfl93ML{ zA41s4i0S!M@h~oT`fUhgQzPBHX`nIWCHHDpNl)k_Y#r3QDoZ^k0+pOMSf{Y1ZetY} zyeZ({u%xXMQ`gq-u6;3D7?r%7l@(LiRuC}SFRDT4sXRlNGJdey=Ee?%*o>!Y}T z4;@c4#{=(YG_el0`D9rBR{yxai(0MPn>G#OnqDV2HT5qbcf+)H_nFVX+9|x;X#1|D zi<`8?8cJHkrEg3Z%EgRT7}aM&gr8@0D)cV-cJ=Yark`uk3(Pqb|6-s+;%CtNB6{!p zqQoisZBH5Xg1F4m<$AM$F-gw_l=uhn(Naing-KL^*Zf_bk_5ey{B;cxa>{V9M?rTH zQ+zXOK00=LQXENdtZw@udIuAqmjmkE?jZnv1-)GTdi5!V<<~+ zg$r%;Z`Th>%x?{b{^4QxtApclRl`~l$Yxv>rhcyu3o9B-M#*T#?k&$Q^P=#`{5{4f z&A5G7XmWM(l$dQpsLkV5`&p%#%_JIQRe&pMb$7I(Ep4{MI%;|HgkQjwHhP4Cv_a_p zMzt-=4SRwSZ{V4o=_FMDZ(sIG#Qb=RDSVk1f`vn#J6zDOmY=DWO7`9#t=AkJ<}`tt zwvF1u7kwJ+??ig6+DH5RT2!edDT{sGQ?A&`aj6a|LO7Uc^O|Tqakk+!Ddh=VMU3FZwvaKzMbEVXAI}Jw|_Ke_wx{#?A(P@sVsQRZPPHJ{D#)Afto;rT(v}@IA@cs7&QFzAW%eoy^ z97m4zpM6ocp?{(_O_F8a7e@x#Ty(yso(|GyGf%Fp#69mx9y$7n>4@R0DxZGf3n?>F zTjl`8vNTJ!Pky-eH!nHax8x(0Yk~QFzBJ}#WGVJjqgW*)OnICa5oQ46oecx$zchQe zAAw?R4o6Y8+4(YcP`p7kkWJ;zAGdlO{bgainWtGXvq48EH|h$JR~_2c>c;GSk9CZr zq&D%aTTMx0dHaM6#^Pb7VfG#$1G?fp)a1ASjCq=d?;dAgu`ff;?j2{aF6=)F=wg;$ z-i%s=#(zZ}|Eb=+FAwQc#2+?f#T|Zo@+^+jHy+Cdx%C3$qrDfq2ZgVQu30RB<|QeQ?STU$d=<}Jj;=DqP|#^oLR9)2+u|{-GuE-Wphf4zUC7brKG3x z?dmgHszo!CDUM8yzz>TYAQSC;FBJZl+F^S&vBMpNW6?&C*R3&^Ecgu>Ezc9;^dPqv zFz3#g;YiV(?EG(!sV1%DA%@G2utB1i6iz+nZhq3a4cJyx&sM&pZ3qa$jrlAbSz5Hc zn6_P;*7Wtu^WMEfYKcC6K59INW??wqTqkoCXu^8EvZ^tTj=_}fiPJG%tyFG&MGwZt}aW^lPetcdCCx&=6^ zdHST67OKtQ$2{_ops=aWGy=RQc51xn4(*FxQ0ds{Vez$$LJY4L?!z@o)xKl1BrA6O zJ#kltGi=`d2n+q*ZCvu#wma8+BSwX-Bm{jU?9R>g^k*m>nZL_fU;xS6)8|x8GIPBe zvR!7OSNNQhE9Pcv%*|`PUoSg2VSLgopOcXLEzt?Vd+Dfs{u2ev!#*E;%iAVHm(}a# zqb}elZ%R+A8M}F;^0m2jv|0ReLmtZLQtO{y3s6C3CYHk22h}M7xIGPNd-7B%oV1w1 z46tm(_1lx9DQXlgm8`aY{PZ(Q_1b^g=CJ!(_Rdp9A;FDbesdKvL|CGk!B=ZHBWYi9YRtEp(HPe>;3m~dZP$Ib(5k)pvi;CmW#ONFc> z;$vAUd~Mho{$Si|6#S&;9hkX8`md1>#}u9`3`PB-n;G*dxXRoYFZr}E1Zq&2$@cgI z%>RwSV?48GBotzM+0`CK>AgeRv()Hc*Sxp4|IAw`C zwQ1%3CYqW2Wpp>B(SB#CqybsirrKQHrmD}MX~HJ-ZjhmVPCr(-F z^*rRyy%#%i^P@Ww3-;{gIf6JAu5XT7|D1{b#oG>X`t>>5@s&d#a;Yt|ZKZ7}PJnqj zE~i>yMlEJCMoj4?|Dha~l~Og9JOx{i^tvV=02HKYs^vLp=o~=@-B&Q(o6kF#T+w1D zq9^OWQFt*Thje|}_%LfV-(LL~%$W!{k=W*-#ex))dKATrU^~ybtzl8m9$%_Ev3Pbj z;B&ChKlV{i2F2F?%Q_5+gim>L@93Q(Hhnv@#O2Ml`TC-hF58o{M`;GATl$b!uQ6v+ z1;%*!+RPAa9lQ$)QVzEqqMx03u@iM7@YX+?f38DrbtOy~Nxbagz30R>@D^{ZAKlFR zd}7Dyn=VJCIAq_53Hh-X&#Q_&vWx@fh%<6Iw+T8f(5k`7}kK5FV3G+p1h-x$GH zYEN2(1~aAXo1zEhC|jWVh{RI+p9c;29yN6gmQEZrU@NtsU9=iXeoJ#cYR}Hf@N=}6 z9ZRM>A)a-EIT_HRxX$i2}pw}$!{i?9!*{>`46GdfWW zIvyH=_z+Q7bRbe0IZuCeu%AUDrAj^7HFJ2(FJ73~K7(Z$9K z?f;YAeETbcvq$a&^F~VEFJFsSzwdSkUJ8@@_22Ue(4z@x{S$ofQ`Gu1dDGX^g{edx zlsrlDI`-_J=+q(HUNK*DnwSab#tp3e0Gsxq>l`a`YAl}=t}Iq*FxgLTjXY>l7P|px zN}E|QTNiv!9W()VnILy%&)IY|UYfH>4L2lI^)ZsNy`8BtH^=W$Wv-8REZJZhoyV$< zg-fHo`4*aPuEg!2toLIEACrJXd3Ij#r@QV9&05>pF^-6=R8Gg ztMI+8#WHX;h{gZCbo5i@)2P&=U=VAV3;S-Dpd#g?rmjZ&dCU*3)OZOH<>No5Jf!w6 ztyFDOsSPLRtY6U8ANaAusD`89(5PsdBBep8{{La@O~9dy-v05iZ)IO=Fj=C=pu~tV zL_}FyYz<>gMYc&{X6&+NmnB;$WKH%gC0h&=(Ik>}M%I`tW9$Ez`u^Vcdaw6?{eIW= zxz2Ok=U&copZlEic;rQC-nq1Sh%jtjoP?2Cx8eQ-^?*e9^xH*3>vsFDifBQ(;vj!F(UoMGB zG2L0sNK-4-Qer=^CqPamYL8Tg8tNXgX6a=3qP;fhW6Dz#`b9f&ODX?HH)}&YkDs`t zSfWyMywF7;f`qUx&G^EPQL*R5&e3n}&(Ab-@lvrWO_Y((Hn)#&V^zeMc)oVa?f72N zcpSa&CmK$ElSpupTrJRTi|6$emtKb(&Yqo^AMiCv1RcrYI&p%&GRF1N1@^IEbnun~ z{Yt0qL`+n(5Z}J-m3J-aJs2gWUszUmI9|ug0m!I{>r5S}iSrUz#`~h0)A+ogGV8X+ zu^Qs}&$!m!Q4@UOx;b2f{Sm&CSOX1liGhgp2CadJ4$6sXY-Ibs7hEcbD^cEaM&F&A z^tcCoVyBVYQ-PJhG+`1Qpml0G;M(kd;g+sGV-6P`IrJCSpjhDN4v8~j z`SF-Y;Vo|1$_e)M7{xZ-Ss~|u_nNgmn0q{1!xF0{Euu`jZ`UN-gee?dHo9?dBZVLF zz*Z#K(J{X6mwV21jkjaG2UkDpjVH%6%Ls*&Q?_BLp2i}CQ*m@raAqloBL=g=3H5Iv zK)l(Gb@(02>xF`@x7v2#T6%W<&Ai~J2t{F(kG}9zHgqmp14VcW+ZLnbD%+)TzSw3N zVLuba9nJTVn2a4Y_si&|wYId!tRSEDla(qyYRSzy)V(g#0hjY@v<%_+a|*BXhA zeiB{lx^Z(+4fP^^9%rW~ZqK&#N4`cRItEL0(d)%AHL=To-#=TK%TF{3Cz>=skNKg_ zO}E~e#SNw>5|t^L5|siZl~}!Ka16ha;3;o;;QilT%+77@*O00=ZB^G=@BQ9=#j|x& za!+EMF;h)eyBJrB_sW1NVB*fsHuQqKF*Sp$gO|n&o;2$p=Rjxm zS*Ud$Q%s*>MdJDpdt-f4psG<6hzmC2oN!0yw-yM|x$4 z66*CYjWYo`)_O;BikdyZ`>kFbxS5XKuD@hbkg$dcY*T*c>zl~eE>VsIiB&EAwm)F6 zKd`j}^z1%)ek)gUMN4KP@F0QCe%mioK*=}9`v~&4k|&SjByab-&S<1{hS6EiyXxsi zN{FZizpV3CX}Q9>e(A+c z#Rz{$qj&YwJ5yOUm;O0ftw?67)o&U{iQFYcZS{ZV0T}(vmORF_8~`zguUhCoVf%gu z0$G928xH0fK6Z;;iq*UV#-wxFA0fP9@;fgU`#g5auMR@!dMDf^oa5rP3SXPpkC0;h zKylN{c@m|>?&zD-Y1z~9Ize1t29Oc(JI_mK%@*aRCoD&!FRYJqs?{_6%XV4fJ6@;r zI4bdVJDk+eGQb9KukAtBsM_t6&<-*S4}ps}SG@2YMV+>;%H$BS%!zv_HOs5zkcgzjQB_vJBio4l7&fEgsXaC-P^avJJuRKhTa`y?9S|5l-PoP zZSxF7270c{JUdsVMR3uGxr`M|Ry(go{W|G4h;~pUpbwnascCE!C?6RWU=X1=?(c8A zmnEE`bOq`jqa6y*ZC75*eyC>qr&si6DPJl1{ zB7$%_qcXe{+&We~aW$2iJL4wwoNA)nr$EzY~i7C-j*#ABYW7SBcD_rTGh zCzeN8QbF-R!ZniwF}{>_j!reJU9EFQw~HtKI?oH`OAgOEMx9vfvaY`4?)t>UJo=d+ z#uKrm|!bj0ylb^WOmmmFg8!kvz+4y=c#XpSSTC#NefKX<*x z8F)3tYk1~H7n>LhZt$y6D(fCQVN7RkY&gnx+|89OYRB$z>tM$&r|14H2fZpEJ zb4JNe2%X(^*laCcis{^SxQ)X94_;5To0aP2y7 z9uzOdkL)_0N=cPUPb^uG~HanYsb@l?vOdK%7qt`zbaqQN-HnCX!tf^Y!$k=7tRR#3T^=7T( zyXcJrY%cCm*1T7&S9G^_uENsiF1SsLiO?{yedk_T<;bF|eW1cb?vp+0fl3)$#73|i_OrL|p-kuQ1GumJ1YqaE8a$g}1|ZIV4#%nM*L~c5K+_6Sdc5_s z9d6TXLhjh~&8;YVJ>u#n*tK@-)?lUFu8%pu=;Pd0F;V$u-Le^FvAMXguYP>Sx249R?Q<2|U3t3E#M4JkKCn z7ZJxwGvI%CeSfIR;J;KQkt2h^Jdu*W5)19so~28M%&@}JB>`#zkMvpQ$`eVqE*c;L zSi_al#goVp@AkOCT0QUg5;U~JqGeN+wnrrzT{xn8j;`4qAw8aLJfWjc%|PYP2*J`(N#wMiac)u7Nyq-EnZ^?*buY)hCkTAhv@mcAh>Ana z+67$BK}oC|@pt{rJ?VH7nk(0FSneJbck9>Se8<{2Z{jTpw2_@V58+H=qqM&}8~)66 zqxAZYWYY!CWk zaU+J&wyhY|CPhl0g`HIFE+(gkfs@l6CD5_{ahLH*AJJEw;>-w2Y(!`j5t>MZE)bzK zy}Bf!jemN3_VWMLFbWTCniLASwBWIL^oHD^I1T2j=i-PrP=+o2~;>}1fLtjy;0MQg*QKtY=sh;cY z8mZ~P?lc8BS&~aSG@NsaXm#VIr1<4D%`mVWP9-3FZT6INjv@X!$Q(xlTA5mLQ%&XDbq&2|nOwr{L$WtDV1&b$dCkVxt~MK4qWNn^U9+ zzph3D7W>i@`*M5x%GCCiwY3a~28FY>X>65!)u=SD*rIJ=6YK*`FAbu7Y>_7o07Z$U zPC?4xeMZruUD52_hlq|B5OAzGOYmt&rfCwrnv1u6&8B?K*4FYJ!lo6|SEI=n;$Q;e z=+j{IX*lVIBI$-24Oo1MFeTfs^*ZV8G?mlQBAkZK?h5wqis*P7fjAoh@wcZRV_oo% zda)M3KmGSgx3?{(wk_7yDnr&P+i94dK{3ss!fEL2Ze#Cmi;fQzhzk@D|8rWTQQ<7m z88&OkZl#)O$2;MUcRIU2v3Gr92h#3O(ecky@rPBWu|&LXXs2P?(JS21tFwEWy?Z)3 zzB4s;u?fGZKIdbzwg~i~fH*-8Opt@;SSUYNJ3=x7{>-2%V_I*J`WC3XGa=zLbapdw zbTh@oa|p(92#O2IgN5Yb3YKaLmRMw!9kR-khV2HskB1$Ztwg*@@DWDIgK2=bTB@~L zVzIA1v9Gtc9o}y{Owq8m)_E=cYz+B|<3L%?StVmDH5#y4)t*_^+iK2JYR+q3y&j`_ z{G`7uurF5FvNxV(Z?-L6-dnm%(XjS<;J<6RZLLNF7GL9uuh~w&JC%NSL+SH1VCrzY zEKI?YXDT|oZ8*AZO5@)O#=aGdJA}FTqch+~XW%Q=YAe>b@r_%pJmJK27_crKOLna9 z>~`nqb}x}NV^kC<4>gZVy!e$B)sDqHtO|!I}HntgW-;Yo!$8y-T9^QdTEBToT1dA?)<>n zT(dpPbZ98qDE6*U+#xK)KP!MgE5KjcsJ*noU3qJF<*g?TJLwNg@M$9yXZzM8IZ&nZ zwrVtllKWf~zlsqW!Kg}jtL836wa)&p*ReZz(JW13@zkp^6Lo*GN*=0%WvSfBvGJ7#Wz;r;sG*=FiC6@=c zKyc}J3FE&HdewWk2Jc`QrmzefROV4pHWe*6OqORQ%NG-@Oz~Ex16JGvR;Iac^0MCK!Ckb~T(ofmAz}h%>5t?n?hl$v zv$pc!tJ-R-+PH~Ohlx<{iBQjp(4A(Mxn`CPKdyE^t_6zNImjwA>3eVUam`ilm9U+0 zwyANpjYhucM!w!gzV=4G1++{GT4tDR%t|&cCS?0^vQRH523n9-=MS$egdbVm&j%^0 zBrjRA7c1Edt2l0%-i8y4@Dz*K(TLl+MsEgYraW5T>u-cCptZx$+QZ}!SyG5Bkdi}+ z2~1`KOlG+p`B@zKa3NhKAzc^^IE6@N((2^)@%mfFV8V~|>-kwUz>9QYMY=fSC~xDa zoh;tYEZ#X9Hek}ZbF5D~*Hqo>v(z{a0$5ql$P^le$qlmPhGK%3*?^Z>?o59AOnw#( z@NPX=w;nDo#yc)%2Q2iYm_bRIc@eR${?1Q%f#Q@xaT+FnlqG$X1yb_IVnVXnK(bk` zOhJ}R0o>%0lF20)4Y-`xOF(Y`RSksa@(_N+PjN?ouoL~|ccIts!UE-C3gzK2d0CdU zEDNOM8?w?gs`@?;~1emuk8|d47%uXzPIm;ZN4}7w{rO zSdk&lIMu;8)tiQ$tkZK@r#E0Xdto;h(64enXp2sb%g>F=Z!}tETIwee6MNM2ZS@tq zjbJq3;?lh1(ssbmIWTksW*ZH&?WJJ>-JF7M9wz&qBKwvQ)~?~#t_{$TJF~&fJSu6c zFR>WuFZv#Pc8-P(>g`_Y?FCAI3Z;LT{OlCz*(o3;KPw@qULR1sp6l^4%i|^d#}%a? zS70>YT1PJmyTucE2CS~R|#=%d>b=Q;6gr&)EbS#`tD<20~nTIypb#$4`p z$_B`nNy1l`Vc=oOf!yl=aStXqh8LMC6`8_lz!^XHHh#X7r8AeM zvjGc_hK2Xiuz+SyMYE5P`A?JiUlC4WIaySq(0r+Az7g`tSJfv=h=m=QDJ>^Y0c+?N zsoa_3teIkXw;8P43>P7#O{g z`=%uQO-U9Fa2LvnBh}qx+-WlI6=C-Ve)q<}ZpZ!h$5UPH{<9RgSLv^gHUBWb++G?M zC~)z1J52LSua)ARakI{GvpE_z8VhLLNFz8afT6f?#DdDF1z)kbq(mgQeJ;&Sk&wc4y zs7<8293fwoBVR2gJTu2XGasNKS9PD(;6!xg2-#MSWGe@xWZP0gi}^r{c`l|r3sVl? z+ED`Ir_2Xv$o){B^`RUdaSIl43&&aSz*+B2!wz^Q;?SjIvREqMTu3D@B#Z`}ScA7% z!;XgMoQCIy-y~rw@4Pp>5x@@Cdk*WpL7nZT&Mr_s3Q#_#(lA0!);b(C++5ZJ3hbvf zFv1DvGYOY11}9XL`Pa=)`$q*>D^!fp6^Jn)XGB!B5?b3b2|*AMK0Md;-(dcq<7f;;J?*H zet3sH%20k7wNSXDp)_JSlI1;Cl(AEtwbzF`Wf78I8JdS=(Z-1~&Z)DK79oEP@TV-E zO0O)+Lz-ygG@0i7*@0g{z#oUI_p1n`xSqEBb(k3@-Y~5wv1@%9;&7E|E|a}iMF3B{ z;d|(K$NGIl@I+_DvOYUxns%c?D7EPbmwlcl$@PLP@u4DW?0r>TsMmd#xo?~RNti~` zZmbKXe&Zxe>FU~NlaBF_Ty=$sk%}luoyJRH)MGq^DXGH(Yd(_eRbgVLBFa^#@k zQABM`pEy$2y?Bl|poqHgq3YpdujM0i-$Y2RE*ghU^Mtf>oV4g6{N;yYMcZ>^;0Nsf z6IvHikRLu^k8*uDCf22*k>cu`UO8p|mo#@wjO6O8@i?>=5$hT(OQcsqadb2YMpCUI zy|oBDk=~D!Wh2KmT9(MKgu33*@G_E`DbcHW3T`~NSQeN$HS+Bci@ zO-iuESnF}9KS9Mf#Wf47n02*mtF+I zfIccbb4-!s`c9Y_q=aJVYG96~9#bStO{#~ueiSAqDWQ!1(YjRZ@Wdd$BP@UE71EBa zPh-8#h)`;sVqHI`S4vaBoE4G{C!cs-Jw{Qv8|ylhUU}IOncRiFno0Kb6n$TNKh||D zz4E>za;yt`|M<+e^CZ_Xz$X`3D-s=%lHJ%R;F)7ElIyH6u}29dNrr)u`kv*YGu9VK zuFHRE-3^!GsK;Q0!(G^ky{ycasJS2Do-?UCQ{XPAFG7Ly0T6sUjE?e z=*I}S{vwN-KMc50N4Ll=LOh{daq;*2$=4d8z@)dn)KwdcCn_tKIXfZydK#W4Qmro? zx@N%lcN+KTf8ySCnz?BO{{@5^(OjS4O^2xyy{r>8L z_BPn2Q2ovRntxxLk0(YemkBr{<$4>;Q>fN|3;N%0yu=fqDVM1_BRzT>CIE@+f9v&L zr4&yrJJcnL-0f}HOr?Ia=&G&66I+!laL%opBaUj8e|j4ZQoZ)&C>xcri>QpsKxgD1 z;31JxV4U~g`_#lP-pQye0CsO*}9T`O_Ksxet34I+JNja`o4Y2z3>%IC>j-9FM)PIP=Yp4@ z@6P>mK;EWk1x!GH{5jZd+wTzW%`N5q@|L)PX0o8as?pron3BC8CU`JD_+nggDp&TY#XLaFYZbvpR$PRz@Bn&Y#* z)G}c;Zlx{N6Uo5Wej06S+-u&-qRN%){eue^lUtUqxMu%QATO2{Yh!Q$ zhTn=RYDg1JymtVVRpZvnm|9$QQFH9(U4qL%$ES-Cw@Pi^yT&z-F^y@apGKVtH^;o| zUw*R>ajzMxJ!MfkQ0{uYy2iwIjHO`2lhDY!vtCncZ1hco%_6FMut`3qd!+Z%EAryz z<C3%b4VQIbILY@^Y~9PvdF1P;e7DSjulVJ{$)@tx z7d`H@Ro>P>qrS-yvJ$_N%j{_#1Lf#WW!v1`dv8wHMzfS3KK6~A5T%e!Dx=6{ z$#t&ZZ!N#7_mjE5FS1+B{b${ZeslLcoGy@x&CgEt!7mCyr(usUXL{ZMjnI-C6Kom( zk^Rjv95?mbXWf$ikN&NO&3iw7Mt{?KqWNbl_Yb8&An;(Z`JO0Li?w^VWxW03(yP>} zdCfBq?v7wiq->g|S4KW&YPS?^BZaSzysdLg!7eAu`+o@8>0Dgon7ish6ufNwL!rHe zJMeveGegbzPps&1c{XTp~C> z=|sQ5y;a(}*u^2Hb`0URD@T2Gv5K)F_loWBtRd}hVzzaaLJ$4({03*PvfQ=0J=$tJ z{1Y~>XQFphO7wfy&a!`Ocae~Wp-<4}cy1+_Dvbyv`M;-Fu-qX_Qw`%#^y6Ijp#E-) zkaBPBR^_oY$QI>$OwOjdflOOn1+vdKI))(I2zvdCY+8Qy;ao^~y6% z=(nApkTd?1stK6*dA$plL<>bf&&q`dunpBewXNzOrn5HKs08-T^hX_P+__-%O8KWPG zM4)$>Pw(>FJZ5GSSL~+G7{LX7Bs>^=ukAW2SE{R|lfzh%Ip{u}PBYM6I@36~V<4Td zi!@XnCIV5vw6^R&t}hQ&_Y{Hn#LmhYP{!%b)_UZ%%B*vI!gWyc8FJ}{zTBBxyg2wk z`FB1#pL3|LIDn~yPuBdNwd&`+!#!u`XD+ABkXSyrpUo=zDNfiow7(XdXm;XhWK5PrCpIBlhV7 zah6#FBB%!oU$u9JD5?qS+BaAdSl+3kSI+heWqUqM7?1k7$T0JOee5yAH zWa!~TJOtgBsl?)(LW9E6I822Req1T6vgJWTuUVAotEEk^zuVbhbBliAYv$AmdVPj9 z9NEESAPV_$B~wxbJ9~-co|R7vP@5lc_M=FNv8;~+6zJiw;)W2Uiw162m3n> z%1pnSWwTs@W;G4y6K1t{4!(In&TFSLL^|^SsOScJ{r2WDU@+)5Xr;@Z^J2k&&qVZ! z>4J1M4CKl(7Kuf`TY(nzw68N10-xAqpm~M*rPt?~E>_zr=(>VZm69qE^orBk3$MkW z4Bl~5$qXp7Y16zrp6CRPJbfIr--KnEPfb&Ze5(?ivMgKS4L_>GJ*ipY$YsYD1PfBb zZ$H!~_cW%(6dp&YUs^vp|LXRj{mK`{r22x4nN3@TI1iAI$o}TA3d>%L>|SMP*ud+y zpcJ-zHPC3>H0L?2+1Dx1Yr6I2O#E6DRH#xdXhD%I$K5WE*g3tfns5Z-M>n*wJr+6( zzCq3B?xV}Um5@`14jwOOE4(lXg(z#YG88%ju|@0=|9p&t4vWEfC_e}o0ukcOaf3gX z7dX$>%Rt5$^ys6F@;3R++cd=qN>$M4$YqH4lJ*gV8y)Yzo<2KXAF%{;+tSl+W{_Id z<_#)jGWZ@U8&u39Qo7(_vhb*IjUzvf1@Vnxm@Q8o^qn55RrZMPH<1r9!BEHsfdv76 zXVZgT6D_pqdFvBu`8CuD^pPW>hNT2_O$f3d5`gJwV|b6^=7)pU#UNKfAL$;X{b9<3 z`GpFXA20MUKVWtMIdCMX9ZpWz@BKNQDV7Ac;2jgc2YHQ}bfaRjyrxL{TKxN&u}dFB zYyX6>9&mmN)R|NTJpDv$DkVQ><`2= zBai6cIl`H@(r>DGFheSOl6NAk|$sq8oCUMe6SaCmE?d=daB`TC_0 z1|`p}KVUXB5{0)ePvF@!p@yqJAuYzEfBlwq*UU*+&o)+KS^IR*FjFMw^;Vm&7ovXZ zow~}<(PhvYQu9{H?&T)qjm-j{ARaE>c+E(<$TNr?(VaRG6&cSK*=*OK2Y;wcg~r?? zbUhFGTLL=jqBs(iuTUSFtrpe_y{I~x0Jx+;;o4|W#y3?{_T53JAYe=y z#IHUdOqsjmbRqLX_^KWoj-jxUyVX7ZYDOTmmjMhZ-|p~$+zm0{%v;hwp~${gFh3$6 z$ncu29gO%IFY!Tk-GTpZ?DV3I$j>CGVGbCg47h!v3r}2gZwW9`56=nGom4=q2b_z# zl>D@yWOopPr!N%R-^pZAC8v9L{RI8&qo5GIjAmfOxA^>a*#!swCeco+!4C+q=)J2e z=;gYvUSuIWF)^pX=Q0>2JMs|G-X_Gkci%y`VV8tVeLx_J-Ovu`wS8~>EsRTjTYw@F7c>im3CNQK7W{Bd zP_LK)tARPf@z1OfghBXLP}u$*t59OJvglBfc}>9X%!Iwcc(V4+<6`_0P8{Z5%hqfJ8GG zV1m@?Zm>XZon86H2Yschgm@5yeRdrEF*;4oUMXlD2ot9C={2BJ7;ZXltDxbQ%Z4X^ zwio(>F%U_}E&9$DD<->MdZ~Xt=5{rjCG%XpOx}KT)H#podlMZ87mjoj84Aq!=9o6j znE#KP(>P_L)z$ zJ*JC9Ml`cr1|Of(d=Kmky@@ada-ydji^_L zxStEWlxmsHU<(l()XppGQ5i24beSWenuQ0Hco>B8v^mg20n=<(G_0;P4+9J9;OY(R zg5HZ_=6})dKT)QdY0#0m@fM#!VB`*ylri@p-K-`e6O_ativeYTI_QQq-(dyDRfON> zwt>Df+Hu-xz2-mpRN>^)C7Gw~9YdWRN&6kw(k+|PExk?3JO<7SIbilZ?d#|YF?k4t zJ)09I&j8`Y_Q0g>aK)$wm0-BReGXFo{{rd1ep=CH4@zM&_!fEtRKmeM8Zt|(Qsjy@ zeNY%vLzG;DPH53>`alTlt3OD|(e8p4a~ z25Yf=@G;!uN^Py{Q6Gt1f>~flHPhV^g`>0XS0PO-Y#?4iNF7TQh*t>W$CU(sF9!VpxzQ`Ka5KMCHEfQVXbq@hTmeO466hh$bV-{K0mK5m z?nB5=b?6<)byxa9O#@Iu73j650b@b~=p!b95ptI;sUFgQff@h(-)wq{@ZlSbGpfons_9V_NP$OC!E8%`=bdzW zyY#|@G<}1vWrOY++GGe>S}}z@Vl{eHjCsU5%V|Hy`Sa`BivUILkwN!_D1GBa%f^f9 zn=9NsqV2t+*R(j;Q6Gx*sT)Em4&tC{rpWH2pHL>CCKgscgeRzuC6W(;1kIj#=d-4+ z>v8pe?`0M@pqKf=U_n(Zw4Ia}m+8r%Y0&2N3&z(kG?je+&>6@S#9<{Qbgd3@MycU& z0oUDv&>`CCowWM-u25>yN&74=fein%yMLWr+LsItEDR6)Ee_s4+5zeigxGT>(MdrO zn*m8DwJr~sOi!2$&B}bFULH3Jy21-Frk|eBXT<6X!g;sg5|fhEzY-g^c<96v!{a+z z;(KN#r?FBiINg)tJY>nW%|wsB(B1Cqwp!cQPxBc}gzV`l2A=spTfVQ)QvZ9b)ihvA zXkr|-O*16EP^gRnmgiANmdr7}1o!?SkfJ@E115nL;zgIV1z|%B@j78_cx}>ZniZV6 zq!^`u(Q`ZvY-?t}h6)FLrFU92Vs9(JW{C;LNS>R(8Ik?9z+-B~^ zb9C42E1&)$iy6%zj!B3q7uMf;MsNUO_y`;`-UpC`1-YZesmF~Bt^w*^H_q`}v z)@%-nNDGhH!q@&%Aq4L2%q+SbNcS8b{3@m%MNVWQ+_-q@q=2<_BITU66pQI5NSUsO z-p=)LkVv&+!HPCNVmNfx(IfgQcOB?!T)Q2Aov_}&eOH6(i!0onbcLFTY|sKAa*65e zLi>@?kl&`^9EX7e<58YmZ%!`vTP+u8u2pDOS#7Bess9pQPim?E^6^$FZ+Ac;XTyMCYEqtDWKJ$|UM&&Os8!JL>9E_QPm+mT0&Ut_%RtKq zj4+#|N|4C|_`J4S zTIH>@v=4Ut96-kFsU$;>PS)a=oB$Hv$*Mf17y{J18zN~kHgjK zD}iqePj1=+C99is<8b-$)|Kz@EAHZ1W5kv*7SG)(&)ud+yC8RQL3h-ayZFg^u7Tyn ziDiZcoFz>OsGe(LdG0GsTh&N;c+e$w@{fbBoqPnJ`lYfmA!lG!tE zJU#hh|IX=m!_qwu&!t|vo>q{!e5azSniCCdXTOIsg4m1_vM*~^Ej_l%blM%%4T?In z5n1DO+1ks*n!Zq)V<;Lk#4B;eD#?7D@`U?GPm+hj_h;dXuK!`X`;X1=KWyxnyekMl zwi+1)y6Ge)uNRtL8-`-4c<*zVXWA86a&HL*3EePOh2h*`e|f!ZWkd`nK__4}FBJQUFRqH21m zGg@vr%E(K;G;t})D5~MXWn{IC0@L&mlh?B2Dw#4Y8#6_HOtbobu}HMt-pnQNpO7INs03V#wjQjB3f_dgikiCOv|b_VK? zNZB8^*9V_9cb)Cpn(ef{zd@bc1m1rC-wE-?E%r|fM&F>AH~TnfB@S)PPKT`jgHXAz zT(-aNuv~;;@7I0qclmi!(WltI!>B_^(z$Q)TtxO9RCaiiKQoF(AOvK5g+fOOn@efI z`|Bb5ZiIjqhc8Fpfctaym8(#;Rk_PTi5Y^4evOeenok7t2CMVT#y;OUaqNuIvD*J4 z%(F6!DfSI6-K_yVdCK(UTh1kp!8=w%#moOM1PHAI^9QR72b+rq>CagUp3B@iXB~N| zFX<8`K-$_)+FDRW^EynK{0(HF_fGbjC2ESWQBw#r>iHY|2s=?%p#3N z&dbZj+iL>t#iUTdp)i19FGoE0(SGh{@;p_xM&Z=C)l)U};a`}-Nt)s2`Jb8!KQ$M9 zV&}IO;?LaTw~o?TOwys`=*YE~Y1b8;U@tdfKl2|A&i^#jEdA5)^gkM^|7qCa@A)D% zJq4V*m;D;(xrj_$X_{OX(^E~eQ`K|!nzzMrtU=WxPsDmYe98%`(z!O%G zKS5S;w~glgb%U(9{YQD5#1b#Pk@{UN{XmoVojhxc8=FnMZh;jqt%zQcLkD_Ghj{VM zIU`zz!Tt*nEM%YDzC7;(=ny`XaA&jODj1Y!JIur%0VFB`3CYiQo`%`hBg^#Z(wT&a zXM`4e?1h10bZfMXXIJDMe^r!6SH5-su&k@df+Rv~17ISSl6^~9kg=F8cnR`ktI zMpgq`jQn@9y};pLD_UK9IFRYxmss}O!{H*;qMfN+KH9&5mHoIL;qd}@jM;nuzkLWR zN6@k?eXNB1CHq~o4mJq|P+dW!VswMB-bB2_RqmfCx+)dPV3E7_mqz1tPO@5o+zxLy zSjFbA=qp_;1DH*P!*|SL&sCrhZXs1n?;i3q7gWv3ih)Lr5SdaC7+WNU%>Y7o_XM36 zlMH&*!SQyUOp&42f^*-70SA)wh#v?g`N5r;{DDZ{GIR26WJ-p3o5F~%d zi#W-~EpsTWsaJkc{?h9-P=*vDi?O4H@gIi>@+7lR_oNBPtslge0H|$Y?2)3IrpY4c zooI%YX;lS^QyDdY(~r7Da$Mx+#F{h^-JwL`eVFJ9wnh(zczvuTFlWp@@!H&p`VRxG`J#j2aXq&B4~BSr)Fm*YW}kR$<|CJU zI!=lz6-k{qYvF%(^MP)iMFhE> zKr{(Ko-y`hfqvQs9bxPdq%Zuxa{NBhV;ik;X7BGENZF(q8BVZ02&|`1a^L%-v z49_hGOiV<7uVH@OD>m~U}YRIJVvE7IrC=GZJPhUns4#- z*m5pPMT~s3pOCX+k}lUD8FTj8a?17C+w@EUlj>@D@=Nog z5@%?Hz-*PmY}L|Sm9e*FHW+@`>%VIhe%H9oeTuuq*}dpOcmDQQrNy7X{kl5uJNoI6 zEb!BEu(iqjDtDim2B>=E#)WC%yFayu{Hz6*huUvlt(CmWZG64Y{Q9ziVs!XRI79Ww z%?nN;o=w(uP4^<+$qE9Q>O0*>)}VA>GoRaa=~yh9TP#0vN6`wGm}qj@Fv&r1MT42NB5 z2WKe~TV67M8m{^@40K&P_@q6jar&ZdIs+@(l9d8?A+ukUNQ?}=_|*B zbVl_m#Mo=0c@Vv5GeV28TIi=@)C0T3I!EXbovylXVgRcXbl9GE;hoO?Zrfr8R-a!w z``kUY%O46igGVOfT1;8E7be4ZP9(H^>%P1!S=u6sc^(HD9^}}#2*K3GCx6p7$6VOd z`CjVtulA+5tYLWdH^AlstBz=kDPYrLSFHr+R9o)|9p(vB_kRx9tladvw%c>h1F$K{ z>ht@r&6&T^BTT&_Y=q&=QVChB((i(ova3hyC=Xe;dZ0|u;Kxt3o5|C8BKn@LEnvJ z%hCs?|GObOvxBb9IS;qffsPe>{f8B{v#Ki2b==*7ogX16S!j_D?N-TK@=yA)I<=ik zf3=-nI_t@zTK9R7$Zue@|u_7scS&k}vWBs+BbZ!J<(~6v}f8EDz_mK_b&Q%?-ZTIc+wbvi{v)!8oaon6#x&f9a3r;6BH=-@W}32 zH9;*~_o3#t5jNS20w343-Jw6k@1w?kyzM&Y-=6SijnWpd{u>iRo?TidG*L{x>{!gV z!8Q)ixlI;};#$-*_H*eItJ2vO6F(K!aRE*B@xLvoXLm@851Q=jzwCbAf4jSjbF%Od z-s(>uc)U8^-r9ZhliaAE*xq2KO5KHS4$C>;k_?2^~$Zgkwl{rH{s)?>L`^&Ts$ zaiyLc;a<5f!vd0aZ+|Ba@A2>ZKLUPWYFOI!S;X4mPZM@JZVOX!bMe08;~eoijB@jt zdE6MuyPI=HxpvikH9pa%h3tiT+@tw|fKfj9bxLz{a^L$`6KGp!ZhK9NB(pH^9an?}uM?%r2Ge{Ntn{Mc;lK0h;m!S&+XW|^(N zOy2Y>M(a^-9X;em%GW|?imi#v!|WdeG2a(|?$a&*Uu6oGZ{9wC=vK_l z;as>A))4Mp_SDG-zw{@iHHigvtLSvv9uBgQqoVQ~&LM+}-yjN}Oso zHm6g{vd-TXq_K;g^Ma+|7?Vsoj7 zvu6>cPf7e?jTfZX7GqSrPxa1;jzsNzs?+VZ@*A?ih z3pvTFU4Dk#Z9zS|5L{({edrNQ=y{-9n(i^|ZK$RJhbzAce}p-iycCvx%nnUIux)#g zM=`n$B?AtxJywO=|Kj}LcIp}d9jV!CS!4(4wJgRb1nEDsuDur^3aE=DUN1xoZR9I009ave8$9<`V#t4->EL;JXYcHKOD}~ZZ{oWK{>ALLl4gB&cvym4gh^Y z<)%X+FdbE^K% zSTI8+rz*r6AMsPhrtR}Evi~?8r3Ee8s4T&S z(M$o+Oybc@*Zow^otMqo^q`Pg(#cB^bBu2HRG}y$IBI@JAp7xcXwg)Pg{S8GV$JvYw@?cXZ4kz1Qw_?+m~chb z($9}QKsUT$udr;X(FxC7t*LU_uI>bSvdl@y00*O-aU){elTLT#fvyEOmOa*LA^nq| zZ_hckO50*RD^Lj3^M^gN&qcKI`Dfd!UTE-kC{`dx6Xdn9M4$NBa-?fCV?Z(8pg6?VOKm2eH|Y4I!pbBZ}R-p)LJid=_K{g{UI z1vhWrBi9G~*Qm?KIMu;)V6Gfu$tN8#=FHY#eH1{^FQitcAH+)vci(82On5z&@_(WK z^;B6oMmcAeN*fsd#JA8!^b4_bS`xsSKsB+{NE!P5(?{UYk$k?+sW>L*^U`(3tgo)% zslWE+E4nqc@OLgh7aB}j&uxId?*m*3B z;!<5jEZkxzmh8H98_kHf)`!dbwVdmpAN#PaTcraDAc6i-C#=`BSM0jo6=Vgb2{ImT zxL`}H%W}hH3NR_?3NB0>^R9fV)m0#&cLtWsqINAKsXL4a5YI=b;Jetk?1o90BG1P= zz%f5ZDSM=ex_F1tJS;c6@A2?P;(4x&Nk%1wfjaW^MW-ka1?_Wx6wQ=jS1y?>`y{f0 z$+q;BcOF?Z3zBbB?b>y!UJW+~vL6J`8tz{tr(0BI-gy)spSWar$+}10ivH?Z(DHD(gpDlfSDc}T-1JHeWLav@wR@eD)aFp9mg^t zA|jV3q@1q>Tr8nwNhy}3s^7w$(o%GZTxRj}*hgz&7?`Abc@&snqVI;I=~6T|U%tHX zY2rFuki<>z_nZ^ZANs0>B*J`HA2P8}>Y|nW=wI%JPe?PvfmM481|rRDbTLhg&X^}{ z3KPAt7t54KPI~{GZU}qIj^z188=3Yh$9Q-f)gay=s73=AXss{tEKXLje_$dBY*>|< z(H*)}yLxd3X3@yawoOqMaBtp;;!VIQu&|T=^uUjd!&3anIJFRNQ@4CrZfZ%gVV(*D z3AUbRN6B?}(CNYZT;IRL!I@63w1 zkvW(qU~2@ZQyKBg4}NJO^Qy527Ba3Os>U=!l(*|tb(AsCL6Q)44yqE1*caVMr2IWL zNeI4!o(f#JCr6eg5P~*aC|?8%J--+Np`&+G=b)xbe~`#{MU3mJ&pApkuwZ-s0AO~*hn0Bq}mP{p7e*; z9OZ^b(`v!H)}HSDu2+qd)C=J0-dbaghz$)O66)UX|FG4Pd(PBg@pqNU3!uO@qcKfZ%e$xvgEQ|*T~N2XE!~-J>1&AFZy918uzd{ zq|i6-OW8-;TcSTAV>Bb8en#`h*ov4LlVD=UKM9#hs-6AZ;z*<(qloztF?3p+KX^tF zn|XG+Oi5*ah|P?Ub@eUYz-BffE2WD!P~xY$y}wQ$`!aS6PmsmjJfH+=vTD)BKKn3| z%>UA_OpCFu`s8QBZAKLT9rvozoA}xm>YbWAuD`P#d(Hm+6@(yuey#BR)jZ`H>Bq27 z&856U!?GKY%RDYIq}-prHpe@r8^nU7k6O<+$E&`UI7NX z$5WC*b5cTcK>A1M5ysFgaUZdC3(!i6UqGwn4Rj>`@gVMCw0)3K7*JQr<8$dgs&}#Y z|0~u6)Fod_S}g$%-nC1OMN*Qb*r~eIOVwRzzUS?3EDArdyCE4dyDDs{_ETLWGTMm5 zowRMSc2crp`038^E*+HV0Yl5m;!(tqA|qcU#?{i!s>k(-omHD_kiU(+ofSuxrJs#( zmSunqTbAX8zN8Zi+5A`h4+I`)F(&h~Ye~kQCu<9Tm2JwlUmBo}sricizpz>J^~#Wc zy^Z%y+{uYUri#>Wd-4!zUWD_H-DOIOkm?nWz6i3NHlGw+hJSV*m{yi#GuR&y{lJFvq}y*26C`*kRHEQl+rgHCa6duQc9? zKel@Zt;J$Z;)cFSBh!Tke?`^zp(Z4p6ePJG=9zQsFM>f@UQ&;G$oyrrBt;%zj$UW; zvyX?!YVjB`in4sf6?%z2ker;Bbe+Vf{~HP>r6#AnXr}&8_|Qxxi=HeQ%&GN=n(nnB z!gq4H)Osk#zb_c5hh`|6?qLw&CqlPpd`i7GaCcRkW=(u*%ihezO<(pzYqXpuEN<4+ z&)%?{?3>S&@s|t8Uuxy{J@#ndL0L7{qtZM~wRSI5@ zl?;~a%k2*kt(t*7Z9uR3!0J)g0ziGK9AUpBqka;JOG+I6^8TMV_;rPMZ!LJY--Wm%<@b9^l&H!-Uh2AvE2vTu97dfsOu%dZ7)&eTa=ANr+ z1hKuRLCE^*0=7|L*4j0K{5nf7rIL16_=~%q^YBZt*K)R7PRT2%ooPO@S>G5B?E882 z+vKno`-^>Ye&nI{VV8S+{(QuSPMjvi(=mW?)6Kv>!Oafi27Vs%dL>``3n!hGlGhlM zTI5e&#|NDv4|KtAuY%tOfOCf3be6-c#Ac>RpI5{UpHJy@1c#8<=d+!gZ#kn`36tf* zx>Y}K3tnDo@V_#jn!gz%bL^wUx7<*GcGH+oJpvBRLWBSAY~4>Evia17h8T+Zd-u%1 z$39}*E^*uGZ1T?+@nxC972CIUcV?-Yxo?8F27{O9`A&Sinz>QiohEAC-!N`FvvtRK z4?B2jES?JFXQl-T+k##8XD3M0_J9CR@a5Zr1^=lFV7?WgZRYlpo`65Lk$h9^=wq2S`@6;x1SDp>g3H7m^w%{s_4yDz)Is}aol zRDe>Q_ka#c-5ug&Q{evtUk#Z{fQ>(*P9cl!_83rwIO9XtghX$(eQq5_vf!wh&R?gd z@>-J7R6dM#sS!VqDJrOdj$Bp0G(ZW7_k&rHLE?);1G0_i5j{?_$~;E&qKJ<56~Db5 zl-+FH{oA`c*LWj)I;2C7h4IVIO|_pC3@tsi9zS+aYClC7TG~2%k9Q>gO<7u03_qsh zjYQm^KUh=@JvM&3+4B#jHw|$=e{YPyFa{XgpAHtsrHS0%Zs)5fh(4ABnv<-_9wSM@ zNp^!GgJ>kY_J=FKgBvkqnccrhRUrpnn`f~>lZk!^h7?T<4!+W>E%e4_mGI% zEXdGER<_>Y)nvC;OG}pY%O*FeY!#vLs=_C4_YByTdPpd39K~7qX(V$yp)m+azYKDP z`L_x*8xTgj#Rw)HW*sK7s%VecAp<+IbfRGntsU%FVa8<6t);I%usQ^dhfK$1SRID8 zHhYmC$oG{Z7p0ml`#86p6C3I(QJh=QL{)+*j&sWqFPgyWu(ZLuskQ@t94`hjf@R_n zCWiU@5Jm&wCsSSY#h}4@m3V{{Z|-Z_Sn0#1nT2z|4(Ir>Q5-)6`y`{ag^->e9^G55=1FbDF9g)2;v`PC%}9JXY<1(4Mw!dL zTk_cIaOKPJiav~URv$)c+>@C~`B;Q<9=DLp)A*$Iah&223PRtEZ95WqY`{MX47}*L z+tL9$-t^7gZ5Wdr9y>{=^f=Fqxuf}CBsOG~v}6L)7>TFfAnD%b&|9pNIahVep`J;^ z$pYLG!BSRRc8yc@cJ+a6X246-3{**8D1qt1?wY#k%Sm3zS6d6aDYSEe1&26h4ve1= zn01)RAT`G6-q)eGX4csuH4rAp>(J?Bei1Dpts*T=NXroJ5dQs&mNjJFVwfYS6T%j8 zeS6ws_~`H+G27YIM5VSq{auk z$UF8ZO@$b;nBz;K`fvuqZ#dMC*8(BZ@t2u z9PX0t+v@lA48I{)jO5#6c)&PcCnK^Cv<%oru5hEmT@b!rd#T3FF|x?*mY+njR0322 zw6W_{UP-^oT1BZ!1X1e`#KvJN&R?tQi=Jk&j;1@RFq`PbuIn3-XsPV&&k=VIqNw?e z^fdj9qSRYX?N6miom7~O^xD^{D6)P5+d*b&NeNo1rul1<601-|pJC{AXB#KK^`rT- zSU0KHhn3Ek+MUajF^(L`ZEraUYd(l=viBi{mJFMd>;%TSybt4evv6S*xU|vnH=vUi zXK(a!2=xI{R|w*oA-QyZ)am{_3-`zU`gve(&(IW!sg6-=INV-+1jQjwfn^={l4yiN zj#`LXh>q-QHwM*kk4-&B^TJ7}^nR2QZ~B1dg?fkZ$KNon@2N=uJ9h`o(L==t28;;) zXOHa4JQ}P&-EGQ5(8ZcLkOi$cTTWwM)g;#@WWAnx`?ERmx9&lH7p2DUQ-?SW29@Tn zq2pi2>Yn4vEm60GfBii4HE;iYW^6y7R`u)XY*R!0+tItz{+W;BG=Pxq+5Ienb2+b zQ{e5j^!j7X7IVEHyW@O*B7%q%qr7y^Kh?3LLzqmMO}I=*Od6@++yeq=Ev4mnP}9({ zKomu3%AgiRrY)iK-4d6BTR3|D`lYk8X$CPAO)9rOHn1R6Ph!grbK!E+bMoNoRokQ9asgysA?gO_NV>wf3TarALWFP`6lv5=0Lm7D;-fGyyKy9ULbrNv@@L|Wlzu;`h+v1b zKn+k?Z%;R^UNIxG%kt<)e%=|KC@XT1l20iv-96UkfzjUU?rZ4=>LyaU#ni6+a-bc^ zLjAm1Z@Rc{F(-1h+e=5}1OgS4>!JJ+)VI}jJF3-PxA;6#MG(Y;Z0nZPfi)5p{|>^q?=vL6pKkwckLWyh?Jgw4QRGc#PyJ&5hluRxQlcB4zMd zQFAN|HV%I^X(Ep*#X(;w=X%f==e$5qm%_x4T=7|x;vB3+)u2Vybh^8mSqmeQlMIoP zQn|I>Ew*p01EY9$kem+m+F-Yr9&FiP{ZNEYY`vQmI6Q?@>5HUiTU`=)huv95S{U$|2gd5nd#tJB6CuIt<(~otBl-e zy1Nc+C;7ZI1hx|s8R313Kk+C8_Fwi|{~oPsSu7INzW7d5u!;&8h;g?uQ~=Gt69#23 z0Nj%Z080ZV2^S2V<37iR9qewD&IS_S%8qX9VV>}3^97-2$KM!~EWmu)`+p_~D=OZsDeEB5=Tv7GP8o%zW6cXy%&*I11hy{_OFwln0SFo#PGC^FIX=<)hmu zbH<3KxLOM-cCtgNewDzZIw~m2^&>cd2a70VN{OxMD=7F4oNti2c@QOYwF;~{lu(qv zA@*XPhtNHHLu}+h#I9XNte=_vkC$?T4@afMUY4tpco0o<@8cq?>tq!baXqP_0WNuS*`j!{zFt<^ryq5?pstA9ObrcGw4KSG<_-*W z$@?i#3=k+ieEI>szsuYV^-;a7uP?wIUg~W8?}nbu2by< zV&vP8U>GChu|N%?Gi#lVO|rgQdMNJwrOug|Y|)ma_0-Tk{~Ub25vXJK${Th2D&()DtR8xEnOg- zJwn4;9vtGs;!wn`riM!E!er#SI(go?E3NFH0y=BZ6=HDxarZvXk(=zRDc;I1zU|2P zz;4c64{31u@u}s#_5uQB5}@3`Q|OeJ_obr>z#LN-;U7I!l87l{K3`C&Zh>ZPVYhHZe%g0n?4>i#` z{6=H~b=?#k$cL>WOcTyJA|xmsM@5dw0|7xMD&`oahppR0%?xNLus&!DlpB!MD5Vpa zsC1k7s{%Xc>FR!!tVL>zYl~lXzuJ}yYYZu=4=t&W0Md;nhxkhB7t}APR_jJnWT+qX zKq#0Qv-C9^^+^;AS{0}#!k=;IYuZUm%Vk9KQ$IkE#SbDElv&i^Z~Od02E6h>(`)^> zwxcEGz!Nle9;hu)WFS!FDF;`;JQXYYX9I?jmc~SZ#-s*F`PLF*5gJja#H&kJZ`rx& zwHd?@W-oBEsJXlqV9k^LJR9C=cACU7n4Jta+DW0#ll9M&Exi@(cydd}Kb=lmZjQt{ zX#X#{`XWAYbn)=-)@!s!UW=$@Xg3rGs;^t`hhmU#}23ho2VdTQgo1mq_utw z!9(r$e|s=GM%PP8$we}~+Y?wOwO50;uNm#&%ZBEG)&mnig{R|H{cQ1q&Wf~pWWfK} zKE_+igi;7TI>MUs?U(C^fKV*$+L8jWo-d0@l@IL% zx;7c!FMMMSgj)gvb!mqi?WKtOd=1Kz_3@!)7ok9LcVJW7aJn=Pe0ScS^Xs@vd68dyOS&({nPg#&tIt1UvE6N=i-7oji;+`DtZ+IX>!X|QrV(8P1jjbYj&H;Q}Uxc^WO@M8V`+P8*j z5ApVnzxKL+iltQPfqIWXWfhIVDWYgFT7bvF!roh{Q6@=%XMT`%8*V+%88kOYJ3mM} zH)z3Z!a2atgQFjpNv~?~=BfQO9Zb@=fr>-7xb*c+RU+S7-niOP-R~jfZj~=K0rjox#(g|!-D5&%Z61MWr z(m>X6IDIDNJZ_Z#|>CJ7h}}MEOSE;ONff*B~>?< z>>RqibS)37Vwiykdp}?Mm}JN!(NY^^4&99^Eh(^xhk_B7qIMi$6afsF{MeXL5;P-+ zt#p!Ko_pqVmjQN$mZvO=PJxsX6%&VTZG$cNf&9ujl_qF;yeQ}a^*5hoFN#O*9tu7B z6s0!q57TqVtM1Fl)8s7}cv#sw7QqlkZh2!~KkCqGQj}?ZOa4eTDMXj+k2)jXte)k{ z5IcI_EJW9;T3VmGtpYH4xZ5C~3cK6vCF_q?u8;x}@+sX&r2#M4)E3u_bG#i`{!V#j zoM*$6{!sq@X--@OwyhcGM^I0U^T2Nh8u6hdac7gVL|t95-HFUHl)8fOJN7i}UWIaq zSLI_RT&R}`9}3ZhTc}VD_hL^oHfUIPF=zJNo#0VdpiIN|xCG{P;qIKw2uUEt@=t@i zgtAu@THjqI`FgROy?5=`&&}Inh}A%Zms{RypwB3MjXULZb)5H9o5H5{#P@V@|0e|5 z5p}oRSam>QGh1CwG_Ai!FmR_^k{8({2#SD;r1dYQD~CW$c##M_oLXA{VR}#RN~o#>5ztD4YD$->A`lpCHasTeE2+smf+GS*V5N1emEk7%45`LH2J)q)f#S6guTXi zJ!4QDqU8P(Cp_n`Fr52Uai`HO zsd`jk^O?TH`wx;MhVs0u?j?|^V*P2g*I~JS;dd0$25`g5p?Bzcb3eb1xMK+7RZ|hg z>n7DyPSsSdFz_o8P`uRseAM=Rn#no_P046}eQ~%al*oU8^ug+Lg#5AwivQWp7ald0 z7v>Cnxu26l@0jrBVxJ@4f2|mJ9%zGhZ3+QnCJp@WnxQYS!tY}yweVstD;%{X`EAT4 zcd4w4i|oG<|KC}_`ce5a|I=+b4%3G?d)x{Ek0Tcv`Y+NCHuU#2^aI+Z_3D9!{?!Jf zr%k`T!c4`m1jEJ6)?lRe&)i@nkjL4J^liETa^3)=WGI6PoQi<*nXPr&r;WE~fZ!Pw4v7F?FL%;b2qdRgvosLU=>2PAF1Lnt2scI3v`H(3zBL zcvxAqWq{8SioHXK`OZ7}yPH!VuxR@8r#6!T^vxgH>zn#v04L%}PlKPF5{GC3bZvV?=7`3XgxtD*` z@++ZZ-#vd-W4Z__|5KxZVj&xBngOHU8ZDY^S2PGjfu%EG-x)R#U|$3dTjiV%t~J;f za>wxxXNzEYzMPzF>N!g*31LxdW9kM~Yj83G;{SKyqq2rzjln(+S)rekWe|t}n-*)2 z7KO@PcF(}Mjx_4$C<5ONpMmop>92{u2MTYOb@$1D4d|x2kMwiC$e)iCI*G3`$oa%v zVLGyr&foSqenJ27j{ajH{hxx_t&hsgLNyX7g~=tD>u7+hc~xakFx6YHjHmNuUbb(& zrpmmgps!9}di7>i#%==_+5P99R>i`s7VeS3$w&54Hf;e`<>_oIG&aQfXLM_FJTP*C zZm9oUc-BIhW=y)PFCeeHc2=+w(ObkBP9tp z7$7++OH3Fm5o+O`%ix(~2Ea>5|AzorGuC#V9_&0_*?GFK^K^%hx;+#cIA`ljUPZ#- zOHJ=$7%I`7T3~G_(QB^Dks4f$zj+(vyTuo){ATTsW2@%;QR#DxzX}fDx zp3PSMkr@uWG8SvoM&D77zaa(m&NUUS5z%jJ4C+C##<`ByMR$ZB29elXNPZ<#r2}@K z)Gz2!O-MNEGgxK$>de35nLoKS=Ro{A6oh+t601=*f-l{Nw@ihdqjMGFSS5|9BHbCp6L zjrB;-3R5N2lAvlyl50t>y-M>XXMd7~xfL@TFGnQ|Y=+soCFq2y|IJ7O7)tk)*?q|m z1u_l948*$LXgauxLBxO%39!C#FI=L$sBXu~(HGcei(gd+Vlj`&_={Nc7-xg^-8Zcn zQ?a*VRxFzi2lF*ZCxb|Sv`jvv6>Up(I4%5@s(MSU)@vDpOQM=V}!Rrod z?okE<$B{cRB+7!fpMn%tY3C2D2ZmDn64B|>J)EIh1Kl)wlKE#0=yEiZbh|-&1-e2U zep~}w)%n;T@}uQ=dO5X}1x=I%CE?}T>+pS2o<2@g07X|)S0%b_cMdr9%%s{1&}~~U zQ_Kf;8jGP>Hv$~Y!yL^02nhKr02)AFseNfM)R^-r=*#|56*bAD)f8i87xRG$d}Jw2 zR3&ux11PRgfC$y;FqyCr2yuuJmsIsJP%os}Z{CJbx`=&v5eN%l>qWSAtpg*wCr$vXMu-fw4>}wTS#p#&ZZR z`&-_k^0x$-5IM>JsQpFc^NOCJ|BWC!8|BhT<_Fnhei>E)1mq#A>)c7w^(Yrd*gD0 z@ttvP83c?F(%87R_P93ZYXZ(!m)jhB2neO8xW+(n4M_hAeOW8w!r(vF_5Yyt-MI>E z^UXL$sDCBxGTkrn}G zvE(>j)kY2Xg9>)bs-W6-0iSIMK>EyuHw4W@`u~%+sbrEKw1Fc{U|(*9ZLg=@rxO8< zL&Q>E`P4i@y-V&fl0j07fDW!<)ey)#atI?>EM8R~YnEO3)#_W__Yc|qWC)}q-m+%| z8|g8ULmG&H+MqZ?;4G1&OX%sxKt;0qg%C)n90D$fXm&6}FC971i-moExAI#0lkxbq z7QXN{$>`zN`Hc>SFvj|UoAa0G8cw&Geo~9l0rw63pR}|Cr{2eNN>=U}m*`Y!K&DTM z(PQNu+jD*Se&{i~IKMmNHMDw{&LeXCZXk?2ChW6=MC4bCinGUr@Tx%L_Th+W1s)N3 zj(-?Q2FAGt#wV{HUQRxW{1p$PrnqSwY7jMQX+C1K1Pm^+ezP3lr;#r6UCzYYknJ^7 zF=Mf0v!W*Z#CG39+xYg^#VeL9(?V4PuSKc_e(fJGkOGs1K&G+S$ZWe=_9X|DS;(i% zMi1v?=&OXi#3h|X@1!25FaR1K+0BaTmDB5s?#ZSv$~3LWG(qn{^EwVHCFR&mcZ#}M z*^wjyh<6M@#=&;W?o3u>Gs9_OV3N^l4rdPg{JoQ9|9w{_jzyWbA6}`x-6N3) zB;a3z+zE}qU=Fj?xwUt2VDbn z9m8}T19YFgW4Xd#!7?U{NhRwe{M(Us{Y>b!fOtV z+885kcVH$}t|6u|!GIdYl!VDk&d0aE>`h(SZM*46&U(%S(pH+SIwr0}H{L&F_G4}^ z-wc0Q{6)^6`DrK5vxUsfYJ%bs~ZJL|=M zrL#ll;U^xrgMy?&Md|_I#ZOX!98>IQ*Wqlwb4r(F>|RkSrcjX}-zBaF|$s;zKdyqN*!uo&6c%{O!8r-88?jdq30s)Z!V)U=@kLGe` z=)joK;FwX(i3r>S=KfGtkp>3?zH3KlSyoZvvJ4L9B|Q*W3^Q4SA?ha`eXIts8TCl% zkX+Pyq5MA~dC4iF;64huDC4|^xOy99#cMcNPhD|f)yfg7AKQyBrhvTC4^l({cQz`* z`Akif#;_S5kZ(gqKOo=Pl%g!T@e_Y<#Sl8H;?~KU8wo4UwWrZ&ykWhu|7KZ#UsC9# zqeG|Ex&_B~I!q|1>XWEP!kSJFR{ec<-lGQk?ljr{<HNC3Sz0dIUuuiQVZ69=xD)`sx7_h}!kjoL(~oGoc|F+Y zn}uN}3fTx_9CX8cP(4sCZOr%)0R-XuS+(9*-lLD1ztnChDibi6{$V}+Lk|Iegy!dm z`m@V#vx8u~r6?W(*7Rq+N|0U=E%+b+zheSIyC> zTbSBL(N9IO-)zrqpZ-po-+1;@QT(@YZ#m}{#)*b+fr)r|4zr)88N8{rXI>CW5*s&M) zl(A!&BgY)&4#FbwC;@KkV@u$(ES+!;*SVi0cPf18sh} z@coXEys~Khi#zjo_^i)~>G)jS-hB1X@yy>!+Wh0LWghKoW zA{Muh*sd3fqecT>CIk!w!UCmAkUZD?_^w4SK{~+*k%!7?*htyV{xn16JG?@WDInJ! z7m(94OmZIT*j(`#=xtS?w~^?*$KQ-VS))cK zx9adis026;#jhw6M~!BeOpB45;6PdIO3{5gc+PsyR8J^P50Db@mTw2@J---Oc{kt> z2DI}K??(~u5moFNKuSQ`6mbdiL(3X;bL9_G?yHGqC5|`wBXj^->bMS0ug#b0mgteNSo(d+7C`KA% z$CogA-MiLUo{^+d*da0gY79f;t%_agegF*ot4=w}NSKNHmTieFStzGQ!Q3(O6f0593D&@u1p+`&7=l;o&K}i=$3?G zv1Or#0l}Zugzteo9sa3CV3}qgOS6w50GCj2c+tYgFH;aK-OoXQqICaJsMFT^e$RE@ zp7s58Kv>^b7Oqou$zyIt%H9LM+UZBQM@qMHg!+{Tb>#uUe}srRpm)@_W64bNO-=Jn zfi#s_xnywd?&tm(-Xnw4_>QuAq`ax_T@}x~j3%V~J1}t9StQe?zy`f4la_DJZYDOM zfSK%hIp8Yx6NXyaC{$_?AMkk4t^RRxkMV4Y@oa_h?0}Fyf7`)X^;JSiN8^f)hO$nJ zl1|IO#UHB|e_$^D=(+e~osj+!l!YVB(ccNB01qnnzl>kA33Qk0fqibwmRGETS>CO# zg5A6+13*$5k;zd0H4OSU3K|9)1QM%_l5(90%$$(S;wDAS3=wAb0bn-8iq}_ zsd}Y4Wm9!YlD!ItDGOCBU@hRW37q`=3=B=Ep>V$ySM)|}@Z@P>c z3JkGy&=gmuH=SXem7C||8oZ^hrlW@9ZN;-UT2r6--962C_HLBC(P}E@-~yFl`$Iv2 z4*lr$GxXlg$nc#exiG2f2*PC{usfJa*NU{fqCzTg#dLDJzbCrI1>=eT>zOt>9}6D)NeyB z2yh5RlSVzh0{&FNtfHMjk&OT0=?@EmXT9u0g4QrIC6doV(q#khmL`GVPf{dd0}YMc z*~)=d#`bWWSI5J`MV(<66n4D|J2@MRz8{u<#^Z31m&gf12Y zBhWK`aYBBl%u_~aD}!*a8@rQ|Q$BG{f8tF3#QExj&D#OL?=-JLhkF8^Qk6>rs;@v_ z13v#eSs=Y{vws&qJVq~HSvCB1ym0S`Txr@bTRw{KkZ!F%$D8^Fdeyv|Ox!kB=&}|N z(ly5M<{{=HH|iUJa)9yGD07h%OSGq)96ymp=)6oeM8;Ug8~CMhAC* zLn6Yr%nzx%Z1!QF%X(3(Wj1Uws#HK0Q-(B;|Ef|2Ye2Kwnw0~yn z%SI%zLJNkvokG#Ym-Q~D8$_QAbDO%M;C=G*TmEleA!7dwB2*2l@vWrd%dVqOi`=h` zR114gWn3F)LHH#unyHt#U&}4N%qBvDu0GhOtoZXewc*2>htYkZIW*o}|7?_v$durv zUo^}Q^9_Cs);;e21=7fTYIj67U7WuXT%uGJqsxGmRrck!zR=aTC!^GCPK<{!LoWp{MNeAn>!g+ zD((`wMNfeHBqd%i%mMYIH?Kzj%C_s7Z|)>nsYr=bK6#WB21u?FxrI+mh7C(hByuaC znD~cS0J0mtpn>gr5y2niFGZ>P6~H=&h~ej~)2DcwC8#a;Z0e=ATzSy+RXIN-t(_35 zmK>ufCl!MD(W4Kh)1v4;KYa=dvua}s>xuo7&HLp#N?LNQ6_#wGoaL%!!xz4+F*p~H zw>_ryn%&O^lJ}2khc0~Cm)3X&F5scTLZcDoTOWzdcsMhNKk0cRV%|)%XTo3gUyEBAF>QZGZ<5Ai-Ch#9rMHV5-w6i`9vC!5F%9`G|>-R6o09Yxd;w%OrM- z?<2;hA?dpfFUTz?V_&&xSyn%LH5&WMOUn{%VMXAvU4Ch?u^RizuMLoZ5)hhKOYzkz zmtXc0*=2Fy`M3OWNI#`mH zTtcy^Yye514-&|%t=tt540t+kF{z}D2qA}nQW(P>6ulZ z^17?rwcSpn$2EyFIM=Q?yrNA!Ab4aaeiVPlk;5u$@nviZ2lrxf>I(2O;Dlu^2X~E+ zgl#R`o9U#_-jHt!<8LQFY`)|Z%r6MKHT>a?+pJYd(5)vYwD*^04M?9U0S$g-*U%5Q z)6!LE!GR3aJ7U5uMe{3I?ENJjh9AEDqH~1!Dj@eE0+e5Whg4TxTl7OAVB@)+YjVdD z2f{#Qd*B)2BHeI{hP%kYmywd)_-qe6$-pBwyi@89CME>J@u8B&emLRnm#a7L7D#*; zVzd9!D|H7@FUd5k*njyuSTwkBieFv17$=IMjGU(S|j>E9oJFk~F!DABtVx9bDnd4ayyr;SAiE#DjHvms; ze>|<@IhM#lR?xgazQI0{Ki{7z?<6H@F*aNT3r`9!&JG&yfp0Ka^H^ISP)hzFWj`ZM zlT+L0e9}J5SN??oucS9D8|5oc+=eT?-5H1?!lVPw-e!Gy&%-J8WZ}%{M`Uq`M#uGs z@&l)w_sH1w*x9d;^zp_((psNW4We~1eg{;Nfc^?e@-p+c1FAA7la7Lf;H8~-Z4;Ii z@TCr#K(4Iz^wE{S+g#-6(AJKqzb3Tb-7Pp|K7_@H+lYl$z{SLT1zfFKHo8TKBx-jc zF3&GSgQYS5I>hNXvePo6F~3KFuvHe6!-1+*ByBISzoC!PvCtfTgE~p+Tj++n1z8jH zpWTD3JHiu3Ikt<4%^JJA;a7uwaGLvrcyTve>7=3)=#&|2bc^*JA4wHO_FQgz zW4ATkn+L=76<=oX%7KWo(fW!`KWO#|yXQcFgxrZU^iD$dqm;LM)`5q=fM+Vpluy++ zxCfL3UBWuAXFvpd3z=MpAB=p8S17y#;Y$@u*3ATzOH_R-sbZelgS5CNh`RX-Fj$`( zUbXy|@cJYJA4^g=OlF=J7`xQ2{*R%<@s(azZNLS0E)*Dx*$?Wm^j1>40!pQil_o5` zTyGVZ#d`8J9(0$_Ng~pRg_rI?@1%EyRh|2DbC#^dl#4T9YzZDNbc;BJEM&oa4EhWH`hXCWSz=3G$l~&1E_gMEh_gF2c z5!Q{#wwmhAs6cgbDd+w0IprZ1`cj*WoKi74W2{}azK7L6D^oWR%oO<%35=hr*;c{uRz-CAot4K!P@NV^&5L+G@+mdB><5AF~lg2=P zO@F99@bD3`7%pWjbVXvcN-M0B>AAdV7>snhFvfGZ^}XAIE!gkPSnkVpo39QT2PqV9 zAp}z{#ama>@ujg5fHsMzeLZK&UH4%mgP;eL{>~l%N8Wf)srFzXjyFwJe=zC5NIuU! ztXQQ_;0pJ@u3M);VZ-cAZha2b5NX?+AydhppFBM%ynGL@Om?Ua3LE|mhAfYbs8WWt z%R(e>fGtCd#dBU=PGchVGOW5ReuS_|FXBd*A>2{^$2Tcb;?3 z-e>LAd+oK?K8&Z*=C6sa%dP1t9{uN`$O-JWwDuV~sFey7Q0faLR(_TU56raaq?e(} zghdjETzjc_&1A+79X{Nl&;XCG(Ksh&!g9;g>umarDq)5C)Mt8Gbv9#|>#`Bfi8a!7 z=b-&+i04!)ri)dfKJa*aZ5UptKTv5N&w9LreV1Z7k;Jygpk#G|FFJ(Ownz42HZ!%H zn!7ceT5f~i?7!Q^pO|T$Tbd5s$@uREr@dG!8_pLHv+OUG_YhD5_y&9?59myp_Cqxq7d;<8dxQ}sz z55zRTS|Adu?4ow9J|-&n^K}>Ji?1L;!h%{_W#;Eox9t0Vk1~A{5Et)|b$67#c=B0g ze!gVO-X3hz_xrPzmjPJZ1m+djhko2q`y8tmI~c?dmUaTrmGr0JF+TrPR%*oSGzdgo}oyAI@1 z#OFs6Yr^li0}@n@BbrfT4HZCN^( zo<_~pk(j}PHyM}?n1=-e5!F0VzcHnE=n5pq5AfX6iZ1Xo>_=_jECe(X?(ot9p1e(^ zLZw1PKrfvs|870)>WGr&vm&QaE)grT`xQa+5o=DP1p)&Ly>pKet`W-t{Qdl-Q>oO+ zRw+{$1&&jSycYRMH4`4YKKFetwbNw`QuCw4dvN9mq~=`YG{#k9MP^tLBptctG*$qq zXzy!wrP+PUz+)Cy@P&Uui{vNWL_9Wn9wO!jQw5M=lab*!bq37JH2q3D9k$YRE&}6m z1JCiB&>;R^V>+Z7e`dF{Cil_$8e!efQwt+E0^=19@YKePF)#DXtWX1ijai)Z!4Ndg zPZ9FLTBQ`lJh6cHLyu*m?9AQ%o@3ux?GIn0T?tp-;**}RH%2AOM@eKSJwZgtYr7KM z$C&HWWysl1>RFZI`*mNRsND$b@r#!V2hM7Fz()XU8vt`HK}lBRn9LbhtN>t8Rp)E6 ze}c!DlXFCD6utlRXhr*Oj z*BMI!!&f^-k?400=6KdbFz+|N?gwsD(Qi&Qf2(kCmE_K!3_9;aciG1t-3NdO^vOW? zkq7!<#y*&1Mfb5pz#WozduX4SwSid>nSt-06;W~hNH9ZQq-^d|@F`dKlNqjb7VOGA z_W%%%o@T0Z%HXa+KMX3^b*}D@1uja9foqxPN2%=I_*2?(aDplFNO*sA{SSo~@$H6L z?B2%PduT&aYXeUxIYz*9K^`CBxl-;C@Cw8d{lJ3OM*rZ3U_5#`3z#d=p;};ENpr6~ zQmORsYy{`p4wuOsgCZl92BQ0*$XvBVGo*E9RU4SBs`rR6bLEk8=wbap6?&gXWf~2^ z6`8A=SUd0&gwZBBXdKwF?I5A!3NY*T|LlN8LZ7j!Ml1=yjTlkXJVwWiD4;6Kw0_fR z14r)VQ=}o4b${N`f_(oZMjN9TK+LE(FSCo1EE1yI$c9ex0YyA<zh|IOf zcChDVlC29YT=++283;2U48&J^2%-T2d_;lC5Sh@7%}BTnpRx)^gJv}gH3-E#poKU9 z4`}5$N5c0nqrdvp6JSzmWFOxrvEB*PmYHVDBp}llEQC!wFAI8JHuKKANw^SJ`JV4x z;mpISd3&<=j*&v2x;&9Wp9ZVt<468_SRu#Vql9iWzvuGkH{o-6CTq<0M$Fwo-*io9 z4&>u6K@bs~L(tC{oYg>giA@0m|51nY+D|Vq#(i@~2noI~4Xn)qe)2K5w)d8m#miLZ zYL(-K(WCbdfU#MBW`2Zx$)UO|;Bx?^0L&zI3(ae~f?cY?+WA#MrGo z_cPF$$oyG|;QJjmOu(pa)}r{$9Y%MGp&DrS0NRJp?I8PUx^BOw->qwO-SbRyqTqYJ zz$mXD*t;|XgXE$Ixqm@{K`7q)o&OC$bDKeMmt?#zCIu{MhGsz3vwOy9LI4J2Ua$~H zE@0QM0vyhJoZH@~)BXK=i;yoDYsh<(xC6|6Sd

    cKMTdf8OEGQ;;_JC z`(kT}#rEdKAlC4uIyQwrs2j(OD1%0T&5C-^jSIr{Fk)>4AO4^9Ient zqh8_unxK3Y_#HSnb%L>cz;Xx9K~(U+0uD<(yJHOee0+@mQvcd$TsR`QE9FY?h?CjV zA_4wa%J?tUuc>jrUfpZj`vaV_s=p+I3YWY+p<68F1G+?$WTsNS6!$w|_c!6Ee>z_P z*>-F=O%eTX^vO_M`5lZ;VXL!^ghqeij#%RC|8qFfU`I+eCW-tjF2HM)25l-MpJ6pT zMY^8n1@9u(+pJ^*(%mtIps~|&;7`|m!oizPW^cmB0AV9rfn!2(;Sb=`jHsaWvE~D2 z6x*v8jHnt6md)W+O30O3yDW!Sb8R2MHM`U4x=g=<(%pfKT))!DJNtz6Ll8Xkpb?;B z_7>j1hCjgURiPc!jx#R^?Fik&!I*l~N?f9+$OAjGr$~T~HAYmdJfAh=2H+y!p}Twv zdx-$o#3ZG=t6r{<`jv>@KZ-_&1?jqm*E`e4hW;?3JVgMY;3D!7c_eovbo}Y$$|Mni z{0==_oAxUR?!qY{zhmhZY|oYmR8@2kuUvpD35e~1ONco?HsYxnSQu~3G4nF zf%72gFs$tlzgpKBd~+)jVG@ow)aSQp!1q*5bBD4!Mv+~TKsOGPAbcs3o1cPNoB6Obo2 zjS0+Y!VhD)@8TUc=+VahF7`zt6$JI$uW>`hE&H@xQ#yJE$5(S3nG$EADywFOVPN3Ft z9>}R<1~?@E1}Gi%0{{Ym|JEF`nj5sY-NIYMb9K`}6Ob6(b*Yq#c*ufD#6y4!QGAm# z#=_Fxq@JL21i)SwC5yo8&24JkqX3Ds#hm7!J5wnT@Cz|;nD@9$T)XU ztZo8jm6PVhdDA}h#CJS;052cR^0r~6@+TzxYTO=S2Q43 zC@yO#9{;O+5D9QBlk&@Sa4`R?AWEzgOWAnJ$2!+;SztZq1NCD0{3fPPlLGqaH`4>B z49{z8?owD{m3^z?(|l}f=0jtCSLrgZga1AC=Ho|+4{8!Ia*Q`ODI@8@Ni9shw~ZHI&UezkX+{OD8Hb$u>fj?K>q{AtIekR*?7t?GuT=9Svc6YIdK9a z0z7Rw;6-PPK#|`F>1F;_ky28gffa7B(x%pLw;aM0l5awzKpD#vlAL}w3OpADZj6vs z>%XNy`TQ;(6aK-pPXEiZPBbN)7iuZ5NC{@ICb9-n4y^FcJ1r3{+Ps8JA;4b@QtMAv z?{CxWf2v4X#$Fu>DE8}=^x0`DMN0h)(I{}iHOwZ?T?$1?c?=3o;XrdYy15x>=E7k1 z5Wesbp3a0X!adc#Pt?sw{*-dH&fZs%`h**R@K-hAy{;=NWq@kFPEYBka{c_R?~1hi zdI zLxV+L0$hm!zlpdhmL!`PaWg&|y>oUOJ6!jADFsFJU4MqOQ!)k0kxM5N1O8Ft#4--d z8CJ5gGEZjPvabb1v_R05_3r!^6$DHnYt3!h!L0WwqPGDYDlT0_`WCR8=#PGB-h&rp zkh*Gz01Y1&lk#N$x@Dn1~4`zHg0hAj#|q5i)imQ3K#!=@x~J> zAnP9#uKqw>7{vA?MT$rp_68S!>a%PjuCiWA3d?YUmBg%CO4Xb2S^8%+DxVXUQ>BP5 z1IA)0X}P>deK(2afNcemd%(8B4KXcPBd)SWN($9Tn`VkUJ9zgSMx<=u=O7Rp6EZZo z!#%tA3He`{CIRadR`^?{5OxXxgfbcgMwvAFf1~q}XsL#zr-w%Y9Bz3Qj7PTe31G*L zTK_-i8CV8T3>fyy8N*OwhP3)@7c;G1X?X??I3p82GAKlpDWoi2GN|y;7~rzg?eS#; zg0!aOW;fD5-Fc?4WN>}#vPr>j|^9j8v#&Adg9NV*ULyk>5&m4LV_%j zl5Q=DdnAhHWOi?M-&%>(Jd~Xc%zHWikx(8*PrXM^JzB8AC1>EXOf@7V$RepoE!dA} zfmJP72OzCZv|_%)MalTfh8V??Pzvg+r@X(6+q7YU3xYYlZ%L3rxFO@UT4IucV~c$}!Rm_`f0GThGWQ;415; zq#TZ)D+CT3IF>Cfuh$?~1sG)l6TO}?fPC?ZKk=bOn%(_&2$3w}xMf|_9~Asa9CM#8 zvV-0&(oA^xiBD!VPRl%ERY@&DJ#7TyEQ`{XbY^~W>9bbx3>R#=u>c1?L{aW;sBJ!I zL!xEgzpA8>km5I$je)QmUgO?GM1US9O_rNq(?2f%&FX))EYKj(Aq6!>E}z9tbzXP& z6kB$8`Vb;jL>jwBJxfGW+x!QEE6cd5ke2zI)nLjxu1|ax6}Y*46o0YkLVM0!KDaY; zc6T;vtwbcvq8WR9=ZwYrO(t7+RxSV z?4Pa|*P5k>>P~Fxu~?1Fh>?@U&=mOuQ^}NvoIp7&^AT>Sh<|2D?-SRCI6go>V7R!- z8@i>v>Gj3Qy;0|dC81qKAZgo%IBs+X8`5&$QX4ubOsWO#?@&@lq!fN9&jRt~b@fhd zF5#&PT?KlGp?e4dJ+{v^^hrwx-Z=)Lc+nKDdAbPoWgRtyJUgEZB%uC{X?zEI1lI;k zTmvG~f=b;m(uTgd&6M4BvC+W*(uV$6cV!s^{FWL5C)!mPf#V#i{$C(2=a3L7O*NRt zZ6h6+0~NJ@rq%hROp5ep)+3pYM{gwKDqDQHeOuY)ZCY;>DKb!s$ogKZkbkCe%F21H z`QHHkZc|DTC6L)-l)|5x|GU3GvtXk-OyM?AWcU}J(jAoQ<5 z8HR$dulA>!1$0m^;bAVHlQ*@4zt?$sQ8qKXn-S2w z@BYBgSEeDv#iZ{0WU27ANy>ZX2tji!Vr~$w@+uSFZROP!MOc;o zz>?z6?7RcealYWTH_HSR*m&COT&5cgWxeS>_36D@q{y4V`EdJCcUfJq` z$i7OY*~AQ@2FVe_sLA-JQ+XFF?%OCpD->*xt^uyXpSfHHz^IZ%;~W5yp+>8ye@MM9%x@T5l@H5gC`Cg(0q z*wOL#GGJ@_Ws15W`zmyGM`;bZTF$WwEk9RG9oR4mR_mcj_gLL5uo_VFVP5EuRE!v4EwZNo2L?0Pw>Z zWHL}R3T74P+XaxYLXyV8>O36Zu}}vp%M{CpgjveFYw3;L-H>}O`jkvQ}1xn%-Bx}?sfcQ4&$HHDbj zxt%)mIis7M^?+vMDJu=ZG~e|P4eOU#AoS^ks#XBiBMt!7r)A9KxG@9^3n8`zSL1Lhk$aRa@qWS??7c=T1@_w18iX~v#!MX39{a0ody6nH!q<4 z@ljgSrt)jFQn_RX43)SnwWwQ|H;s>_yU4oE_GP&Y4|o6A@*GHJq5f|OvVRvK=1#va zX&5Zh8}6PIQdqarc@#I;{ew&NXt4YH>~YV$-wUCC@X&0?j6n}l0SsdL-{OQe{}pE) z=Nfe5b%u>VUYznO6s$nwy$ZFS3U+B0#P?`Su@T6Q%Q>#di_5v@q9#anKBtGa=?JFj zZUL0Ygi`?a=lO|d#E$T1@_%4}G<+_cCR9U^3h3gkKa3i@@+dnFbsi`Fkuy7`WR1as zGk6csKHj2FyPiEgQF1+-W>gZ#PVZ`b6c*fA>?jIrqM9Nk-4=KEtu$Ke+3RhALX?6- z$tkP9RS4A-*6HV_?p&%NpAP)M>77gAQ+YXYeT^QwIdSFAe3bGt#6NJ}RgWdxWNu89 z*klrn0w4k~Uh@)@m4Cc7FEA0912A!!#$aNl@XBeP#$oN89>ChK5GcH|VXU~G4Mlgj z%<&aNW#xXx9icrhs>}M@aMxh>qilq-B~%#|Y%`griptAJ^bs9rN&x3Jx^D9G3EtD^ z)8yMsh6>L(j9xT!Tq8V(zGrZ0I+ujFcS~N#6S75ISH<6+;PL5NDqpT=2nrt z5=dR}{KB16LY38A9z zhEnFPAm<5xh6H6$n6rX!XFu(Fo$b-iTj>>BwIfZ{-J;#)dNT#z(#uITLjvhJGl&h$ z>k7WB|IoyoP9l_6Z1s*T70wAceK~V-p{RQ$l66YT-0|KD(>&6TIsKvKGmykWt>7EkpLCS+E<<9E zQB}d$@zP=xeRm%=pUn{Io!Nl zPsrlfX3%04 zn*Juz(Eyx+Dw!Ua>jE7TFfMqTHvG^sSqEjH^_+C5s{$#U1Fe2OWs&L8!h*i7%7${W zJzCS^i)H#E;|)>23g~_0z2ur9&MUd5UK&^b?%?QOos426W%^QaUFhMJ>aP<3D)}tv z+s~|5Y&sqsM`2YmeNk370U*3ix&DLHR`HcZX<`)CF(&G~#A5RQiG>Z@qhl>TG>rdX zQ9YE!^w>36^XkvPi}ouv3ipEUz0^m0ilI;9oL8#NM0QVK%t{4&X}2mmbVUV#ljU zP%;1kg2v(I&wnc@2};=+qTXl4jvi!u0~n;T0r>D3J2EJ6DYK+hRmM@jZ*uTCFivLb zm=<`*O(GwbdsvqP`@7Qg)L!agWv^2eb80FQCMfCi4Xl;34L=D(6x- z0Ovy>z~|i1pLNSzzNOQr#qA5+{zo|1JG|uMPk{5`QuZ#o@z#N*H2=J`*Y?9f&iyPA zs(H|TD*p3i!fT)Ve9KezWj4$s;1!87Knw}W`NEw#3WKzs3y`27GNm~%k2gTG^ES{7 zk#QtraO4HOOFblOL}yfhK=knhF^vCS3TLke$CVr7{FgD@Y@3=fKtn8s>922D%MAG8 zWW%`Fk)AxDuWi(UOXo*8{=vg^ptuTj@csjE;@o{h@pgMEFU;m@IZ@geS6KiF9U+Jg(d6Cc?__K;%Hl1 zjF7|lNeE$}%y7;#zT8|^g$YspXk{_>KKV%3qX%2AxKSZ?X25*RouWGTIG zknT+Yc7N0LNLj~mSV4QIL2VZloWxyjj}-DXg7(2wD3z7z%R(}tILskS9^@JC`=1=z zAxzb5-UXMy)VsMl$K-`SS--1@A8Kh#k2j1dwd6Gul&)wWTUNA=XC~m1P7{U$fBiH0 zhW~D3V|t%~aTK!x(P9%MR1*FUFZD;^8SjliY1w~+h$t=GJZ*soSVflh#EuIoQyT<0 zxM*}+Or>y|mlyFoG=ENs#$t?%&l}O+*$d^G=#r1i0Z>2<0w|yiRywb9^SL8X&`T~v zl}0)Yo07zoQU-sFD*Y7P{{)_DC8=NEH3wlek6rwk9=})bx0vTb%DniK?FF+tqPf$` zVgFErD(k&pXD^xq+@hl}3y5()tl$!T6-k`VF*hEwsM1a}avr&j4%(4-BOP4u-vv7e zu$r63mKqCF5gGxg;{^O`bW3S?Dp+0IV2PYKXzW%%u!)Oqmr9_n>NA}#3y_IMS3&24 zw2%0KW24PhI$g5AK*Xg%CN3IX7I`LmT^>AdOkAd9(Eutsf!1xHwG-2ti*5y>TkG+f zt<<_&xS%~v@OiNP9dHL)KIRh$aUCE~A?c`#x&jTphaWwo0A4)-O5Q#tIAZ|Ef^2d1%}NKXaeJ zyiT4-9_5b$N<`4BEf3Pn2|SiY#T<3ITTq=GXc?$?TX;$zldhZuMb|1}lz5EG6iw^a zcL;|$* z26u{@C7F?*5AN1L@jddsc8>C68#?y#w{9RW1$eY1GxHNdd<@Nx%nOpF!i-K`R%WYm zw8U!EQt#d;=&AIrUN?2x1(%PDDpRiw1~T1ZEGF`wK6k6G~53*9B$7f~ZxZ z`s+S^A|exoZ34Oy-TU|~=OANzo)!?0*?yN~PyB9ImFH5Kxli3MD(u)4jDpDM?spk6 z>(+LG|5BiXV2O4IhJ@5-ckyqQY&(n%xj{>!@DId{?LL+HLD%wZ8QKZn zk%ILWC{J-l&$~S=qAcwX$_RcZc=DihrW9TtTLJQB*?pKCflQsO>%aft*-uqNg4E6TC9jmq3-I1%J0o>Bg8$*0HeJ+T{2{@YM6CGZTZ^XQfaeo!bx=Cbv?ixw0i=Apoo>eVJUMml7 ztnL(vtFG>(iWeFtCA~YJzyytxd-kZ5jKitE1 zA>csiXd3Mm`Di1p!17PKm!1>#Sd<(rwxv#hOssy%cc&AWc$qs$!Jl?VZgUgo?iMM8 zVRJVn30eP67xa0jo2fol|(jw^!< z=$Mi9%!83TZCRY_g>26YHT11|23fSpI@`&G)|m3$X--~|jG2%eXkxUw2?{x%H%k?K z0mDgAQ2n&aY9t$0JXs%1!-Ba@Rq$;XvyC^*xa6SKO%om%rLqOKGGSy9Mcbw0W2?*V z4`LI`?+0cPq>{x8*|5m}$M|G^ElI-oL>cdb-k=^6VDy$?yhwp|&;t;H_KN)$@ILZi z14;`0IKnZ`A@5SJB<4f>+yR>3$E8E`H$M1FoiS5mUX!%v@BjXJuci{UD)w zZNl)u>N*%sVsjnL9&L4f^)mbkm9(egfiVYJKd!=mT5*N447c(MWsE|_l|_N%(VKXB zeZ`emnykMhcd=JoX%?Uxy9w)8C{GjEeY$j#Y!bQrabh*_Zmr`6W4= z+UiON=i`zazXW3Sv8>IQ^j|sL<{7<;H{M%ZiFKh+l!_r{IkV1Ov6Omk3Ne)Yn3+Tf z7OVd%NYkBaQylwZ_7iI*ER2f*n9%tY{U{Y(8N;3cu#Ycs}huOuBpK*XY{9Az2`aY#I zLY^t-AOQb(Q!&IOC*`EfDJKQL)Fg+O=EA{M4St3(V=IQtYNY8{z{EHWEnv-gIu>}b zlztg4GVC7f87&u)S&K=UjulKonF_K3Kq%&IJXfpa`+jqwOQ~jcqkVX;;O0Kp=P2{Bv(WiPZj1Y|K2G-i=xV1Y5U zL2@qsz>EOd@BJA8Eu(=MEp|Ef#e?U{Ie4j@qkY7WD0{wCrS%c(7pGA`&_ON`Bq)Xi zz1ahZGq505#1H!d=q|Z_F&ZFO3??UElOW_^}SBpfw=P3uc&zVNmF`CD=C5Af$m(#}ZNMxJN;_6&$}}E3kLT*{uEaT2Vhytguildw*cr^qodY(l@#} zlH_02h`+OcrjFmR^4RIXvkM@XNc_V2{iiR;6-eRfD>C|PtP6gSXgtl>eqPYDMJJ(k zub1bw-q+vvI0g(}tA*ObUyAzMw&${)EU=x3pGMIt9Pm`Je&h+wmYTM&Du{_Bc6JzH zY^V-w3+#e(Qfi}uT|T5}cCp^Ca&NkYfOeDL30)y29GyR1mjlIP2U6(X}!lUU!*0=e5I}| z=%zqbfGB!NBG0I2-!YVHpyEwoc`tYeTF)aZG193kMj1d3;w&cg{#;Y=C);Af^>{hl zXN=9L>sBnm^NKcNO1oVGJJZNQfwXQX5$nddhmB1ogO6{6`^*|<-(UwFf^dDE9)wu< zCiQqP!oLZtcCXS#zo@L!RsJJNB62w8)p2n5zP69<(MnSQm-&RrNqLwJN|Hs`*!531<#xVcB}Y{#Cs^&#NkNBwvGN?{LN5Nw%afaRNtsx5cg8 z=*8yZ;jh?$^TQUEV`bf%pvkAX!=4$T*o*e>yZ50|{4b5x za<_xfaqFm>SU^mjaJe;|O`I@KWNjU+0p$jMF+F&3xz)5}bhrR*ho~4^L+Dt!xZO=1 zO*qk7Z)57t>1yj>X=Q6{2H}L*IdYoX+PFX*oFHbLPPSZjX3&Qhud5lGLsXotO#p+r zgeY$VwS59Nb)w_r5dZ;*Y2b28N!hy5>GJ?LAR#avh*!W6msFAcJYw5JZFH!+;Y9{{6LFenDPd@c-9nnaKUT$25DljqwUI z(U+q$pBHCuXGTtv{u~#M6rQa~bZnj-o}JCjoE<+u$~ryu_1Ww3J!|znY|c4Rq4sU? zv9CIvJw2Lf@Hsk0bQ~ufw!=m{Ur|xJ@T~B|QWS_bmS@U3XWYh)G_vfHs zH_M;oke>y`xjuu5Bgtux*=VIC(x3 zUz{PE!OFdqEe$gd)Avsm8QBVHks(Y&adGiw@64WVg-5kSQKRG>Dr8F1nOqwTG&Wn9 z2lS=sjdrev#A?pjh~7(MxaZt~v6-5QleT6fC_xbebC07nP;a#6Zk#Uo-F!uY`Bu?V+ z55<5lzYJ|OP?+X~rGqmUVB!&_VvL%Jj%Ky-8m{x<6!{M%;oad|4hoYYawcU@QY+*h z!8vlKCl}JEn0$R?R1U+VTcYlx_Mm2>pYF&or!ao^v{+Auen>wnM&x6`ZVhJ|Svs?Lx7W z&TWoXid8G1*_r$Ut2RW|qm>cvuy8W-2$^{SaiWlk-+6ns!PT#}?r*z^k-F9fI96|r)TFV=i&s_J!b@gq+FUJ*j#YNVcw)VVxle1vz|;&{ z|14)&mt|>oHWmN+9bJ5H_-dXhO;pv}=EZ2?z`aB=f4R-Ie9h4Ly&twTD&#EdIou3s%2IwzJ*~bYo>;)Zk#igY0uJ` zG*(WbbkUBbLJ__3kg)^Z5ntPO&!!!91r9)$8S)ZQHH;qGf}$*cBD)<038gdX7lHvjK-) zk1P+h@pFf8OdVb2ZPWRU!Z!UUrmga)V?~WBm-ooyIA#<~AMKPK3o81G$x0iAakldd zA`aiUoUIoN-}k1Di_UVkm2sS^XJX*qp^M7Z+lD8R*gBTfB__2A>T7Y1ne7SRE41|F ztVDoJ=SWhfDpS0>zkRG2nfE@_HXDktHlxnpucZ;p2ECwX8e07ZHtHnR*DJ}09=o@^ zeqd1;mv&$|ZWI=h;iXvdz0|p|Y-(3^fC~G2 zkKrMz$6cws`b(CFW?qp6dHN><8>I{~QxQ}*5zn1AP4|a?m-TQWsZMx2O3F8>;%yw4 z1heApgdW$-JUOV6D-kgNG~?4TnZ^-6w9!iFy{{flMGD`G10&qE{Hw+jL~N4GAkFR! z`(>@(EjuW8MMlTShtkK1pX_UwiW+EUBF9?e_xA~F9nV&U0zS^r=8H>I-BQ%^o-}hQ z(McF8IO)yl={;_Nc#72v+U^zP@1>2Ov=pw-;BQlT`_$X6?~k12P1O4y)KuBij@Wij zAKbR5nV&lN2=RJ1^PI7pO5UdsxlOImkv}=n9KFo5=`DDmN?pR#KGK>zb-eg{^5~@P zHEr0;ddNY6ice*|>#O2{jUJ1$_x5SO`D{rP?>9U`?h2G`*Q`(Vfi{_Dk{U*Ay=*vr z7nZiI`{zY|rX7TS>QbG_TtC5S&$=dS?;`?CU-DrtQwxqG`}M|kgewK&H1qp==F?yL zJtLo0_(@PKZH4s88Bfkn&m@Zz?<5|`ZFszEalreXXdWhda2h%>cf2!>Z86P!7EHBx zkdVBaJR|VVxw&b5emZHAX!{hrA0)K#$#2XX>1G20dM2U%5O7jwm)sfQV8z`{dJF{ z#Flug$<{A7qjM`Bt13rVNEzR1Hj>-3h2`kRrJWWIpf}i z-PP0XBG{VHnmG+Dx~jmF&#-*`92(>D!AIyAy( zN%DSA6)$oRK~=e$pnf#j7JH{7p30hfSNX8!p{3?;`WO1Kg!D6E*L)Wq|2qBpK%yI4 zdSanfXWBdfkk7Y;TU*P*Pil2!jqAfZ_z31T+U4g@66}kI`{sK@y@CgzA@Q5! zLw4G`@4)n+mejhL8S=JEa$%x)x$zd$GvuVs_Z?5W{8W%Tj^Iu{3CHxWZ6FE0ux1HD zIp4(jJ}=G=w=}UGc0wvf^X&P%BUrKg4K2kM2<^{;haOhH^s63d)Zo|m=-uw|8>JNv z%&2ZjOX>ptD6g4&Xow3-aJfL3t?%%a4eNoo^eol(R74bSia8q^_(Z!z_D>Ml4VK&j z$O$ONvay@4xNQ^l)=`L$4)wAqt+LOOdyKP#t>tE`TZu}`)^?BROBKa>!5uDcw#c@y zG5*kW-=!3Acv~2BR<1s@(=|zdCJCD&!YBA-huUmMn%s6UgttQRr0n>#Wt6*p_Mk`f zv^%Ib&N?<$Tq`_Qe2_^Zv}+_dLU3CktHW)oXXw~ei!{9}$G+ESxoZPOo#<}(#^4?E zPW1EviKJbd^U>&CY|SMnB=AX;!+yZo=;oJr=#*4Mn8KR`y6w=-;{N?k zVfzQc7M~~N+f5G-Y=a+hxj)_Fqt*Pjf-T1<;qy!UQ8@h4 zjVeM7v3ZmUkf+L7M)q-k+r^q+(Q^BFcEb2z+snk+mmzcwL~DG~CY?9Aq~awy5ZELB z$47vN9C9b{PDfPF&ON0@q0O*0)|8|<*OWU)g8d&e=8eaCybN4WB!b9?R@)p`-P_E+ zE6ih;YGfJSIJ9%878O7$>Fu~j5Wmlt;vP3l@sTFPsGY~OcLI1owb75na^t(CYGfzCqCuagA04h=0Y4e>w;v`&{szasM%p+56*+ZOE5 zT-+dY|OcM{=yru?v1S>p`*iJLLJdc=Z zGDQz|=hcrzzehu-emX=yoF;Uajx>Ek-&(u2CE6p_=9MX}&cm?%RApI2u&~~I$bMHo^SiqY4s-nUbaNi2URl_h3oA^rrHdgCymLm(p4zVN z@pvS+Ar0l{ZqfwgMT;zxw(I5eOs>ABs^X9hi*U1oNA7gpo!Fw>B8SxR)-%k~xTAO? zvSxayE!FX~Nq|35ylR5?T&d{QjPKJ1xMPCxqs0X1K=~;5u zdjQA%UJQX4T~^-Vc#??GgjcjkP@2X)U z>Bgy-f3|X?mo%TwnpzaWy-|TA!_cMEU)#Dg_x!y5g-Hi!3hX|+&q&N0ST5}C@vz@VfDz5V;1s?#|2%-)}halJ!i!quZfR>Jr~4#*Ut zXPRt0X0NS-%OqP}`)^dIcmANiZ9Q+6rWn}vJ|;3;lM|aYpf6d~;c+gx3?D9!$z$0v zJe(txV?{d2RK=2Fd=mvWL?wweNfYbljn0=S);2n2x~M|MaQDMy zfXhnBO3Iewor)0>81bnbxhI}LyUHiha0^A={gdg{w|!$l745#XZ%L6i|$RhtgP%4*|Oj~;CVXE+im9tW@GCYFVe2Q@_E+G+P7Z@an6O2*v8#EqKiyD2M@ZuUWEW;%se%I;IIBc{lndY zWC|P#Wg^NBmZ7lnJ>>S5@GD(nqJD`m zc_v&nVksGU7@i4O=W2f**AXRCt?b>xyAzgCzbKhJL+FhdDn?*h`Z$jGAqpH@y3+Q6 zQIa1mv)h)pyJjEscCC()hpCw__!IvZi=Q2&8B4gWstt?&6iK%hjr|b3JZ@DGg?ucd ziObW^)lXsXhntqlHS{BbepO1Ate)7P+w9J2qbwPY>nQ8j)y8ba;%Y`^`8L*U#q#Pq zt5VvrxYc=&CPL8O$B(NwNyETC|EsGJd0fhxl%RV6m{_mZT!$q<_lOWKR|hME zE=2_U@q(FCsmK%A7%Rl1plB)f@)tCXU4s*7oXh-)Z{7*^(iF)%USmp9e`n?NU2&zT zVkk(RKPA;`P=s+XMfv{H-kk=yp1to(j3a3(EEV0O(hbjjS()fe$yS1ECH?P8lDUg# z3Q;)cXp{95OUcR@B8U9d$ttSBy%6huL6yF!tHIQdW6LFH$e;1C0p=G0X>(5Oc?=bB zOE)jbGi?-L-HB-D`=I7W|FnLU`Rta{VXYlKt>in(d;;AyHFfO%>r#ig&amuju$Mj! z>)Tt^YT~A}B`eZZ`{Li635v;|5wUg1#xJaxJM8$krY2@$?Kg5T&7O1!`^ zKigFroFLuS9z(>>M32V0MAHAkzMJ?E@)ZY#jvtak2EuIo) zvk!$~k7EgMvuxjRW|e(MSw?{4oZXfkbC=%_oE8gryOn0)7r`<`IDGO?X>FUAf{>-y zw`F1DY{jPqYodlYYr-i}|A(=!fQstt7Nx=W;$?k)wTVF(#=7zX}#(BJpI@4dJF>$#S?&pG?-v+p^(@11+Yr=*8H#XSp_ z_k9Kn6}T_~$ib`RVeCk&g%3OHrOQmq?-CJwlJN~i7#RFqN!34GhD$hGw1C$rIo=!= zE+Z*4uMc+dBk+@+^dsA|c=!;$4T%Kzp~PsoOi5e;8#EFgj=Fo4Wv8%jL3W2B?IXqI z)i${+FUTHahKxWf#Y10P(6oI4rUUlkPr*d;AmzJ$@*uhaSo$i&nZI-u(uSt>0INuV z7IOXvd=L;tzI+g%eg~AqN zS8fnypK6z7&fTxY%9q8SWvV(96CRUGPPGgQ5!R!)4c>Xl=mxgF?(=M6F97Xv%OkG6 zp#_QdeBYX%bQ#{-)%E7`s;PGLaomT>SB;mf2@nVGl+iiWaXV`@x3%u(Zx{=GW0wYLMTBy(zMaR zD7#nJmC>X=>VT4D1B!iDwK^t`DLm#DlVfrJ!1D!;>#O{`v>tOYB@IZk6W2w#*Pj<_ zIzp0!KF#m+t)66snm&FIluJg{CMhJjob*PI-?}Q`uHOhM9Ayl+g;fp(wO?ny^O=TI z%DQ?P`&ed-B^In+q$Pxi4f23g%P8Mk(>V5tv`@Fo@VVLiGFmd~ec8p)>w=3t;9nyp z2JbMa4cwvskBd~%t$H8x{*iRHKzK~_WW!t6k4jgvNCz4pty)cZi7bA%fA2p&(0IyS z+>mXCkP-i}OdUzPvTp|PV*-d9I3r*bMFnum2Ny|6Y<_3{u}Us0U{p+1-779>uILNpgkQM{OEA32#|cbO)vf-Q z2s{Ow$RZ^AR=uau79Kd*3ljHXkbc#xdhfGESNY!Og@6)Ya7r+%EaJw%>Z4V!m;con z4s@~%tU9fFaV$-tzdr@vmPJr-bq=gX?tKQxiFVDl30UqgMilq5rWuKoy<0%moOSHK5LDKxKPPxXx(^e}UdZ4$#8`&vTPS z$(S6NjKvlrC{;-wsE)=2#{dqWaccyS?$8)JCM5|v@ePOM>TTJ@my6MELPX_M9y(Pn zEFytRm&8Mzh#W-4D;)PfgBL%m?&TMLcC+na?{hK91=u5B ze)Xo5ABaly0mhw{IuEAE_FinpRESLs58H`~Pl=}ivvGg2547(xUS=X@Y6l2%I~X|_ z^+u&BbvdUE>4WoKE8;%n1~eoGH0b|_m`r-fs3rsd{CfXpXyJoRrzldaNHlT~@irAu z(z_DO;!mHbNz@{?dTnS2wxYab(>`M#+k}UBeIdQ=9!`n+b#GAvzq8UA9g0%wRZA{4 zZvtEp!16&r+#N*N$3ce`uXpyQytXmFt{fdb4&~k!8BWXYozRro{F-q4>i?8 zyO(g;<8dO}yIdwJAP8|_^cGNc7bM{bqoHKHQi0@Okg@v`M>ctR+UKeVTe+oLI5KKe zCb}+es)TC<8TFLyu7%p;$;<0LDs^$3C0sSgsPx;pB6V>U|AqMvsCm(AB$>m`WrN7v zO0t54yYl~H?(wBc_y>eZg`Y(gDQK?6R~)FtAfvWq{!C(({d*!`mIF(JJQRtNq7>E?2zQeJh5_di#+P{czNjFGJmM2?$Ern{UN% zg7lmI?m8ft`!?v(4+g%f=IXZpaqR0*+I=o-O|Ugieq!bJIjn1FvN7-s8Wfq2J<&yE z9+gIG07gQuZmRtcQS+eeic>PS*B4jV0nGHztq;3-vuOEFCROiYATQeO`N5 zI({iJEiH^j3NF_7_*#}*nb1!fPvBa1jU|F5g_)Datv>B9ER8Kph$oH9k5)Fh9+vctKfi8%el@>Zp01ppH z&cd=WEkm$^NvHPew+Azi>uz--gaVfcaUs9z^%MQA`o0&Iw=7anrl)C4&U>-@OX>2n z2Hi?p$RWSw^qe$F9*(TXoNYi})6WhlS`{H722!J7d<2{DI*k3=Web>n@{5!+%c5Sd zin{C>2`;!B?C|x>9M53~+?%3q#rpyQAmPCzKSrcENdkfTP)G>YrAC1q^EFpti(nvN zqS*@w&76V9k@EUo~V!_OSpX_6j?v*V+q*7`X?_eZ(B^}*dYD|a(*pA-a2>Q zukvv#Mpk%4nhq9c`)tnf5|XJl3E?M*n1fx>l&FIdRBP8oK-TCD;ylc7R#rl%`$XkI z#!>XkS#R`IuVeJxK$+WwwjgF8_vP-l>1PZIcz#*cusdm+6bbE9Fb(MMn?S3+@O*&i zuUo3Qm+A^#u1U<+ee&K$I_ABdw1FY#g%*oZj`5gVif`O27ABYO2DCM88IFtD5A&zN zm;VOH>aqX1XO=^s4u0D{q_lMIpOf9s< zz&_`ZUtX@O)5RULkQP!;uMpCMN{qvT0fxnImQbsb@5 zi{9%}AD_m?KYt4YOt1?ZnRnESz)p(ggA?7lCa#hl=ZT~G##Bm+d9IZe4x;3T#Sm4t zA+U-)Xl>+>BO@@Xt|`lG9{I*j{Au73(Pk`MziAC>v`IPxbKWGhoB?xJ(HP9a)cH%d zAj%k8CBi+7PWPzeQaMe>t)d6;ZpB&JYPTq7me3li@EVRxx2TC*L~bl(ZV(H9yy@63 zmi7GR@+ZofWAp6huiSvI{*EU{$JD(f%VH$K9oA(ZjzX=`ff_@Deu}e?K-xX{WgIYk$deKH z(%E`yCWZUZ@jl&K_v}w^$oea~#VC6$R&2%7cqNndv=o;py0WPIH{ey&lrk~LC3n*) zmNk$q>4e08-1#lk5b32Fpwy>dMq_Y=vj^B~B{t3t+CS+EESntgvKLa|qkbQjiA!8K z!fs{>b_B>Bi3Zy&z1!#vkgV;_qJHe-Yz_;SanR{vM+g@~6xqZ#;IY)}BQh#u8UKXP z1>}GZZL76GZ?YJ^nct9+s}B9haxLgHSs$}{7W&i@v$Z0mtDLZs40`c6Jil{*Up5O! zJra4jlSRy7(LmnEVa66ck&!`-D;5|dhxAE@T27&csJ+XJyzzlHv#{I~eS$*{S7j13 zQ_xXY7&VhmmnvyJPH_3t^!35cz=r7S!|Z&>aG8veP98s~8ka!jL8@g`iU~8QshIl3 z6P-jwRat*>E&=PWZ&Oq9&d@r8u^!H1|fBX;&Z=9|48eWq=(;`>AI zGo>8~Dfk{~s;H`3MvwDk3J-528l*h((MU^#8|dQzT&{n0EXU09kLNq6U`=OK4Fiw& z9=^QDOUHOjEh};zY<@=oR!|ENJ7CvvmL)p(ssj-YxU_MvNEqKo<9^D8UBv;>^+ttS zDwbUvBS%h-W+}HAdu#fh_oeb?sCxx~7sOIdqdLDYYxGtofUr|!l_1%y&6oyw8(A7H z5C8(3LzV|AlPR0XNT>e4NeoqJU(cMj+q)#Kb!om&9A;9h&K<9xBxk@@uC~9WNqa`E zPni`WjO5rGP_&%d7|~C$@xhfm5`gP41uP`sAkfN||C@gh{O<}mo|6HnRH8n^t@<%7 z169_|feYa|Ah2}8^7rEdI+-)uVW!|AIclh|`}uCJ2LH%=6eK=Y^k9m~@nJHM8;ylW zp@2kP9~LE}QV5xlF&g7=Q3eWKxYJfc+=1)7@rHT9u?TTNinc+jR!K&z>qN)vB24hD5*L=q zp^n#?K8m>irCb*^hh@@ZU1vI^syuQYu>oCG9{n?QnQj&U0-(>;u@ugW%rkXPZWhD0 zg#W=bo~;8&T~IZ4TO^pN%XPDWu$cTC^7wy4-riX*rlqH?qnX9lSfg_6=->1yKyT=?B zDx;#KDEpxL0~ImgiNmTZjc2Fz4FJ>R{IIa566c|O%6w}c$+F-MCioxdFXHnIYDH1h z%s>Z)kIh)?%yhxlW6C_p1W{F`&g?WJ?p#b|XRAKM;#3`&>mtj-1?W1d>%(_7m0}sx z##e@PZ@KZ=E3*l1*lanB`T~WiAxZpyAOMl?T}{&EEr%gr@$?UmXLMDol7P`N-wGF5 zreR$YH$K9d?%XX06T zNyZQaq01$XtS3Nx6&X?wAI}LDzA@#nh}SO4yjBsa<4dy9c0VN&X9gyci4fK&cJqoVqveN#$^IW#Ryw(RrCiVP=_@3&dPw5k_`3Gk3ZSu>10vhc~(LW&vpibISm zVA)7c@GGF~nV_f+n#VB7Bzvsl7_LdSM%r}}5(Q;9SD+oDfgcbWU~sK;5Id5T^CZL> ztEi};I6YowV6g!ouIGX>geT#Eol`KK)9X8Zv@ejuJ12wp{_zD7uJ zf>!}%&!ADCASK$zcL-D*!L`WN2)j;#!@=xkAle~P_yN8K2G>fbVMh|uodg4DiXg=a zQtmBWD;OMHL~~3{h_T12D=H{Y#B*<{(VZj&L&J+eZ_!dLKwNr=D8}k3icwabKi&#b z#vqEYG|uPKGw0d37HIgavih8SE2!d7Art%1^}M-b7|NXidby@Hb&?Pc~lTF zlDQ}-uc>jKT&{tJ55>a|xGrPK9w;c!#M7Q6L_x!gK^*&B{}6^B;se*5Nn?W~Z2H=A zX8M!@OBD(rjQ6cfa<^v#_Sq;Ob9F#l+azw_HVad!C5{Kd) zkZP(zyXYe>wWN>DAT(>C(0@2?E}?&`85)gcn6qV0gv3x=+eqp-^CP?!$S}kDFee{% zb5asERqAQZ-w`OBZM0p9cOxn!bOE9cT1k#{IadJqJ&CHMaok#c0cxwcb-#0UCY8h& zyCrx1vnve`CztylCHn7D%9DXp2K^M@p=B*rTmiTpEH%rg47kdBN-6Z;YCVGO7^%F? zlmcW4eQXQ0AeL=PDIy*?|2q^Bc&SE@$){VDq5ePOGyz=g8&DB5%Ys}Z2NfL9)Yful zG>eGBa?B!f1%RX+7gIujQZumpWAE;i%>7(DT=hIJgl(6)4i=|eteO+}I{;pvUg zGyVrbDr@o42Wn=RteCT?ArL(>{^EoXs%xXs2QFrqsu*zW&?kE2sQ5|dj`l_R{TE(L6Goql2BOA)i|Gba zaPBNfC_b<&mnL8xtg;Ci4hKpbNLmBHK3^?_4B^V_7fGd$dfr#-UVBi%7Gx}teG@Vo z9*NRGD&|2TY-!^hE^Je4zmH-*%AL^m0B4739iq`-`$2x6bVSBsjKf)3(Qg6=q*J$U zw3x%}ypIXEsFmN!Ha<8*KWH8t&N?l&w!;5}bjMa?r*B_`5dHZqrgw0)5g^bh7Phvv z2}<13Ydw>k1^uglug_3XZ#3jcT=@hSJP}&n7e&@GO@V5#E>j2_4DKETmvx?28O~U; zSfV28zl8}~FI?3T=pvi?AlbH$lKoOYgUj;+dswrTGg-8{!bwn$rcUe{hQaEnP11yJ_eZ{W!Qi+c~z1J zFC5D`w)b&DKZ$0ym0@k^b>)Kh{>u!*R?&(2>{!5 ztu*bxgvXU_$T~10BhU(hFp1tKJ!yypmzn|K1b(2^D7Y|VP|*0_Xl(5foHURCm5o3v zMa0n&YKj!O6Mgs$A8R>!R+70=jH*qEgCGEc}Vj6E&3kVUGjAU z&>t|zu;c?;VQJA1?3w}sl(jto`%i!ZE`5Yxh#vk$0c6f=w+j#7W!NaZ8N87s>a9N5 zcrJ5OcyUgl)Mi(F2ix3v5!2tgYztV*Kgr)#dT+{|ixPL>qZ&ORpS9&kMPR`QgA`A|9KOGB?ii!T zh#@^vAKA2O| z;U}1LIxsw$ooQ97bT#(!t1ovTMbtgs{s*sOtiCOAe4|))A&&~c_Z#A{y0AN0Ul|yc zt^l{Sx79kJL}MJLY`~KWIH#kc6UC44QMh!-l}SCk0k5VW$0@|W?o`ojz>BEwB8PCO z|Ghd=HgdbE2bU5QfNmTt{ttcp^&ySY=CJGGhCD*=xiYQ_=W47hzDwR!B9CDg^xq=q+6Zj*yH(L2q^L3mlEcw zGU#I!jo#YVu)|;B;L{7O3?kiXCdWP-Ig`yer=AJAawJzF zIw##aC&vaU&wnV|p`Lkm=BjWTgB5GUbOxW`ao!W_?Ir91jcAiHJ9jR?$m;(QF&&SW~NSt7^vA)X9Y}NBl z`?EnJ@quMfg-6YUYe&s(LruV1z*LEov+yPbvw2X`MCsp$Uo;HNaS2iJo=Xnx}?#TQuA3!2tC7<(fr`*%W>MpB#agr|*ihpi{)d02(4 z^YcrP9S*W1T7w-9#v|JQMk@3v&ES=i}erRju53q5p$*6 zgAYWm!=s>r!!p}9+b>qRTcJ+ zDn89UavR1tM(>pBZ;8xbN#w=KGd6e5+tjnj{|Z^wtBqvwGhz8`eaJO)*}?zzyg$7B zNz z1e6twn;+Dsuv%{yH~BNZ+xrqY>DYa<`QuIjzO>d3s;eY$@bmDC9cIth<$bju{jeQu z5$_)aS#CRjk?Smp;eYK(Uip2{y4Sb^c?sJ!*xPmaLjn3$|6v*)$y;CEX`QUdu$ zwQ(~KE2Ro_UrU#6a@19J&D%pLp|9*vRPOLg&yQ$q)W=`mOv9Q$I&IEkX zwd#q$^?O`RS>6&yPk!9{-hq73%o;BGk?oCk1 z9?kqLDb-4=z0o<%N*`-jJ$L8pJc#F}q!vY%kL#Q&Vp}sjM<@RawY3Yx=}iR7qUfu% ze((UNMOJ*J!`M=vxLQtacKX0`c>+j>tH%k%DS1A%k?AgX2hxDZHs(aV0g*M0^3FuggE z$Vb=9Js3<~;g@?bjQvo1i(7VPm1X0DzoGQ%&y&a(t7nl$TeD5&&0ae%MNa7t25Ks; z=8sD&#$U_yy2u6X#1)?J1YzT6$4}3iYu&a3d|p}a==DT}sxKxSDeX@)AmvfCrHhB6 zv3ymeyPsb}-QI0*%yf)KOZuLY4hQaFLq8lVHl#qC<<<8!FxB=!TknnpQrNg!Ad4ZSS%=p}rZ8f?h zdvP1p^ACX)uv~_Z)y`7h#4|nxsF3Up`OjgtL;* z>TFW%xbQj3vGMON#=O`Lv_4UNPNypUQoN!jE_^Ez9dR_6Bu>Y9BXGOFeh|9;Zd-%V z_E;$3z2#s(T5CR^Lg~!em_=F-C`7BBi$6O~;-a}Ga&{+g)}V!gnuJ$HcTD;8PRT5J z8^ypCUKP6#Wz3!N$=0u0Y|7ffa^dfCkwmGV=tX=y#qd1|QaZx+xPD46JZ}x@3|DuI zloY(e$}!m8MKPekt1@CK0F|_v4e6nXGr8tK$-f+bD?k?J*P7oKuHI64nvu`7B;DlK zY8$8MwExx!EvLMaKdAKqPbXL|GKG#NDhE%`=ZrvG+dpsOb!nW zsR_$Zk++&K47D#OPk?Em6n~QW4Gda6O}oW$ zFI-?XzQjq^*T0qHdwADOcTip5pvw=6f$eMAWJ`N7A7B9@K0j~cCmOy}@PE1G@SAuw z{0b-eLXeM7-WhE72iSW;?NK zGDiXV5<|pY1jl!VCv4ZX*xu^~%jF19sxg%7np$sE`QR7eftgpgOb>}+RaZDU_8h-` zKyV->kBA?Bp%@`T4V$^aT14*9eWWGVx-qHtrG6mJdV|%EfO|VTU@p6Wa5Y6b*ed;I zT0q0BDc`t=&m(z!)b~6K#A=7!95g>`o49M_b$q1RhnLNLOlTqvjSSB~?{^!bSV!tf z26f3xh=)k8OXr~yXz~PQDxQGv0fk>NDbjt`>G}O?vK1drntw92gsaOuCI?Lp9+v$i zj;FrH{RO_t^p)b{9kOiAP(5;xJ8iAn6_Mxq-pKpIAiSbaDk9IFs@NOY5gqnHb^GEp@2=&c*-2;-igbEdHGM*T+0bZ;8AMWJ zpI0UMg7gr`vg#a;>M7!@fG2mLz|BiB>CX*tKm1ZNouu<*MzsWsJ?x?wRMTb$<+Lo8zuh4?fC!dG!19>$}ZAL(W5uK+2btuhE6k2wb{H zO>1tCB3DKg1=$@Qk_dwN@%cX}x|r9-W3WP+3&dhqC=vtI4dK4Q4h#gBnRfA9z~S`a zLg6a}r_Xzv+k+a|nH`j-BIInjM94VJ;L=_SbK1quNh#5CZ}F(X>5qf$@b*Ta4J?Kp zLcj;bDirrnP`UnT0y`_(>y_*}^?SQ-p1jKPQ!?rgUs{6{gpLua+()fG6cBv0>X`Zb zn)-du)913a5ts({V~9-^>|yv7~P3)=Zs^D~nnoLMMJ8*{wN`>36} z(I{Yqpes2ZBBN+;OJ_vY@NuU$O!#arh*;zS|m)5ls)Q)5~Y`a;2*xr?6! znmf%K*-?*_9OOnmX?=k?H?rHfDlgGiX6uF3tNAvv54ZwDU=mI_d|MHE)*3wV>mWqP zwt<64l)wX8CYlq;){j3cQ!c5n1lL+s++Q0#o#L9XqHV5W2O3G1KL~$V(H`O&$4OMv zi;GsYLbdF63df^nA=HKbZ$-Zl(@l0GYOcy$-*H^n<5j;GPZ3m6>d!t;(ROl8Wz+S{ zA?EP7nL&k6IO_QQ>H3N}jH*eS@fX3%`EJB}^mX^+(6z7RZ)LmU<9825+Zl+20K7#M z%)@LrRwT;Dg4Qf*d6ezs`c-r&Z8vd3gemx47?T$Ip2zDe?DQ#`Xu0cpcq%$?)_T9i2*bbojSu=RlM4qb<*kRS zUyi<~K(l#0=|o(tfP(w}_99oIeCh#lMll8F{gS|2QxYVHISaN7in<;%tJ5-s53L2G zeDNI)Y6jnIy{rjT+T057`{0dvOz@HY2SfO#a8%vUp`V(ly}z~Kz%zXA*zLuzNW`d1lQvi z;ByDDrZK~uI&I&KH-Wb!jndD0iMB=bca_K$*U28aT7W|(SMc7x4m>Bq=^K3QS-x`0 zM!r_8g?^o+v%7oxrf(qwBv5o0@4^;P!&jcY%+Ly0yO-)ib510PC#a^6`Z9hsmyLZ> z`J>!x28ZICU6T5sBi;uudMOeuuVtUm-lMI6o3$YI;0+uV_(ayPGOPGWg%W98E{#yr z`hF1?4{%ZV|{?Qpx29*+7)ET|TEWO4`w90ujx6j>?U(tQa%t4`5 zRKt|P7DCx`;p~8c+ASr^zo87fL5IDeJWJ2ve>bg^_=eEbqlD1XyVJDoc$uYljm^ix zt}Q)koeWDYy^Z(9{OMHnb90vLWAkjP1j?4%fkoONkTwWS5nCJ4;gpfkJY*^)3BD^e;RO3jIcPnJWF*oIB^Pj5F}-Jl}BqJ{j{M0*9QtHRgQ; z_ku#ls0^rDj-1T=Dg%ByZTeSM_*L39Fkxyc`De|jYmx$I&2G(_#cVmu`(AUD?QQjS zn)iLv?|aQ&wlYYg*H`1!=j`d`?7NmDo^?3D=S%ju#mJ`hNP)16`~^^NIr2!@<YKgVwVZoSblcnhBjC+v{VP*t;gWqT9{z)#$^?&+65oC)Z%KTsZrhm z$myYqk-_R?_K(L=pZS_LpjgUd%P_TAtW$_>OGP$=#hjXii1SJ@XHe(H`#%fHXg$ z@*@NCEL7nkXW!fB?k*X4OIMrH;$L6K&=xC zk&Pkz4EL+K&93JfRz^d9iH;h+5Z76R+`lLF@mjiY%O@Yy)vy;zE_uX%ToJb=nEQr0 zSh0EpHxrY zwg~>Lhat3~R}R3AI9_JR7V7FOd3_PokH8r>1r` zBG}`T91102brgq=(hR<`@REQm`XuL-zA%|c*C&tZLgOZ=?LiN5515~T|GH8;DGy!_ zm%0l(LX6->FcGGMq^8COY!#8PEe==aW|>DDLj6$Vw@xp+h(3YaWzn%SYJLg zktWnU+q8H;jijA$>#jDyQrU*pQui{9=A0s}#!&_*9 z1g?6np1mJd7Frh32P6Bt$e)OXE>PVV{vx<5?w9>8{L{o1a?aqSHvE$T-Zbz#lP$i%AOH*UrMBb|Aa(`CKGa> zzzf(9@HD{L0_w7gr!LoPT(0*?x}QnX%u3QYrQHrngSn-VO7y=|=>K}FKkV(w-g*xL zuL^$+?{|rczM&jz?(@A*&jDac;G=L*G^td3*oTF6)c@@AEPj5;4U$f;m!i-1t6cMCe^=an>P4! zLqQ1@*+oKo?dR9)_BZ^_LkW&4{_YVsaK|N^jiWuHOH{aTbWU+8bctp`cxY};aWjk{ zxb1RspgxhlTxhiHkbr=;jA8)|2XO{rHk$TFhT*d`1!2m?woe`}Q)qhdderoPD-kO$ zlc6S!?;!=*CXDz00k|2IC#n6+FD=AUw5DY)rbVBnahe)>TNn;o8xpxj$GHlgxJHkq zWq!RFsm@(1%gt=gRe!cN#ulX0iV)K{CRHtQ;j*MH5|Am$U&097gGN(B1<}ZtV=pql zzR)~-!CC!rt?Xms&ZiZ_Zc;B+h9DiWA^~to{GpL<^4Ee5Gxz{mH5}pzRtTEO3=3|iu6%ZNPrl4F%%MC+xj{qy3gAB z9@(yZZF2~+y;d#SYinE4EJ|^+&(k6mz$KulWX0iD=0%uMQzT&{%*NVo!XmnxI&c0I z>m9bQXud;nbHLN${iZ+grVCQ_Lk1@UV9GV8!`gDw>)J&@ktP~?cDp%WQ(>pc7|9shh{xsR#^Hun~2)QOQj_=pIncAJEWTJHK_`DD|swW4%*o3E2#5zlzVZ4R0Piwr3mTQuN*lZLHdN zeRPN|iDp=J?)uy&A_^KeuLkLR^%Gl~*;21$eqISJp#-Mg^}0>uO^?TRo2Xxk$=f(W zIyGh`jj~?Q*-MfM*CU0;rlY#2qpHu##j1@1@RBaa@n)fUxq`dN)RKk+k}fBAlaXEk zEe_#X-Of$jWH#b$!w!=34n&UPZLJr8DAO-z@icdFg4CF&;!NJabpE8vMcwJWx0&#@ zRqwo|tpCnN5|JtD3sXvQ7Y-F?XicN25AeF&ViBJ7IlZ^>a>mfrj=89z<#*9}+IOpR zLxty!R7B}_9R$}r-Ie)CBFb-bc%u)Ua@!SBvu-uzN7)E2bQ=vV&xPx2U$S>sUPEo^ z5cyxxJB$>bpHp#k&#b=f{rNV>)oNiroqz{dS|`3`6_Ym=zwDX#7Ip#HxGoG&5C!?u z+4|Gz&0ax;wWt$^40Djhgu1(PPQ80xb-T6pwqRNe^{~U$0RN=qMh#N`MYY7sDv85l zi8!Rhirecp?x#;BHErC13>CFS6`nOL#u^Ls-23J1O{SLhbM_t4AurojEND_yuq2k+ z!|m!RRwopzBeUh+74OCs<(6gtnC0&L3b&)zNbAZmz9$jBr#B@$Yi-9pab`aI>sbd) z92Y&S8ti8s%YrZYrjE=Ei$YJFQ8F7_=BD$t-eWGJD(N4F37`@+L5q0mUoUEpJUM#i zhFa&2GhPs7yzr(R|I(OJ7+a6v^jEkGZ2&1XfY=tXUGYa;^gC*>=L*qH!^h! z+(X4q-UK%)sx2;e-c5{tl?}1r=9zyk#wY@27Ex$PGz#WnBe>a3Q^rkJmTe!*!xPlm z{;0DZ#+CxI&?xeec3EH%Ci&W~_H|j!B{6y=8GR2 zPZ#b#BKAG0s}@>R1OgQyKoXj?5}KW<2AuOx`|rt9;Q0N{pI>Jn^DQ{6sOAauw}8@b0k$x`ZW=HTeSjwHry=M3iDMZQ?TkI;zkko5$UDl82UToM zf=r2@7>sw|iE_xX=f08Pj$hgFo}=WJ4SxKuvL)Ep#7nRo$eo+z?)Va>Edf=*Pz#~_ zI&+zC>Em{+;&N_3uc>*U#{JmC!lh)5ft)IOq2Y3|jq!>LFW()P|rWxR&f3F4m zX@Ls!A`kUiXMC@<`Jg$o$XeP|L7^>$y)7l~a?_I9aUyVM01_@z?vA}=+U!{ch31Lo z>)XnNUrGWAYSRj8ck0{P1?`xO&6TnqLZJ;}N)2Lci?QADw{tVa9!3>Xr4D&YWa=O=v^!fIQG_Yv1S#u`b=v_6b<@|L<%|L%&6Bb8RWNXaH z?iA7Ply^)gufp|rMsl~<7Rm)MPF0~y#cC28q`pa)Hgh31x6vU#h(dmNQ*P#Nz8fz1 z!|$-Y_Z{@`uk6gP>$GgTQ13fR-gnr5?`jE!7RJuJocO9cMkB^YCiclbN*c|vlC9jg zPHU&zUfWLp*h7BCPT~FsqaqnLyYcRLW4O z3vH3j4}K;?)L^))<7~)V#ipGH+SH}p)a|r+h6?+kLHuQuW9mb+yE04akT0-*V{-X< zeljZkNgydbS}DEGJU>*{O1?`U)50S{V75*k2&yM|`jPtA(GqO_O8ES!*y+d9-~RW0 z9eI;Af7*CAMDho#Q%^7sLG5vB9ad*aARC}flD;wfD|hp$?3ArSRxo>3a2yly(!;A| zJ^Vi*s`zLoVoE0BfIj~8jTzgf&^Ff1GQ^t}_?wo_Dk9VC;jJ1X>HOY@bH=8cEpY~4((VwY`JXwz6vx?9sgpenMATO4@dXf(!vC7o7V-cFe56Ip%mjispHfFrT*G>rRjyI z09F$zq=^)?C*L)AWb=Bb6&65)+LLEQ$secg?B0dDkA;bE{IVItZYI?-0#0lLdPrWl zc?Il%fFlCi;DK$On@Rp(7anC@2npkX{Ur*Fz|Eq2rpNHMHs~b^$R!Gpq3M*Kt?lc! zHrUl`O#xZgTk>E@1`ib&B8`P9L7ui#gAuk}5x?w(DKVc#i#%YQteXjb zc88a(9O3;rLl^b~Zt4y~XIKlXq`}$!<%nCI@LQdoRnmu}E2cU9yBuzD*edBr zU@-S$P|z)o#>ML&_8aY+ofQf*u>t%ugHQqxga8D(a=eWNT;+x7{%I9Q9xzXcej8jQ zj*o_ucR_jCA-wD$3H+Vd_l2>ZBCzJWPjM2_$T~_st;gr^TDJ@4t$a92&NM=fPSriW z3*Y%m>V= zlomZU3GV4ZxWj9XZWyJ;p#(RRI5#?#qZ=B@T}Y_`c2KWCaCE~tx;rVmfvvR8xhI5% zKk7aMeX}_ZV+=SAW87SQEbe+?Y=l=*E79_B#A&x6I*FzmvB?)C&K-mjLnmRE^zL^f z0@TkO6wpZ==%o0I!3xc@B?xNuA2!sd&kMPV&Nj$Ez+a3@9;HiOfHuTYf$Fs}vmj_h zznNsWp6GK?K%b+dLdt7n;Ts@Nv*|%c$1cZZd*K_H&qYO^W@vct2~PB$`gVq!9$v9C zGb&gpa z8hV-Kte`lgj$CPLwSF$ep&K_>k1Be0mLX6P47!mL-5Aif81;Qm+nb$RauqwyH(Kk#ZZ_ueVeb5>4!YW5_wooOa zrVn1z*IBg;?Cir&C|j@kc-aqs+25(X2~aOJOP;(* zTDra(A+Z#(CnoY9+wk-l!igV^~TXfI+?LDP2-OELZy=b__0Mt_&;wcSE>TM=N zHRkr*TZO!l!I*7Onr#I1-Fv8@^}+a!45(u4;=+MNHwK^uvV}&^z}fYch>ZdG#z3dh z5pL0Z&lNOWVh}nY2N{q9d96$jzJ2&wVi5KoeQ`-hdEU87#PdPpKYO3n`3=kaSmhe%c!l9KNC}6Vz;hWfEOz=cNCs zA#^iE-Nu+RgocN1N+h90pED$$hpveXWm#HK-2yYG*qk)C$*XSZ`~w-ghR{@BYr-9T z$&qPU2sV`JyX1<(WgueyzFodSh%pA48VCM_jFTP~f<=u2f7*}3fDM@}>{0uj5kQ1l z=3)e(@_=uE>7_B@;Xc+^4#m>ZQ38po71*sFk>PJq8ceyuEsPM|Rsn<|Y?$PiQo-){%@ z=HQpv>&Y${ig`0-vP<8J3)JfxaCzxuw`jwA3G#vZ5b5oZH<}RdBQsSxnjjL3)(fw* zv|Ae)j>oivD+CV{XxhQJ3r^0^QUh(9P<9vCse_Fu(SZ2e3lV0+)>`{=7glhg^?jFc zYC~V|{hjEzTC1YKGLfcQYpT>TF~e5_JRywc>^k~YK&A=4s$|! zT^7yx^{#o!yc1!x{(J=XM3`yg%aVOyib&`wmD12fYH^EbRatDFz_EEj`#$|cRK|k# z;f(=@ygNzp^bc{%kQ8|9fRjtQq3dasIj*R3?|ufQvlYehmTnmHo$1n$qzn>W@I(v1 z{JdkHoeWxEn-3%PRD7(ZyOa5jH4*v?rLi_2D0@y~V3x%0tWu>4Fq**c%?kVsz02>MSK$kNqU%x_? zdkzEK3qxKj_Q2@Wr$s`NGl=ei-zc73aBr@O*4J9col)7>JJ%fQ-Hk2W#;6zn>H9J@ z%hEM(nHQ>!)`tUVrCR#q0-!<}$L0dV`^Fzo83m&_skAXE2i$gZp?*#VDnoMYqD#%A zNaO(ETFO8w7nRXrbm*$>m?!o+UMd&hx|X-V)EIoVum@URK-pe^DmNVmn4IAL!G8u%ngv{!$2xPziPNUPaaH{HorE;76;@t zAK+e-oN|FrmJ0ofZG`qm2T%Qqo+%L0nX z4gn_R4RYF18C6pkoX2|=>Ak_8IGBy|^}B>qzRk3XY+9*4~mF124r#FFxGKPhn)F zZ?LMD7MR?rb-`jm=gTHB8E3iN)@(sPZ6(jKNMUhlr(UE9lT_)pLeJ@r^}&E~zkD8g zzIlef+n~PU{EWT?6Irn&Sezh#Z^Ngyti2uISedyHlAMUMlbR=Yq3qve zTfgkn&VTWNLEpUDnG`tOdA+Mq|H;AS!cdq%Ip-ke+rIPr z7S+vffKLr34Q5v;1{np_@)+FwHuq?8W3IFlfgm5V?iC3ambh^mS#r)V%cvRjgF=9K zy_dhA*5Rt!_M^m`|I5s_56&K zm`l~9s6X@i<-RWUoe$lgOSudZD0PIq>p1EOC=;Juv?z-=V)|0K`y!R$v!Kg1voI4`tSk;>i9E14 z&E>}4k>>3qo7ibsCf`beuGa7|Qan13WS&rwFdo&$`#@D*>5Hm)0=!!LEK!_xG^&5a ze{3FdjuDPen*FhT*!b?tF3P%jyFPjS1(@XlibtS-ATY=*ZD)4##Siubwt>%HoxMjU ztL{AyGl!GEA7Fu(uOFEt6phYqH`Pqc5}yjYk3Vq?JuR$vWc1zk4O2T%zHA!mwGhtilI#YO|cZAFp_) zWxftJemt}+S$cM3k}*LXb@a)QwKxb{&+q~?jQ*V5M7KV@v3XScP+URk@Qq2;QEtuzs0ldom$eMou((va@&)U5KwGTWAmvmy$i;O`u(TP z$G(Ty19XS~Km*ls@*B=OVe-sJDa$FVpInn8i$=aY<54&5YHWVK)j#lgJFmrGOLS?) z%0Y4mapQO0)30yZXN0`~C5IzGu#J zXYM)Yo^x)_xpVK#OuU}myUOxr@t(Ew@5xzuxLY#mmUQa#ghy>$s2gEVb*EN6B)=iP zRhe{hKAoliM7e&=96nXe4{kR=M;bl_cH>f8D56W$JP+IynS+W0$5 zXYUVQ=WZJoZi?92qqLiv8&mJHjMQ5-p|T2` z6S-%2vYskZq0W|1sV*)v2A=Pc_zA6iyrCt$i%1q$?>Y$eqcr#FoEAPRI39nscC?J% zc3Nws+YZ!Qu}kcvJv<3~-RzkY^sx;+yJD8sG!x0xr4x|Q-xu$!)5Ee+~MAF zP=EF0P|XV8=5|Tn%X7KjJ=C_QQtH8jV(0cC@2Sy&^q|oh;g1`#aSzMXMT2~U8W^Q^ zRU23nefbCb{Z3CFtavp$?@6%Ekk6oYua-ZGy<78vz$UQa8ZYX>{iVaFrXK`$ef(#c zJnqgcwX6iH^zZIG_Tk9zlYbP*HtOBGd9{4D=frY&F7Idx<)7-?Km>kSy*IacM}Dqs z=<@2PlV4ZMN0)bJ8kxSaMs_M41f|n8%LfMf1c6sWchJ>G5kHcekNdUHPwMy&2FyFr zA6CpR-A@lN5wwauiJh9;HIzwj7+Y>WN1rS;+2#6uOF8J6{w8*Q(0GbILQQR+j8ys_ ze4L^9YMS4$;;@_%-T?l_kRiTo=J@Oj)d!3A)#kFtoAw#70D*Ez(^85+gO#z?j0S6@ z!@+qv-8njAujgc{@@i{<;1oKu#N+d0`?KBE(7A7?&G!RwD!J+1a!UA>(}bE?d;1Th z-GA2kna`f14_1?R4* z@{pK3o8Jm(A8VUnogUp=qd@)=_4#bKSncn&a&R&|u(}iAs}0|4@j58=^@&-=>kOJ~ z!j$Ib$;rqEUu@!1Ht*Jwp1J5B%}jwz2kC5ssNL>phSH3x^Y5!CUJ)aWeyonR{W*cE z1LZj~phm19|I`SO0cs?FM&fIJ{XB(@#iVT5w5?`F?eNUN>RPBQ@;fBINvJ;k!R9x{}=KFydyRFr9MXf`i>wuAm~^!#b(G?SJ2B${WE zImBKviPp2s`L&A&;e)wyVV_xa+}Hl40QK)DzDS&>y%8Ybe=T;Qe^;Kv6&>m=&vwGR zcK>AOcEg@?TAXXZg8^E>^4pU&>uY7ZcXz%u`sIu4p(Ceq+E*Zb_B56K=S`#U8Up{PX6h%(n&@E^#yQQ9%?H8n%>;lWWJqxkUc}uJ^RJ~gyZC!YsR9S%cA23 z%I3JKHe(9kH}zLY+iGRZ>Z`HkZNn13)icDZyv5Wc%4h8362f?s6?EpOJ{sClmGTw$ zZKkJeg2)0mzgATkCo3EwT#UeYaA|er)5&Qauih+0S-zjk>+$mw(_c2|U#I(z*04R0 zMwM4#olYNLKb}V;(I}BqlgjpjE&7)duL>`BceiGhw9WB@S@sy|v?GjJlfbO|7Hs{7 zEKHnD$z!4KXU~3lzH0jN?87;#X0~asVRH&0!BHsdu5$( zRtwPnzOU4MaPq0}ciqV+_>-SAo~G&KzoupLyY}XMa6Qn+$4yOgE@y8(=)(6xm!JEl zp{g_jWZHRKGQy|pWe(=b$NE1y`wcYuSiF7Vx7lz~hxD^|Sw89?+xV~v3ZSaxmlK^YMuxUFDTe4KV!3BVemJ)l%KT&*18f39Kb05^+jCzYa zw)&)~#$8!$EJjbB|Gv`CM1|^1_d2ile{Df-5!htG^?hY#^V`CwkQ#KT+aD z=Du6`bpPpyDrw|}wwx;Qwr?g7sk-nH>h#lUUnTHqZW8zNqkLG-#cK#k#Yi@l3s$oY z8D40mlDQd5jYyivnjr_JM779MC7D74!8V@Yd)z~%WoyCXtD}7a`c0JmL1zk_Z2R5? z1dEs|wjG^HkVFOkxZ!d7xscAcMvDWd#PF06Yu*>hI* z;7a*yf42L1rIswnF!XKnb2*;_K|u`N@Q>rJn$ESiL#ub4G> zw4cohMsFkcGQS@vR)B6@L|G3CnuN;|277$)MJBGrxh|UEy#QVB*+X%M*-w@c_w0ag z7nlqQ*ioBeg&VgI>iA9-k&D!7x++aEpE=p*1F zf9@;jSB~*b3|{ts$`IGZ77y>-M6Xluy>1^xPbF|D@GpaI%QHvzK5;jMP$^8I~DGMYdm&Pyz#5C;m+y&NsG%sqhD(;9l9MRczhZ-w(%63ZLj*X4ina1d@lkd|I%^G zdRvzHrXI80obN&4v9{YvdHJpnZ}6&Xb-<$My2EB@IAmaO2X}=ok3lMRsB-pQj%0=_ z#IyQAq{zVFzWXwDE-T9;gn9eye)yKC z4UK1^Ny@wj0B;iu=nK*KvvPG=jH2 zxBFKSD|lbXD%XMphlTtW{OW45K6l}a;Jf+5RGyyeP1Lu8v~Ny*eq=Gr@^I27_q{-x zj7gcF5$q^;w*Y0+wemsJ|LmmZckA)qrg?GYf$Il!3$L*oXpZ^R+%(+JtL{9!j(i|t z3N?vLXd`N0|IAAZbvS9$-=s0k|19NO=!IXJP_0ws6+g;Qfjr(7)XDN9E;ZEIObNjD zf^dlX`*7+oSk8E*`H@_7K%J%9k+}WLC(95XKW0BhhdF{4Z{0*OxdQ@D@vmC5sgHur zVz+^>oTD1hY|cxEnhkIaXzo8aA1{{mk(>Qx>SA$vhB}?uUM!JZ#*WF^lV^p^8K7v- ztSus&q{hBPj?|@dKU=t5(nDZv@s@?ITd)JwEYH^eILPeduJU2EUx??u9B)(W&x}4z z>o0{-+7fE5U<4(}$zs28*GqO+DH6wd%c$tE%(0QOcuJR0(BZ4U>Zvp?PR-l+(f7-}{x~Fg^-DdR{zNZl zqWMi1`gD~7xAL=3@f8(n=Pj=@0xNT5#M5xG6-7SQ7<}iF>8|iM6&*Sk5cFiDDd#76 zu;x!qa}0$2Ga25xlrO|amoE~TT3^U{P!VBFPDwjD-f7r-7BI*dN(rp3@1_1S!l*$g z*MH~2LK3A8=;f5x2p58X5QAF*Q;4?jGQb~es0XR zYQHb$+1Uwt)mFk@pt#qSHsk!kTORY~rl#F;G1M#2ox&Dz-H!3#cW^snp|MbHcSg6B znc_NBb2Ah*CZR*gO%C7g6@;@yra*Pzc~As26sqiw?=Iz@x(Id4zCiFO1Cz!*9;)m% ziN{?2*(90C9{i+1baxi;#RG}kZ4A+nU}}8$1KQ3gYS74tK*E)vAorE>$8bfs`}{j{ zysj)ZD2*ozG2@Gnj;zdey#XkVC^??_i;#J}*UZGfn28NugnY+bD!m9nW@WnbI7nd_ z5Xy>c7;L<PU+_>|&QzZq>tPt<$+m-+0d*;rvh z;ng#|g{QcfF_u&1q7{vT4HtOX2lRJBB`90vMXR%&h+AMl?T{KkKOavf$cNYz=rAAr-Tw8WbIHX* zl2*%DbGf~il!KksfXmmKN5@M|DYZ+537_Bn-APKwt-_%~b&cpvm_yhP!M5WWGGH5S zwvlIH2%V=Hi@8&nXQ7s7A%DeE8v7^GgKYy~{pBr#&5v}qTIPQMjq4R1^=52K&av*v zHGaYoEsPTnW4-Ex7)ykAXZjl`tv)mQ5wwJ@S&=mWyd=9O+SD3BgKBZ8#_z1vGF9$K z-LL65o)i3fy1j>%`|=Ct2=q99M+xe4(E2`Xq)b^gA~Sjd+(TuGKcJ?}m@Lx$4s!e2 z&e4j#&xRZQ?6~F6{T{nLz_?A)mOFkEJ5k?gbE&~5Sb_Lz{lIb#Jx2Z1>}tX8dOxub zG})xtp4q=I*>V#ICO!*DgV;I!RD-c>g~M1}TEM;4Kd<<_acP~-&gcE%=>c7*H(f(> zIo(yfNjdlG1Y>UzYwjBw^q!SIA^|&}-X#R&SD#kx&I)bWbm-if=-Qa*D)O%E*0ICJ zV|ZeDwDrfkh^1lg6BwjTY`Kf=xjnXRkQi1iX%j_mCOWB!CVxvTiz9dO79g$IbEAr& zNuWz)L5bis_Euz9Royh%b*Q*$@~QKw^3$P{gK(D8${b_x7g+ThTMnwyrk3gu@9OTj zI}?D?cm66)oW}M-dn}Jmq8f0z`826=FSkEmR7+G$bk8gy8)vc&r~oAr!b6l;qw7z` zqN-Oy$rVMV(&EV8V2*lF?U(K8YvKK&RfXZH#mXCRL9LrlEk-r!NjjDTz|SyOz<-$1 zc6(0uVuyb64D3f$`LN3hS+};eo)g)Wq7EB(X&1L@iCSyEByJ*s&BL9HHZrcxrzoicAPbD8rI*BklB zgn+)x44jG`0T0Jy#x(=!bLSAxZ3Cma&>1Ve<-DTl%-Ib^`blLvjAFATWI~rr;Hz=m)GvNFR(YNtH=cTXR(7=zwm}&SWx}QRME);;L#j* zGVU&i5Sns~FkTuZgn5yU62_gOX8Uh(jz+!`n|*te@~*R|X=vz5CJjU4H4R=WkzKv$ zuo!gWwNL{aQd4ldH3x&*&!lVT0=%mDxwj0WaaZA)G(-#sys8~{qql&2A4;jr7M*oF zY4`QfZvQ%(Z0{_7)}lK`c~?;K7x$-T#ofo}`xkj51dO%njok0$Kua%IcU5uU7bU$Vq~ybbSq=~2&1AiZi#-`E3uu0=cDv$&Z4F{gN)#Id=RL1&D0t+ zL?Tm;VMc!m;p3$89Tu%|ls&&3{rCWfVD??(Kb5o%(}9b`OqC2eBL z?!ccTGgeh}UTe@lbfupo8}ezzoMWk~I}T$Q>=EE}12-JvT@fJ6*dNq~gQL6tP+ao`W>&&$Gdk0>mxJDO5jt!7wHoj0CI?+`t; zn3NH63DOIsK5ROXH1a*$wc2E#2$bJ>yd5C_>s9rM;)F>SiLHIC4h^>^x2C_|&a732 zUpWcSE|`x*ev4XED8%D&I8gc7-;YN7SLo%{oAMZ%e-bh@ze(R3T1zT_7+CS}LsK;P z)#|)Uz}`F*JG$1J<_(Eldh0t%CedpuVI~y&*3k(Tu|gASTS93&AcAA%3mcR$`AiUYrO~szJ%wZ+mG6a#UES( z2;fgJLmvc(g4sVG%cIp_I&fs%+c1VThx>tY2Tj*@Q4^N-qW z*AcHy-~vRMk;#cJCHIR^@OfT-o8uPYMbSmkcE>j1`KOoR-j}%}sk!4c`#L79ShOnL zc*LBo)q$2mme_K)++k16KI3VtEVs8#`NLa$V$!*GIT)N~p$V^8@!vDTpi1A#TeB}v zv#-q1&K|f~A_zmf9j`+*w)m?&3 zF~nQt-n|7EIgzyWMu1_@xz6IC6^6%?`Lqo=C(FTS)|@8$oPr0EK=uH)!>q+{^bq#`rhxq zp;!#$aI}5hU5$^}FOVkNC>yF@z$QbZYUj?aiPwF)9Q#E=;Fp4iabMR1R--{q6U7~(BXh9EGEN$ z8|A-kXmRr08C-^z2dp}m$AvcSUz?T2BmlUC@__Vm^uSo)j~d;k{g$yNRLx`m?X;%- zSPU~Oh5FK=@yC{*konzukZphP5yhYfju)li9Vy zmnDUy#Aik=tTd+xitOU~-D~nZhlY6P!SjM<{k&uBhds8@$}L!2klv3Mw^(UUTi)|v zSsdDg7nwtv8y$s6UW5d3{orS&JymRBWhQ8)d9kFg_oJCthJ-tEsZA0$sIGo-;DGfv z`o-~?#+-&5c-`=ipFbY%gSng$a9V1m`R5w?2MSMpxZ0#O!Lja+}Xn{ zq2Chp$G0QS;yJ9G)&v*={vpHy9Rx}hKW^~_)AZC;@+1x?vm_;iqTGNPn6El)*J3Ni*ky7(s zptt0cPIYJ~W6}O?tg3zkKhf*;mJ*S7HB>q^njx>377Ix)t?cxANogU<)y5pe?WBe) z#D*)~Fp;}O@6JK4qN@_bwr#Y|8O#P)QqLeN=3d?+8s{cpB3n)`H@+WbNDEwU%rlK< z=rWb9I^JI3kBtZOVc^DMv^Y$yeoZv|Mtpk+3)$sV1IjF3I@Wfs%c=|3L{v{@N=)@~KscecCH_MI3w#cekPEks$4b756}$CC zM>*fowB=q3t*!SK5ij^GcK;mRUg+7!_u|#Fdb=`x#^y*v@YjYR@N7k+T?35rwTnWU zOEKRL8FJmd`r(4^Uf$I@^tJZ6KlEwb`}YaTf2peH_}y7gmn5K&pQ#EE=zgj&O9xF) zm)x$*EBzq2`(gV%>Fj)?pI_+G(URAZ-{!%m{&m}vpyc|iLsI>=fz3?ESa10sfBgMR zwj^-SvY}?lL})mPz7c{~&URT(PU_6q{7BP=XodIb@mbw0{ew0K=8djZwS zR1FC7N+v0HwX~hViG3daIE!u_{>)SG;FO=(j!`7NQr^lKNbz-}+84-BUTC>1l!B?D|Uyxezsr z#`nAkOg#N}dxC&l5%wJC@Qse*coET5i_f|C^0r>)5GJZ&A+vrV|9CO9=`fQi^>@2+ zz)u|uv)0SM+qw7$)?dEBaQF}4UEO#Im_z?Z1}>*mfIAuSz#kd@12`BC@{gg`+D~f9 zu(RG(w<*bKZ|tQTX0{t@Jw34C?N-ae>=@trXbm$FmS$B1ToZ}&e`mcd`mSqk($H!0 zII*q;ami_XFgJcN0Hla>LNT-A?||4r#^OrwVyfkh9gxc68ru43m17NvN~2m(o*;IZZ-<+(gdhEJvt7smF_t~=5@ z?--XJgildRkytUFt&lBrhWN=$^!xkzWfa|BWS8~JZl~CZdf(ssK%xOtIdvXzQ?j#*3rWU_h(?QnhF0FV;8OEgtx_*P@PeOsZA6U*3ABsjmdr-0uT zE;j0WVvI~esg3yNJee)P*rldn^>Fs}Jvt6e`^G4g+5*N}khln?w%n*M`Ivq+_KRjQK{W_+nF2DRQXwuacxtuMywYb!R9+uck%oJ7q7WTNSR9Avje^ASOLH z=0-kT))e7^bR$nr@`zZ6>qG5n+&_XqJl72=gn;m^lCJ7)OWC{iz=ivewYEsl9=LlC zJYu8Pc83tgr6{V?e$%6aMtTq>+J?jcNA&6pvlC`MnBz-f%0_TZG^{{q;~5#(Q(LD^6LZ>V4Guf>9A ze}?3kM9Ph)uLvx_XBBiP1%3j5$y zoPJcJG@o-Tdn^jTd~P0JZ3(}_PwOzm)9PWsl6QLZ7phIB-R1q#>J}mPMW^ zaB^zHo27-V!?gm)Fm=>-KlaVVJMRU`-m9tX#idw$I($GHAP8tSx1H++kme~JSjcM- zifs@QoBe8@!g#PGpf&U#0vNuWe$z1`uHVfs{N^a)bRlQR2LAE}HjW_~r%GwZ>KHC% zPOOPaBJwozH8|otQ#m*8u4AHV`GxKkt{bB6HwuM)hH8_B|9_AIajH)mmO|v|yviDM ze6p_RnHod>{K;Z5{E!cG*)RE1 zOvfKk$D$sy4$H8w-4K=1DkC?{Z8bU~}{7OB3ZNg8bxSKn=`X!Hy zbpn$TENCSX6D*d#k4YYR=>(c{H_w0X)S8_8j8Eu$1NsjO9fn1EQ1VDPbWDj`en(6E zzd$#ZoWSaHo#{W2_Fwu8%w-zpA`mC|Ps%?CfUAd0gd|wFVT?-E2}E}Fw;wHkUxlB- z6D)?h$~}IO=mchA=-`aNqTGLZxCcuf)j_kdDF6}>5vR3%lPQ!g({_*Q!M{TKOmmu% zUAoy7|HLO#Vq5?rWY)rMi{e?3`KM;JUEOP+bwKbwcGlwVuHYIPZxx}pD@cElEbhF8 z(qW9!!J5!0`!kZVK*gF#In!J@6JXtTh{&GfbGOWM(!+73xm!9k^p-xuak;KcL5aL| zLRvJ0phOWmA=84cf56$NK3-xKu5TciQ_${D@6ABG3G zB^sIjFGzEJ`q5L#Z8)g7LYC4D^~Md zQNkTNl^Q!uJ^W#Ya$Z#T=o746p#wyb+T5}u_s%9^_NiLyIV@OQ8lQe&u4uC}F7XGh zhotR{e>A^hsWk9NyS`NMW6jW`qT>K3ty}o%u?Xo(kL%FARhKf&C+W$d9s9(3bd$}~l3*2)CBWaWFO;71P)5DwH#6Rn zByooaP0T6}{U7YJxR9S%Y~Cu*cqWN7lz`KG+=xzm?TdFb%&Sg;hc86HrHCXABP%0I zU@McPN9D-x^+`wp36rO#uUxKIeT5A7lbMq@i?|G)mRuS^1tdMn>@i)xI+WS9D8hxV z5?jj9e0jym%>Rr_6TO_jk=^&GCB11(-VfXW$ z-A_^g&t554KHUh1eR=?&n7f!PoLd#_W;d21WA7amOJKi03=2s5=-(8?^lT2ZhR%z- z&?^V6%13Usz|5C^!6&%nuEHk_?e`Y|iI><4kdcN0TDo;Y=})rW`=&o}Z~H1)waH7@ zVJN`o!(t@6oE`Y<e2De2PUOP(^4J1#+tp;^$^Z zL8J=;j5=8_J61(X?#LUrI0)^%uTEG#vw89JD>(^~K8A}H7|kIaqwZ~VbwYpdYg{*n zG~cT&p?}$y-mr9F>GS|ATiN>5Mt%7Wi}9y2vf|EMgF_UqWsv z+wJd7F>w-75yyk&RyR9VsVZ*!{nu`IAgI8x-?t<-AdJWDq6QqeN5`9?XV1P_jOF4V zZ&K~(9&hIGVfKw&4x|CMFX=HAno%E9_ z7l)lC`m*=c+s-Y7(yt=S51Jm}vtwvv20giy;oyj=K>eUuTHt+4opZH|@PtrFREeHl3pnO{?DUqb8iatF zeG^D?ney7*G@;C<&Zf%d1I{y13*pHhOQ{?!!vZXJ6d2j?*+VFG2=7L!MXC|1jNi}= z6iz?2;?=)`(ZCW}aX0TIyDE#&fk3!$H8Sor1rM4lJGy|Tin zxS>LMF>XyZB>-bXOhvxRU0`RFn~@URm!?3>g0B)g)Y{`l7ls3BO@SQmVvv@!&R3Cu zQ^Mbq*t@t|7OL8Bg#>?TGNUBq8NPjqI1~rZoYzu8@eV)!MdHn%AO%Xjr{E4Pn)#5F zXI%BQCM6jUDL##7O&AWINez80@Ty38=r0lH;ow;-Ja4cH3}sXh%@m^7n`iHPOUm=3 z;=9*wCj%8FK20r0ekwlAQ*zy9WJ?=X`e=X19T)3X$SA7w-6 zv+@UoMR0zSFQR zJHIaP7jGhTWIu;K%sFY6PX_NZpf@*9`Y-E(9kO!nTJAAm-;=rf;!DE=Vcq_jU18nx z2}3fs5bTOq4AgtksJ*al9c+ctSfp8`Y3FUz0K2gMJgDx(Zj#byX8_A0DcI-w2JRtH z9p>|9HzjcKvz;N>B>&z`dei;Ip;jk@vk9NaDOo&|^HJC^lt`pOq?L-JievOQaOPEEP+3=5=LQKc)p#Dwm;8}cUBqS0-4)=LH(Kg}Ne_e+w?uHHr*cn619W@lW6m9q%HF5Md z=-oE8x@xT9uu(Llp}wIMSj31})ElP3#(16J*&Vw2OR5n#t1=G|tqR;)59xWTT^5E; z{Dmw-S{3esJX5N^z>!d0V1B>^mR~h!OlxRV7ZPr2015|jP3TmV0c|c=iQxh{SAv;p z>GRO`uz@``U}+{dorli`u9Ro+l|DR1|0@kKEL$m0?@z>tm?8i5Ps6WIhwf%To@zH8 zD?bQm__0AZS^ZOs^s^AhTCks4CfETd{2n)QdYJh3gWy%9V`J&g8l z`2xj7Ju&qq19_@mCJR+!8>Z?{m#($@0 z9xURz|CrUwVAz9c(ChEPey%g_nP{sLW#j6{9jNVrHSwKc`=sL%gA7<0r7;M87WDJ& z!3;CRHePsdROLO->yVsgaCm~B%6Cco`hqfO2}XN)toQ$Ns}{AscWgU^$$J?P52w5R)Z^;?D4P zCQPE@VY};!DkFB+TV$LdcQK+d`K>X*YGJH_8Dg~L*lO2+tlV*elt)v6^)u$(Sf{EE z-$wm3$r_Vfafs=NQ5r*rOYUD23Rou#`|6#lkdpq0@mjriFZI(HYG8%p5TYghv^q~A zrz)N80o_NV#%W#{lUIuR_-bH-d3lq)hb}iTMgcp4kr|UE#p0XrmVfL_@-79O8IOUQ z5xdyQ5<}VFhG|~0X&}KqzJT+vZH9Rp7|CSyjgq~P3$d6M0k7A3>s`DdV)DT2FArieE2Dl( zHup)Ekn0EJ*fh_trV^BxMGBi1j}|5V?#qt8S!!`s=8itF^(+Til_us?1+r4uXJh%X zNIU`WPQJKvQ6FQCNxt|dfcm@%UUkMXQKm6bgmbF#we0#llOs=XS<0gc7TBM7ikc5? znVoEy4Y`;Nd6qfeiHg`rwM&ZR91~5$$@S2#^5`qga85NBGs(ZcIcyV~+FRJgCuU-- zeTR!tLwmHKOA1Q?#QO9JUNxyPNLraa2)z)dV-VX<<8|p1p0ZUQvQ>tJdmge7PgzLq z2H0y1kVAFpCXQo8n=s?WH)j1VAbDLngPHqFz-45Izx-8-$!md-)HbiosJJ(A#45kn zg#cr5Hp@-Vn-Kcz8)iK&W<8!|w%vR+o2GeXG#)pr+;3KS09tx92#pf(FqSzF+vsRt zzcE~vs&zN2u!|9cBXO#PikUd93G%2(DFEA_z5M%8vU|u3DR%D2)pcn)d zny`ro&~h)?xqR+M@!keIovMo4wh~hm*=h3INXgFe@HB)@$HY#@=+8WeHk}Upxf;8F zSd0Pjr*t&R?h)rowsv~)xVCm!TPoLf_#n0m4f=N8hL|CJdCh?j68eOb2O@22m(x3p z=aU4hT${m0_3ZF%_2429(cg5W)OgB4h^*$0fee8U&TG0?8kw;1hiihMTp_=c`Gga! zIC+E{G<(&e3U6=o3EOrx=v#Rwr6@+hXq0?4dxw8m7`(=94Ki;Hid~R5cOCnY!S5## zab6#B91Di2uhDmueS7*uqv>A``oA2U zfI|m1!3*K?$t>(m+&cjg@J$eGy&1w_i5!YBhC~=bq-wAT*tC?eoe0BXG#C=|d$p2a z8p2eGuq=@(Lp#kC1w$C`jYEV8ru72*372^xhT!~~)7Gw_cPkMVFFRml*Ubn1<3S1% z!eBJYzTLe>KnaLol^FgaNbS}#Y28hPS^lRW;(-7?JMV6-J{CO~@8$u}zynDTf$)a^ zN`w^-_S*E`VCW-_wewbkFg=F+M*fyVlHt-QmG8ai5uCG zYsSCBlr1P9F11pTDpZ$ucW-8|R(G!=uc!`8(zC_i&Cv^i{-j@>;ND_J#a=Iv;;eL$ zu2-3^cW$Vem04gj&ZEV@V3?VPQ=^apyTdA(r$)06xjOZ~OgR{irsIwbjq6ZFAyqvz z!q@5@%GL?ZL|+;G+lUFcGz>6B3<@R6u()@N>P8;6+IyK3m6j4=yGOJn;kS!7^-!_b z5H2iEXJ2qFl`KPq)@&aOJ2&AXYfXixuJJw(*!PNDX1r#$rB1euiSJxmXXt zlEGYv)l5iNAcdQ*HN6MQDjBVw<3V! zW87Fxpp7m|~;eop0sfbzFF>(Cotpc1{oMgai#ixvbb~Dk%vGLc|0;galC@ zVYk5hc#q+Fa5i!&Mq>{>F(1qip;~e2WfR0yvdN>M1c@!8Y7%V2d)Ii2q~~j_RzpL_An45Fs`!k4lA#i~LMllu_T4eG> zTFJO-<({5ce$mQclwp)d!OEOED0pU1(V~@1CvsD9BcKRm+Me(4&FC&o(F#ay)Tc4R zKf#h!WFo>3s;Dqkow7aZNr7D_J717ID?eZ|7MdqX2qXFu25NVp%Sf!5>(W(thmLoF zU32}SP>ck9CJSSxHogPbM-EYi8Qkf9g`F%#9KD$W?rBvip)4Uc%b z*@%-+nNM{1R&Qk&Jc;83F*mSJ2wz`k*~~~1)tKV<7BAXcgwI~vSbv$HmqTM&#!Q+4 zd^@S==M%owYwtmIzr55#NNU~Ja?it|M3OVU{~ihoHcu)hwu%&`-exB@MrAtb6xnIq z0UPvEg_K5Qr1T3?NsK)tjXm^7dY2yWm|WqR>?%k#9HlT49iZe%CyqqTS=tFHSX1Dha2^B zL@Bj5GD+#{w40ep!>SU5rL7&j)kLI~D_sq$AfhMX6AT+8zrCG^zJ`<~ScxDLPOboQo8Z4=vi~xt$X8G7_KJ3q(_7LM z%QpQHvw~FL=-0`HV#xz>5hMPBbkd9vQGAFf=fQO`W#wNMYPRZ-e;hmV3l!In`>HEq zq%MS#D|E+4N?qW+O`Y^spCEGpXFltez>DiM*mrnhpsBgSDY;oNiPT(n2BFr!^EM9~ z$EW(-!JX7IRoiqgbUtTNzxKQ+Qj^p5Ma5d(1FNMv2PTE1#+_+os)h(wF2}^LCTJG+2oT%mWPc z8>FOiGcS<}bu^e8l%!Ou)Fn0h%mD_TWYY*_@OL#bFZ_s-4M7^ z@9+2rWN6&`=yo9*t494lYUmL->0g$gXpY6^AcF@PgrqLz@{wZ-=3xOu=+IwK>XPbT z*<1fnLk+C8yHyDJ%+J-lMoRN%>Md<*Y@hiJBcgpo#1mgsUK8=0z4#`u3Y*Js3TAKcBs-d0SxN#QtM@!zyK zrA3m~NE81V%|UJ!9v~;R%WBf#HEE~uNmt$R!36*_X9-CF6jxAH-a~(+@Kc9rm_{Is z;)}L!)oYqw|5Nh(IdK0HbC|r^CMI9|Q)+uefX)((P*itHMqC1Dt-2N=c4iXm9ID{sG-vC_r&0 z;J#HN+!Rdb3bude zD~q^LTCiMF;Po;>P=_6ibCoV5!y=WQHq~1CSU000<`^R5y?upLLBEIoCdbP=+8|K> zZLfufX$D28H~GqGyK-NsqenZ`A61gVjPNdkD~ zkE&7_|62pfL3yI4YQIJeZgSiPw)E0s8oz!|Z62;<_@b_;zkZtlf~R^zj7IfstdxEm zA1#m0^9_5=*Q1gi>DN|EJXTCsdrelizM3*kcG)aMHpKt}hW2pP9swDXvPXJ+hkGIa zfaqiGO*l)P^>5pIm_)t4frtz*MaOV5?{8a9=h6bfoC(0A6#xUs!dmoi zTQfTGr_s|l8JmEErNL}c!57WJU}H8eWIkSCHa<_}y|ely;;pO4e_&`@?BFJ=nE7-xCyr)3E6@`Z5?U|8mNRn(gQl(!R9F^*Ns5BsbClo@$o!S_Pu%lr;+lPc z!sB|m)+OS{|Btozj%#w+{)Isl5djM*Bz8fhN=fJ-C=jKD-hy-p3B6aPC`ykg2tpwA z-jps)Km?>D5JIma(whocK;S+JaP~R(p7*`KKdztIY?4{?owe4iS!E`9*r8#mP|ZLN zDXQcnhjb&CAi9I7q$P+n4{@~mc816i+`aRXc1LRl=-dbBq@%y}<-D{K2VNANnJ+vu zFMW&H4Sqb)mot_2tjhWKm!2G( znUjT+j;1qLeR{*jV6~^)HDtowFL+L1LUKN$c@s3f6=}tSE$&9^T^U5#?w?v1z;-}! zlJ1oD_n7A6>jjR0eSk0i^X^7jUz*q^%6sbzKR7TQ2PmfN4+@ zBn&my*s}mlCZ`_oQS4$whF$Brcs;Hdp&t-DXR)h5@swJ-S7t_yWZy`oL#1nTifVd-OjWrh7|FN!hA@h7%6|>Ke1; zsy*$>9L2Wje@o1!MSJc}3L!jazhPPO&Z$RzRH#7}dM^S^+N`fTJZGX`W?Bef=?IV& ztR`eC=y`NQMP9BZ6g(W5PyQaNxt8-V`=X_AIVWTdDAJN!fK_OZHs3Uvwov;3{$hkORZ;-}dzq%HZm7b$? zf2sc9!>uA}4})?6s!(wWXoe93hzLE1bjA51Ys1p>MRxp#C`yyHBl_yIVshdp!1ECq zx3DC|7{2cOTUe_HlE&rPw+wS4TA8)$Q*L1gGCcmR^-HT4-7Bb$E4;V#uZEH_Y`a!K zsmf~5aARmr1ScX{*BIJf=}vxKuEvTv-dJ<-w3G|^qU9}vF*I&a=7)5@VvLbW+@QyP zyS%rE@-ZI#QA41#;u#Mdr5SfFNm5$PA?apWU9p$3%yd|3LjYZ;^JZ7IZ#H*9jW4H7 z2BE)fmJ(QVk>%yZ>vVc38)GL6)*2LcI&U@ME26Z#SgeG89CCSQ5$HMP(fwobi%@!*@GM_Bs(Jcw+sB_8HevR@}fk#r{C2^@Gal4NE0ha;b z;WjRw`|Wba66z9aP?A8Pv|^7WoJW#~xh_EZg=-0z?||@U+4HiHTeLrtCLhrFxx8Z= zddD`uoH@}ayv&7(cwB$z(PiMtKbH8ERt%#@5YdL~PR26u*U$6->B+B0d_KHQxshkA zq9yfj&5pJ>E^~m-ATHDMu>CCKsF>FHLKco*249?Posq-+r>ZzP`)iY^FVhb=m$){FyM2}i>(91L-`G#aO>mwJmZCH=k#;>ix%pA21lbrJ zL=kWFoXScHpuUO5_4w4Pc1Ws>x|8-&ij=yA=YXsir43qH6b1NmZ1j#=?YNI*+%S*xu7>DyMZE*Pu{7FIQq)!OZG%I zCxEn^N2!?1L7SpJndN1#YVEkaP~2Yd8v|Oa_ml9AeG}@Fy0LcU1F(yvWZ+7iaZim&PbbvWA>sdQBVAvV zuJ2&}1|fd~t6ZqNAd>Z3cfq)zSBlcM5wQ~$JoW4L_5js>b1F3~O16$UXX%SAR9*v` zbj)aX{>Jkd;Auy<4Y)R-@-lceb#38{L|<%l+Sr0kurF3gJtoJsHfcoWz&%nZ+%oz} zul{}o*vbDFJE~jkO6rh4(((pW1Y#%yZ`W9*0A}VSY&`q1_YLX+k7;`}>AD)xEP^M9 z!10&?5qP`$su77{zpmtm^x4c_o2+_80|Y9yGHX}?i4W9)Q*+BDCAnjL8s9~cY%VWC z*W=e75d2(@0wl9!l0WSL$;E@^^uQk9d6`MNxCr%<#AA%h^GIV>e-aNMj{Bv#NaE#j z*2xC`oz((NxLLIvL~mWKBpz!E&ylD(6vbxNXGT`ycxNtYYyqkg?WLcCh$&ithDhR- zauQHk+v2#{wB*^;P<3ByTC#Oc4tD|(@CA5{>>SXd4W|tL&T)&RWKK1Xz3o4rTkhP; z$QfR+QFe6KSJz&TS+Ic}9wh=xZ1RVHE-*bVEoT_H0Bn6V^)eEPVG|mYoShVVTTR_9 zH>aJs(@E)9OIi+S19}5rTad$@H*iNCvVV6If^-k_1RfRfPT@k0!Ud!BSPmzpY*Bb6 z(=B4~Eh6V@w3p>gLbZZapUdpjQdQc9hz3+bh_=7vo}_(gE_0f%?R^x<ZSz5|pUeC{Mx2fA_(3{kscmN zH|(V6#pfPVE`;N_$pRcI<3IRtHq7o34w?RYSgW}Jb6n#-vj}Jv&`Hw%8CbJ$c3j#+ z5dfVcXYU%IIe1Xcbkd@D6bz{N-NXqiz}^0(!lwS&ueNT^6^OInBWJoI&lrfnM*hpvCN(Sh;rQg}p1dgQUu%v2d3*`6= zkZ_#14M0#no6=#PKoNtD=01i@674Twvzl%5t({HImcfjJpM)l36azFtB5X8l6qxA1 zD`1)z9KWp?%#02MSvU|RO(@Wc;VQ?qyOvbf!cIg|GhnDA?{vBw&W2K#7XZAP0ld;u z7+JpY;*lTe(JlbOa!~s|O>bnco*83(rsmdb6ZdsnBL{KzbBx-0AgRvZC*!ClQ%-dn zOA`<*PCipx*T|6ocK)JYE{Tu(n^KNXC_n^!k63DW3c7cj9ysf36n4kPsFiU}0uJZ| znL_7a8itClROCGLln1#xdjjaD0O*hptApYsl4d;_4=Bjq1QD~=ZxeU)cP2^Nh-|<> zajTh=5X;rf{iJNtm#4F;g<6gc4lo3KvhTqXV zz?c32yz8OyEkeseKl0CzT@#6~mQD+2ji1dSN!I{=8FJE~{QnQ)VBtX?Se2}QDPsBh zeGjZiVv5>29U#Z--JI$qH8;&1A3t)QNYUgnJDK7&Kyja<$=y?(e;e*-?xoDg_;;}2 zRCo3=_XI9n*V+jfkC)pE$n+H6+T-Kz?O51j-P}Wbo<2WfdU0znXt%*W?EdB+^1+AH zJ=sGi*|&%CiF#l~qsRxD-|Gyf8}>G<5i;-DyCTmozn7Awh<$ZAfpXmzh1~t4@-%Hv z-~oA};W)w1d$M~M4l{*4l^o>fy*;CbY(b^{Pdji@XT+uLna=OMChZ9 zZ|of>bDIJO&;!``wGWCOW?PVVc-1FbAh=0Tl{T=89GClvV8}pn95>t9YCT~%`-vK@ z*bFMvbv?Nvz|;&1nqnB9dI=`HFg~BrE4+WgYYt*Wz13>xFMXUIXD%-P(=b5Z3fje$Tx#Z zyDh}|Go~UxIK#}vGm@qv)2A5XjH{phWDS{$Y;q1>{nq0gyj;qLiF2W>O`mY~6oaLB z25<{NVRL*k4d4|e1l|V;7D_Tli8n)&%o$Lxlz|%{V47y~G@TZ}UX>$%_J^qxEgqz( z?}(%a%={lN+{u8?rWnpYvhfUts5XOIonbD9!4xKzzp;S{J;vvO4S%rJ005JSyoNp%Aa`bg!!%fiPV#sj8di{^7B3d}GdWTW8%(+C2>{BI~QwpJ>uvW_0M#urv+TB*Xh z4~{r2selJH0=x-TFj!KR>LSq$X7_98EU5t1w6ZliE`OA;q}tn~e6VpI9V^ISGe2>G z(Z+eNvu4}4Qsdwr9o#Dz42`^o(dril2nYZHgVL<|{S5T|W;SxyGJ{P#nSjyqeulU? zTW?Rj7`XTI?rV=Ln1Conf;5A^+QHFRLG1RHII&a z2~AIrd$}XPVDoBUA^(oS!OyOwpvceuze7CkPzKI9>crowo&}zK6AiPn1r6_gcmY#7 z+%flqJYG}O0R$QlSJwJPxLUG*7rk^>iVjq%``B#!uk_T;1SyBC10H3w;BssnVV z0o|k*FeG4rEeCq#`|h!?*DQ)K+n?OMw9M}}9|ZnLyZb@M-cuF_IN%0A0KNY^2sY&! zW-owpCg2Wzys(TeCE5YEHOm|@^fJY#K7XEl20Xx9yF&};RFa>4v@RI9jEP}O6TJG2yEfPM^Rh#;&tN~$VeHp=z-h!4 zy~v(;7@CJ2s@68zO~)8s06cn%9RDMGSYT+Y41FRU#<9}kY3u&|Y_l*h%Rlk30TtAKUaL7Ak@1-)`-N3jm@0DA&DV*y=vdG^vw}3ZARomk8Vl?ZVQaa zxggPK=xo0|TG~-jURxB33l2t2&WbbQ-=8!&?v~{W$h#bnGqD35fs!>w;VF=nN1>mdoq482M4Nz z)UkUtT$pe{qryF5K_=jAo>LFbt*AP|PH5hJl_3oDU-#O(ae=FtVI{J)4h#G!3ir$& zB`}PDOx`9=mqVI8gT214HlQ1(dk8Emk+k&yO)#0}H2`pWCO2}WYbl78enqtk$2|hV z_=t>xFytAkaG-KXgXz!Xa}*R6Opum*nN z%s~J6h*gZ?Yzt4%djMq&=bSi~G|d8UP7fR0Sru!RVp7!Bg!)+H)0NyT6^VTzWHwr2 z6GR~g03AJD-WGUkSd672gydjNi)UD)C-`6!Y#_}`{=X8ZF5MG^LXr_>3B)l2V%G)@ znT6*aLtWo0CwEM!!g=K((_tcsAo%lhc-5)|5EN3!D?VpqosDOBvppU_^lwW`;KnBO zp7I{8fP+{5b)DAPPzl(7urN3EQT!Sc7?YmI zg@r!RKM%hgl!0CpQVu9Cd%fi8l3J zJ0PNp!Ff1#VTrtWWGMn?_N9Sqn1 zHdtT|j5*mBT#&aSI47FxCQkx8lM5?-4^7PUd9Ox<@?kj@nVnn+fV8g_nFTB+oPxbB zHfca(IZyCom1VbJL@3jNF%jLr6Q#&=YUiMN@MjF6vHrg?={5#XczAZisZ{`>yBS!F zi%@VqB1ep5W>qD&?tHy|_}#t^G7!-3S_?aWsVQ14`Q%9a`duMB+nfmH#(LlIFv&sJ z09q>8@E1D}ff42z!FlSY78JwwuVnxL4wm7+0es-^4QTND#tP^Wy~qLwM=k^Qtd@xe zcart!s?(Yt_F8#Oj7Gx<6wZlJ1mL3p`2AJj&0CjLB&}1H0RwXqoySAxhF9=VJBfLG z>%KW+tesk$3w|-vapiZVijiLBWOH|t;({jZhZ5nwkjs8JN&4*|=IN*6Yq1Hh;6bHI zZpq`NN@a0Dr8fSDmL&T9+v1KR*^-7cxw{>QGi^HW3`6-7Ig!j!?+Ht<;IEO)>Tf2T zLcA_^WZxOiY`V{QB`$>dIFe*f*;EvZt_L}Nnoz$ASTw-p6q!pKfXnRqVMV9b?TU5D z`eCF~D{tv9$o!>{3HzQzo7S??L>q!@Pa+q-<<7#Jk3GIaPk8jmfP2G zC3-h_n&jB~URH}_{*p?ZC(w=~=2EKPkD<4k6l%&OD7N5OK7{+uvAT2g2%rbA0g<=1 zUIUx!kK9qD)#Y@lX^Dvh60T)6@}A2Ysz>U%**rnI)YdDzgm}kG^wfbd4u6b!x9^#d zF~{}z6QSagT#4C8lH%}3w>rpwGLQh%3mH#ngDntd_Z=e`zZ%KvzjpI9U$$NAN&{Rqz39aVQr+N}mM_HF0a==ae`xH4jml$HA%}>vvL?7C?gC&rDCGF;0HkA0?==%zD~u zQdKjs*l%MdmbWNo@F=&-QlpT{2e#$EOVt909m^daH9wXM8d5suji5Hs36wUMapP$O zrg^ckbM%0Xpn!>1cjVAIfMR=~jGxxh?0&KVWMw2W?%dC;AMT0b>`gTOX`LoEePStr zl-M#68Irknvqy@lemGN%w6XG5jC2%WwYK9Q2Y2MF;_~(a4dCF;rM8BK06%OLOGM!vAutV8exeVt%XCB$OT5>KmnB3ogV3EsR-e$z$GE4&W%@hD* za}v43x+r`3e9BT^K<8G}T>aWyH(-;wd(!vqcXG@ply9e9`bk!|&BIi~=l+7gaB zGy2*l$*cFZ@lRx$z_j`IYBkf!^A>sJAnGw?1${wlC5c%HL@D@ zgBR7AiKNBun0B3j*ZrosyWR$minVv99{p;Vy!|^OsH2C%#2GRZKL92uK5{<~+?vMy z*gkh0Sc?9X?6jQzl$_|i-CG3>8av-%TShrs5A*`+bo^xlCR}oNZvjlm15DsKOmzYV z592lk0pLP+Hhqf(Ezf@5sol=nKZ)FA&6l0HpHh>ytD3}i^P`VbxyGJxUjTS5c_08> z@;-O($Kej$ib4&py}k%2b5WMjOMOX}5nogmtAO9Utj1tC+Ze@EBFaN1B!=l;DlZ z6C$ipI8iqQ^{uT~MZm%vBj|fbi+X`rwuW3P2*pJdcU2x4(>WVKFQ`Xm?|9w6&+oYS z!jGrX;n+Lw8|TlN9hE;ef5wSd4ude&36#(v=fD(OO02fgKkr~|4-ptq?am*ywzd9C z;U*nF29??_PZ*_lCcWX~Y1AO^b*x@PA(f1f+Ohb zj2}YZ0^D|j@ac=Q6P6})X0iKPL{1P5!@c$>m;QoF@LoWcVmZG7rF~IjWL_7nA(YAkO zpx92B8xie@#rc8p4jI)8`sXpT=|l!hHtm|on8{`TQ<&L($4Cj)4ztKynfn1s{jH^fFOcGzzz@~0D@vl*7!#wAtcqvG`g$-&?Fb?^^83i zs{VA7t6s#3yArj0D6y~0lL8O-9Dy2Re=8i7&sey0L=+2%fSHw~SYocK8xpNAikU4X z>qv}l2n}d}qQp~r*(Jgu#79^6Qw1)x{GEbWx{}mQ!z1(~9{ULsj8{K67)c^C46O0B zyY|rf_&}K3FnYDUgN4_P4Zjw(pEr}iJ?TEeNN#_jSl)l7O3Gd_n&%xlhLI8%IuQKw zp)-ZA&uS2Ebq@QLv`Z!~zbKo$(gM^!Jo11Q!HeWWG1>ZO0qGCwCx{VfBo!fvW(BdQKJMqc$5zr)`#nPpdTg6Nq^BBFDr#5gh&vK(KoK0U zSi{iN7MhusqY)J5TRK$9<0+F99wGrEV3R061$4vTlujJ`r+Dd@;mqJ0c~v&*>ZwVv zt&-xZpa|3iRkG_+#;&IOi^3+Dlgbo@sJV^*gXe>JlJA*BPc;t8n0 zlaH@sm|tRh>&@Pmr*O|t!-q;tGJaJyvU<7`;b36!s;qWDZ%4-QmKlI3hKhz%j9#lu z7%6#+hImyAV`347UFMK0q5FQIV^~pQ33)EA%#f{w3*|-egBLNC#tHZi4Kl|-?+#O3 z*+|)2pw|l-9y?svbq&=Z8xGVAI>F>k<=Y&D$*$z%1LI{5(om&T4)khDOL1-AzxNh(#~aF)v}x( zznM=TfhdYJU@3c81H5;k#a^n#zAWAW6Pp%4&Qca(q1VY1*HXv|)96|~bc7a_=Xm9X zYWb~MTMG4b`63W+B2(kXUjy%ra#@dZTOT??vH}XmFLb&NYzqJ)?yD~Y;Er&pfC7(m zK(8G;&}#(h7=}rVs!421Q}#{3z&S2f459%BiH2_E*Bx<=(6@Hco zg6~P%nPrn=h8g>eB!`?Nhqy9_x5BT=5?wvD3ATH!rAhrvk#LFHDoPZi#DVU=Tc4lZ z?XFu%5R)mZbV7G3`kZXdMoo;uVcmbXkpa$X-D7;HQ7hzC)Ej}0VYo!W4j_b{l%VL> z<&*%ie*#MP*ey|z^m^4NY%t>K33H41)7I3j0La*U!stRm;*5Q*!Tw?chBndTAMs;1 z!njZsa!_(4IlL-ciHI#p8V9Vbt^`;oYD-pLONmh~)P)&)shQ=&;%l&O0b8MLH7sI> zYg@H1-!EA()_}o&e%5OM>Lhchcpc#Iq>LvD$p?&HUVFXMB=MgJ^~xWM5lhlP%`!X= zLXsyQQ(S$H*OH81e;?>QDf80|xs1JF?3Q8Ym}BREShOUH`IU)f42juEwI|z`?-$S+ zv3_nuu_{8xkeJh!wE%O8(|}f#3<9)03!60BzF#dcMmM zvHup1$z%?1+n34cztRD8*>=FNf8sIktLGD!Ht@)O0^tpO;(J7*W~EY==qBH9OJbDy$%Xjv?9&PfU2kvRY*lTZ5 z6I&9y0(#bmB@3kCws#tz9xVCK_7dNRr-DMNbU__MWDY1X*?0CZCRYf2=n=7N@2s=~ z5d3Rqe;y`=#ntoV729@2&SS|!h&b(V$Qrwq**Uu76$g#}Sw^sVE}`P9VuX%zgq}&m zHt@%@D8~q}GP_$fWKH5@)9ePqUpoxeZIb@FN`9;>5_+BO*p#U4Su3*6CjxyOrj2pns_PmbhTj%2`r86TDRTNRNWm@|4t8Gf9y4Kdb!6M5Yc zTXk^#;H|MlyTb0OV3yqO#7!T~6tBf~|Hbu#6Ty}13@kNz-@V7-mzJD!dqxk{PhYQ{ z#(K`T)(FJq&j026heXNqUo_IhcsJ7TuIbG0=*%CaBZhQkLul-8v?H{rISuA?c%q1z z$RkF8>sx@(5jiV^<;{2|-Zzg2*XI(YVl8Avwhm;kq$?W+MstZ_E4MYWstzaTsn^b8 z)%AT)++~e~u4xuW#(mMq5-Zq9S6wm|;AsV4QPL&_hl>szKQkiS7O!2FFv13VY=cwh((HUl|A8D9#5fbUe0 zPq>L_y#*XkeQs|j53n>a$d%?;;_@+FUj&)29IfRXRr&ya*>v z|6x4H^2*;(i#5?(C^7)y{Z#c~>#RBp$k>UzUa|^w4^_}=mFgjirA6El!v-tGGw2*z zuW|tSkX~7!U<2?qm=dGn$W|o^JK9-${=-+2w6kOn>Kawr5wi>%8?7-knA2QXuR+Fvqg80s@Fo1aK@jkG-9{DM=Q&s=Wh^ z>~;MIz)yqw`9AuSm>>&g2IF~!} z!wK}Sv>&(X$f*=zwW$SOTkvS89g_rlq$CMCX5#1AUisqk8;Hbcv1-Y(dRf+yxxkAy1)>KTgMq&DQ$RXyTMu}VsorABQ6R0;7%+;gZ}SmbJ} zvD#ECpLnvV#)y)t|o&>9j-GiSk&sAJZ56QWXq5^#s-ZJ z;+FHG*HERdOYGzh^t3vs9k|M3CU}gkJZ)N)I{BdH3=wav_;G73H8k%xW+^^ zYEH~oGx{Ff5f*K#wOLpC)JupKmQ<-@Y^v0p4)fC5fd}3VF8J^B`={=2?f>y`Od3q6 zj|;;l(Z}`E519Yp04GC+w&iha=F5u=&>9+yMXDw?)-_f0ue=fEb(5TBZ!iJU6VC+Y z#CrTgc#nfkez(YFwEgQW%q3pPhU0j1o>n>D)MK%(nghd?lB+`QEc z=#ifTS*zZp+P`>Fr3yb07>9{vrV{vTair&f5#S{0i=buieJ1iCm{3M z@QB3#$d(}l9F*3Yc@Brl{eBQ`g@)!CM9XF2QXL&qU6MfA#F}>Mz@>yD|b1o5Ni#}l_(bpqfNzkwq?~7*;q12dG>j05}-TikSz%4uTlgES~skpiv@&o6$%p14MD3kI?09sp2Ws zT!@?N2~&@>vKcHuerfr4cprRJL^kMog14w-FtsmWtkQ? z*LK$n*7i12_I@m->^^!kIk~-C-=H+xusfIXCctlRGGJ#dzOH}cWw z12hZzkQqjU>fg{6|AxPg?lW)YdgFIMgjCuvGyB-Q7mdAf*CcALD+#h*H{DVznV=BvUK%_EI};~v{n#3(c%8YN zPW=|gna4*S(zUVFpG)KBKEp;MztM9xH1@S%$eD`Q;&Xyw(QaWPcg8r)G+VfF0} z^Q@0fXN75hatMY(B0gLgxzRQCGFeTyl*2rdtG%!0V#Mp)C{_(+owJD{rPV3TZ{p9z zXiDVJ97k-$RV1Z((R_e7^{C>p^$M-R6&8gg!n>Nk25@uukGT6cC7UA z>~hXGFn6n>XvwqJlj4RlKLyv(#`m^fEopzL?eqL8qsA>>#%CRvy9hP6=a{dBgp#nN zb*(tzA>l4+WSaeR4Gm3}>G8}b0i2h?<~I=wup!?E`Etwz`*vl}JhkAR11 z#k56lP^p*&HN}L!m~>@MDts?aA=@*WqLfbzp|rI|`9dmM{hLiA5sH-l9B zIX8nNQwWJ8uY4*MxOoz2b{lCUgfH{Vias`Rh0s4Y%fcu~d8;69YK>(H)^tsm-m%iK zKUwf%@M9Aj&#bGN*!|ZJ*o8XvE|jp85r&)3b`5-GQp@ZEG8)Aom9)Al0#kK3R0N8zk*za*OY7&3x=i`ZE&_x!%AWJ5SdThN{T z7Wk_h!^`PSfivrg#8KA(CxKI@tEaGuzB z$C{(Qx(E84jWZ!~$G-93zLZ_|jPHFq(O&$~dZWM2?V^y)ul8eCbgX9U)wkfjGhZj>j(Y5U#%oo6ej7k^~$Wxmg< zlW1MK{^a&0_s8-qCj+2)sOh9Nkagn5J(5d+7KU~$?-2}d75pdp3odAJ9G@yF<9l6c z*0D2QapG*>{aeA?OGgHWkZyY z*Bx2((pV92lg{t9>yvvRu(jq`ymjQ96G?W={q;;=^vni7V)w|$R$U9+8bisu=y>J` zH)r|fpiqyrOC?L&e&;MY(e!^ZLMrUF3}V9cO|QkwhtIoSf5|f}O+rH2=S@~DeC*U%2>~D~<9onP2{gRZM>-vwzS-jZkQ!P>z9HM?Xi63)i zu^Y!UpBHf1O@dxk7^fD>)=URm2%v&&?>@M9vwLB_CRvo!^woMygYSq_Mypb6wbYBv zamnI)?gqv$;&QHeO00IU-xK%h`Tp*G(l3dj*z?cqP6j6y4QsBx)Qakv`I`+&Z{BX& zu*j)~_3IB#BebFYE3WC_Fe8lhwE6gHbgD}O$mmpoSO1GXPtJ`~*Zveo{k^-rTUZ^} zvuInhGX)zjA@Z6gUu1UT8yol_Szh**X>vt=uD?@)sdr^K<w& zuq2JNlo$46&z5M=)J`{iS?bq!!kH1nTwXV@ml#@v* z8BWJZbQc2+v);{VaPd651~O2p(0P1pom(jBWaP=yb#kpEfxuszBtEuch;cH@4?33V z&8{rQHrNM_U=g7o(E4ga3p{RbwWwvKNz5i20}sqfxXbpgiiaAsbA5~RcU@S_38&TG zrKq=2e`$`SbMT9wei3Qt*lsl}%`XRrQ?1{>kl6CMkhwnZSHys~NGtu34;qCJ-7t=z z#F`1=mN;G`bJ?`1lB04KY?WYv+{!P_&)20pY!@qYrR|wm;#{SpEFIbZ+WZ;J8u(hc zh3;4mn10Cq!JCFg=Lu(=?Xkou&u?@#_Y@0Wr0XqxIGM>H(sjC!nF$X|-YwNdIrElB zP7X$l^bbiy-q7zC&~LjpYzkjg?9lx&|N47QU~)~(#X-{NvCQBbx)P)QS$Q4m5toSUFS({}lRhq5+IXL9f zr9CP^w#cdfX04+CXRc-dBx^`ZcX|PB4-0on_6Bou1#&m?Pf9i?L@%JBqiApo$kUK& z<_^fKT(<<=JS^Ot%`K7qZkFcuHjXHMq_Z2prIVv4($yVl#qaKP%h}4B`(U7kISQ%f z;a~wId52g^j@C{JHkR&Jfei!!Hjoy*z}>q}-d7)xcayL<^s2Css4=~O7Sheh!_^Y$ zM#(KTT%9bnk?vO?TouqzfL#Up6}{c>X}beyBc)$Uj0^{*z}*J^{gZ7%M1a)u|B`1W zIT$EKkBc&lFR@5I{@^2iC%>+2n~vwT*ueGn>w~AVk86$RnS@3~MI9BV`n@v#jOKMA7>h)g!?hrlV}>4Piil1lNm`YxSGKRtC|60cc!6)fIX`eyU%-*s@rp|lZ3Sf}Sa$aDOmryZL zrqSRrQf|ps6`D#dx8b2)vIpIHY5DXnRzuK$9;WfCns9=O=b1{*(5oxEBii(_+Yjct zCuPHwS-;%<`mS*>kFbM7iA-k)8B&{CRb^-ziIw!-|^ywOiem z-EM!F@0p6dk3Qu){@_b|AN^8c)lIvMl(tmUw&uj&Kj4$Y_b+HCRuCtvc6TQt-pNLs zi9P9NiH>3sFWcO9TiCM*Q9bZbauTO0evASewTu>#$7%)?>{9Hxbge$%;P_#H0 zz%)_qd_yM~Y@oe0_73>kmm9kP40`2=m~ch?1>ePHBT`Ptsya+;(6+@k zf0wI9}B9|0cK0D(&7w`4d8xXGG`*s4NxyHpJs*rU9d7b%h64*-8 z`Pi6z`#+|`8(CaOSiAr-+q`avL}A4le_$}AphI->qlt< zKDz%z#6rWbN zFWi03^?>Oc({ol9)V--=%$H6HcUz{n@6|5(8rtl!>w=Dvzl%+OJ z$FlU8lme{>$)sz-+3l^Qx0qhP!07mbKK1WM+;n&s`n#al@4e3Z#dm#2 z>(h_=S2C$_qte4e1Pmk2UM%_@dR`*$1KT4d93~oOe3Hv;GQ>-V-e~%14burvy{`-r zPYs3~5^fW7k!veRk@qN{oJKd8bfi0!_mdyW*?GZUMZ}z?QGlsQ=JRZTaMh8E!WV)#5?+}*d@?mp z3Hz(?Fu|+W&in+r4=^df9y?^$c-A6)Ky-NkpsLD+TjO17)1rm9L(U4@tMi=(e zfrZ20LV-USF>GHNniv?$8K@@KmO0SRprC|xxq1~;F&6zjJ_tvzlVUEd z75x^VzY!RF;{=_&&>hFC& z%q!`-b1Od_?|Z}9QscK|-pR!`bN|!#(la8)TMlWA)%m;qU)nA#=Z2*4n*}QOeAFs3 zlR~JiPFAWvIKfh3h;qOS%O6FGmtgn2Sdkj2Bnhz)Yom5$|R`!T(O7>;=O*7yRw~yf>C_WW{FXwfyq%McH1;r*5^Vpkg|aCNJ^G z&*a={e&`)Vbyk<_fr@?s^k+B1kyEflhx(rdQ=jkc3~v~QUvliU$>yi+=^=l1#{I=yyp zwfQ3^oyl+S^X~y_IJ<&`C8zf684+4>dCQw0KYRPA6Ya7cm^9Vm+arAxs0+WIK8fnH zP`Jd|VR+{S-Ce$GAI;NqsOOyBEh%AGlsN zg^9Xu&Ocy=g)?ZCM@v*)y!7U-Qmm!}5mwn7q+_1>>8c{{pKqks>r|^a;fybE`SGT=f<-S+;v!6W(=BAb! z`{yA+bYRFo1xFBkHkw2&U0q#sUb|JgwkqXg2(2$MU|rO&;=8#A!EK;o^_61 z>FLWxA;h}BoTKl|+RI4Hrl@d3(MJ~JBwa0UgNeGAJb!Ato2?Lo9IZpq$e&1gh6;&( zQe@=Vy5E;0pC3K6No6DbI9pRL6MA2N{2J>`N#1YnG`!)UAFG|;e7cMz;Ooxa>oBZp zQn(V8THo-;6YE~c&@|B;U+l}558qdQ6lZ;dQi%IBE{wex_b{fy*c;JbK2MF|&4&+{ zPk8Ul6+BgOh!64zGxfiG?YmAaX_(=!-g~|;KELZ`4fQ^(N{k9mf0`6%GmTTicbcX@ z_&mW8ciCw^7-Z=d)up?6f!(hE`_)K0$J=qv_T@@{MUN+b)RV!iL~IYeFN*$vbo?cw znO0TjkhhKT-1BIV*@)^IZ3wX5b;D(^uY1exQq2xFmj1UbEiM5V{oz^kK{YNWD)>JS zF?#Kelxm#UyF4)b3s1NNEn?*Q{lpfT6DVQ;wepf5^;QWJ#q8+3RT~B=DQ&+j8kK;ee@e0;>k0IR4pB=dxTC$B^8grK3 z>F(mEs!fRb$QcG&pVa-qKgk_?1^tGWmB=4Ub@IL-%1rRciLas5A2<|r0`D;SZ@lM~ z$=~4Phn#!*G{Yo7C^5?y^!MT;8TNQ0ze-@B*3~hVyFwhHff`ru$G`d7Il(`EM(|Zq zjP(u9)5Dr*X2I3-{tx1-r4(15Yb1pAIvNPrWf<-`FYx(X#*g6i z6HHHEzh$387ac0vvAX<(ZM^H)4W*IP65(y(GYl(@Z3^4H8uyj-dmfqp6q^mC9cqXk zr44=84nE6qHLmwa`&G%zV|2^xBJbNX79`ZmkL?Jq=_tx&! zm2cr*@vAqIPrvx`_0h)|2aO^v9GvhG%$L9)lk^EZJ78SkYZ4zPcD}Q(P{~qCcJrNX z)-P_A8hzpHSl(^(yqlM(57am~t-p0IO|zai^&jqk_6m zs**{L-*@Lp?ux@Cjvor|f0eoCKMKpMGVJfai^4tFcFguE{?T0g;@8@g7rP_v?ztz- zDgu0gPoGS$GP-_)PfpCQ;Hx=rtD8MJThJ2f4Ry4BmNPSc@?2Nc_A^J0K=!_e`N7H$ zFV*HjjG;BZYyV`XB>hre5bihmlN|KFDEp=;!P;fXvW+fw*|u%lwr$&XRhMnswr$%s zr_Y_avu5W0Yuz*Z?OXdf5)qM^h5GNWqcJ_87f?u8%YO5H0embU;4-$Iwk~tETJ=zY zSB?Qt=ew_+jYi!nuxq-sfpHobzIKf8eOVOT8(W`w=e*ml=S|bpkWs>?5{sq#$b z^(W`3DjwL*?XRgcZ_0UHU7E`I;TvQQA$bQnOqSR`0HV`Q{Qra`c9#E&BsO;Te;Y|t zD&n>qY$)9)s<&o<%u~{uHrff3C|L&Um}C*f;A_R!`3a{A^M&6p4`c~Ci6k}(jcD=& zgCj50US1&72>hz1hkAu{3g|t3F#KHlYzOoPqhd_Fp016jhlnL%dJ$Ni!(xZCXs8wRG;E}&ea zQSP$K**Y%)yf!x)LJap4GMseyHX>*eO|k4cdWR>Btk?21@_SbuP5v&_>ML_h-R2-; zp+48}bSo-f#Gh}kAenD@8DM0u4-a7j+4PWk$(X1-+(AN7YQCHzOX*d7$9m1ovM6keRI_FpE}1ycPPpb zk?xO&LXvTY*IvF-RE-=werYwhi-pVYT*BS%x@)h*-x}Afr^6W;KfUe^r6e?NvT!{& z0`S%1)UFHaw9-c)u>Y7bDv+WlZ}F@wG*7nbNBpsXzrjyj`2A7wUJHVfyh#ht{JB;C z!fbdJ|8mZmFB5r;XHn%k5lO*GC`(KCF>V6_WZWP1XlezTWA*(B_7u$Fbv zZ4^b5w|PBGfDN79%j2Ed_F?MV1Jf+o;(JLqE7~o8rQmAas##oo15^B5tBJoWwXQhy z@;6B6Tt&Jg(gPv!KiA6B%NJR!z+Yru-|*gi9T;48*rxMuGYPZH7`C5v;co7Q$gns? zZBU?^vJqnJr_s#}3!`$mIZr9>?eO+`14Io5!E9T$o^cJK!OC4qSz&k_o9K!uq7CP) z#mbvd-s}rSZVOw=LVlWvugwa~HogPOx;{RQSoyu#Pm{Gqm3*#Foy^4r9&ESM%JwB! z7LjY9(x9o%cw9hrBXgRvi9hIV8E;fiixw0`^Ca%nu|&=d-*Bde=`u&r!*j#VY>5!E zLO5s;_8i^$vWJiq{R61!=@|Yis9EX%f6}9*?FJo8_sd_h8n_|9#QJI3l@n%Y9dko} zqfa_%mCvH2p0V+#TZyQ|ab7gx*XmG`(ckvThe&u91ktHkRD}psoPT=&il57b?FgwZ zNPpbGhzavXyXyD4#y$w5RM`i*+9kEtkL*+y@G^4=Iazq{?N0E0a#JkcjvS7OXP{y= zf;3%$LatSm0#!KQU;5ZBpdRrZ6?C4m9qPwOmv_!PP%%Cqq#{VpGW}mbjz3hB zxBb``PK09`l8`WwRS1EMB9Ox?Pofh|bM>p4fH;gHg zR0e=9hEj@6l!k_`bd*lK7x_y;6(co7*)!|Kr6&vVSe(Bb%&i+iLGY+Vg;R0f8kdTJ zw(u|N2eYuwiZhjT^feE!=9#RpEf0!YoHbu1!G>Gs z8D{V~s&u3$wk*Z0An#20KzvJrP^>vOaABY_QV75NEEzGZRJL|(BW|wQ#y%7MihC`{ zo}fq*XmCNWTDGdYT&yqIH;f__69{4;9}wBwD7~3xd>({e@1)JGR*CWZoV_ceO$Wsp znXaJl&bt}<>x2KW2 zw{czu!W2h4bp*LQ>+t)H(GES9tI%VRK>@Z4m!NV-b0Ub2wM`KRF)-Nx7picuW_-MW zXxx>0{t*}dP&P6$)BoGaZYV)swx14RWaka#rIn=mqUmD&P7EZ9o~RcIcM&`Y$Ww2i z9sTp!#RUd~J zjba8eO<>EqRJB*5p%r}{qi-u|I;e3Sp6uEcsLRe2Hd3mJ;F_U6owoPDS){3>1hBJ& zVoYwCT>n9A&r9*N0R$Vm4S1ymxALB>^$i7CLo-4)HywinN)U z0|}(>b5}Js!mQisH%NSU1ht!=%T+2Z{Ph6Mr4>Rm9ZfT$_05D3En*N76AUIzTv`j2jgq2&!c3988Qpp7M~$D9s|NYj zO+eH-0uTU)=;Kee>F>1=MqU1e0RPMJyy;h;L0Ks(l3KdQ1$5%gzViHqW7U#>{LySi z_N@H;0mr)vf<3z|TH-CBA(cnn8WmciTZ`BVJ1Kax)VE{&H^W&-Ilbi4fRrI#df*?K4B z6MdWU;|14N(aPE)xJFKsO?7LwrR0yLPWa+S!!y|2-E;Ywt8;tt^82DQpckmEL)|{+(?Z z^iX0CzGLOrSPYaFp6;+tKuuJ=qxr_R#X{1%P+Y!bQro_3Z@?5s7sK~269t{F{gLe1 z8@KH6lr{&j+mbjd_&wDF2FR3TLBXW<_x1+Wq`Qtr@G57`^}|;DMwz{=XHcuNTz_2VT9&>8K}RqrMCmHCUZHecOGhgG|+RS z;MNs{1qPdN{H#i3y-Cj(SylP@i|{XO?E*l|;+#Hddatf5qsUpBFI1d6_a#x23$~1F z*LY*%)vgzw+sTMuzr4=bWJTAXIk2$XMhm+AI@TE=J3pJn>nl33KHp*PX4IWjKPkvt zrI*E38Ux>MI-DM#PxLN#MaH-u5L1Q9NNqL03v}5OZ`(?VE7j!_y4j9tp6WrK}FJWfeztc z<&p?jAS(CQY49HbT)Hd<>w!lA>`WnXE~5H))b(%A<&?}tbIC-MkjSQlqNSFdZlPHe zL?;hE77-}I;5*Vvgh9d(WE#XsjAAMQk-V|KqXI$BST+$5#d998U!2gYKZ=f$y@pfb zKoSJ_pDps;b z&+?fPW9NxU`alX0P(e=MytGxox>B2FrsI$U``1;8)7O&5Jf(i)+gX}rDaPvP7iDRH zqD@QJsmyr1c#wX8X>m|gLWeX{P1cRl$z|=mu15q~e~9QM-zdjg{}^XSTd6e;o(hCY zX30V|*g?0^q&9oJG$yvt0nFy)t3UB#LB&y+U;N^ ztH-+4Wo~q4eyp+Sl4(~>2vxJrTl^Z;$&yw66TQshnyKP{lv^W>9aAK>)%7R%5)&-y zF-7I-x8D}bK2oGuFSoq)(FKy(tOmPE;&5c|lw;osq(!H88m>?A@dK>FI;>-9gR&&a z;Tf{?kxCcj?n_O3vm0KrLil;=9K}f3#arHTYS+hIv>}+=(E|WkKav6+Zn`y%xL>!me0lY&5 zc{H12ayDg+Kb2+SQ=j>*-CQ-%!B%_lPNa||<{$u=O^lWk13tbgmbew1T50Axzs~_8 z*pH=}L*0 zmkGjB7`QBN(dvb%a_l!RE15M2i1o<+-bXu0P%BR((kf1Z6y!iVRBilnJBj#QcAmH- zk!dxM-$?%Icy&GbP&&MVZmjjk>GA0^1;&(!@ZRVg zyN53yG?_yC8z>iX2Vt{Y;o+#Sr>84~tSl;1g>#$;Wm#c2;9vsGuM=MJiJu74@V`R-PY1ffYq^M!GE zmYsPWhJ;Lrfn|No`#x?%!r?gik*tzIDNmgLB8mPRih*ui9)aXec!1PyAy7@`lMh^! zwJS#yi&urLBcjg!VI7MeKq!k1buI+$iY0^6$bKQ~NPRUVy&kpRiudLjci=5oE%~*A zjSw4AB2_qIc7k@dA_z!A&cv^@T%~;G>Y^l1_pdRs!u5?+3X5>}psT8?D^|EK#G4&z z`5hEIhpbBHK<|?NiLtA@ug}39MXTwsHuF`yV;lu$yLGw)t zrl{2$+w#|u@Y;;cJ*n#+w{=^jPW+qeE^hjUp!z4&VKqIfmKUUhEQlHu66=WRvx|R6 zo~!Amtd2g+j2QKZE)oomXn~%aHp@fN;_kiqJ3%0hh<*{>H}ZmkdIN~&;`!%FDsPK> z?pl_jzLA^l2`CH0-y?9sqFs!tNqZAdd!3_()%mpzgL`v zRgMFX4|7*|HeZ~Gh9H`ol8QX|L|2U6Tei)#R8P^aaP|Bwdh|9!+RsYuFh@cj$1&kAEH=TAIc z9i^!P_@MYicna`E;0ILUOL`@iXn;N42bEa}{e<|r&8gmh$JsM%yD?z-1%>2nBe~MZ zCsB@d?F0~H(U-LdiqVUy_^0zHsuGJtEoap51IV8O0|$Zw7kbRw2=&(Lm-UDc^M98N z<7Qe1cn!Ii^q}522A1|mN%+5~iW!Q781(D)qn^XhzUaArc9d5^6OxGArR=QTivHZf zsz<#9i$Gxsn+5v)i#?DRs1+{_wYxn{#o-(hky!5h%L1wi>+y;G+^#O41l@j`a7M8a z_nnLpm6Nbc>?Ij*7fpVszG=Ikoe&|d*SIW{OGNrhezDM&b5JvAQX6QjOqqqK7?`|< z_&kq0ur=fC%J5ugh&8XBs_}_r{jW>><&e$;X4gVZGo&VGRXxa zerqRqsTp|;^R7m|?EQGop!Utv)pB{ikLjwv^DC@r>knd8Vcl5vR9AMumBFm@>c|Qj zu?#y1tnfwkxp1jbrN zlq{7#P6QGR{OF~~QqEox&CK5k$ZcS1I18sR^l(fqV^y8o&j(38(X1{2WJ*N3uS@TW5$cv&o_|sEKn}&a2o2x2Kd?QXlijV_N1Tj(`|2 zJNw*}FSy-gQqG-myGBdl*#<7$_qV4!cTqUHj~dx+!I-B)ETfiTy-u}=I2zMyDRRlq zaTFColEg6-1m|9!V`OKW0i>?wuImkuJ!)z-E$v@i4Yt!Zmq}`OI9$3?gK}%Cr7pX# zF*s{wXJNZXL;B1#FQ=syCa#uNlWy2^SyaMb!qRNfWkWiCi`h@Eby~2n;=v=?A<2m# zInFf)+Gn(1h&xT6;fm&$r2P{%{7#wTx}e!r6&-1$ znqK#X=?~KR07Y27al;S!n7PM?)~@`$(eTUEbtX-RJAc#xad=7;$Uc_tiM~zJY2M*Y>yVd}u-Tw#_(&1|~-E19#{yF@Hq~P zLgWxM-B#;}*pZ>RxKl46v6G&Nkk}m$)LLbzne43H>{kFQ;oJ{>_vBM|GTHb+aZj(1 z96g99K|$FGximf0oh8*E1nGD$9wcV7g70lm#IW6J#gVz2$;e4l=pEj%RSFj@ekLqJ_ekrIVt zrUDxlvo8(}LD|@$*T&>2vWUBS{N}78;2J>X=iz)iEvwR5hZaL#0mG&2q!qD|$+0ZS z;)QFW8vhuBxva6qSk)G^bWH3`$%-iBo62ud0NRcY(^xCVp$3g)+K}hIVFds0)i+d< z@HGzAE`KXC>b*xl#*Mfn4qWY(3CG*m7++#6C9_kMB>{Y6eY>VOgRRMNRBLsqcm!xg z#P#y=@vAa?^G#cOMl6{R1e2(ZTc7eY!1)_wjcmP55(5|4hSZ}iQLKujkXGxg844Yu z8mTRsV5UB;Yp3E61?xu|38QuoM>*hmjeNK&E5$)k{Wzv}s>MDK4sxZOOo@I)4~sdR z2ny|JFp@P;-3S-vJc8GW#m})XFB1)};B1rn*A{$n)e+AxKk5u3Uo+ajYiLn|OcTm!FG#$)R6Vv~bL}(UTm+Bu(pe94 zuBNl;&9r$s<{q88XPwKn^zIGTap4{1nN1;y7>8%_pr-FcX{N|PYV4j zi*e~)c`~-lLWUXQO`WKX-V$xsf4UC5s&%c{z|{62W`6;aOnF`n)etw4orAgR6e^fDOL$*30VZdTc9}wdA!B%v=)TimY%iQT91rSIA0{Y^bvzb z#V7nJkx(S;QzIMvj=5wLv6%-3wWzD8-|W0{QI+rz>A}NK-3l?6%^MZ%M#C)DiB+?`d}IGnAzF?_v>$O z`=3AXSlC(E{wLY_-$$%yS5Tz|?+soBBnt8b29(w_>m(;vs3@}hNJGuvHD?P#t7|tf5!{(^8xn`ncUKA3M0o@AhX8{&NU;|x*+W~wA!O#V?6Mpj{7wiG^WyZJefH5`_ zZbL^11B5}b5@GxIBMM&UV8{^_CntRKZp7UjnR|mm%x9RQY8*&jL z;F;(3lY$*j20oHQhkb3}cT83|q8(H{jEkEealFGp3W9?Nn$U)iPYBBA27vH)nqYSZ z2mu#nKNay)QF?IqCX(L}AVvrs!ncqx;8pM-GSGtn!0l2ysOQEP^P7CmuMYs62pirH zKQoRj-Pe?~95JTHc>l9b%+`-NOpKQf;PK(1h7^ln0DG2$~oHhTLJ!^*3Pw%{U_LtNK1E z)c)O9^xy+LGsyR4G~R9wan!7k03iU-&+*UiI1~t(PoSTimR;4+pV&{{hR>SMpPQJ* z>-M&YAhR-$q; zQi3_*z61lju^kU08R)ZUyVmf*fh^y|vm0{+%T|2(unaTo`;#HTC?Nmu36V|iR?0hv zK19>!4Ui#3G{hgvPF`aW`=#%-P!gyZm)Ew$eT8`dvR}|odH4zeWa5BceS=5Nd~QGc zTmWPt0teyv00bt!euS8k5010*cmT6kru_NOsR9yU0D}l4!7i^w@1pdt+Egj4Q?w}v zoNt=n&RBQ|+YoG1CG<>MJcC6Ph3-89$pey3`h5Nd+}1l1T28sWDNs9Q>{hH9dMR1V z)jvuXir{J!%SB6KQ--{z=L0D>Ud*o1v4_=UEz1eWtW-9aRxg`o`8PNxP4w+x38H_G zf~X!v)MXK|w&kB~lqUbqvGaT9|*c{ciH2HRS$1AeQl6E~cNhf?_g;q;=;Ce+N}klMZRYwt*>h$c-KnDh`YQ)HeXFQ@#!Jr)Aut8l?u1L-JQ^z8 z7}YYO^ZD~ZOLTC0NnxH1JOQbo(=>F0pUSplc8UmzDVvy|KC~hzQF$K54-vLFgzxV0 z*w{UCPlfdCdL*l{P$EZY+J}s}2owBVyuBjeT~>Au0&C^RW2)BW0igBD_GKAoU z1_qO43aet4{UegW`T3=9oi)lsZrTd=Sj7gXtZ4#AW|GH2^50#B)u9*7OHhw_3Q>-KT0*xHGnU$ zh4+QRYd;8C8R|h|U@;cmKJ7V9&JJ)gB}dZuk_-(X}g(a>K|fnu}-X0-08q@ zNFI<~s1vD2wkXsbfM=ZxTH0WR9bZ$X!YpK$0_5HzUVU;+K;aQa`^-z5Wa}}<`<1Ov zPfafG)vabgIFufgK_|J!d1bGbSDt3j{ZUsWrq-OKm=)C*c^>a%u@n6cT& zS_$FNc9Cf${A+BApj^zo!TA{E$27VnS$)w)K;~qmpuO+=z^<~_ML#t5Z6GvWO}%lS z@g{@~QGFv^UpMopsy9CIh%|wFS+*!iP6|vLKC#4e$Mu}GEY`swY;a)OQ)NVqzF_K= zJ|8V6rkPf)q~a0X!J>H!Jq$iT8>zwpXVvaNY(4Xb|6|YfXltm2ErC=Ck%-UA_`6Qx zxvjr6F1P~GRh*^SIvds||HQK6c9yGy+-X?VoatAZs>Zj_)^F}E0L)#=C*Pnquc5t) z8pg;%1r)Um4&13nz|k4OO$0zrSRYeO#M)w<8`6%8gmIrcx0Q%df)jlkU+xHOMrbiU?lP znHt+d_K^0M9YTDu|2!hw`+n)ore_I*PV`2mJ>-1&56xQxddKHVt2PCNRV%hI6W0Wh zSD*&da^w3*rrKacHP1y#9UcW%WPW?8o3 zyZGBSTca+69h?rvl{4tn?m0I^)|-J7;aFSSbfi^I`98do%&8RQ#V-ezHFuN5+b2G7 z7M;mlX*g#xyYOopyHWv*1T2X-`37g6yM>`tSZtr#0+Q(mVv&^C@ne_l>WV&bMEFWj z@#sj`T~`!bje5}a6(i*`UCqa8wnKP=*r_Wu7#oU_6_*zsdIefdCdN(gSS?>)doA)eB*B$kox%R#U|b{tT&-%& zW>d?`Q7YjFo0wPY<)jm@}evJvC_9=pgJ-vyAg%J-cFa? zy2Yv)$f329cT|IGlA|K@NwL&u4`B{}M{7d@TIlm@X>X zO~C7)ND2;JWq@i={-eJw&{Wb0R@htGTH^p~LB;7;R|fy-zmCm50KD5VkB61%jUe6c zQm-qbn9oNXX>{#W*LxqLu@p`gX!#I1oLP;s(!X|9fcCCBu~|T>Tzm(XIf z7#%MWw1UEa#Z#^?{mj)&{R?@vMZOtPT+*C5zSM)@pjzU!@qsyVGjB-jd)>k#n$WTo(IL#gCNq~q%9L{sa~udz^7%tnA3a5zCy;@p2eO^C(qS*&jf}xWb(*ePjjVSm6JyaU7aDAigMPIBVEy# z3(C!0XLYT`U$cEF=?dxmC+&FJvNPs={OxHwu;PplGkOiQH&Vw!mnh%xT7W~ntiQk^ zCMCHKxo5?oyX-c?uEl#c@Dsw{Amz^UT*J1o4|Y3dQL^R``qQX-$Q@Tl&Ypv?$th-AwDt0R=IrFB2yMC zZ+%Wy&oMb%PH^U2=Si?zUE?dm1P8gOrhhjChboa{ihZ|0u~-NqtSZI_1Yevm)hq^TnoGam-2 zLv)k9dFkts^?%oz%BO?ZEw_o|Kr^&&%%df|B!Ao{$!-^6Wqr1^>L)2$hEm7m)8Je0q15elWB3v(ivN9`qCSz&YXNJj3=YBOi9N|nLwdX*&RNYL zyhek#0z)J{^=Bc%3^tEZX4dPAYRQ_~WBe_qnfr2+=CNFgUxd4+chMxastrW3O;lv+ zbozZWg=476)HJ(l4wjRq1cs`_A~_t)k~ zt82}?C>C5nB9q*=DGSxEJ@~fxL&3!{OPyBrU5ZeYnT4QC5;=#(RQqJP?4))-ci8jz z3x<2NYwq<*_Kp5{$D{RXB{GgOTdtTI$aEzhHH|MmHd^X4ZTqpRyZ; z-CE-kwQ#}S>}PT@Mr#+p^g=xeP%d3n^o!`quzI(1d;IR6yifIc$9MWk)e@irM;#uP z1w+?*61#nzYs->xb^~1KrwcgOBX3t1yy%3Nvw?L7U0x~{k4_#5Uct5fc8-NTx`Qu? z6?Mfr&Q`YkS&}|5Xg{LHH(e`@g)ZMmZbh$zs>}DGe!Kg}g=87a^9ZH%7s%TVQl7sn ziTSG;jqC?m6V|uIVoYrVH3kGe)2nP^j@3IaQPfDJV5?d`Ji5JRZGzCouYTeIOGxL$ zYA#J>bDI)JI$~tPO-yRU9PUujR^-i+u`5d&v{!RJb%uOmq?XuJbE#lnhU*e!_4Xkc zbMMqo(%E>0)5%C8RD8K}36NM?sQU`sR2?Ub*vXS6^ppkpyVr~I3tGPI-V?9;{n=vv zT-a|t##=-yrn&5E5;k0uxuw3I+An}p6{xKqZbrYH!&@ya-J2AoQlz1h*4Ya_lV?n- z+u+QA4qB6FE<__>uf0o(=UPo>+l_C-Yiz7GPDxItVqDsSrDfSup37#FTjEfi zI~tkXt3ulf9~<7>MkqdL_=W*`#Of1ih^h2!GWaT;BTC6r3R&cYf^w}X7I|lz(JU-& zg~uTG@6y=eXf0B0Iy+K_l;uhVwY(om9~jE9L&op(1nM7A;pd!x)^w}Q>wcHo0z!6w zONDr|kdR^&kgx17Wn?i9=0lnmN>5tTTB|N@smD+)Uo`KyB^nW%opU|Nej81drF8aJHEg=( zjR0QxWXznGl!;=bHRJPHU5F#PzO`F`TNSl&_8gmSS0&9v*TRnbf$esaSZpe>CM@y{1+^TbWkHhYk)pQjxiE1{7UNgQ0o>D`XWqB>V&uRnds5 zfs*m;)XZIx7*;GnKS?;I^iV}*aaItD)%{d6YFRCFOA+%W$kgDmqUt~>KHr&nKZU!h zjHS*B%Wu)1tS~)Bp~Y#I=1pKJhH{n1%1M-mQ-*tM&*i@(NFmBzc<*bD6`3ztez;B% zc3DBzo11Mw;icsV)BeC{Ke-YkTZCT^_9Uk$PKE8$N<5WU-qU@QcYn(|ni%!QBQ_>8 z*M!1s{XpOyl(~@3=xid~oFQ;3u+cW1wb>EU&p^ElXN0qY3CXPZzI@lASn7jvP0N4C zWmxT7LUJ_h8yIm?%lkO5WUbn7HcK%Dd8>QIYw#Va8fFIK@^8N~2Nk+7( znv6vb^6mwk--as@vK0--mD}2_xMGR=tqJDkh~v6^Iu&->L-a|w=AI1~x^*zS?^lo- z%GWJDHo@(l5P~7;Xq8V_{xP*oU;bERVIvk-X5&kkX4psGFU?z%ax?LdlXKt@Pmo3> zJK4R#28&Py29GJvaM7;MtH~E$1s7Db%N<5D6h*Klsfg|zEY=3q9zKVk5OAOb`Cf%e z0LsE4y<6oc#Q{{eu%bF|^po3=!n8Wp8rOgq)ev0x=PJzAdx?)sqsOK{SIc}$T>OTo z)&lXyw<5l{3e_3&_3CbkT*^J|ZBK460@qJZkkf?N3hVn`x|p2Z_2zM-w5INq9^n81(P*O_MK6`Y8O{16cNQJ<}ymC?{;37Yd8e!70eD2rGEW9ERtpJO&Pb8NdL_pB0l6s5XT zshXOB?ZYwCt~j5uR7>7OVxI}<+=Yx}!@U~$KoN!x1GPI`8cMns4TRtFKK`x7O}#yxT|COOkA%yQlpmVBgV@t@~0oLGX3NI=lf z**`AChf0>5TNzt99g@ek18sSnt#pK3gVg?k(mj5%5-l-9DURg~mR8Jq2l-ujNX_3y zNaM9cC!n7iwEW>Z0pV^u{n3~6Tow2l$?-O@G5t$4mV0nK-}9wSgLDTqME4AxOzX-; zvi>$@)!&G>t9HT^fUs7v|F40W8Op4!^~Ho%9uQwOPRECJ2xbRYSXad~lxOD9H?s1J zP7C$geS37pHQ82ck;8;Wlu4ScC0-t;s{gHRQ2lov##cP=?fuYOG8M)PjVOxJnjMRW zoT72>vOHW>YmkSVUt&=`25>WU5jLy_@iVRJfSK{Akqg&+sn%mzT@zbYNr&d3o{UNJ%ty|^L&!9Ut zg~zKrD;CC!>gD=A;0YS^L|xJDohHJ_5g7?KmRU+pi8y`4bA)@kw@aekzW;h;)Z!&k%ULJ`)Ic)B0je ziGS_1>0oScS02k`U+^72fNYiFk^dyv{hdqwf4u|$66_fM_nJfoJQjL(#{X35{!hV< zmHzMEssH%?4Z+S0Tq$v5o<*9k@I{8t0~W8#HEug&k%$kEh))2#Y+k7Rk%a6wNTF+y zglzx{sQG*$1Vk8~?xWjv*U9&f#!gGU%Kh~pQ_DGi1_-RY zeIWM2?gK(dii_X=z=4ys33leiXK_W}$aP(}_NB)6uTFzjCN4j6lPSCA8^o5VSnGCA0UhrU?1E8@m;xh za0mE)<834A7y8C5#2fz|f!>1o$w`Qd$+iDgHm~fZw$9KTDMNMpiZ$U^j>jwVF zmpwTd(Z`Pu5Ru%^FNqBSkBW*4E-nrM803d>rblMi_PM7D3~rXU<0Cdo!;Tb$@0=Ft zbm1c-YzEiZ?gs-4r|~F6{>wL}O-~?9u9!U=|tZ$F`LHu*QEm*e`GU`sZp%fIZh#2=Y2= zxy|pEn}4^f=TfeaV-X&R#V?U-Hrrp900qD~bM0juz5Kc!2?i<7mG*{KYk5B)xG63JFhZqh4DTq++6agUJ zkggYUPx!W??nMYt;FK(gb`=p!WM-W9#x@j!Z*&VQB)}sV`m6q{fMRrG0-8Im=g5D1 ze&=GR1ps6p91xLe5}%JDzPg5hlg1($-3ydu#7UCJj$90cQRvh!^-NDAD|2NFs0m0Qa=G{3N6vw#V zN97wKd7zWhSldfRJbLE1fhon2xww_n(6xN##OgEB1g}X1*m@$ka2HnAlT!cnDKED5 zeYI%V)Y#Dr6)xkt^iN!E78 zu=#pN$={Vj#crLUi22Pqq~^4jIYy+=k*kGceMI2A+^WA={pdZT*#6M!j1>ctowAd` zG}b<;X{&aLUf)Cecy7a2HR_26=h(D#UZG!y^9a=9(#cDQ6019z+&o>8uv&&^brCWi zC?kt5nfHh~ZQKzZlTHVrqaGfhH@cdSs*y`f$<`C6hbN$<$91vJt@V#Cc36{tiIF>n zB&GFV}+GPd3RYGWFc+Z`wxBa~7epbal{zHo){?B1!Dc6j7KLh5T-qB*U1 zsH0svXpe1A1+iY2Y+qMt&V=JkNYkW|`!>fk5S4$v<@aAm#D&~xmcfFDrb;?DtkkQM z?I;mkzRHeeaMpk&qBH5v{+!sWzaDV2#CX2w^qwWR`mS}nEs_>`5@CGY|c z%y+Unw0EAs>jfjk>xEQ5i{^V#6Leb5>DJm}YiCvDJvT zg4rJI;t~90;YkWT@*Vam5aBli6(QPQ>g4%bjILxkX~0{)z7Pc(i(kTi5suBLm^)`>B_bt1WKjL5q_JE6=HI{+W(^_#qw?*LN??xtt4gp^?4u9nfna_$p zs=Uo+Js9y{je=8Y6GqOlK2z9_Du>;g{`F#X%)T~Q2lT+_q@NhjT{Kq0 z3vp#ofwv>gl_HAU6x3y((xtdB^4IPUWeJj-^~WI?g}jFoWHrB2QG&DIOQ;xR9WM?= zct#&Y;VM&AT)6crKDU!nq#2DHeJ4i5h^@QPNmt~Sg8gFLMCM|6ed9ccQVSQNGvC7t zkgX)eFZz3bRpj$bxZ-EzgH$pXV(bpXa-c=ue#8%Av!Xl?xvehpRcw>Xd3Jiii2sD$ z>P^-c7ue~ZM$TjmLSFPQ<33DMb6~#*M|i5IBg&T@)=z+GLB8a~QU$*f&D_J+vevex zrJPe_F5i$>7JJ-I3roBr^pwPFG9ZY6)mX+AQgqKsA~tX%Nk=lTRi-*wL;}rzV5JC& zHl9BSu^=b|5}WYIIwJ74|1RTy-Demg+hrdb3ty1Ydn}~>Q$7)@xE7t?TUp6`)EK|j zwmY!`4E-jCNJ^88{BzW#(b1R6NQ-LCH$u{u4HtQ&emmL&9t zcI-pCYd~BL4coLgCM-4nLRFj?`_q2^Pn|l)B=}x4@1F9P01hw1hH)!$E z?K_d;)@=&!j=#gErrGM_(X%;J{_XONLpy>YI?ktG9C%B~Ho9!C3h$$2^Tp?eF@}C2 z5kOd?ZU~2lb+i{Q+V5$viSY)6f!5D6Q&sbi8x?@oJ=W`~9LK>Tff%BZOY1?r#G z(jNn7;)*=7$E;j4UfnN}c#=Pj-*wOX0oYPNP@G$Hua=&GLmpgsZ5Y?gz$@n0LR*LG z?BlIgr=XB(dxlw{sBoaJLB@jx-Hxo>4UXXPh=ql3i|;A|IQP4am&| z57>o#R7DjRwAb-h=ywN1oV9o_5QCE&v_~(eFsvJ;<%G~*4`cxf$Y|bbqwsGyBwb{B z*Pj1_v2$7y1&Fe2*|u%lwr$(CZQHu#TefZ6wr$tkjzLUE_d`GC4`jwUE7#r?D-cp1 zuU3HEqV5K_-3rf`$j^9IKZq}>WF*{H{Q@P1qvE#)(Xzrk8Ffd{^MHDSJ+eg(e~@Gs zF5k+01ht#Du&d1)_00X+dNzpR`25nnx;(nBcdN3Eq34R5o8NqKaCXdTclqv2wL>LPmlqB>OiE|Q3ua*CA0KiAQ=^D|$lQ3gf2^9xh?^;sLKT{;pD zG>^FGf5r^VHrL7CvGL!mf#w%ETyIs@hIDIjGN|SX3sc+7*FBN}19BWR9kwM)yZw8( zLD7lsL^aNWIC=z#X!6u$uk64$J}#j}guDu3r9yc=@V%#mkM+KJT8crE zbH>7gAEF7gBYl;;+qb0$%_xi^zQaZ@8-GAf40(7=pwcpW3q(bT*bbl8r1NU?F{5Rm zUKyok`UW;YMeR~kiyUk4g{h+NF!%ZZvY=wqWh!a%>Zc>U;f_zjxN!gznVVkqn`gAU z3g|BoMJ?ZfKRfcE52m(auUqB1KZ7WRo@+Kb?@-|5v0Qg18th#sGx@^xKA86$+d#f% zpc^c0$p1p@V1?16E$nu*9D#E;lz5J&xn|_ljpQjjOO-fq6}L^?F@h>J0~gsp%Ft1j zaQyp?@pu!aY4K`6o5|`3N~4h*L&Zq@uoZ@%BfIrCpY_~BY9%|hshGJ($jATo&SO*! zRm;s**NG%HW%_fDXkqXp)oGpOgNXv1_?zy=ow0F@w~TVJO;pl;GHxu`G$LIrQF+T z%qR4a{3^E{Bj2N!qE+tKeQf+U`9R!A2fn<8T&M8Y4C|Ub6b4bWJ2^-&wD#z244*As z(L2L@318YXii&o6E)Jcz_V-9+Dp+!;dvT)>g1W^ddMo{kL_@5$qv5`z8vtT?iE_Pq zyz(S3@$aFtC-h3|jb%dZVALUlmC+-1izPGa^mR1PxVs%o<9MsdH@(wyS0ql}!8KaC z>kD)m435#CC#M)ui1kI+Z(KP(<}`wsADRr&FijppMv z;wd?C4#dS|0eLKOX*q zA-OP;D&BkMfmW0%gTvkNzJq9IYK>zc>wl-zT6NA8+sy&(uI%it*j`_(${peap*z$OcStOsYl=72?>OVOv zMbZ{vcZ(Q&!rhgRYH|_AFbRmcH*@2$PyD*hPT$MG{AxNNJ}<+XLGJMMZXyY-A`>oGL?1+*qM499Y)L5@Uf-kS5c zY$??rRHwao`Bbzyo5W;kxh}1l`51j>{KkKz;*x%p-#&Fhb?XW#BEpx%nu7RpJ>1hA z(Sn23*)@{u)A_8+IP}FpzkFC9R}#|2$#tt4N-kXkxiEPx-C@oUlOR)DYWrP#N*@Ti zr-Q-EvQA-M&1-O_*)$R5w`trjP30U9ado%Zf<`_hh-LxtXG*j7ol{d~6?tRGaH&nY zYa;{Q4VYLPifjvC1_*u`^9A%=J^!2^#&A8`m!gB&TyGpID*B}2E~e=sKth2Ukh*VR z@}W%iB~&jG9A1TyKZoUPDoGPi;+g$EYzD^s!>lXjC6fQv@nPw+YP77GIHAhes~fD~ zz}h~b8Yc?r*6_EOI0|tiyxJVp zOLKYb4uAd2R}Hpv*nRyf0g>WIh((Dj8%xz0d4TS@+vNb#PZJ z@z<||W9<%;LJn!ecqpJrwHJ{covEBS1U+`s5vHLDw{1CIG`Fw$VCVIi;HQ>zHPKW( z^52SeUe``Kn>ce}NHgK37l;?8w9%}YT8UCMmFz~-v=m67u&S)aDNyRNx*`A}b}Yq| z{QLQso7X)s6N%VO5nmr?T%$AwFWVGq6?9X&dUa$`ZoM*!pxjo4wF~7`_=A(wbqQlC z&kK7=t}j3y`_JEf`VorcFjn+L{s>Z)fk24{xt>%b5)@tg*x#F6KsL%Wvcqr6bx$3G zA2vPV<s3zz4KXM&xin>uZ5XYl^wkd^bonH zy%K*RyxOYms@KJR=tW-oqrmv(;74s>Ln0D$Q!!~{Q`VkV5>eaLRQUN0lOU?wN5Rbc zajNs}^)_>ErAL`7A=DDNmFypPnMG}iQ?X6tVdNstVya}Xt>K3MGF%sl4Ucr0_>Ish z8p77p%$`8CQo~lT82N$J^{J8Runr)TtB3Liwyd?hkF!{!C*Bg92hFlbFimm9f zBxgeKYOZ$X-}^g-+CRHOs4Gt)_ohLb5psGx39ysEvy9U6!b?^ub9kdP%NeG+#%pqq zaAK8p`G1PazoS8h8u`>nE-UxZqz__Zj|R9UbpLU?D=Tch9Nno5a z@~HkNK9_jf`a%cV#aX|GHzFPiIrj#Q#-$IK2a+XJgeGL)8ZZ(i>(ON!PWv3?)We5^ z(NA<3I3zjK6kAy2=SgMJUiU|;UBv46yRcT{M)q0@ScKahl(q9iA-|1YVuNuL|866E zJQ@N~Q;H?^uD{ywkkjfJ{>&Ur+`5|)<1!z^rofwIHADC1pD)jHpLQkNH4#@!!x|p| z_;BawD8}-l)z2b!x-i?{1Np}vQS=-x$;|`l?hy*4v5$Ohh>DHyXWF4St7TsCuG33@ z!vc-i4}I*kvWZTV9^}sZkEa0^#-n>ml@(Q7l#gY#|5%HvNZKQ4TMnKs1{ZS%1@#kJ zS77FHqytrfNIO+{<#~o=gkUdE%r14}5PD=$!ZW;8evJgnC9+ENej82uXu8@qJjb5B zYa4&kmAGqF50P8q8@4^t%eP}dXJ{vqBN@lt>zVeh5g8zg^nUV(VgXB?IWZsn_D zu0w0bcUJ#?U*_??Gx+@#mohV$l*&xwh?VMiX@+V^u(!?QCe=F*H#~H|qKEZokpFv@ zgO*Fus_<$0vGcQ}I`AaXZOVCyMm{gxG6vhM@?KwFK!)j!ljJ9qkB@^+6U|Dt@>#&C zlRfAFp@x$!7Dm~9nVc%MCGp!voD#oV)x^HWkh!rru^ac03YkIMe9%t3yMp~qk?pAw zyGu^zxO?d87_ClKyj`&|_2J=SUzqFEmW%3Zn~pU5-~7o6yy^UOw_2FRxL zVKlq_E5XPhd6U-L?(?cR74~K7G@aIaaQc(2wzw?)ug;0`$!Y>72xu|hMeDm=8d0gJArB0xw{_F|jfOGo`>m{JVkUXq8h3SM_4=LD=9b!k zGfvzbkg3`=Q|qS@eraddi@5>&a$ohNRC=u{qH+y*-{)I~g%){*8z-8H?{{moAEjls zk@m=t#iPFKt|KT`t$040Kp8fP$gO|1RUw+Dnd_u*w5-aS_B-v}a*}c64)yz7v6?Za ztFQSNCP73TKj2h2T(ASD<0U~jL5O=V5YN<5=V)d5gR^;q4)2$1NX8^fMlKypuwR%G z!403q;^jQ_iKY8IXiO#gE5Tvvv-PhH$#&R@?JUt#ZLcip?%^{0+dLVB6{jO8Z*|jA zm)1K2Kfhq&o2j~;e9+flQd_mb_2JDTT|ZLBx4M-mFP$ufnt^2tofWFYSYV|(!Fcz} zR7q`K11YL=vnol!nGnycALPxJPpE+Q3Czb#_2GK>x1v1!3j5&AP<>ZU`tXL)nkw_n zaD%B|YT{w5Qr_K}pmrc2a2jN-_oVtrX8c3j5~Vz~+HP#k?P1ET-BtSV8-l`K;i}GC z$?=%JPD%_=w`%{L*(vD(XyXTM7qwk?rL={i2}@0}YiXwC1$GB5C%OoA0WhFvWZ70Z zm8oazTBx#m9i8E8c1EVh-KO4+oq9#85ySQJ3_Eag{2n4-)oWknE2sSutEy7nLT5>y zyO*NC%>A{@>i{FX%EV*@CZJT7yYHZibW;^7L`Fj8rhjoIm>ex_ikZmCr5Kfu`$O%I zG=bDQY6ffAp$GhT3G)q zW$Q&v|7*)JM_HxLAe@ERskjrBImk6a(+J0>jl=f!zjL755BSTz5#f$nMz_t_4C$XC zWk#+Gyk6do{W{cY$coTw$%w6Nn=_)BrSD_$q< zuRU%$pFJ;wGlkFx>5XCef5CRf9S`tE75Fil1flB_sh!U0oL~E#4 zuyaTN<^QN73SlSEz&J2ubF;8C@Q){`gQg>JNO3XAn_oEa5e}h5IVuL+98l3UK^!}3 zbsro6!T=PMp!XLw=qfNb%Z8+u!rb(_e13bkRngOtD0DwyhE9l&f1s?#0-8VFZ zn*gERL4S=wIq=#8*j=Y9gMg+SJV1}(TR8p%6r`(A5r~39xIPZ3e@Q!LBhr=@;Qkpz zV3A@-?}u^-5uqBp^DDxab2|ga0PM~4>o^!xYsst2I>$1 zu`Ypc9^b8pyW~QIgaNEeP_T6&YeM@WzvF(!VQXKmJ?;J^OSlG5U5WV!0B@JCv)S*l z167C);PJnG{`&O=T@9sqK}5Is6TckC$A~uo^pXI*-dKZszf`PKViU!6g02Vye_0IU8>_FyQ$TH8D! zKfUgI?qk2QAH5A<{L8<++)8ea4sX||AJBLHZ~bu!;PJf(Qgm<#N55bgfSy^K!|IlhBu zsO-I~G!4tgK`8Wzojkk-ke*cOYoB>vi&;pk<3*e&)V13qSX~LF9^EI>xAoqfZ$5%v>71_eBCo3ffdf$I6{0Ka( zgzX!3bb`;s=P~?K42v`U`$4>0jxQxQyxS~(I^TFw^tZ>!@Pv?I)^0oxlX zYf3ihmAsO5X^962BguB=!ATM;HME%roS6AY|6+K#&Ip?cboc*MNJ z@glAV#r0z!%qw-#M~L{5(p6o6@$OS`o;Y18L7yi;O_p3O9Zo1z!#+9P^*2P=-Pf?B z&d(a-O(!_ZSZ?(H?eyY%9tu~`+cjGR6rJJVg_9eA=b+yW_S^FYZ)r_ChrwAqt==&9 z`O9*BxviUs(sJ9%rYNb==qci%k8sJh9Yjydt9{BkXY@xnF0<=LJ6Z(aBkui07)+^G zxk!q|4g9Jv*cJ)@#a{&BL?mj$GGJBR9Tmma0>_17qMHH zeSEo#15#>NX$h$Y$o{gy9+3!KNtPPcS`|JeCEeKZq7R+HmGt=ukfMd|<6^ENUa4J= zep$BN@^w7(4_#65;C&=^u-zFY;|vM^qb2BpNRYHqdg|1KOAR>-<84<%=;6kT#{kXW z)%=pIJ;Pi%mc`J>Z}f2(lX`RANh(KAh7N|;&<2H~mMiKaUo9wgrZSFWPB9xuvmqr+ zX-62=epH@V2Sb;FU*t-`hdVZrr?jKx>Msr@8rk_}uleFYRuO$LXgX%lTeM_WS3@In zWK?UM4!Uh%KUQiijRKnNE;HiD-teB#&Ih~7;7I@xwyZtN;hbD2xC%q;I^G)UvF(*M zwpi&!t&_R-Uc`=($@9;0(~F1?Et)KHF+~h<1Wu8H{c&#&%YGm7x8YVtaxdHC^zkNz`qVKlC*ev{!D>;=)GpJPGuJZ_z>wIdF1L2+>%TdZ-DUV$SWNd*FCm3U9v#|AI-S!m{EUs&5_xNgOm;?HK@cFdfYOg(+xQEQEKQ#Td^;&LuxEv$OK!;y&3xd+ zsK*euhfHLqMl|BD*O2FD7>#hMqGJg5`Zs{T>V@{JVI+~JP0h(K+cM2IH}jAsqO?N$@flPoiI z2%{@1OdlN@CP9ImW!+$k5R(!^bc&X987(!_m%@>_B7AxSce^#cmn-NfQKCYsuCW&FOUO z#$fMZ?4ixq%J=SX3HRtY?u@?lpm|zaBoi)t%W-F{4kdi z|NhpWM{G5aXDesz3(EYMMb@hk^V73k$K&5QUW#;e7GQ~pYTVznoJ>$dFNc}A@k5q2 zo$5rviY-=d0P~}K(||x4;ni=Ym3cxm3{JPdI#vVAq8+A_uZ|tFwS|1U9jq}TuU^Go zKVK46lu7#LjpI^s&|Kw`sIuJo#yyo1d5|`h9D>kS z-)|RLN!mb*obsu+~x91b|qvPjw~+`x6(%obmt?y)jCd>#C) z;z+#4>b~~Q|E<=@86nac@Qy?1ohqXjrz|B%+6?EcQa9f^Nk(HkRF_Y3;kw#(MQYBu z<%zfGmMIPGJCS>a{A|^uT)6J#_wIaSIDi|zOs@{Z*Q_3$Hqo!cZw`!&!!r@(eO_AG zjPtyMle-e-wupn?UNG6%GqQl){yfk-+TDo*fvf!;0!1;u*3>Wp`-9`-qDo(@gj>^t zKz__b53;hs)y}}H>Ut-8Ki_yYXXu>MzfghzHNcI4LBC5tA7!tA9GmZ@34tKE@&eQ@F zYr0!wGKUDt^JQQ347+I+F2c>GdM$K5TWN?%g8`x%%q7^WgK1y+FijJm!{}~&%*FWh zCYp$~s)n|P!L+!Sx=!POjMW8$VE<>%6Zp}6KOGnT7zJDqoC8UUmdz@57yANihC&?T!W6r)H&cnNQzP`=`r&{sZicw}-$#m`z_%AQ= zL1WoKctf<}G&IMJa`3s5Q0sn0MK$(EacV7RlRI7v)}^WWqn!E#MO_9h=Sw!^&EU0k zoMP|DA0sT&6TY{ggDum7NlBy|TdIy%o`51!o7J9ADw<x8?3+Wj#^g-_^dL)VWfleF<*`KiOBK#J2Ba zgm$Kk@yw6nplYk}qE>r6o)eB|#^UqyHmri|RKwvZ8{e2$a1=h*fjr*Jwa;;)TU|2Bo$$gN`j<&xL+SKF^ z2sFu7(p3|B&d2RjTPW{j$X^x-3A&xN%V51)?i1S2<)ovDTJA@CSkk71y&suY#zMbR zuV1S;gQ!svXCh?V7Zq4D>pB_ZVpOHusNK37x!y5 zlYL23tMAyg=*;5je=!D$?J3y)obCI0|1F*}EI&6nn94mE3Jw2IhDRsiz!ViCYp*2` zQ>?L}mR-73Sr`3QR(lq8{9|@Co)%%Tq0~Gxj~p5&&v~ZJ5@k3TteT_D^7BDena$d& zr_|#a8~m=Y5%$l3f}mv`PP!a2#Cg-Q=F>Zb8K^2J11cHd9fn+JqwihP0s?=S_U+h} z1p`BQw{sX4Z;7-GJ)0<&pte3@43u2P+>V?OVl)_M*5091X*>D`?q>084<-Jy2!8zi z1L$cjtny41HJEs50xDC5jTmGI>3sl-PXa!k4B}*^hCj7twqaX4&7GVyROJ^k#I7tV zpWLfyhuG3S&GMyJYj?l|iJc<(q8tz9)gJg*=aoBr^L`xQ8!{GYfs(jhH`bXOs=&GM z4wyO*bOt=yheWseW{gnLbSRW!dn$XqwAm><55I0y+>O3$T_IplP$VZi937YSPrF!8l*=Q^BWKkInBIv-h`em|q0{7c6nB-h|f zi|li~yOfRpQM<)Y3)gO1PiM~Cteb}(L^PUgi zrSEQ<7?2x-Kj&n~lRZbYFQkYAxGVs|^zZ4-6Q#sWBOz3DwhTU+S3Z}Q7jl)mgxbLy zSZpWMmF~+Cd&`NpFWH=%7MTU!i?C#Oj7QV;5+{T_spXBz-y!QqI7q;I(BYJYZKG81 z0WEj-H8wh2X_^Q=?CwSd)~k040rng!^rP#@RNIzJH(bZ~@^40Rtj-!MYA&;kbl}5ij89JD%ma|DY)oDE$k!@A$67% zWVC04W}mpvZr~{_Q{4S3U#yzMj zQ~uH1UZx9_3t-*isMj&(R)A*tG)Nz6+0P%%?=~-TM9>J@Oj+#g#Dg*iv3Rok>Uo`S zN+9*Q8P=6Xd9lqvB4Xq!8#iOp#H^I{;}0+R9A}T#>EIYDkub)%d}&v5@U?lPPls~Q z>|k_!4UIRcJMD4T-1LTVqjHwe>dL8mmj3E%ktG%alw-Ai3@L8kFU-?Dn)Qfx4vc7sgfG-5c4^aFKpbiXENwLeQJ9N?wuBIGKJl6qggvKC@D9iCwJc* zWtEGphz@bBK3xqdTN^dZ!>xE^R{U-jb8M6%FF{PWNPgw)5xIsnL4AHHR`+HWL>Rv> zX9zn5zVh@{4J91GBPj8TI4V2f zEjFiPbz=`X?~s#!t?O;^r^2~O2G=kV9?k$E!@M0fDnv;~@B1Eb^!e~mtMQ(EWqa$` zhHyO>4d}!73_>;7WiQF3Ii|GEbhahp){2)}&ktUvw3(+v9@kdF+$7XShZdP^R+wZF zN}teMkdBgvM-5%ATYF(h_m!!x3v^ZW$i`ABm7Xg5kdQPG^Oc=5K&`HH!(~^jJWukY zl1Nk{EmdPxoItE|Fu^R@=|?Vf%6eloEVuei(=lDvj|FN&YBn<|+rwz(P@pEEIZAwS z9}Fa}xXxtielS*odBOay82P@Z=t{Sj`>GsfUF(p6&A0UzXiH>^{uy3P9(0d^qR=`> z)+f%8>ltS$MC)<3mK(xpcT-<4Fb~e;T8FXchrBu&(GKC7;@Ppq{F1yQm$bNShh|;# zd0qkD2cumGkC4qOhp3S*d%M)RDkG*-IqKI%yX zWVCqmt)^Z-@Z?EtX2$$0Ltb+0`h0!hkVAB(=nARmWCPKP?#C%sc~T%P=G0*@-gZZvO_zaT`wC}UedxZjCGrO`fBbFUOTh6X60zwvLcA(M+J=a3AmSt~8&G0Ekau2;)AI8%Amn0dF^lzx<1k zF|j}nol8yBR@C}yM6X1>MJGfCj-%D~C=k{7w9{E@nkseZn<7bol)tfQrG8gR{I2_D z&J!n~cm>-rc0+fek{mznv+pT-Jp*XsScfYf9?WXRkE$$dyOYEk!x{8+=fT zUP8oYJx5pY3(00|nw)s+s3Y=a>yx1r9^mhvH&_Wt$XnaLu+5=;Xc5N2%;{$FkyM*m zJS}|%93@sUpvrhMQJt4vyMtL(Wv(v(dF`$I_7*{uMZMahsC&1)r- zau#gle3u9lRjIz*&l*s8PB^8zl7|gs8iXWMV{>s0vFJl+Z_9<>)hf!o4Xr#Kj7MX* z9@M?u)@?_-vq!RZuLEc0^iQA=rt9P4m8iZI^(zOtSzo~b_U-mLZuv4nYgG<0@Jq&N zDRj8TGEFy+QTpThaUhDaURiCgHv7ySCLnMTN+0SKJqv5gUru@y=}_f}>Zg3uA*@Hi z-|m9gr$vaQ-lDmDVwCb(Hz>$|cRe}@SeXXhEcXwKiAD@AI3MOxwzACk5n}USFP5Fu zuN4H(1dWrGP9T4j6yW6A7nw`Y>(hi0u5H`Lx?nuopH9VRS2?>OdzWk`jUk| z0Fh%=Max@R>?+v%Lq`9$R~7jxd3FUYc2y)>i-qae{w9k)ZIEcxeGcoaIDz8<_&i1` z$wn+04%7`kIa6{V6q zHg*U#sb0TN_R!*qYCH`UJ60+1c<%AcTp>G48I;*8#pdI&r_xfnvlH^1=D1KryIC77 z9zhXnKea8MZKuIrT@y;T0NC3!I9mOE0i(cUK7@V~5GFc*ijYx%vlheFkUk_DD2s4V zPZ7xr8tc^EU*h?RRB~rWEIr&ewnzm^u$gt|s`hXB;H>8gRi~aLOTn2KH}195cu&x^ zG4ih3D`FKb?YIQsZr7&cl}teq;TL+4rph;vol=)w#Zp@!*UCobTvyCVGrJBC$*GJj z-?ZO+HKj<|pakB5!dcgJi@Z9NPCf;JsWp&)(vO84`1n%S)k1o4>wd}$&r=#0C;`#O z&%}MYdho+YsToqC{PZ#ZxH~tc#NJL0g{)mkL-zx2kb`Zbbt}5wkS<0gT0H4)yf`3M%oVzs^Cg@%w)-8nsLec&7xS`nd2IZKv$*Tg-`#BkPl`BKphbtg-?5#qpPJRVee+ zjozoqyPlC9`g~70Z+z6ACH?}F{R*A@x778&hDHAeb!BG#|EVhz$NxS3XX?uQf4Ud{ z2g2vSgw_=3RXWnx;*h1eZQKRgZKQ!d7zT!^J_Z+dBA|so1W^G2F6;}iR1(Dh;OkJl zSC8}0<96ptxAjVv=j+aFocUvl z^g%-%hERgSoxYV0nlZxwEKs=Q4}Aa;5RAyqc}l>TJ_iR(!9E-)1Oy<62r1|g$@@EC z(AO8zFW>-T5&&rdI0(qx0jNcvp#i%NnrK@zJCMwM1Xwv#Swk@wG_@2Vfq; zf2ps0Yp^kQ0Kovg5Wr1=Gkg3~9*&v-VQ>ho{9eFqxC_V;0KhjW3K6szCvK;QmzfxUy@$KTWlATOJk7S_=2Zh!+_gbdyRxFG*b z)pCmmqV9w(00NjNXo!%G{@brWJOKz43uo{*T~34oqFQi(9mKEbylh&agCLhf*I)sE z#iLKulbXp1h6JLmbxauHj{TnsdB}ey%R9~6*|)PMxdsmM8MpdDxFBE+pQ1oVHv{G% z!EGJE%c(y>TYnvX=huT10TBHN1^oa80oG6fUK(8YK2dk(HbK8ODek0wNBeeHL2rQS zI*9>a!q)-soH-!z_enonfgRg(a+y})4 zx&ThT+&jqu_I{t=KgS>Jx&<6CmOk;{Zr>j$FD5Q4Fr2;(zglGl0dGL>P*VWzA|fDw zKtf300D*wMf&hN~!{0jre+hrJE1^TaRB?X!5tj|!90Jzx;oPS`;o;+ZSAxE4llK9> zxP#fg?9%%I{@FXbLHZ%PFE`SAzn=hponN~zKk6yJs~5lSf>bvOXZFmW_Mg9oU|hll zJN^I@Hwp{~y?|tU{NPofV1iq@znc|tAUn9BJX3fd?vDg^R0#A866irqu5XQ;z0Z4{ z&Tp-?OjBrZAFk{{M1=qZK!8sp-Ps$tBtUnlZQKk9YnQKPKyMy~4oA7reZ#ot@O8n& z4*swrG7x?4t^9rZ?f&i?uuvbNec$S6+U_6+H(q}6_cbBEW4-dIFfTxx2XeA~wj~2N z)B{;FlShAfJ=MbSeGN4kB@g%RbA?zs^>;?4PAGg)8v-~|&$9vHC zSCbd%N!E#5pRnlL9ll%jA-Z2#Kj|>M8E=@?Z79xG#D--|#U!KsgqS!+E-LHt3I*?{ zTlcRN%8u=l4vQd)Ih_GDw@6FXk0gfG~#=s4BGQ zIt3HCmMLj#&$l=b$(u|=37M7(;3XBA@d zur$2ZcdgY|uKS6U7IoM-W$DZirpD8;E;z(xOXcXbv;9WIA%+EO7wV)un*M0BB{EXq zg3Ca1c;AB?e+j*7Z^mEUnRYwn@3D{ldm26P6h@67mdF{)?FHp+SdtN1rGyC()|>N& z-sOaH-wk)NVIZTn{tb{ye`+W{Kl{@~+bPjm2C6M~*2e=y%5NxxuGEGt;Rcn4x~#%2 zQTS|f1l#L0$BzvL)?O`Oy|QX{vUF5DGfgyDeK70=!R@hIVsL3Etc_FD-G?&NEOS2*NG2BLVU~UwJ4XsAL^R0O6EsXWUSUOxn%IZO;XTZ zeiYxk;HTZ859|PxN=3`;O2l^^!dpsRs|tQ141kO1_4z&GO2!@{K4R5753fEJFQB^E zfm;wQEl&qX#p1mPF0j8uT)yj4A!Adz>LtSo}>9COh7TASoD$bjSfUwz(?t^=6aK7H88NTbF| z%G?3q>iJ*I`vK9QKl;S~sF95B&!-!@$BF>4fUugE0Uvuc^r{!}=j63P zb7egf^4+bUf`UN?W!WJ( z@kM%&D5Rc=s@eigc{#lm+FUd5t}YyH=F33;s7-veiwnn!^FQ7#gMabSvyEPX;kCe+ z7hmIy>YSNta)P={S%YDR?RSC48pHsl{cJU$%bCY4?NpZ(^d`ILt`z_wZ*#_sW`Mi^ zaxNv~_sKaoVOI8VWOQR_4=*z`rL~Unu@p8Ax(~?jclq8==>z?;r>XQ=*Zyr>pMwx*$eo-|v@u^aeqEu>?Fv^f;G#=uazXvR_~{bH0tWoZ0fl`&5w- zb(HIvD_-tQHOVLCP)aOsk1oaeP*+6EH>Tu&h(*+w5XQHaf{BNW(ngR$kAevhU35>* zs-7WF=A_K-*ptZG@UNCua&>9y|L4;;x1;hg80_;vE5&Y}QvbqiuJg+SavbM{k@)Jl zj`e4|YnMw847dP_V069r*E(W24tzv`RNg4?h9+K{KZtEq=0oDj{pH5-Re{=Yv$bN~ z1(BXIS5{BwUb<)aaG>Tt8R;-cdbLNY$WqmLlQ-t>M$9{_KZcZMBF+8yquy$<>~C#Z z_sIaA&tzZTjhoA9YOIGOPTc83b=y6f5X=V(F4%10ybg72d{JGsI+H{u1?uUAtI;RU~KVB-R{cBEYs$&b6Kvq4}{<8$RDy+iqL6 zp}-oTpG0Cx4wr2`*zBvX2d5r@dH6Ct+u^OVH#LoVcq8x5Bu?w*!{56jQs76>K#kVN^NV~)$UhBi)5X#13i}|~i&Kg}4dT;!}`cwSk^W=qB z!5du;HL0 zfwLZA(jk^MG43{3HbgoQ?~?TiD(VM-&s$h@FOP8K(nurmTgPUFB6QQlzAJLKVB?}8 zX?a2g)}Oa3Jjz-zJJK!r9YRbbneuxIZuAfZ77*xOI$J$Aw88yoy>=Y`FTB! z_0#Dt(H6OfE|ixKVuj0brzID);#OKK-oMOh(=SH&ynlR-q-VtY^5^l&&?ZkoeYSaB zs&*uXwjyY7SVT7GAwqb8FbiM^xXSJ+o#S6w=24Ys@M>2uPcj(OmM&LgEgY6p;1epk z2N8`-B(Z1sqE$=~jKM{q`BJDR#T0imQ4MY#aXR?e8S;C_Fysv6aI|7i+VsbSxT+&* zI1wm(YVVBCqpb2q5C4d-(WO!bq5esLGu@e3mMKk3KQFP1Scj;jRIb;g)Z&D-Ep8cC zIH7kz8fRFMabZe0RhZObY?3n;Ub$ia7a@1DH&sg6sJzl)WIXj1OoSZ8I9DTewa%Jz zKvBoH#ixOcZxVNn4rhoE;)jQ`gCcH2X$}hShvY$reVxmeW-Q*Fz)VPYG;njc(t3hA z*`@Nce5`83ZC%MAO3}gngzu;4-Zf7t!II*mrCcr!rqIV54!KFQhU+fqp%uG;x;3Nh zNiG`6)TUliGL5!tp>+E4+G1t*s(3xbu7voC50mr1peKA51F$O?n;BE~f|+FExV@t; z@Chub-Fw0-MQ-d8hwJuvN~PE?IX^$pn28K;IQnD3k%9dP&VBv|b?@wZvBqS&O^!Tkq%>ot`-OD;tu$=aVP|1#Ax~__Vwwr8!8g@zmW5-w7QI`5-gq4&Ce_`Lq}Ug zYy7vQeCm`d&*fhC8TCN!H3A)4cq%0X756GIfD?0W8ZlMPWpZ?+Zq9YZLLI?x80HbQ z69$1tsgVv@94mW11M(_MgyGs9Po`zJ3~_IU&H|}@=GLs~eGW61(>r!ez7FjqM6rgo z@Z2rhdCBwVP|%0tx0O3q8$51;@W);3usXvZf&d3g(Yu{V-H|)}axcD5ml=>wtR-6? z34{;kjMnX5e0~vk(TZQ|cUVH_k|`C*GpE@vQFS!PXH_RHGWi@W3pJqZ=sNga2aEW} zbzWES@KZ97Gv0+HutRN^Rz1q&fVRT00 zZ=gbkUxLNAs6z)}M-Mwp9Boy1CTIjg4v872LtU|JyE=JZrB|fUL^fYkQ{F|>*xn$l z&}-0N77GxH#hNxvTPXxfTyQAUCFYIka z8R_j;uf}-j+@2!Dq>2;P3%jlJ=JV&0YaV@MM_o0jr*C;{a&3^y>s{t{gD>W}VU3!g zI9GCym3vl9k;EEz!Lsg6U~Z>qV1`N)0o`J3;+RmH^I5Pe{BuKo8AeJ&ra#-u=5SEe ziA#_uNSh4d7E@YxqsxV=D0Pu9q!=arhxMB zdOmp^@mJx|`~0;K?&#d|oE4hj)>u)4I?6$u%%}1o>hu5#yV( zy)^JRL6~hK(k1Sk+BP}ZoOWtb1abTtU8ru|7sYhp?yQs8BC0{p*_~ zIQSh^`=P`J@zAb z_AJQJz*p7a0$7y>a+48hE5u&K)q}-zNO@go@mQrp-spmVx|+{bIJ_ne+#hY||D0cY z_#KT~iOEz`U73=iP`CS4Vk~WZ{O8}Xyb$+D?DpFy4^eGT8K zh+o$cK*3jN(3uRc?z71%)m5B5N-=0h9M59*n?VmYt;|uGK>j=Y zn_1Vh@j0)TE0)2vrv}qh%lkuwTr;a2@N^jhY$k8#^KO3u=%TI*QVE3!Da5kpG!|S$ z6&c#xm&ywu-oRLKD*LBv)y?Qz1L`_LT4gW|)g7?EyEjSmx6yD(F$_*G-QKv}s-dz1 zl!MrI3)R2dVz0Rum%vFiWtt3=+-z9SqI?he#n|Vnd1>>uYfFr9QwHeR*jR}DlN3vD zLfITNnWr^{^0ckorwgyUo9O}D{Am6Y%LprYyWFGP6n1zHH)jj#$rZ}z_L@84JJ#jgxddeBR`%+2)YpF&EsH0<@~7NaM1CETj3RDK4mPGE? zg6oTodq1j~OwW?RtUuWR-!E1h!`a{k%tBr%hpz2ts*#h8JOv#th5zPOuy+>(eM6P) zAE;3iuWhH?Pl^&#ur(jySKSu!NqG?mr8IOK2BYP@wfJXh)m=Uo#PO=XnS~+2P#?7& zrHs{vpq?5697H1V$md;73qKPT=!|;y7s)OOm*1ApuVWI~bToohIwdQ~KTZNOuAr>hN1<%jHMYAd zgueY_T){yQAHWQJmM#2a0D`!Sai%+K z{t%GY2}1RRPWBh%fhm`yoIG?D$<3$RC0x;m;tq_Aea5#x@x%8s)Ve$H$K3ktGhQN#`7j-kId7>|;`sVzTeLja7 z)o{J}r>1+pEa|{;vv_LJiLFw$tcnpgCD-@X9iM+*IzLZ==#YGzvL@Xxg;rt5!2U^Q zH8uW>(|Q-doPYl*bS3*^Kk#YI0-}9pcgmQzQ4ok$-6LC*z0i7WNu}C5Lf@lf#vwbn({6xxNEX z7|G#Q$HN_T$3Q3Ylh+hm?M(SjJ!;tBd8Saaf^?ChgfiCr$7x z(5PLiu&KD966F0|9Poc_5w-WuK>Xin@?lNUOh07XB96pa^????N{=EYos`?G^~KeI z#;N`q#;~gZvNJmUheyh$EyxSu@O*JvDKKLS?4qbcCIxAWc^h|Tksw_;FI+~%pYI;o z0@`Lio6^@>T9aR489`Bi6(Z2XQN-I_MDkaX)6fwD=TrYs#*V_cWq?n>_GxPK4QbKXyDuy>+|-IpH!X>oT|f;$dd+K zP*6a{YtLHI5w@!8MoA6n$jh;uj$Fg@UUD!2(&&0Z8hl0G-}B-yXyy-izbwT*3GpV6g)lf?IoH6SUVpbQ2xa-Ntju2!FSUu@-rDPF60TIys{3Z?o z1V<4BL{bpLL|0!w4U^0aQc$W$5Ck+CMMTp)UJT(Ji6rSp>;ZfGG|Ri@`=6%$3jfx* zn>xpH+j9HT-Hj7AT6B5Oj9VT#dLU9NLXraL0|K2J=mrg|n7krJYyhx8DJ3TL6$~xt z0MQHuBmx{2kQo6^Kmdb)6jXwWf@1C-hB}4IoBL7^2f+;| ztO>m^G3lQRct5-u7lDH7UN5pBut6L+0m=7mA7qN((1zgU)epqyI*K431SLj{kQb1{ zOpd%Jb_7`(2#(KyZ{Bs0LhmFkwYd39D-eB z?{ADBFN$Q=ylpQe6r4dk1d7Dc!z%`$f+S>k@6Zhgk^W4Xo^a|nF-XClud!^>DZ8zG z7~4@xOZuIj-r}xCh{*E2D-WZH!SC528rBc}A$mv$*9Pz%T5>#?NO8>su){-w-r$Jz|G{rb2#R(-ZLPt$U@FN@VY!dfJ;Xf|p*->ggw)6O3 z2}0y34_5HdcoE4iRCsD`FZB8`K4(xett&br555v0YPt>Er)Xbq5%y8F7ZrC;!1tc( zrMYw&qHeV>=g~^)6Ow7NaxPnJ9jVR|!#f(J(Zw3us86RZp2xm9rr?ev=r2Va7ecJU zl;iCKPr;%+ZSC8*KO-$ECnfNgN%+2XP^Dt?4^)Eb-pFVihxa)xYt=|=jK@8jDg)`a zLe2SR_++E|vPMUg*^8l%$8=4rd$RQ{f8_7XtLdhtc9L^j3$7h)%RZ(MpLA6v6SZt8 zQsqbGo+m^xx|S}@epLmi6z#0%#MpHMo`{|f!KHK#7Yj`+6{X3I%V0m;>De!|FinFe zTKKnNzQ!K&hGXunm$UbWoL(mvNC2^l9WKi@NmjSCnNHwQwFWcId0M;V49yd*=jAJR z$mwZPoedjLva*rzOYncpQsZ2LMIW0n>Y_M{uxA(E%Tr#MZY7t-A&SH4-6fU2%t$0r zZPc-K+!v^3Hx4Kc9JYPc5$DaLYpL8bg)Y7z+rjchLeQD7YEB_pQrR+`brfGE^cT_b zy7FHdtDS!dqV0#edzi2LG3yk^S<5c}F3c9QE$)90 zlOQwY&3X;_G*4+>YxZ=a)RQytnjfK}5dvs5s0DsRC>)E=qrl`6EpZVm0eLlk0OwQd zdat1o_#knBt3O4YdK~0=s}NfyvvrU;g)J-^e?If!7;0SqQPdd$Sp-PwczQ%y?wLP| z_|y7V1M=0>!P)f{u}-6Q<$Q-DThn~Z(4PAd(d;IL+>v=<)Pe7vl6M6>9B^eBLi;sl z(QsU9aO1i?lVd3+(ONsHWDB`e!}MVKZfu@9x*RwPA%V8)CzUlbe1or*(O79vb_;g^ zG9z0n{jn9e38=Z{1UT~CVfWX0@{9j}QCpbshUMSIbcZkS!ak-^j%hj-}4^U}uiIUXpLbOX8b_VVvSPa)7#1=m%Zq@kM+=1a}N zxM7SM+bx=L+5s*cPffViJd50~9T;w3-mVIVU}BOa!#d4-K5h9S5^5u6gjwKYl3M#5 zZnXSfo1~V(nO#pDg<)u6%UL5kfE5%@qeauud%cFQgH&~_lp+V6XTgr>Jay&85oM|N zUkk^BJ#Sg5_Wqm4eQW6YI*W#!333N>A>)Mmk3T$uu-MOa;zglyb~sf~nDral#$G0E zQ=H@{QPdpMuhG#z0h@v$FI1)Gz&a4QUjw0y#A-|}>RSgg670d!K&&?$PYj)(1H;8z z-IjNHJ}o@?`lZrHR27$=Sl4iM&BvJCXz%9t=MqzdTylowE2Hf8z(@oF;w5~eyrf0+ z#<>erZ4(!pb@a@??idtX*%o025m{lVwdc51)_k|N>E@>WC4P3qf6W(u#U9$)d}{MH zaLu&$@RVuEbBc&?_6v~D>EB;cil+|<5Sa;}Ij z(pLM69M;iMS2G;3Yo&6!y>@XlOv|pzI`=y@QbW8AQ}w!>uU?z9PFQ>kR~jEX#9@0Z z5`;tTW&^0eA|{}BOFLDY&Jr>7ta2l5e_p)t>BmnWZN{nVDLw8D!DT;4-ybN*O)~<{ zRzbB~Qs>uk+JYHdNw+)s<_vE_za)t-|6p2k9(6}>Dm#$>3~n@dy2RzeKt4L$$GpG-zb$v!Ix@Ov)}h950wI+9*T`lgUC8PS*R-pv&H_E=RL#*Res>5r^m z8BL&{iFX`(zMUHh(zngoC;A=Af&H~8^$MOTI8e8&v+WBF)tT$0gr137&)IEeIwbBA zB{bR9ZGLQbkfw~}>tEqooX9sfUABxMV(rcxJx6I5v4|ELFbaCm--?0 zq|4^R{4yiUC`B5hdw++@zj6|0(qeNcOt}Hn-hI790+S5mxbgE#AQS72*O!x$6KAsH zqyJ6G_2+&{DQc|q;%#Uyq45c9)f0MyuY2xUL<0}{_)6x&LvxSrP~6r*^K*riW`=Wo z@Si>#5|(%Jx$$|Ew^}d5C1$}sCcX8di@_`MQHgh6l==`^5$K_vce7bFU|c^*HI18(QJ%7=1nV&w1iz@utAFrJNZHnc!4A_L9NCn40dCz)`KbP-WS6l> z0<_yqL%u%CP?aj(40@%HqOUGDG>aO^Mxs!~jFlgPjj*FXGR2?T?Clxj``(O#a{TXv1Ft@`ZUmoqCWzSgbc;Res(f(7Ws4)`vmip zk6QezVRPN~%SOqf%o=62o-S-5FO6Q`-1{$eJUGP?rC_@&8Fto@pHt*@*H=-+&EH?EOWX0L~yrtPB1TTd? z*}O>7U2V$6o_Ej!9!?Je3BYRK60!)kGzi0!cS18|7gPyrH!S0^7d9Ml1?io8!H1Rb zB+M{uIS!w&V(6(Dk;`n>3B7W`R!INq>A$GcXI!t;J-}jYs(S zk*Mj__ne(7QLC6$9B}hI1w27kQ!Q6(T-_}Zn{-O2JmB1)jo_&DuF0P5Er9;+zFmAc zmFSRQdKJGl3j_I11M2+O5^e2h<9>^m~0KmouTDYzHYSQA^!&cEyT%`eg-hCy(Y@(P|sW7gW+ z8MGsFi4;qzZLAA+kSNv&vRx*nE2qUkw$@K8I;Zg+1F z?%%s6(SFk?7*6O1zsgu;pjL<;)%k<2a z^HHT*Eibi}HPKvV`%8v~)7AH2f#KEP{@UD4bpPORNYpARS-MY%nQ$sFF?%uD&6W#g z`f-No94oilmAPgZ&*{S81-U<8NQKl3?|kU>$&+R$3C>`*W)#08zHj!DNM@VVcM#bL zk$rAS;hD;F($_xJ&J-zFTmd&8ZZzg(UEA-E2KgrX)~sP|pW0iSTQTKUt|Lp&AJ~8^ zE*WoM*$;*)WF$gB$dsF8KIvS#e_ZJo+00070XAhWe#b{iI3$-NG#_)`9QM=J<=32$=j+^;Aljomu@eFHOOugL zpF5k#qmM8-xvKwPUL8(@`x{WB&gX8rg?0HQU zdi3YK>Npel#Gt9m@YxyLlDMu0?gbk6u=u>rWc!OMo?R)!9p7rEL$t*<1nGlrXg10l zIk;&|ixp%z7EaPxM0{lt?a$8hJn_-trDTAWUQ9p{@unc@= zi}csx$HDMEHFFMCW}`~BOnNA>(O;G*W2+Z4$iIh~OO!L0PrhoeLRfB#x@eUk?(Zz9 z`)<}-MpzV2DYd7N>HsiC~Nw=zSAyi_fhCR`xEKDmy)==Rmxr0Y{Z3e@R2X|7k%m^&FU6f z5|(c#Y3hEieuhRRh5kpZzWj{(!prug6vD#UZmXTB%66#k<&)i;k3RCDY zY^&3%LIiJ}n2r>173uXWSrVeU$l)3C_E;Y5(N0Yj8b`L7xpF7gp_4yn*zJnlv(cgA zqgkz;5GhGI$tDx^vl=B&l$=K7+DxUOme;6}f!W8vdEmEzW*IMv)|bcR{Uapz;!)F0 z8Gc6+PGUU3*T2FIWHv4QGiRYX=66YW4Nm8Q z)$B=QFnjvdFMR$)cCN9XG&^J3^PkDi$e=C-GFW9|{Boxe1{>8Qcb6n)4q3#AEu8SW zJ^;*QFHC>HqqwUOTS|wpU8dnO<&Ri4WtpB z=qPa5uAu|l+uPaEot@ml()&067F=+rQX3k}E~oeBOIz)3?#-uRbUhQ1L&($^1~ocn zd;n8+UU+tVd0KWgGcGbOF}eVpnc>j^iKQvEaH)~S4bU4>Lw|fcBzFcD7x1-}C``6Y zJHSN=833Y^ApkS8UwC37atsWCmFew11WT(On0y6QxzhaH+)wEdKC)l@sIOU%3m4$D zHQt;gReKeRnF3!5`D1M7>UC(y^>Z#m~5 zX1TuKlw!%l(b zcKiBY`0UE^!(J$ncez=4Z_vMH2BwzRfDDYRfrfF7jz12Nd0)MT=|8=(|G142zgiGK zw)wBW(ObV0^S>@(zk0KezQJgY^(`sPP45@zM4rwz}ies29yp7+geT`ePWP!=nBc<_-bdc2lo9^hOu1_i*nk%pce zpUrA7MboVzs_~;NLOT;9q&$Xi<=+-@X<`^w<&=L&YTkd&ieg_RdPd5h?J=?`q6y5J zK}}DO!pY@gQ34H#2Zedrx`_FxoKfz&N?>5;+oPKXivKM+29P{x1`~>3e{h&GlM)+iG8m?5#wN> zU~qPtkfkvkb=sOn)lEO2YXVpL+Azb7-v-fkk{O|QcE&k=Oc;5sZ41^rcK;kGECa_Ymq_n)`9I3$uqz$!l(r?7F>mgk1*6Kun3~?Bwe@hO zEHMy7kX40wn}5+&qmF)bqa57AKy3WsrZ1*MppZ^H=^^F2YfD1okP(MXF5@qNAbDp! zZs_|yf(G|?jY1_KvcLIMq^W#E0d>BH_qJ3sR>%;ZEFPXlslKBra1A5GWpze|*Vi|9 za_rxgL9(pd@#eqotdiw3+kZ#pXND#AHP1}OS;gV$4pnMVM4wk5B${w5d}Kl&zDrXJ zj)&^wnOAM4qn0n1Ng3ghU3hXBAgm+VwsHVZsCf(CY8Oy2qfb68vn3$SZBAR^8;Qh# z_H;8?aIf!XejVS&(=s)P%!D#XoPMxSf2b|B0l)fuC?7MDaPcd*btb7_a7s3nq_CC) zjN~rHb$+4QF!m`EWXvnH{rE15vNwBFCM(u9!koTtk$x|tMCiP&saLC)w%glfikpUb z8MprAbqYj2iE@PmpNGj3@s8_%MN-hmER?6IAcsefyYxo}50S7KCBx+qWcoL;$`EOZ zw~1Z4MM_2!A>XeM(jZ)%HOP}$HnDL7Bx1WVdU;#y24s31#Z0UbnCJqSt6=xsG2XSj z4N!*AnKTcfYiCg&w{!g=W;1m7iJ}!}Mo~HXI3+WN23sOWCSGRc7zcJMAK8|nI4~-c zvSW+vYt`y~b7b*iokpV#=K&oT3>jIeN4goaB~$XTF*aH&*5Z()T9rZ|7{VK3Db zmrG~0W`Ar94o@cR2DA#bQ{l*m{O@lGZ6z?h8xp#&mgS?5tdimI%NP-* zf*LE?*d5MFGPmTJQ)FGqq4NY9+oM2sWrm3%{k68n(m**sec!{vkQBk+_XW#+hlq{K zZsl{$vor-#D+3txd`_y+H1-lqq~7}Tg0T#)6K2lOtsQ|}Sz5+=)%k@b-cL6DeNx?{ zRL2@3Flv|UK!)VWs$cUI#pc1g-E>>}smi+4)@bu96_Xg=KX79dCbjPObETE|2>S`dl1$V&8Jv|L3 zF#=mqN%6twc8n61)8El+Yd?lKwQy$!%_OL1E2;L_I~BEI%>f+MZ!Kq@kFQeS6&Tz$ z$*Sh;CzvY2)g791umL-KEn_^6eTzWNVw8^)TZDA3hRFtQyg~B?kV}KXZNf|RRNy`v zjv6CbXLZ7BkiCi>Dg6k5eKH7SOe{H7?`m|Qfir>$C%n#Ew2 zcM&%Ilb;7)Ge<@Wv@dO5rs;osCTzSQHf?HqPyZC7v9`6tPZBx#vXU4llv~jz-FES* zX2x#k?&AruS?kcIR(m>FVxPlV$>T%8S7Z>23Wrox+#fuyo4Wh^V;~Pl2|#`y(7TqUnbK^wJR12rm(lEJ6RU{gKx;{bo}~saodD;-`QCgx_!F@q<+S4 z!JcOLLZ&c?pJaCUP)*lsxxKa%`}SNfmqFj5UY33k(X`lbCumqTW2r3|$CyhGVYUVwzaE!k-S{VOn4 zvzR@c!tf+Gb^Va=Jluop_ii(P?660JV2{e4u00M8+{kKo_I>(Rv3h~aOzWMZ==>mG zjw^Y+It|C$6l7gsVFC}qARq6c0&#I5#aB%vro%G(X7$D?#sZ|p?JD@r_KeMymU5>A zdb~}qm35SnMbHQ2_^~t|k#Nxd5rs^261blIS1b*b+bU)mhvL?u?oF57i0c7c{Qef& z{n~PJFNoid*z^q31Zb|3Lu#pE=b`Wo&zO2q8_^%%p!pLKcrSl=z#5_K>?qLuaYn`4 zGKaz{YSp@LT0l8?*Fk3bhp2wKak?0-Dm>WV$p#l2OBk+=!VU4$t*r4;WCT>}!?F1O zhYoI|Ja~jx5;Xojljh#Gylww2)uN*UC^X?-eGCJ(dshCd(czcW=c2YFF#l{+`}m zlnf!9Jdv3NTFO?wqo`Q!Br1eo2ak{yBJLpe{8{&qj$w0JvB1qTZvUvW0o<4FMi=XL z{W&cKi2m?&sk|9us=m+zZA_y$Fu4B+IBx!4eL+L}Oxh4vWcPBVOz3aB=7eoP2 zN-NWL~?Q6#3($z#=5eHxr*$^3-C7 z0HSw`^Z6?^u@oC|)Lq0(dZ<(yW|@nXqr{o(SznPbQ?*{HJ-=dy zlJCqp_{=b%6`kpc5X|(6m|*xJE!8b39Ec3hwty;3dA<=@tNv%dP(im*&DjidB-W08 z85eXtrn^Me5qMhp<|a8tna20E5bd9yc6pQOJ zx=e-1!s;x_`RK;HW8%>or_0Xg%Mmq1QB2k_11*aponBziCpXafhglNp8<2%%_SI(_ zfxce6>lB^~n%TCuiyuSuNSVwTbEr(lu@Lh0{1;ssLH9t^6p*9Z#RSTkrBBMihYE@- ztH^FSx1oK5yW-zTw6?h9LQlCkIfFj=mCe|a4oL!J9;{O<$Ga@CA`f>rX@(@4zVpDY z{v=LQXx+l4{9TQlne1GMhuXkQ=xg2(xbTK#(y*gxRDof>h`j3)GXi=kL*uo=VFAO&=0Yq24H zY$R7LjNhC9nf+7zIKY%gV8d<=AJ+~a9~2GPDdRbWeT*n(D{$f7E{C_wZ_oF;{oP+-|&${cM2FLJ>v`IE17#yy-z)^xhPNZg_ z{}lQ3f7|_5Nzu7>kxbUjjL~Ji5GtP+wES9Jo+?dXYg(WtbOwOKq}?f>(%Rp3wP?iD zfX8eObaRyiGJ$@+?SZ?eBw$W=d_$QDJsI*=S=DSo)JX^POJ4$V`<=w~3G*f=TT3QR zf@aJal8GORk>|f%mxJO+9`w+6pnTHDFWzlmkDddnHizX^^ht=FSx9gkmJAr&kRK0i z=g%mUys?daMrUHNpj!=Bg3~Vgovtx#Pkjs_PaWH8Z!;$|Iow&^-<=@@Om^d0gf4uJ z3th@;7R?nsL$ah##X+acf+^n^xMx(xr3tnU!|?Mc??RS6;h44rG{>mH(uV7%29@S|ZO8;iCd$_G5hj7{A-9I(kC zMa9O_=^EXfoljzoXao7R%SFfhqI-p&c$bsbI>gr)+A(`~ zA}d0+1(InL3Pfn;o^|s1d}Q}_c-PtKnxq!Diy$aS?d*t+9c!4ouR_+Dm-3M_&>#XJw)nhB{`H;Ko#xgbR*nnqDt!+LiGt zy@qW&D|5@MtI9%RS)7y?1M$$ziUhaZV6i4h> z)F+xz0pm~BJYX!eEJrJo`D&pN451vv%Z`vWA<7w=*Gj`)K#(U~^pU*kfjG2oKH&TQ z#!y#;o7bqJr-D^drRprc)F1qsR;FGQhwboF*sQgYtf72kU`Gd|J|+y%3JTHKg}%m- zZ<}w?WNq0;4DtOBkSmK|I~WAfi&!GU!Gr@1d3S`MKd%>!({(8QfI4{hNE!T;k)AL{EA5`Nj1sj6at*PP2pu-15~j8Ez_o=GOTem8LtMVN0Ap1LXb z%^(u7ha0^buG9VLj05H0= zOVHF=DXon&PGy=#z((po5YV+V6!m_Z_ZS6W?8c;m9+DhRQnLM$!hz#vYdl&U_8v(04TC+>d%X~hZt-`#Zg?u;hg|MwKR8p+eE8t=||Ax zcR@i59~?UcAiCE+IrveI36`EEgq`#bO!9JSF1OC)3y;8x*g_UuKFLps7nZaJ)eNU% zm7f8A;Q2XCxto_Sfbm5XKnl)+oA88)ul92%yDEcP2*R>WHbvboTbG%V?cAKn{sEC5 zm%%Mov;DA?we2D6vRG|u&*Uet?H<_c*zcVJKXd4?WkbkRSEr*a@+&J;tg#z=SAFr6 zA?T5>U-1+&OD6x`4+*#DvZ3uy+eRllrN$Xrn$h+VXbDCQS8}gNSMDo@a<@9LI zrD0d(=>r1CqNguy-;Eh+dtdykWzLyAXoJSO?*ltkb8#id!ncVxax%HL!tdp0g`iT2 zazIZRQP}EQFKsO|F%~PS{*LHj91s?-psI@J#&Ez4KUzFoF`K7C0k%%trp8VC-jaVA zxwx`yZKZiUu=FTfe5pLA$mC*oVO1G=3r&G%Wc)|_&>zCL@OIh)UbQlhrr-IIRiu-U z_9Wq5LRHliTU{9Pvi-)8_?^{HVYKj7$wChF`Y*^aDI?I8%z{RL3_W2qzQ9@Yt%V?( zKhgCuNj4pF%_LIry-(rrKPdyc0GY!2rn`$#P<*)2Hug6>LPUm}ba^c=i6IgzdqNBV*6-29Z zCm^{*R;2(jT^vrsz&8@-fa*zwzYP7whf-H^cTM%b6|yYDtdZ=49VlNkYHC+!sQF%F zv8bt_SOYDE2aAJqIl+U+8YSv1!15{DrEQb2oLhz{Ut;yJk3$Z0k4X-J)D1m^jkswT zsmFk?%jd+~pfxr7xDUdjccw>;8))fJsM-#{vss+5MfGa<n9*2OebC{>swDdOH~N{8*8x$w2d^Q}hapjg*QAdMtiGHhs$(*tqvV+A zyfmMqhfPB35u2P_uz5O5qBUO7k$97eZwdc(iP|ef7I~Ty80(_KtW%KNcC_@oB}t1Z zeeV~eCtJNybeU_L&;nDvdvMLFy54&9QUR-h=?Cc{4MBFShY)QoKR|%nc*6>s$q%9bCcwNS9wgZ!BfGoubiW6m`Az91*eu-yV#21=}v-5a*=|@q% zqF3?8sL7K?EAi-UO6^guMQ^%k4x8YC;12SQfC{67cB~!v1%!>GF0Q(}2J}*);rl8F zBS3?v|NeAuCkyP6*iSTDcsWa2f==G*cUiPp>S%LiWHC|H_|F~g$P5g!zqJh!?;bC- zpU9%RW(`bhwX3Y!ONm1KNLm41zd$@e3Muc$c$>A;-_NIVDi++-#ui=5@9jpsGInBC zjYHWoxtcBiKg?6NA_bLIO1~uWi*aEMgr;a~l6O|i3E`7AJGA=UJ5tQYN+qP}nu3NTk+qP}nw$Zm|Z_tDHAMzz9$=++JJgl|zu^At6 zVdc~CUB0X6r}{1Ank&_oerqBChpO3->r1ITJkqJLyY{2%d6Ceqhq4k}1Kup-=NJC@8e!VpgT62 z8~(V?D)uLMP+j`#9!f0hk@GimZuYmq08Xh5f*pmV-at<5e}dE#h=Gu+E5Unc!DlSz zjnVUh%v^CvjJsvqHnTOI)V;r#qvo_3UUwUQfzbTLn@4~m=}lmq5iJS2;3F)eDFd*u z)5UEEU*f7jxSell)TZAvJQZ3s3u$y|)SHN2O{VvReLmSDeOe~06ZG6Y6fAA083`&O z_0>S|eX8XVafpFh+bMYVF-J!%2un}% z+G9a9Q#b*7iuNv?i{3#|Gm%X%_UNFZ@T{ze!-GrT^yhG0tj1t3lLZY1H zdfNM!w}jQ#M=m{aI&5t{eK8`{kH*-AnL>g(f*jKiM@w zE#0&qU3HitMz5wJJvT&(I`V4;S0?es?vvRaYz~0Egwiq$V^cTtPf1e3yt<3}F0;DE zWiz0@)I_|Rds}+-D6pGUc9dUEb7SO=xHm7TpAkQ&3YLB+Qt&5(@Y$D$T&+X)u{Hie zL{>b87Q}vSU$AfS^X<)0iq^=@=irmqEI`M84vp4_fy`P+7srQDE0Ec|YDq}#AmYIs z_7wIqjb5Mu3hg`lFy^)GFd<{v35sDJ?@YgVXhvHD&FD|P8%Kj1CHc$_Riivpo@5N1 ziB_+WGCI}o$oHF@70gm=t{!A83~bG^phB~}P#+|lJmorBtBb10JVhpDz5aWic4o`& zpHEt23pWDV@z$@eZ7_E1d@)cs^Ab|0&1ngoa(zQdR#Lp7RD=kAn71Z70YW=7w7~05CrmD@?PVdktw2d`yV^P;-9hz#j-87CJ zG*MLXSGp8=Tr-%DPSV`2)T&2oN9{#t7E8}lr56LWjVs8Bp9al3a~tKy2;hxLp~&@= zPd5pAN60Wl<{vVfA!;>3lID^3xa)GF2nUT)zTn0fT8ot6pL+1B2?CwjI5jwASw)7@ zE$Vw-hSW75fcoxqQyssm^k`+2Hi&~aD2W}?yARMzebORFRx1y^^;+V(pIk@87%(W3 zDVuZ})IeP`dObI(PkG$Sle-?=*o{51YvhJIIDSNkGq4%tFEL){xgn_GJP3(C=Cc`P zBI2D<5-9h{FGu|&?yQ@Jm;H&|4DhhM8$Zs`Ln7Z%)~fmfS_4fa>@0N8>AQZw9L`6z z7w;`UAlc2k3TJ|0JuMrgY2CzIV&5P?3B-afFJ_P!U0TMcB5(17xH)s}_QQ^~0qke) z2al$}7TTh`%Xmdze~x)CQIh5AF_&E&%qV9FJ`(PiBfG>q1pNenx$siN?xTm(oHTf* zaO^|5Nn9E4^XdS+vep7lUKA#uyOmpr_1`dvG!Eh0{5de+zdrz3W`I-rDsygJYrWlL zhG2=lf~PY&j#Nk8vu5$BTW`pHK27j`(CddR01o)3L|69yaco&!JfE9=p*68C(bN^xR^D*4B*T6tDrZ%4P+BhB!F&=d4s6>u+`SYNZ_QZX6_G z=@K|>Pp8-^$bS^3ChYph@{RGHMNPIl+#x+`;q!WU`+$HA+S=N9p2oAsOb#M42pMP5 z#s>wNJnV>qStV|9f3@0N8xfrWu))wnV_uAISg%eK5Klr5YHq={AqOG9-x?9re(!En zucRW-dJt~$Y;xiUA??5^(c9C{Y1#BTO~e<-BuWj6Hmk;;_-3B=&TYWpg$1l#po(zV0X1#6jUE}3&ZqQMa$}86z>8NfVy{mPJ*NRI zGMyoNAWuvu z=2SK`EA>5Y0A&s%It+x695w!--K?zv{_e{@xU5uSBtFSqovZ0Hz_NbMj9%B!&bVg&CS&h`PGV#MFaa5gwVw=lM6HNxOV$m` zpmEK(Wk>t1=O3#J;TO=4f!g`rHsRoTZ#i$%_X_K8vT9# zXtCKsp`A+t-a3lrI+Ma}(Rq(! zD#U`Lvu;93@p9luN2hh?ecLQ|LU^wu;aYmF)3G+G!}*u$a}e~-%{(78Lv{v^7amoV z9UK}ZpJ?_FP~(7@vJ*I6kU2-C!w3AhVP7GpbN47JA+@5VWH zgChwC5(o#)2^H%J`s1?2owNpX*bW47DZZ~-1F7R|Jly@a_xZ#KE?XFA*-e-TG8p(H zU6h{>61E)`Ah*+&tORJ<{v$vgWhRd7RJ)S|Dekrckza{>Fl~( zgaPKGoUI8Z;2u6)(p+!f`f2g59v&01DoyDuSn8DO4l{@RC3`f=a8>XG%Jd~&^jbP} zQy}(IELYL!(WW~l^jpTpJA35AG+21|-vov6S)CUAOW`P+sm5+0;Op{K5S1py((ghyi#qA-*s@^a6%uGdLCkt?0}IoynqSa$nP2A=+>hEGw}huw&Qn`P9z68tq(@h&ZQ z6YSm>#2~DN#oCz(0wGE;;3%3bThK$T(PU7m;)BZ79nOnoK9??4sU3_2U%sSpCPg{5 z@f|+5_h1F2`cJYn^Ty>qz3JMG33?8Y4v^hSR$n*n8h2`wO#< zCSM2)QmlB-anTR{#d6WE)cr5?Ar6;wgi_U`RVk9p@&v%5O}NHi-r=?m9nS}^#DDPZ zF?3(1H5w@)J_SJ9<-$hzUHl}~G%9M8TG;_JQ3He7+JpwCE5PK|mCjXi@2HmLT61e^ zS`ZY!xGT>VIKhXl)m@))zUxUdJ6Hde#>0{+CIBDZT5*0~cA#C86FCPm`vzH>CvOol zc2z%l#KB6jSnKzi|J=VUS%8ToE2uL8y3=` zsWU?rXs)`;0>r_{3bqR8tMl1`SS>ogCv%nTm*&-imZ~n3n~6a*qU-7DJxJn~#db(r zD>eXazvFRc==Bl;Q!X*1OA8$7hy;DxM{vV|7-r!8W_)LNh^t55`Q+t5t7h#U79ERUUoBxm7*2%+@bdXrtYdCayD&K&fo3c@9` zGwx}e66DVD_ijk%d%BPaDp9RU8h)vK`nY(@;?Uyf%@Xt}1BCt7-nR>IJgkRKWgp$f z;St=nnSWSZjalpe5d!JN&fU_<%wjfjYJ$DG zShl;B{nz!0FmZWKhmygs;J1tiMwDrXf8~O4@Budzd#8*X*lMISE?a&shMy`KQdBNR zijP8Var{q4q@JYByd2xMfn>vi21{`L>ggIB3n(c@h+e9YR{s+^1RXvql|Y`N zc2$WpNfka^;xhSf#w)9eg(@5u!PLn&b+fR>e5A6qRgSw5s!f0=D~NYzTB+>KiOci4 zB22Auq6boub9F0fNWf`fn71JfkXF@iIQl<2TdfK6AGSpeBXzkc3HbZtQ`Pp2k?C_5 z;v35Brpb`>gzS0nNOF+wuSa@^Po55kHQhoXGHapRcf0qA?M)ws9bBtsMa%lKMN;nD z*jbylca>hKe8?UKZ94`}^^4iXfIM+|&fHkj0%cw(ii-Y%y0y(8O)`W~g$@LPwPpCd z6c48TTH{v0srul46dhg+@%!-6jt1j_gG9cr{&-I|cj(A)Aal^gEhkb$)mGUMxz^=X7Ce<;r`-sqt z?w02Nj!ue2J2&@Gd!q3(%#|^h5sMy+k)ihQ3HeH~3Ohl392qo=`WB?EyrMtIU-wLTINZ z(MmI3eXhEG@VW3e`oh9%SzMh~2e<>r=qI*cJzew)@qR}Vm>vcJkn7L(t z6&51Kj2&{Ii_Qi&=zen%Z{(eOang3^sf31>X5UKDa^6&c{2DO~?+Muh*`G&r7t-3W zq0HK+$jP^>Z>08DLDWfR+=Sb3YJ5H&tOWNn!Wu`V*uTiektJPZU)w93`mOjCbKVU> z#?AC^L@ZgAYmgxruq9A@>tg*u6WY<4Uu~c83#~d;?J0@>_)J=XjwY<^5r`1={rvp^ zW_rSfrF5LKCUNG#HH_6kiWn&49}mdxJZ%{=dzej;)S4JGZ;|AFk(q2kX9n%hAg=A8 zyg75XvQaLn8tF{4T7wHFgGV`mzyy|lW_bLxQCr4|u4x8Y^di87BL93nitT#2W*HkO#q3j#$Ss+idOGwxS+J?^ zk3SX$V^`VHDWr(~(KL)`o$li^AYSX(;}5BYc8u}I25!{O3fGE0ib-mBA0i78lbmIG zODPzn*hjUk-U=gq3B)%f(Zq;UBJ_feGE==VMYmK|kjfNylUh<=M(GO2r2fs1Q?1-~ zI#)n1qWf*IPTv5l&Yu$U41nNwwS1 zD+)zR+Ve^dQ;B}?9dMB!B*Mn}gWwUSKS?Jz?6nanjO{fI$<1^y3;Fzoj<=RG{E0R> z95tL~x=_aLNVQ-}n1_s~asQ>%rFox#w#uK>Kj_-tVNf>GhF9&wiiVi+3?@uvj zV>5oJok6hwpOb^(m(C>`VQ7__hJofYOPeZXrl5@eQq*g- z69jxN@1hzCzqX?}u(>}Sq_*j<3#5{ASRGToDLVs|agK}sz8|9B7qXT>)cJeSgvpZq zGn91sFluY`#nkjsCY47GOmfe)px=3Km>|dBXQsEWrpc>ydWt#w>JB49YHfobCVmw} z4s22|ThX71udXHwvq0s`uKmHFcvDt8@iO#_`$ev!2vGgak?_S$b=TmcQv6hptZmwF za0_O@fkV4%y#f&Qj_ZAQJteyt$8K)64{UtHwbCX*Z4SAc4GJA%kG^7iF%v6PsK||W zRf0$j$c1ysqgo@IxFjNeQTNKTZ?_Y?>_*{Mf3sZxo;E)`n7-`W;9K|%$0*>2G3Qh} z4q}aCzmF^Cn=ZvqSI&;F!9osWe^0ZPtm4#te>7hm z{HLY=F|Bld7&S^kQ7lS8(S-L?slUq&=0AW@3y_4h?Z+!O3p*_A$QY9XnX4tvm!gpw z$w`i^2=0^ORcE#L{^oQ$e!eX(gEB8twMk9$THCeRjaI|AtasImmT^lHnbPw!|63-M z`ZA(>9So7vrjk$8aWBis_PBSeN*nPvc4zsPzJNOP_)f)+2W8ifSqpXlZUSTbAlKdW zZ+4&=b`1u=V7io&$!qz69vye4e&9R2_xIL1cZ(By!MmWfTVNmHbDp(!2jQGhi zO)`@G+fQwT7Jc_2`U3P+K^_@Ob=gGd2Ww$}KZZJwH@LgeF=qKO`^m1D-*PQEb<=j6NxW{sq0g957(!lK-$01K@knPQBt`31 z>xV+KP12@`a;Dv?SBNVP2rGD^3ZBzngXvu~^DX62D073em9}@*Hv=9`PIDE708FdN z(?B{9b&Mga`<_J4U`S1s!NrwZub&G*isiRNCu}`eq}eZm(7cd)+z!>DTR^RivX!5r zQU1h-7WHWpgEcI4_NbZ#WUpqS?>^Y-i5*U zkkaI$d40JUa9;$%DM#_PiHsQs*tKg>k-P|Thc1h;bK#fztydx|ioTw%kJksX*LU&M zX`T6I1OhKc5?5&0*-A0mulQBac$tqRAzkNcr={U=;V~AdZ`Z@?w}fh4icgfXVFM${ z)oVq2=kgxWPQ#G&GW?xYxyGFAcuH(vxL5UV3XEL_r~O3&o*2d;gbc%`sDlVib0CYe z=Y~8~Hlrk2sYvCbnUGTUOYXk7FkGzev~llwkCP&xT-=?c>cya3$4;Z+vpdDD=*k7g z!$l@%Oih}y+U%V^3Tzht6hP3y&hQiw!EUpxd0rLBkhsTpRX{`7xTOdj#SzD6=HADv z%&|b_x_Z?5HTTk6`)s?RfErkTB>*1ns2yw2livKLg$K#f3RTa&$$Wi)yW#}?O~`zP z1)^|0Wo=8igGRcCRYJ=p(_vIjc^2~N?H9b-V|btjbTf3y`-)iO$=Om@+g_1U zrJeZjDMRza`8i$|b~lcts#zQ04`GGEx`4^Dk^EsXK&91pL*%ovqP+!Q&i@$kl zkqPo-Ql=^K0mBE`_8Zy!1)O@CdDT79^O-G7u{o;PiJ@_#UJ^j8e@%<&Rg%N$5+pK@ z&-^FF+DKWL8c{Utuyhr}CTI}ygE63;Az+IFwFpYre(3-&fx0-Ovix`iAnTKTF>oo5 z^6|2aIJQims$cS4r7TZ_2t*ZAWKbLe!Y6Oj@FaPhBb%xg2q_tv;3iiA5)S2N9#~To zC+aP|wb#8dU^b((2eqE*uVnt_b_vri8fFGn$NKy2n>`p3V&2(D!?TlB>Wd}GXW%2@ z8P7z~&)DmfKl&A$?UA62Dt2)`YBqu8JJ=yw?`gAU5ImrkrGVT1@508{*rxy!CtN|| zZTB0u?CHgFPy{bIauudmYZ$@V?mW&~H^5@UK4*7a_U*Fd>^SGYP`WjPURw`4O?9f@ z??LI(?!t9xd)_+QkF?ARS z<6 zbEZ<~VD0&K?Onoz1N*~mz)sFT0FZS4YCKUhi>iiCwv%DEvSZIz&^lfjMIaZh@bpoLE_aK=v#pfNSaIgm8XC-d2Qn}#%>(NZ0+ z7R;indLsv^js+l@bKoAf7QRIGj}oy>KfSY0WUA2wtw~hI6SlTz4k4H8eQf~pqH)l8 zoziaCG9hq&j#7DlT=c2S=%)+CKjtoX41)XwWfP1&jHgs5v_1mH38Ufp;@X#gOvHo3 zqty?}TX5aY$FXg_sb)qY{w`l-hYJck!vpcXI7+6vDv0>E4_fP9&K6xy3?l1rv*u{> z7WWfF_kppJzV#4|(o2s%CYbucdysT$*OlU6j;@x&wzxcO!le94$f@`n^b(&`onajV zicyW%U8fgJ?gJO!rR6YK&-9}OJU1NIHRt!v$-g}hG8@NGy&&h!HV#AtUw5+_lhE7! zQHx=$x*m&jdd0ZCj2iz%MbRxJee$Rk+Bb)JBRo;N=ntW70^hK_cY+``%j;N;MH=|B z6zKNFh`KR-52d}Zh19+9S>w={nlj7Vi{welybDxTI;@LVm&`vuFfr6t@a;ogy61aC z-*4-vsx6>I2+K-CgnS{Se$rOKmg3zAznEP5mB=Jgj8#iT`D`_gXze4&P4eT+On zp!*u)c{4;^X>Z*hY*dj(@4Uy&J`w&{t!W-Ne8!y&N+ z9>>ZnTx_uHf3sgs1f&H9-?9x9$UdYW2gDc0!DaX{qg z$fgTWFicgv1W2H_ua^4>nc4ly;4#tHG@rhpdZl(>y_m$hLSsrL#c3_^q+RU_I>%_f zJk-a>o6^Vjqkq4$3o-q?mO~K59&&1xygj8sJe|N8Nk@ve%BwoCGaIh?L+vy|M*l*Rp!tV6soSKH7L28G$Rk^% zUf?mnZ622l)Gu6krTJ7e$Af-A6*Fn0W*N=BlUiq=fqPQF6opz80$6!-iwAp%3-u@o z>jd?ZHd2$LDGOlx-1`A+Hi8uVuWCLU{r{}yGyWe)E(gQ^Zsv1vu(JQZ zA-QfQ%2}H!G&eWER9iTKU~X=!6@MZCLXi6dL-%eliN)<G4ymB*R-!_d&Me5HEDKaE#Q~Ir~_U=A08baAb^&*p!)3kCpx0Uh{dF`a#h zA+>>{4`c5J2t+Vzp-+dub{rcCwD-r=DX^`R&kqRy27rsr%53csT3;Su2;=Mw@Iz>C z-4^OQGA=un*84Xj7vz z0K5O@W|n?-&9CIKmKX51+RF+JP3*R}A>U8r8x0J63g^mvGNgaA&u{naZ?Ni}z4KC?tEaAi?=E`ZBazWHw7ahvfTcel zTy)stZ?fSvu*1`jAIUe<2K*PB7DgG-SuU?h+Vi7$QTBC?$^QPq`zE-9n!kI1fF?Zp z9In3A^&59>@72c)eqAQf5XM*4r5+K8{lmlE*I=m`9AJ;@50U@gE^QstS?*JA@kb~62@$*+IB8>paw--;-j={2r zmje*b)>aP4&*cN3+js71uPg39$0!g3>S-Q-J$%?x6|_2xh3#&5*7+)}?oiJwEy=TI z2uOg++>HOz9ZbAqrF`oHlNY%9<-^hd6dRmr_69BgOZbMkmyrTKY!t znplc|;31rJ zWh9a9sFgoa*}J>_SW=Ul)AW~3U2kpcBXql0X5hCFHfLcPOS#_!pbg{H=EQXa?pwI` ztLPYrtl!)}Bb$jr3Kif}JB!kGi(@hkeq?7@_d>XpQ%lFi$AARSF#a01=E!-6y6k45 zr(K2WJWBcbW~&Be+sB*qhT;*|_ghV7+AMuhT|eF`I+7rF;1&PB6l! zeHOELu5vf<0hkZ*8?e#{RFI|37YK`QZ^QW3-#>osS36;7$q*b7RuP{0UtsQsTxq&5^a*4TvN; z<(*|-?_V`*$jz3Ab`pR(*g((GjV)rxjm&74&lYL|ot`BE4=jFgI9BiI+$YitBv@XI zGQ>c%HS9U`>W)!nySso@Fp#x2P10nBY&GEZDWgQ=jQ1-xf*A=O+B2KXl8=DCNQ2Lf z{4_mx95g?8pP|**>J4$Qu5@+ykr>6|5?VW}(5`Tf2;!eZ8q}B&MHLP>8Jbt}&O=3$ zaXg+5S=2hylpi-!0TrWCVNhNIaD(*%=QtaQo?_a`qe(}PBoNn%OPq_m2_(NzN6%0z z@6Th9v%BbRK{qoB+=BQg+fkGVnWt9CTVLFBuk(mNKlUWZ z!nbf_V#XaR zW%f#&P#=dyZhTTfyAa$fM{^Wg;_X*iBg+(#tiIluwOQ7UFtVqazbJTeb&b9n!rp#) zrnwil?;P{bWyjkB>V5RlK~YQDpK3QjAX_G*RpO|bjOJb8n zF0eU(+qAtJZRAckfI!8kY>0V(sqg&yC>Xn?(Q!HM014485pbSEsNF1uol?@CJo zp?4C@>b)!I3GoEZF5O|>L74^H<_)JqHiECWIxq)UwTSbUh%x{iW{z_C&2>Zc@s3<~ zGOsrn5!O0Vv)B{?#l$f?BaM{Cp=QUxuE^^Ed|#|7!9eAkCdUc9IFmY(WEW|PeuVlz z((M8(hV+f`Rgq>s{5f5*xdFV{=*C8eeAJAanDCd2c09D3JF2^8g!@u`Bu52N6o%(w zdxUcQFEbUM{LQu`YnHr7%QMjh4)AlBK{!$0pjN2eusxN+YhJSj*x_D$J+`Q& zVk5)2&9E*s*7{OPel$0jc92+C-zv%lhcd*5&GEsV zm*E1sB~FyYVi=R`kUNk)({31V7u1>R!btNGuvBf#ZX8|->{TEqn=b5YwF?j5nScr^ zii2SvHdq9e$08ME>;70gwY92h(a!Jyxuj{#K&#r>m*$^!>biM9sUJNFf+C*tg2-M| zSI&4zmW=U-;7pv7@65Y_Snl0IIh)o70Hxf&mMp>)Ohg--W)U6Ce(J%Ho$t)4C!ugA z-VEN9lMK2|3F(TyH))36{4k?gsc=nR!LbFcYnTxwx7W!660ze;lTa~pE|+mX)nKhl zy6E)-)~Qz%6h4d(({DM=Z!Ga`{Cp+#Rgji}uB{Ao12LTDx`1hUN8-d;V#nfc)tpa>M}}H16fiSSy;+C3 zTc{mRdz!x=u*Ixl^!ze;LEyV})5d-PJ{Y{NPcLOY+c2ia=Gdpquf+8}<6bI}f4mk0 z10d(Fmq9&|ohwr>HpctN+~)I0zxdCHSUipdF7`r_>*u^^OI8%VN*k)UC`w~%>4A5q z`GkV4HM#`cafb#BWLOLhCRx!4fQqDG;8IKm`yPB2W5UaJOCi0OuB0UGRC!yc&aLD` z-2;~&7bGc`&NDhBm?W&)V5&>t>U+v`u$aIEo}b_^yxp%Uxeo7dwm3+~ggPX#oBk6qJ$H7iv5viTDPSh0b3J z>ZC1IZmCz1P*0rz#^6zk#JLIYZj;&*q}I?l0VzIGf9TC0me(V6?WpsIi^2=-jG`3n z98g3j({x;vM6j7puBTLJtzgnSDa!HGh~gUD%-b!ghxs1T47`A5C&VJkQs4qUh}BcL zbu{}lb13LRI?F>ddy63FSZbehdiapf*b3wi4HR{Eq0_B&v1ISX1JnA(Q1p4=X=neI z%8+n6!|H-N-B7t}jb?9)+~J*F_rLRXPD^o+!A(7OTP|oUPQ`e|IOXZ-!ryO9{=SZA z>~<=H{;>d#8{~-7WN38laiHsj2pc_>t26^FH7b(>r6JuOO1Et20*~lr)*On=0 z)DJeoJHxV0*|9do;ZBgG@}+uxt0nlTJYFimZ|EzSx$RfnrMsuvkVqkkCPlyb+!*jIkaw~u@t zP4723DGT3tV<3B9LO@}EVC7Ez71c1Aa`l3+TK`RX#(;nO?HZQk9D#9Ri>@D$!$y-T zR$ACgnX8?6*Sp8BjwLLAoK4INdfCW2*^X9V?MHm=7=M~1!&qp%46WeZc0RGf71SsZwQEa-4V*qX8)R9%i(X$TImL{f zIn1oK&@ki;@Rp!?MzZmdL{8XVKQ_c4w2K08^AeN6Yk?gVdjgT^EZ=PL30BE znL_KBJ<@uX{s9Su*3~qmMHggOEC1)U(s&MgXlFHbeJ-vAfla-@<;sQOK#%k*JD;25 zJdWwSPcFzVUtq&yM|fwjApahN_h^f1pSqEE(%^|E>jd*To=TC?Qd&sbh6J5}UIMwi zMI}yClj?f3bs}54k`kEHBQns%;Fz*(i2qtPxJgxzvpMWt;%E$+`_UrvB&YV5VDc(p z4yM7NqZ{}VMSJPFcQ(y%*!SL=C1BlCz&mQ`RFyNQ_GmO>|BL(GD0rF2aO#CJk+_tigF?AhsN(f-MQ(q5PNwZzDM_* z?&o}V_s@#uQqpl$Q{cH?VMQxkK65u!Wnu|{o&2uPTn%*i*iUk(O_IkoUjG%Xm=0tChhiY^t9m&{kH-7{Vb9&nlAXms?*16GpWCZz{#jj9_J^JMDyt6&pCGpP$?2bF|@h{sfO8by`@N1v=O8a58Zs?~<+d2(H>j-gjjME6J*D4IQ36v=Q||l}e^_X?9f=Nwm;&0;d2Sxj8Ci zwP(cORz5U)&gW9YvJ_B>lNY(px&mO8s;N`QpJ5?gN)<3GkO(s>DitzFW7PY4Oqkr0 zn>u0KuV;gL#f*cV_LFr`Amnd0Y+y8gOMPsuw>aR4wi|$EA4_R6jHO&qCTV?Ht&U~d zB_K^WU(o zK~v&gGV&EUb%1n#4)h(4P#MkPV>i#Ym*DuUi;`~N9=p)+%Ot(#%|NG~Ekz4sHTQdu z4e~e(yaNMbI2(FDohNIlR&H2bwr$0x8M$@N#@5OWK4%>~*s>mjO$2%jU01!aymo?X z*|1+ZqlyaB9uuCC?#RGX%Fybbp0Va)qq?Y29&b2D7T2s0JuoAz)DU@>EAuIs%= zqsLb>P7>)gBzS4to{xUjPhfUVYdBe}(OS_3 zGn->)yB}T12h)DIR{-}dVZ9xa_qX20r+Lyv-mwoAi3Y@QLFIfBpEo2_7`jLZ$x*$c6GobLrE?<79{;i3-B_VM>H=uaS$9( zP+6KdsMzCX+U_8QW!Z|q;9eUcC zMpIM@G|7Lizf}ciC0B@w!-|vg`|zmnEgxurnlJ$aQs3hJriHZ!P`c>xeaf5snD8{r z-@Dg{F>2CiAGT|Y76K+Yw0Bn?l$w=VW-Z;fspzvVYay6O_EL^7{`9F(Ec~t%E3{q` zObqU69l+QsD}m0)1@%ohJ$J#V&wQl4{+5EoKwJ(^o8{q2t-~N>c?9qio225KU%}(V4(#&* zI`vT8L;RP&SG*pG@qnP0xWU){SBYxO3G~Jm@4tZpqf_kav2O;~g9gHVCak)2z;?<; zvZvnIbv;_qosR@l)-kQq9oL{H08o>kGtKZTc}pJi5mw5EGnbkwe8`@sv0Q~o`SkAU z0+>H8S95S9>|E5N6FTO|tdL`DU9tgz9&}@MWfR>3KYO!|jZuMeYxavP2!5y|jMiRn zN^^(78>e;UqqV>{)L74i{hi=52{H6T>M-o7QnmJ?`u!?ZM$Ckf+m2y_mK&kqa@60^ zcFEr0x36&47SRBHaAd;bg>z`Tx6;vtCgwl_U;V2VU<2$W3?lo_TH}DCSJRjqxBc-O zXYv!6`Q6lRw5O5;<@U={qC22+m1%J6r7i`=U5)3I+@mHq9paG_knkf3d~yFZKSI#3 z=(WjXf`DrW*L>NP@q`$3f$79kdYJ}YojUOIcV4IJZwc2XBHn`gB&jz--Ef#6lU7^r zI;9FoQ$EF^@LDWk*Z$g`xuLBsH%WQE=i9_Xo9uMH3g;@Xwx$4Tb7{_4M8w`}M(&k% zI&4u$lc8KWsC?1(BNFRu8p`hw^PJA<`}AXs-}fjO^F@m!#OzVE`Uouqf%PaI>v*@P zd>96sd;Me&O@FEg+GDpncTOhw7<5Alx$qP+6VBoI5ZfwuyBytY8gHrO4s`e5N)N^J z4#b=&Yrzx^CyasfKZO~&Dd*1?2pgO#1yCBn5C^zmHnqi6B1nc=Xfqb)M!?`juG|qe zC-_N5Mb}E+!3>l&5$%e%L%Xiig#qAmkn@j;#vcRNU8Ilo)8Vr$Y}gs6i5B1$zH?9p zAa;vrUGi)iXs{`$jhoiECtd40t#*0p>yb2oX<~C}THb7rr+*v-{4`}xp?7&9!l+q~ zwdA6YM!8V6c$#!-yXmRt$bO4k+hz8LDi1mTP9~UdQ2JH@nU=WDEFbKB5x5zL;=dB1 zwC6S5!3t~tzLPjmlYQPyB$9Jz%Cy81Ce~k+xae=p2C8+!tdoifGU_-7rlXP%q8yO- zd2^PZHUF$09;~KODYJ~b7FmeXlvcRvcGsA2cAKy_b%e4}*)m8UqzCGfjgb~)x&rSw zh6PZ8x|QeucXyR$u-2<0`*w?`)gUSRk|ryX78eF1T5?|U$sn@P25DuA{AA~gBL?4B z5q^)UOGPAK?Q5OVX;t~cZ31zkB!kK{^c&He)fJ*=Oc|cR0Xj7{0-Z5;_7*^eAeO!e zn#97@H9M^5AY(e9w-xs)j@Rl`B)Au>HoSxRB_h8MD?Yu^8kSqy10X=e%_sHwh&T1Y z5u7Xn`nC|UI_E^uD42k5FOrQNF@yw5&A72ESSVkLQwiFuh&`~`ro2DGcy)aW{t-v7 z&n4F|u}}<}$mZS0f`}^Yy<;nR&i%dN=CpF?Tbhp>S}tWhTCZ;*IC6P$NS<`!k-*b5 zv@@02k55SsJB@eVa&=VLEcW{|?c?JCzkn>weV&*6lfG%UWq726eg&k3$PtSMVnK{S zerM>3GblC{lc9$xg^a|x$y;Iw%*He8q$wJK*|wws5iX<)@=Th==2S*&Qd_cUU_ePD zXV-ybXNyd~RlSZ*T&RN=W}iealKcs~2a}~C|C&YoA+0k!THpc=b=hoe1TsLt+&5uG z89kOkm~?;Fb^5S1!M1|ffl;5tR)tE0Nl2d2Au zIg&SuthclJ;_U7j6w)}sn<|BIyusXkB~pXF6+5M{)@I&UQ`6PrOe(6Ra`F9=Ob3Eu zDM-}dG#;8b@8vvkseg2t^a5|G4b#daC zCwY)^ZqF`o7x+0m$GZ00Ok zevumfhB96?+sl48dWJS!t4F03irTbvd5kF!sSXeN5*7`L*nW>^tgc3jylyuCb(L*n z8<*-kyj@?oLhP%bqQJ^DGO!Ef5JFhjtM&DHL%}5G*9H{KBo7h;>ig1lZyk!iZ%p6e zn<4l44J&)RJJJ%3W1b4Mv?*z*s}BTSJ}7BMt#oBvDn7TR7RQCughkCekHPfifaE`n zokNgd;hIFtwz}-wA{j?|AY1{LFAuO0 zk|S;(CmvLH^tpq1ds}mVt6eE>u_crW=j|Bv`|#+00Vv$On*;h$)~8aJS6J^o(7m>L zgsd56vSwDVf4=B~G6p-rI}BStW4ufAlnpR!%4~V|Q26X>7o=A381THg zy1np+bGFaB(5MCoSXH-x0(9Zetk>FvI+Yb&JaL&lsC#k%F(`fX%G@py;RXM9cX5rd z?{l$`7S;(_j7)TmBW{zBiQErQZaEExz7?mQXU?Z4T3Apm7{f#wPYEwyE<*GGK<0{TO{0>gekzrM3aHlH zaONfw5H%Jya~7RobSmhO!mBo8J9LPA#>4oV#Y+Y`66FaGBWlrysg%izq0#}W1^|rqRJ~J3eKf2MoN|B*4LsIThBro{v3m2Q zTa(vnIqC-kBIfafrW00cME$F&t2O7PBVzWJjJpYi9kVAu@cWSlY#HRQGO!fNECe>3 zsBW&}CoS&?W1e2~%sL{F5}&{A*z8Z8Y^X(9%jW%XJr#8hR1AOryhOiW;T!hi3G^TQ zJueYJ$j68)O=MoU>V}C|{Inl#UpQt8-N(f| zNP{VL;*4+$!bnu^u@!LYEw*<@;F148vo1q%gp#qPe@(`ISL1hJg>QW1BSs8fVM7&l zk7m5RP%^|Niq+vMEZ(!tWCem0RyajvFbINfNUP8glvgHS3qv%`7*!77mFwwSuRIR{X*9|`Pb1`<;~1BTEB3n2+`ji2*GOzw7783cPbE3MOnRXmjqqf_0bU^c$H ziYbT5^?gnDf|927Ty|Kopwzmb{NUHDjRU>R2Bl^DGA7XH5X-W0+3K^4A+K{q;~n)S zQe~G2loS>>6<6c3eVUE~ml!!SEK0AWrFwVG1mYvQ?KJz5`)|?Zsug? zfbah{8?#jv!T{2W-l563k#MhQF3od5`egdKIciy6{d}bx3GBMlkm^&G!52R*NIEcX z)?aMl&2*F%Ic-E^cE(<#omW<>yx4ycM{^0`65qY;pN_-+H)MMr1k5boa5qK-`1BCB;8?ziTeDa$3QJBq~w?BihI(C&-Ke5+_c-l z(WaEM7Rww1f%lkMR?4_)Nq>U^Y9H8fXV@~X`qAh7(&SzxRIYjh31knmqGU$Z>P(Fb zPS>V7_GF%Xb8}Ku5r1^KX!K1A*S#rF?r91F&qGcu5E<8r@fs>|gEqe403Ew>Z*CX^ zv`MC>pJx6a#Rpopra@O(Fi}Clr~d2*1jcbB;-7TZf+w1`IoH(1I$WM= z^|gi)LrcW7vi`2+9)4k4Iuj9}l?@Jh{U=>Ke$ItFX@SX7uayGCSkGQU==3bHC(`*X z1S{8-UmUR5hio5Wsy?${__j!Q&yw-znd$Mo@BEza>9DJaTJ4wP*TR@(;mhEu0p2(O zF&~U1!x;k~$(tZdMC^2Fm>AD7$0a!z(aDP5d;X zb`SMyQx%_xVr|0>89oVRkjWoczQVUD+xYwJ3(x~MH2fcnb`1ZqXvawRzczY$Hf9#q z|M~ns4jgtSdWQd}1E;Fh(5YCv^)L3Oi;G&l^(M<}jJ2}WW{WkJa=juwMS0ml(Lrs_ z>-A#k=zGVnQ!d^s`fEnp-ttvhM zXiH86J}q@&RTXheKBDR($T%=|KP{t&du)u}SQsr`QORUj<)Y>|4gF3 zjsC3}oHtn@-($3xUx~5t;rrU)Z{2NOI#f|rR#nG8mZYqGyJZwe3coXp(-TYAxob5m zzRLijk-aH=qK>b=68|JPv{Sm(ndQxalzp&A$1k!}j0gZ`*B3^n7vHQex^$#}E`5vl zZ!E6$-g7bN0JQj0N@(~v<0>z8(|Xr_olbc#LB430GdbAT-G3)H?{!sv8Nn@CRpYWj zk%1^TchgR6d<``?WV1@3&IyMJwuepF+AQYF9sTT@Tjl+>A>olyS0 z3;6aL1Nf!QPy*-I>j{m_wveckmdtMj|8f%SCj^b4=oU{m6|NqC|6 zo{EX~H^mpaTD!Qan~x9GlGTyYFSvYrH|JZj<{SW|eNCOy@5kY@wgm`XU0v-bQf6>s zV{2s}4~gx!8i*a>*AmqC{6qC;is3=xg2UnIHxu-eRxr6YaIa+l`iZsmS3bIc=*}1S z#~%^d@d@aSp~2xE0Dav}?RTfQ7xKQr-s^ie=<5%{rEdhtg6 z=WOD>uYbG~oh!%>BgchJ30z%}kIujLItK5ZQPz(_?Q zyKkAaiA;(nkxlN81&b7X)f2T(QY|$MV+)#m+lfXUeteH&Tjj$!?pcxfAXQ|Bl^V6HLlZAno)gG9~ zSy&toFJMl@F3KwJbrjX|^ybiU&+r%U$8g|gvkOV9U?(oO@Zw_Vo%3>b(gT4Hd?NE@ zLiW&uBFa~su+cIV|IVYU5Ssy)rg;Mb@Hy)}J1l!)$&T{+qjL@3pJ@TF^cMEZuKSg+ z(Q5k2g>;nSEKa;L4JJZ{!bx_IeQ`bvYBby?DrN0z^nP}mn7=^!6ygL)=O+M(ozp?tMo#C8Qe38S63`tH_q6g8qgUQxMPP zE#rtP?x=2V=4&@x6h{?4t{~)c=A#djpY!lb;=tqyYga@nw{vEvg_!OpWtqP^_cYueE`T~+pMFNVV1w#Y2h!68;>`@u9ylG5{PJg=#t z5yUt_7kQBVrAaW4vZwK1U^}KQ-`NQXJ20dI!dwwx|na$4}v&OJ&RO$~-if(c(^SJdI7wES<&e zx;X5n777<@OzQ3JZ;`dF9lOFhNIG1_vyK~KrhVp+;M(i;>a49ZJuH+)f&x;)>j?By zhsafG`%4?>-4&R zFqa8%y*@i5WwCvIQCv;*x&ldUCEC9=D^9yD|kV&~6vQ)~x!oPE6~T`kdMMYY~W(F&yuRVjvf+txrp zegNx^!Rd}oa>lPYo^puk?It+$1`b3##lr^bgDSS2{B{V!XLbMNqg4aLxYH%V9hM*> z49$&W_8Ju6#?^zZUzK^YPdc?SKXvz^%MEMPJ?vt^WnwQgzDqysNCCxXUu*BK2M5%i z%8?Feg(cQ;Q%v~?n-8&{ZQ^)yA2Q(Xv2oICjM7HNrOH6!21Yfz!A)DOkC|dW%yRJ> z?c_CS^ERFW?bpY8Mk_v7;dcU&6zg(sTsh_Ra+Wr<<(*j6bpQ#Pq7?C!>c?&Ie%&8Y zqMy@54AXQKNi)B15T`Jk&nS`kl)0f%aG6w>Rb%ieMYN*?1ty#ie+!$^mPOhk-wOqr z-PSC`_D~uuy-?H{RdG=QDd3qTAQX6;gfM;07cF7fI$UI1#4~f)+RDH2F|4Ye;Mmb0=S7%0o=wf`(~Qlz^hOc}e?K zJ251%q)aqg2eblHr>5MOl+EozkmVuyJVVkni9v164~@l?Gwu^iO75OHx<0V-s7Pp2 zzk#L>OkULwOiSr}qrr;>zvV-HJTKZO@K1x}ith;bGa{mAGKit(OnV((eet2vs@4;B zCC;OP^%kBn*slI@+xzo<4&X96R4F120=PYQDE9jBzG-`w-Rh1s3wFhQkcrW z_EaTA-Bpm1=Yfg8n*`gq4rz^fIBoL>|AruS!rx)jAsd2KSyKwQRVNNyhUa_4$2=75ZV|Zd$QnD)&%n#XSsInbY$HK-zs+ z4@aJj&#JzF^Xm*_5^}tZq0Qkc#P;hQ7VA+08BR^3%!GxvY15z0`a7F|dTv|i*p=xb z_WOtU3wVhI4DN<<65xhqovxr9H<3U1NB1%;M$Le6A2*t``vHc5AQC<8gHhCWO*J+W zVdeN$;R}6G4eMRypJC|GCratx@@3CE_0SG@;a?jgu5?{EoxemZwS~izEuPJcUEX4U z`i3QCy;mGgK7oSh^XU7fCY>Qr)bE0_c!5;2hW6aZ;AmN{r<>vwYy8{p{~B{q+MZqV>tRsf0rO$gtXXrt7XzSwEi-Vb zuvC;@!pqUnuJ!Tko9v9a)(!&_&55a3|z6ZXMN?c zP}{&<@-~Kk_taID^EF+z; z2@vTs!B291ze!&qh4hF4xEDLx%a$x>63J+@j2>=6CmbXec({XRvtKAPbA1dnm`z7P z&H;w8dDLbg=MUe50gj({x*c1kAKK?yQXM05PW^!Q33tXpoaqGYhK1bzCtfF2?xYQ( zahkI8P72atdyd!9z=Nk5Z&OE{ZUKIE96DxviXQKrVhN>-DA6YUhK3fncu;3E8xBkn z7OeZz0%1=Z;{v7Bm1x5wNwop5{77&t9|~1JY)*5c<5HyKxQg9VtgFUk#P|L050(4? z>kZWZA%0+y)sUx+d0DLT0bIH1OdxhP=29XMhCZwiJ1)Bv$vFIklU(2DB+;pS71H}o zoy(m91vz>fC8+0rH^&uKHBvz+R8Hg6qmz>9v?sVJKpW1nyZSlI4z7|bUJ@osn=$p( zBUN=r!{%F4r6b25*xwc}Er<||M=kSNY6P5U+4;xn@ELT8Rr@$pNR)gGMI5P;7)9EO zIs6kTkQ8X0{LHl|U#oS1k5a;ctP=x)z)?=Q4ptm0{Rth&Uho9iLY>ZCZVZ6Ar^TCz z2PIuepe|ExhpO+9EEHQ@o_GuN^ekMAFL7(~-d#ggQJfw(Oc#79&MN1a0euKWpW49^ zxXYSF$cf@X2^dS}smIBLw2jCnKLPyK{w%g!TH1W=oV3y2FYo=Tt%l5|tVCtMBA9J{ z$$~|eGTs?N5&4%&_j&NdYdq#*Z6>(?GkJ$}S5ZdOUW%JYX+VS@5X}=Z?9=KwNbV6A z)49r1zcbrAA#ZSu3kJczg6%@K3*=7V)aKG-$R6AwZ?uv)4g=V4ru})nnp6xAf`Emp zM^)K4LwyTC9$-D^``6 zmaVJgdU^EpSNf5f0w~|1bSi{0BQNF*7xYw=8Jv*EN5zW(+Hn}vYT1BQjYHzO6xtv3 znm8l6GZTCD<%)4xn?RW@bE*@4EKPCy>WC|# z+2{eO76X%q7GWN?W`1kQ>FHXDki2OwX83cv663O~v~6Rn`544ktfw{K17hZ2CY& zXH}SMa-_Z_d(=RE1*{O0HqNM&k!CAj*F(-m*DYgWq#7G9Eb4f|z@c;V1px2H-UAAQ zTl+^yWP-(nH127j86_gxOdPHgAbe_muFR&no#wu4i^m;h8YHhT5ZI5$Y5-1{b$tML zJl=oqtR@spA!AdDpDIOf_iTcKt`Of#P0pDJi6wyUIL}Mx{N<{em`4LnG^EsQsia3@hJwzCFNNy6J@(s~l!iZK)| zcvy!sR9va*=U7V0MO-N~!T5#qJjq9-D<|97#!;$0GLpBBNH;Cs=C*NW-(ObmYpCkX z(uSVdbiRAo={Pzd!58^+_S9mN!~o*5UXjVwt{hx!*tXQ`N`?v@BF%Cpbj#fW72QEB z3zqOsFa<4gC7bvPy8jcx&LmsyMep#wf?mbDfZ%vi;QUZ}a&+AvdP;XwkFzc*M=3u$ z$H*)XSUwq6lYlHaY!%xj{yHq&!LLM$xE)HsIjQisJbV!N9g0(~r^c~eM+pv^dSRbY zhPp|firQ-t=sJ2R_MIOc4{TV)tJU5c-$w9U8})-V57*vP5PWrJAV;>r}wW|$c+y0aMQy%P&k>qqCl>H+7Xgg zlSUuVwp!2&46Vya+Gdx1jrIf(3+AJU>*fi=L+EH}I@!Ik$!{g;qKKVdWmq|h__>G| zA-SjNF@S~0_=hU-aNcrY7nxx)f%M6(YSgUPO=z^7%T5Hq1J|#|9RL*F^ZdT2BZLw9 z5M6V-GC5k;3O~zh_JBq`jBfuA4F50dL-{q}IuHj`wkT%q8dbS#*5Tq5HM~#v&BNH- zoW8x%NzLZS$DC9<=LbV@NfGTtkN(QY$TAS+>DohC5Uo?#dTBrh8-wJR3ko>kx|?S< zCOzwG1;@5eTM%@b%VR?6rf!T4D7X)csivCcypqS{3_hj7Y@gcU*ADJ4kB>IXK2Q(W zpg5|=ZPT2)(rDR<@`%1Q8lzLBC*u;Yyw3=WLB(l`=c;9~;aW z==LhyorsUy!Xbn+w@r=6w53Eh;8)Hon0CF=lnhez_%olkP;Ebbn@G*|l8n#CzpDFO zIasm`8Mc!ZP*8MuqU*qfMW(G<_njXTI<;w6CGr%6+82?3G!R{or!tSE_LZ`?8jc-u z8B3;0R6sPuLW9U%>8FAr*EU$1*6oZ$VK5e(;O8d592K`dCzxViJ#stO^WW&K($?*w z(Mn}X*0^h}xTj^F3zo56ZHfpvkHghZ=!=_H8{7edqK-nnA+#nO6!H4{5j5ZISwVqT zRLq6A#e!|Y3u0QY2?p#QEv%?L^NX;F&#n)#i0hW1ar>VRQ>D`h4-H z5Gi5);C{dTWtz#JPrnKyq)lFECs%c9?;w!m<_7Y~@pmnmdiboHqQu~|D|o{^V!!Kg z(5?!(bol+qBzdV&GG+i~!}q5Hs0>~m<}0<$L9AuS$M*>vdM-XGD%I8g3k5COY*m_- z;V!HmMUF4+9d?1}fCSo$B5Es;X8nU?^MHc^l`?&2E{qq*n-}ZwI+r^PWxE3=fBw?m zkk&iug>SWIcIojT)cX*%&E!Yy;ej9c*drC2z~o}(_=_A3z@M_x)LQ83-L48=s4-l; zi*@wZZ5ulFBMb693*Vviaq)w0_*hQ-EuSWUWo0A5OMf^ZCH^E7U7q_dHxenX{KF>& z$(TbpsQGs^hkFXIqiiz`)Qg}S6@HF(eh<=ym3UL;KEbzkOClPSpQ&;bY)a5*Fb)x- z`vtR)qRdOY@3%h(g;{66TesDGZW(Wf5Aw-JzwT92O!hD$1ED{lKbWk549VDi83Z-h z$esM9mPHuAu$337{mH<+^rr51P=e?V&f>rUzW0^FrUQugmJHC#DsF)HKlf^`<3S&B* z7_GVO$gd}7@YAwjy7S7KqSSVB1mU5{%W;15d4dGorN=&6+he6U@~0!Rp)oTVQCZl> zzo4KH^8Jz%z1;&%IbsVd>Uarnn1f{YZ`qfczh*~TV+XTWR8u-So?L64wjky|Z@M%z?%&N&p(A3#`x_M@Ft70$H}BVHA}qlo zx=t^{Ul>`4e8!Mn3fhFJpP35bE*(Qu_R#xmH#L| zLlYf)P$IT|g`1k9SK(kr(9ZdBpUr1BkFKDH^n6j&?oOfo2DCuYOwEmF^c|@F4!taK zGVbE#aAE`z)^^bd6ixxmL~Oc{W(4W8kN` zX7m9WpcMoB>ja`b;at26%?g2QplZ!Xa`sMM6~R2uKTnyQCUfDbg9i!F3spb;jn5dR zv`CIj#)LFEk@l5KO(hoT5Z}wnJFClhODR+>=V`OBy$gQh51unD$LvgxnEPJGi|V4E zKyOtUCaMqxqjAIuQ9t@h(4l?#DxIxR7Gr8L0VFp`WV$F?Sud@Ap<$RX)<_DcdF4&Y ziP^x#8l9*6C8NLF0cl+j_%`+x8F%?&Irt`qE&*p2fBpkRE)rh@VMw#7Qw{RRV&{(| zy0@kZ6+?7n6Gt$`;^|E_Onmg+)4qGDnIz3ji4$%;>P6-J9#G(*Ya*#gmLdEqDAlW% zwCfomO=u$l)nD-YMEaw5Ftl>LQ=Bd}6$grQTVQOye0%L$34GuAahmkOr6^+k%IlHeb~rKqsY z-e;cTZE#vgj`0&WRL6%<2p|j;Hb?Ws!MXrV;XS4#jms#8i1&#F8A46D%DP?m=H)91 zsjKfp%@C7&OP>2e8}oh;mXD-Q*r&5D-4hP?P0P(*OVXPS4j4s`5Ry$kCAVeDv$@>g zp9ABzNS|LXz}2Lz>I(|kOyHCv`@pCK_hKOAzYoN&{%FR@bkdtlq>$_hf_BHpqEA}L%az;1 z7AI$CVkDW6vtU6uQR4ho&x^u_vc`pT>Qsx@aNxY6@_edWGFd*OQ`RRA4}%Sc5|+0u z#9pp4`91F$K5V01QsXz0v{*RVb?biP7u9Y&g%c}%+YQKroiA^V-~*{6*bO37$Rgu4 z)?osXA=Xzn0`rx9^*#9?J^8^w(jkf?XRNE%)|jqRE7ha7*uFtrg_j?hJMvNVm_>v4 zfn~(K_?915Q$#d1@u)W4cvy?qD{gvB1dwZdAPGid$hS*f-%{#TZI*Nj^r8)}+#8WD zNYEa2P5iTejgxfBEewLO*of8P+6wpYGbHCDXAw;qeUL6KgoH|z>u$#WQ13c@F&L&W z1OF5ag48Mr%@b)%Z%)m$3coq2|T?WPdF@^gLWuYHY1%dzjz-& z+GaM@O4h-@Na#vQ{k2LhmafLVN(6=cgo!p|giLko&=eGgKp^Z$WJ< zadw46rqwliNAB^#EeQNr=R*X&C%GqWwot+JqQG|i1NhJ)ER4Wnzsg8(t<YXti9zC_;RQkD-81ov!xiFMznZyXHo;V0Y_Kx%!)&FtLO7i8L%Rcq;B?uljTAi8Ha#sf{9TS2$0a=a5UL+ zJ|1NZ-{$@Is!-sP4c=Tn-GgLb5i>N)X)$wV4;r@|V=VZ~q(Hkh1zcsK7?(Hf4(sbeDPV0M2VXtWth4wmV zs3GyWgUD`+W78UJzao>^d2vv6QHtVRqT{kr3j)V zV;=!Uz71R^w`H8<;FYj+NN#{&oWl|?(Yd?nO7M|4q(=KF^K~W7P})~?OgZ(3U&!DH zY!SCxgE9-=%1```U_-no>!nv)i2e%}k3)Ss@I+@yHrnPcAuqOohUcGwGF4H@!Q}jx z%?}ILL5Gv2yLM$}`^9bys!|`N2NR??wB$PP7aZkvqjH4eP2dM|o+&kabvX?BhG8R} zT1G#~h-vtE3o=j(uX<4~BbTA&mZsY>KP=d=-m9BVE6j3=;(p4S(pN%g;x-T9DU8x* z&=&$nAc^?1+!UZZK-p+5gB6`gMTq&|^cCz7?B4NLW6x;xQ1IC}a%n2BxZA56&E|@3 z-|l7OFkd~WwdGsdBLzD|~YwX>^P`Ex#M&T$!HAXUW0Z-I9I|E6xkLtc8Y0WXph5J0cwm8_% z_``P{iEc>W4sGI_rc#WEjk+>XTa+~(dsWJIDj7v(8vF(}Ph~9jczRMCMTk77)>oJn zb(NKEkh{47y7~S;gkQoW#?BxJ{-+>nmF!Z-s*~7IX7UEJMT&ZSUOr+lK$JveH1cA{ ztoBNE{!s*>WrHD5G9uaz7kzKzA79_mpc_8o(!2`}z5z=xnbN7(&|?ARffyZ3@_@JH zU0C^S?XmK^_ire9I__D+sim%}o_!i`Z<m{_6ffsi{~e?>Px-h-|%0smdN zxb9Sw-|5!`xG8dviS9)bq9niCz1QNd{B;Pq&tu;AaXa_yal6VafsUs8qBC(Ig2h}& zj@e4^WC%^K^^gbO+?eJ9MA@6@{UOVfQovgr23cVaS=MMuKl_Yxk*~4`yraow`)A%s zx|ncml;@$*tjzPKU5U1qf64Y9dRr?(`}WRTGj_4kqc=lolM2LnK~=JtnLfBq`1Gax zNuI>?L{FsWI*%rLJl<+TshJO2u#Yjgqsxp(ZX-f%mRi1+H#*oPEwhnShbuO+ds@=v zwd&84vdHgE8ttCS@wY3}h_jP0dx36+@ai|{!o8%m=1sN%?Q&*)@IvGvK$O4Eo+7thm30(xl z3qn?Eg9a*;s!MaY7N{(UfHWL!;m{E@@WaqYMtPUc@x)r!Gyzaa{J-h9E~0{YlbR5V z_}-L*#kweIN)eHkX~9XB8Ed7molFlmPY7IaPcM8gQtmlv%=7#DQzH|We{VNHdg*N6 zz0HE_8E0ph@-@2A^sxb533B`b+2$p#1u4?8Z`>amduw_CHJLf*6p9&W26fqChb`rV zBVi2H7Z&lj1ijj#Gk*)RAGa#7ORT^Lgd36f+KcI>(Sz+Eb-<4hi|*%Mgv*6<+NLd* zo0<9pVm*)!C}@BI%KegoK(l*ocRy=sfUCBu1V+hZDwmbuk*EP`cwnBnIX=xfcGv^ zyB%VR2`q*GS{KOQ^`D9CYaxUmBBIH}HtI|G@{ymkO7Joj>hUhk=n;%E-q@neU%g#1 zM6(afL_v#&p-TPm$s(3{9zou1Ou`WF%9=qBg}5vzP9G85;7M~T9p_jrj)Z$$e<|We z_^SPYbW?%bpKt3Ksao;%J@LIn5j|z=zAbaGSts`wC!Lsjy!>OyyzmCU9nny}*Pq7tH(`Hgt=^<$9;s9!f1x>7PDGDB z7;$aM9`>4fzNg4$|7E@;apEru>f7f|V(9&Z2~H7w@AoA;(pZD=9Rl9%T1=0EW0$-- zu6^w4Es>pG96V+gtTUHaRjMtk z!E{fIXQmJNPTi?}0O(VZs>v%Vf@l4=x?zJkEnvJfZje{9okyg+Z*2dni(9R#HRc@L zbF2&)yC(z`FX}pWYrz~!)SYhURY_-hd0PGYxm^80*u7rG2f5HJx=R0>db6TaMVEXU|jrDlsk!6Kgf+1CwZ0rwrxZR zRCt^=@#s_ck{GO5F4L39rcI#aPnZBtV56@(@g!~Hp_0~ulJ%8IhUL1AxfyWCWEu|O zE^HG*crJDM$XWR878RIT!fuCRUI&pxT9lLqL$5ZKm7gH+F&pisGSDe~q;1!Lw)hgg zaF4LG;Y9z*yR33eI0AdVbnjnGr>!a?Qlw91fgxx2shy&REIsL~r*j3xR3)#Gl_T5% z@5Zdf8Imif;VQrIJ*VBU8inCmNSg}Hkn5rf+zKrJbNwU zZg6|tV}EOtn-f<86cOo`i385+j>FrrKwbFJoje+@< zOM*5Ef_Da6IiMS!AUKy{bxBReCn7Ug{;X75Mubmp7!(7lK13wNt?X&cU}pFw%q(c? zqLk~@{tm_1a8m@MNj`TFYk@}k&@+VI)i`%5`TDSU+pc@{PXr!>rnn?~jl zXJ&+{VFimyb5G8KWDlzAd8F-{@<+dD4ceWEp?S()uvml1Sh9m|czVp)s8q5(iAKwG zDp^(Hkf;a9))qVj=Gdj44l~Y#H->6;!oWXK75USpSiC8uPqcVf!04@D7K2DLm-$~z zX=yPhSQ2h#8fkY$W9W29uQ>{EMryv7X11U;nrFr5jU1W{r(iu>hBCS>bW!b7Iqu-b z(Z)*LXfh*j5|eM`>l#wffyhTR`i<)fl8Bb zery7E{E-~(Fn0?L_rJ~v2E(3{Y8At|8`OxH`wmC`2ULGssE2-|7b7u3+ zsXM=$TW)i=nZ{K7F6Zq{vVqR zsSyvLfL!j5PEG*tzzl+Yhz~9xf&HQx{V3BG)mC_2yocz};t*(pkGw;}rxg5I$o@&Ax4<%&AU!>{H zXdXr|O?le1qrz_otwn+kRo8UCefngIl-dKZx61Xd=ggA59N&8?(P{0E9uk33h>o56 zZ}<$ZJT$oyy;u3CJGV`X^z27bVl>Z6>y*%6_&1|uL*R8j`3JxZ%dtd1-~ zSzM)}`g2|GWfvW0Xt1+}yqE6?7HWQS)ZT6IA0%)myr^Q>={V_QtHmKSyLrs@GJ1r8 zEnRsvc)HmcGccR{LzyoE`*IOTm9|2g*$4lr4_K>&ht%JIih)P=+)3P8Z7g}zhUGbJ zgz2V(>V*A}v$6uO7%N*-K8fG)mRK39{4Efm*&2#)D53584Z z(27c%DugN~D{(F27r!RL>zx;w0ekQt+fK@wD@*+_e|6^%JhjqjlecZAs%U-RW_)du zHf$NN5cmv@MDH*oz7UG_Um8wcxOzdutwt+PyjCv?z^Hddz2wHKXXjAZ7R^X~JeS`f zTlGBdqQrB(LaB9;%+_KSn9)LKXXl*igRoJWW%=m}9<854TrnGcR}LSJqlFFf_#N!0 z+JHI7)3YsKjQAAt_(WFUa0u&rSCvaZq-!z>vVV3`v&W|O(n6>b@>r=J1!A0-Sg}8m zemAGIZdVq>Q{+t@EVmJ`CONpWb{u)DIj%Ya&$Pqv8_O^t44%TP@@vJ%_GBBfPCKf< z^e}ZlN$H~9Gx$gS#nE79^NIM=1cHn0`INU}Xg5OY^C;4U0@c1jd!Vs*0SKi@4qG>1 zA|Bt3XQN?GJUVR8qhVwoyAzzulr=7XVjG(ETQ=U6IgHJOHJNa^RO&Gd?Lr5wfEyJ-@Nu~3x z6IbTVq{_hC*>M}g?Z@GP)rID>xW=DHARGVlg)DO?Q?yEvub^(s=u!>c*9XazGpE4B zHIIb5k9Dd*!FMiohhIU6C)umF=(^!pcj6`aG=C|qHUCjs(86XGDDi_t^|_W%N^`4c zK3b26MQ%|!9Qw*0wV_-#Ajln>YsgTQA0}QOC#0+3Pd5OGHXILcgrA+h!r?amNcP);d=uI{3J`JMv9`+H$NW9v*p% z0*3xZFwc(AIdr{_#7XULeeFg{0%mMG*Q5t%%Bd5k+Lf>VIc3WjIPVhEUgJP>)qcL2 zn%k8f)z|{eGAGMen|KZg0F$=?sV%h3ByT8r&~npbY1vCgX<44r!~ZtB+n}qTdcE(O zCjz%!nwn&PBt1@qXWeKyV$NK3~*MpNWk)%DmOFV`E!-LoIrS z%-FH}UL_rXOt!KVME$f;q4nOs0Y$vJ?K?THt5n??FaGTSFb|@8)V7Q+qYMCdmG?na zGSBw9T`>pLNLy6k*(YV($-^_?MM0>>sWK3Y;DCDTQWR_A2qm{`nU$s9?5Y8(dk5Xd zO~p@~2biqX9tCy%aSHsc)}um2&i~(73zm8bHpKjliz%!~O7V)>Qv7pqzcO8g!R`i` zG}#e$i2Qt@t~)$)Yx+cbsJ%wUfRfIVsccYs^V&NaJ5zy}j>`nqSdW6e9EiV{1yzNQ zl5~Voh)yN7Rm5-}`HMx42|{?3LRj5WGoWOgzSCL);?x2n#p#SWS;Cyadp8Lw)cml; z#fa2&zt|H}W@f#S4;trN`I$G$A(5Uv&k;`0Dd`&gHQ;SErY+UK7qd8bxTz@H4-d?HG-q{=Soa%*yqw}hsoeVGr11q$5Wy5YSSu%$^NmH|2? zl96|s)M=LBg19;=F}?)>e|4gU3L*rFJEASPVsJJptQyPEi$ZB{L**HV?0$gI*JfmA z327#}u8X1IsW7axj?zIqR0^SzGX z# z&rirVKjD}5qVNhFNYyn|*A<4MP&>QnFJ?;7U43xWQ9wfpv9+uEwunH$nLaoB1Bt|8 ztL9ME7HPh7Zl*!X5}5$lQo2Rj6}}0LrEXAs!C6>F$;9K%35Ec%sBvBT5l@A|Kqj!@ z>FNRJrv7V9TB}FOJ<1MI195#xu{j!GDljyCctW{pt@=!8MMi%=`uWAjKQ|JHHqh`( z(*vrZ-0G6My9vnw$s=2>#1cB6eoxbR;1h z39SKyl%Ds2`NwD@^&Nu4F;~}Lj;8)JBJ@ssEKHOmyBPrN{sQ~+>0S~MyWUokcOWv{ ztCkfG4q0Ypu)c{T>)7(p6)W%KC#W_h+-}=+E_{Lt0kf=Fo{6uV5ti4!?}Ja@@={$K z>p^9au3Ry+e-^2L#Zs`7`Vko^8z2h6tzFr$F z3q2SoUe8udz zTulQ2=8Xz*mAkC55D8a5_04$q=C-lwcF-vN2-44XNbxBaA2k~;pc)T+gH&0FgK+QIqWp-6&?w=?AuYnE zeC;Ik#x*St6=|&M2B)4+f~N#8LWj>#vb<>q%z%1cx)Tm4xFn0%BX#Gb8j9F&7RwyM|1Y&->Ifsvl%b|IXoJib;02KRH>Nm2c^f{v%VL<`z z9}3G~k6Fd#eC>7yD5X|qnOp!CI`63?{r%=h8FsuQCv(0dHUtehG2wDaRxKJL63|8& zt+^=WQ#op3L{Y3mm_0~2=&oGSkraa) zEJhiD^74jLMIk}Z^cim`5Ze0we02&7@`;3~8Dw$cH#ARcw%@ai*Otl{z0hc zhoN3Z_GPluG-K>Dpw*2b%(Ho*(G{S9e&Z~=X?B%8KSMClSg!}Tj?Zs)0Y=7v1LaB6#VvDtS zzA)x=(m$KKU0MBjf$CYOnjZA8`4|8Bt4WUvN9qX3a)KqUn$t~$Z{A7lA*zwmE(Pe= z2^+*96JYPpk#Q{gPFW%WwZb8p?JfLP{^-?Qp1)EwOw=-`%X2?H=N)PzBw{=gJ8^GzWr$Gx>> zG>43$sCk$S_l`w@T^>Z3&UBvXwS&sy9^IUw0v8eQ8l$XG;QDLnws;PoZ~&IZXrin) z!&ZipbaF-VKgNU;nIG6jhxMq!E;Q5B0nvU0Hv0ClwlUnmrMW$lS3U3$#vB&XR$Z?Z z*wGI&kjlX5TLDmDy&~8pQ=u6qKw-__%(Z}Z%;+o-xNsKmnH#oQTTK^W-y^$p0{FN7 z*?!=hh3BXmB$Ya)U)At}&1wzbI|@ory`CAwH4y{-Koh*`$Dj6TAMGYIqEmMsdz_wh ze)%|#2FPY@lMY2rLK(k@30TdD(=&TEcGRj7gqT2Oi1sq zkGq~N7d`zZ@#RV2{rYH)5OIPxKeest64p%HgRXbhb`m!Trjd1~S_Dovu|zmbrn8KD zTq=RHkH>-xcestmz3jN&n9*f4G&yot`X_FlJrodWq-iu_$!fhtQ7*!xuRQQS%ZgvN z%gaaY@kk{>q;=iBFhCn-&^20o6s;bFeASR0>ebQnGDz64+o(d=>->QadlX{x>8D&v znkK!viDy%95OV$9*~|Jp#r$IVnS1)3a|3P$+r;Rg;}q+pf=7FYzBucRMw*TaB`7`! znGH;bEHd@SK@*PUYy(ywB8|(}=HTh_c%@l;n!En)v)y06KV>$VI=ypOG)phb}g5zhwSot`Zj&m$Tmrp0ZD76`a-3pR-&7E+`; zFHP0g5!;B=tt#cVB;C3DYbSqQlFx^mndJ447b2|$R@QqYL=eK?}X>CKe=!fMm{3F&z|LxyNZw{ z>i&{NX-WBT!@uuEW1g9>6UBXfF}cX9M!~Pl74f)o<4DQadyUCY@&A0r z96eZ&a@t~*D<;wLP+jA15UhH*53=)7l7QJ9lY@Jbc95XKy98EQ)NRdu^eDF$m5vtp zv@1WJ!o~6YtA>QmOd*|~i8WS5aKSnop(I@FL=@p(*Rvr*gt))Vd$Lhws^a{pu`jQqqg=cuI?|xV90N7_oQ5`kNV@N( zmVMtFxN!N1S48pljQ$G8o~bSUtjtF`dTdcz4)J1y0fH|UvGgK;VlrqD8)BdIPQ8uFGw5oPgLCT;YO*E!9Cv0@1^lKbHkIBJ**`JDL5O5cD6d0$m${iOQe3< z_%_=JELV;&eW3M>lf3*g27O;LrA)!x<2@(Y(5x8)rb5+5n%Kv|AiNQl-)%r`J|!zBMpXHTI*6Q1Rc=BUZJ)E4ASvs8H$Avx-Z}(> zFB9M*n8#HOA1xk(65YdqivG^jLs5#EwrYB!Jz}ds|V}4Iycv@we z9wbfeE}Xvh0I__?(HS6jII|wvRZrGx%pqci`D$&p@UORjPCst&ZkwWylwmNwdRbpB zzySBNZq~^GSTm)uqMfl@%9zee%_*ZIC0k}Qq7f_R9vKdm(t7R|Aeq+utR`pxq`V4O zmprkKuw#VZ8J%SEo=VsyPYWKL<%6j=wH+Kit(VuGt8g_9waCr)W{$QPLPJLBM0+8x zm?exiYa~h5q_-A+)odC9xESG#o<0r^fU^xe0p96`i8p^R0+bcnnr`Zk1`=^HAO(A=X~YL$u_qRr8_>8LPrhAnKQ7PU`E|;`UE;){1d(F(J&SVw*RH`Ee<%v^6pbu;##MFSQ#B3j8 zs1Vx_rhUV<^}E^nv;+!j>93hm8py3jU0$gcl;wKgF9}=IuUN=glKM<30ALc9qH-R( zXQRZoKg`ZynXpjN*k2Ui`=^ayeQkfTkj6apJHLBTub6~#ogg-pWBNPQCsYCj72xGC zU|H5L1sL7Q3@{7~z*!SYEu5L4I6wDppoME+F3rPW+1cY5|4)=Ax)&24+ds@XlsM!sRij`a^{6O2mWy1Z|T-K+@cN+ zfW(WS=JMNVIckNvH@dC1eBacH1S4Q^U?mU+4s`jWPGAG=TJh8CkQpk2JVN&O66FAg z6rpv~IDkyrcwUWKa1`*j>nTKbFp8_<&if2@d+_BJ9z$3folJ=&&O4_( zqOj!BX;WHn&1^XqGRK$V@QFVjv2tN+L$$H=gO60^ty>YUN2g*11Vn)1`x!WXlS(*! z%rc@*b?RM>< zVrIz$4bBUWvgy{A?r>OL34HqhtRRC~p#dg3Fo@61jWZp%cF2V&WFF2@H7La)D?uJwaP?9}60XxrH+Cfa#1*T=dUDYT$JPXLkdV4~td(m>Xbqz3 z&N4?k=&>!L3Oo4B{`M0*YA-M?K$gn^T%P3M;vCE-p+G{_T<&K9>g6kB zyxqNmAwabU4m}&H(#f|E{-Jj`9Y2HdO-ial@teRSS1=d0sj9WzwV>;ZI3>F2U!baO zqoHm_O8rXI0;p&T4@@pJa)x=UY3c{wrpV(5{kG8k_VBKjgyr-}TqV|m{?hcAYC?9d zntk9$fAkJ+1+F&PKc3s>y&iR&%py9GYFhjyMzEt+_kj2+?UAg!@I&n8+>;C_H+LX8 zeu7iFQ{5$kb)||7jM4mKAuv`PiQ|J(A; zKJGgh#H&eEOxBNK?vQ)w(V@6dNTzKh=1sl}Ok~wWZS7iD1uD=`$ej=shlY3bc`W0y zHdnx_@r}ax!k^XkWmHX0OI=*M*TC(6CDcl?@4dx%z;bn(kmYowGGf3TC zMUFSU_8I^lS%B|1NXp~0R0Q^S64~J>ZP`TQwy~@!BQ@i4bG=x%9`_O*jlL=tH5C%_+uix9U;VfU0hEY@>=KAYL(cGxSJB^(vNr zxv^HQ0ZQsT2H*?mm+)VP24g+|hm*#=@y};>PGr@)*-479@(tHs9mts*b}PuZ+_la8 zv`qCW4Q|E_7jP1`&i}<-ERk+CJgnDI_dqq4y`d_RX2@|67g|uKZtCMzYQd-VpJ!z# zp7?%SJx$AZM>OvPO9~6BxksP`3LQD?!q+q8Q^S^vYhFFlHwdV+rJxhEeGDT#5f z!|G#OmO71Ee;+97Z^M%Q*Be466buLnj(Xj7D@$=3(5uZPD(3VZBgS+I^_!KCdjYf!M7P5%BMS5Q3I)c;aq|L=>! za-!}A>Zs15k`b`eTgX^PFXTfa!_5&Ws-*2tTy*6c<-Z0_L)^Acs2GO{C|f6vXZjCN zRK2YR25)Y^dY4|3)zpM*od@j@+M zDOcJ+6SKs;JV?bg_tV z=HA3;9AZqE>dK>Bx~zj*ZP%DIV^RAbR-Zt-hkJTc6_Fpm&KXs+c2P~E0VV~Gi-+_5 z-h}x=yhZ=yte%KR(IGC;OZM~4|j;`N@gS|F4``)=G3y}N0oP@>qLM&Dql28rl%2VgU!Kf zHlv9M!A$=1EFcAx#AxiQ85g&Si;vUzobKD=li>+3P0+UOcdms7MPL}my&crTwc$sR z)i~z4&pP~FX}~+@MH|H$Y#AhNdG9sjFwbkTDwEhLMQOQzx5T4U&6xzWjS)Ur>F!02 zWKk~r9>wGcX`gAxC6!(*C@B`M5=2Rpo5z-9(18O1o;YDK1e*FSaqa1l!^nX7_`nS} zu*WU;BY&b}*_4i7fUJLxG}B7Nz*Cwuu$+uwv{-c^0^M6zmWBzaX zFh+b<76yj@Bqqkj#PVNSV)&4BBIZ_3#t!&&B3AlN#zMx1wnoN~yu6T(P7cQU){t)N z)hecHNSg^F8OZ#c0r(7$unV3y-Qi;K0DwRQ`NU#$kYV`UphYh+e)!TJH)04y6u;ja z=524fKfF3WOkcjma!n?E_ecC88`y<6RfQ zpe-IQgKZEj!Q+zyL_;9ZGf}k#@PmV6mw*fS4FitoVfhiRV%{D?`2F&;qx>-P09>D) zf>+mw0IWpbM=rCnw0;^sT>#bGzk&HhJNPg408k&{TJ+ac7sm1z$p9v#-G2?R#ZDFAu@<-w6SmR+ z(`GsvY?|Z*6aa8DtA82Z34L`C^YRmGABa6rI~(7|=5z-j46APj1w=6K1^^K3uimm; z(ew?_oQvjbZa|jyo*5h&a|r2Ta3{fLl{Uc)H~?p5O~JjcGvOtF*iQQvz8N||tFY&K zUv+%1=6hhi`5ZYAh<`gEydK=pjh2d@AI#7+2IRfaiAW+xr@(iTzf)k}<+m~*S|5rP zm_xIFz}Ds*v)T1d>;JOuEcT3RWcv3Y%lsL;!e{A+zu70Ji3{{icAB*e?qtIS9_9D) z(pA=PwFltS(|gG(cH*mdt+&F5HuUUivN|v9XSGXTM%D*vCD~UABbuiOwEAsJ`SAH6 z^vx#rX^Zf>LwNHeyV+~`sEd2|^TP9!t$_g%Y!R3>2YkDd1DJ;f0}lH42Gfsp_ocx< zKnt)J4R+|gH#i^*UvBn?=JjTKWVg5CTXv>*(6=})a4jEY{}^o_;e8U?UNOYY&)SIq z+|tvJ20Wsti_e894Q3Su(%*lc@TXnZ2_A1}hhES#teNPt6;r^MUoUNX$Mf&Sb1ATn zvNKO|sYKS#WXsnHxWcd7+s2%qkX){^_KD1-cj(cx8*&V_k%v7H?`92ienW0Hs$af-{fgUM3Lm&AJ1}2W~;7#TWL?Pjp$5 zt_Z|?l7zMn|6mdr;6bHAsJw15d)*NGmeuSYJyxZ7$E!U?dO~I`Yd=9L0MyUwk(q*Q=W^hV@@p&8L8eL{LVzoO7okT28$yQ`@-g5H3wR zFL~ir;|>yV11gxoGo`CajU0jAI&CQH^ltX0sCqmMwp#UkB8H~BhU%;+KND8?489}h zjyH~tded+&N!+|XV&CR0-L0gUQfc5cS5Z(i^N~yBqTs^NB8_ZDOQs&ibxX`~>8$m! z#zd{s&Hlv5GD6Tt-l_$k|eQCA3hMmz31tru*>Npa+zyOPLPlCkr82 z|ER={%{H|9%QgD|A-xXo!CKqU3A^R+C7W*nOY{o^A>9zXN0w0xW0~83UWO*aX;ghx zg)KF;1`tO}pJ-jH$$QBXB@7TkOVZIn|G6ghwr;aNUOGXw#vRavgw%8VJqyK<3(*(7f}C%`SCMIs@W{TYebhZq`8zpEr=H z(|$p_aDtV*iH`GTe)X`vr{+$<&`Q`kR!?T-&Kj*^p&`Q5sl8711R$9)ie8;E*wwP9 ztSnbDyVH9W6R#XbUQFO22pN62re3U~5R>W(OU3QoM>qrk0-#eFev)FtWZ>sbHJ5Ws z;Ss7iRW(zvkJNjgA=T8Rzg%%*?)o8ZoyYC87o8Vpg~Dt7$%&E9N zpC^&lDk=fLrzd{kfH)hwo6R8#EaAKX20nuO#$%2$bPg9C5 zy+?ycmb$iO=xmrEpG2oBN5uo2%g?7mR#7DHBHBD}boZ7z1eAzBlaRA+Tw~{ z6v9#6+FE%yoR6T>WyW5g;-?ZVFq1?RS&9)2)20~A^q`>64BR^qc|20GdHjX{el@V7 zM9W27f-gk+1PWA2p&3*K6SCeala7>r^qi3gu||qL+f{xfaCeQ2hRa9snIE*4d>8ms>$o4{nB(SR)-)t<+ zWr<4fgI$YA;K>M%BBAoy&)=l#no^wXj2WAR*c`96jWCMr%IETu|F~Y8)zqF>V8i(` z-43wUy~sDg!*7II4!8s*2XZN?cl<4*k9?KhPn8d+F0A?!D@t?!iQF^;Iwaf3D6~J| z>B~T9TOV{1>C{NeL^!ewDASOMB5@y*wju9;_n=|@SYzvAc2ew~=*|l~5ZOb8x$7Xh z&v=nKwkEn<9Wo@;TJwgGi{;3}Dl=_=x}D>hZ%@z#bHFr4(8=u8Y_?1-D4Qh`)L2%| zP8)t9XkTu8N#m#{TpHI!R<5jtKb#n&zT&vt@366JWG6b$yh(U+aPO-lSZ^QjDVeacf=YLDI(|IumuWME|Awg{EZrGTy^~i&w|8IRz-Be-;xf zgkcRapIj2uyUjtrD;mKTWC{>_FLtO_IoWpDR}kq)rOQ>{+!T5nru+hBEAwb&7I#J- zlO$d`8XbO8H`T!?yJEwkbY`crMfIJgdmsJz0~R(c!_VhSQ#4zO#3d>LAy~eYD6(Bu z*mDgm1P!Q5|3P?EyM*jJ=-)S`L!>Q*6Y$pCt1e3mvwKPc2|nW7AO#8sYuI%kEBmwM z7qdWN#&WvxK8iC_+fSjDCZHtn>g`R;h&^r7te%Q#{_1?bRSDssQ}F}|5~gJ+ydt9U zzdN^z+a*Xv=7^VFdeoR4qVkz$?xr4d0;)t~0oyb;kfiSKxf50r<_!B}%|zwrC&iI= z(-k$~c^aV;Uh9N3Xu1v$GevWA0y%VO@g`ibYTx!3&mB7(w%Eye*pK@n{D6!MDh@F{ zv6RNl<1@Gyd(z#ptY}WmFCSq;binPp9(-%FeSfk0Tunw9g_myY<1XwJi%hwtHF-qm z(*? z<6WrKfbhklLSu(B(J9VjHDCL2At{W|*8Ra2>oXYCnUEe<;1`2#jBiMK1mS3$k zah`l$EC6Mo)vfvyI3fUwgX`GEA^>&0Bw~Ux+hnP#M@!r zm{9KbjaT1#Z4~2WnuUdO0W4d-C&T1CR=a(W<;oN!nRkcP9x&zyP$WYpo@pjFaYr{ppJ89=n&|3WS7=CkfqPHa^ zPffIMcq96$4i?OPXs13K+$K*NMg<6}U1v*S1RoPr$f^sdt!&9i9`gVXQZ%Gbmc7iP zYq?#PuL0tiPjC*2Zg_$Rx}6(K)mi4%_zaQ)*DDTT#*u(J2sLW6ZfeT$kdH!DDPh5i zrg2NVo8mHGrgm#lBkLuC^js~Ny=l;*=vWkxT!r_^I7@%|Q8Ib9;74auP>fHTvdi9H zt)*F?m)`lQ78N&7nk);fTjyr+_*t+LZ;9hY;!a&WxEV^xj4cYePTYpWxQ*8cU6cm* z40TG7C42nA{O|e8`9O>a?QCv_R}XE2*0ljHbw3VlaUx$`PNb_D9I>TlO+Y>y1M;Fq zH+J(NdQ?3d2D#ByKzoYY%flf+o3L-=Se5Z9u|0Q0E_^>7YL3AFS0I!{N?xwek>%D$ z{X9C(sD!J5XOeHv=I`rSw#5!LRiNSdF6EAYJ!?GbM+k{a@FWl6-Vs98U32^ei}`e^ zZu-?C(B6)j@)#VDT#D8+q9E|R;sG$%%p-|OBHW5^IdhDVS!4HppA(~w`b4(}uD`0S z^m=8Jww$BB_=H^qR+_;eh?^oJ-Arq-4Bm%T2fk5gM$P<&Ao|88iv@IHWl*R4#ok0} zZs*1m{6tc=!eZd3;ks=9uJVR=$k+690ZcfMEquf01*y}7DwWeIFV0N_y_~ETD_v3vbiyx>Iq70vLCq;oN zjr`x+9S|^r5Pf2xt6p_WgF=6(aAa^dJ7@U7&iB$@M*pdiw1qiGr*KqVM6JXYE1olC z@h0l;n&_ZY>N^<&;Vp%6A+(K=q$FdovwJ8`y45G!ex#wNL9S=E$>+4t#B986_j1|Emk1No^JGBko-Qbfd`E0o zy20Q_&%x`=SjB{o+*>vxDqF`|I7#2Qi2Q_!5&`ii)X}4gc**5H%6z32ipS3;?B58U z!0jjuwlJ6-LpM?z(sO{@Ey}=aDovCW$V*+VHW)Gvju2k)h$(WBaXbi7M-4YGk}JB- zH3%gI{^R7)OGwJHI#2U;%uH>tyoS-=sxlO130Pc1j1g6k$UXFGG6!mdDmt@&LaHA@eCRGXD=x|>?} zSXA7(S9pxsF}>D(y0h1*e&c%?TV+}X8vx4x6Pa=oUB*6yNOE1(2j;W!QkM-q{ zESonjD3%jcex^7OpwCu~wxI@GCUOgW4ZpfMJ~o{WVDR-0?P7=j5>k$%2>y;3F=|#W zI_cfHWFVL%`fxdTYMTP30*RZA9J|IWuSg4P*&bYYQa5knIFpSqIB6mEXqb?hx1m(~ zM%hB%98E6*NSu$ggeP|uCtsvn(ZgG(L(ek~;AS(C$!U|%q*_EuWzcfNbe)j7L4Bbt ziek6?GongT#gp$$cZ@lp4Uh1gF9dXb%aUR=S0mcWhfqs zS`*f{e-JMyv1yiQ7(4~TlF_nWdTV^tIT>18nJU4%MrXifE8aYEZY0|C&3~xvL@q!rdjN5gN+teYf}0IwL?olnyL;zSVl!)XoYyolKSOA z`*Pfj8$u>xG>I7!?)4o2IjAF`e$c_@iIOLmY@x9_ZTygT)(9&dqy5?`+V1_0yZ(7* z-lU|zDwA)!t)$4krp@4#Ps68S@5PI*2CBO$;^#Cq4k6sJqKJ#an{8t{WN}Vh^Ha7L zK;)_xyef`254eS^P!Ba+oBwBL*#W-Sk zR$r&zT1cM_Kiw0_<6^G^E^V~49mv0B^V!iR@0Q@){~{5>$zj% zLcDOH?R(equZ8+Bu`i#KXl1i|RL@v-3815mX@=noKU~$~7p|xF@r`hW-s!JageAWV zA&RC9Ce8T6@TtB)*0R${9^@NW#8#9AC*u-~B~qObNzRfAnICXaW4ukRl%vrY!sJ*R zY_hzu%xX~93LjR9i)7y$gQHggreijnj~YeJwVWJS1?Q$$o z07kvqo5N$;o6V!H823S3Kh!1pt8)3|(4@86EXwt7CITpO|1@q0krCrkURd3zo3HjZ z;4%Bevp?3YK@ti(T4-2md80>x25dVD8~;3Y<&(j_F}4~vcXDSl)rwN@siF%jOyPiC zJ*%i|NVng8L*Wb5VHlkaIKcGsHW8Wi^K3PEfK1!lu^cOOL=FjyXY+$}HcI5Ns%En!XZYNFdaSg)}=s zO-t3+)sen!JiyOcYCoFF^cdH4!v}|gLzG5t8ufHziPp07mV1Kt7eCqc3m(U#oi3;{ zldL=xiI#kOnQ@$}JY`UgaQo7|Eh!3jaSX8Z15<=o%if%NFY@I8yJIq*y#fR2wA?1E zgI4IGx6&2kuI6lfY2iyxr|g}bM^GnbqT)pSFn3 z+X%A3I2EH6_m)=sK|OTJi{Q$qeDZ_-<(l~gw)-K!&yxRsFqZxhwV)$873P^hdVt7X%Me zBcRyoJiWR`W=a80()WTk3fF{&H48+tQgw5cd2(Zv5}U%OBZ>k_M9GP8&MM%?4_K+x z$=h2~H_b_iKDWg+=oD(96y1!6J#cY&+XWG+whm*|U;uAjA<>sMJb-BJjs{eZtrH9uqMYW$JNxQb)wE|6bB!0IVi7J|-B!+esEi+dp-30Yef5;E zjy>QMk&)(BQ4j#yNysr5h?1zpR z@UmznkZP-6Mtp4JTh_VR6arlS=nxlM9nWc0b?0GfS}=1oOt=WU-$q2WAj@~3p5)9Ck;jmX7Ey>cp?=q zV~`AYOII-A8DRr%KF6X+{{h@iJg4~&fGIue{|T5Xx!W1z)5#iGC^}g~(#ha6(EqwH ziI_V$I^lD$|2Jrg&&0sM{=Zz8{y&h?D@{$s%{D}z6V+4e#B~Fw)*>ZJ=Qa>ARB%An zOzPplbo-DsbkF5yVk6(Lvy>|gck}`1wJkdt`JpzN=6~ncHFEA7w8C2lsI7G9|)kt ze0Z+}RU;@|S$_+CVLuN}@ted*!d>bx&$M0ZEJ&!)`{p6N60-VF#oQF_%!`E}MA(7l zBg6JL5u*rV?Q}@P5vL@fiH}GmlY&_Mi^3OVs{KKTq7TtMjA7RI@Hzb7u`{%JG6^!? z*4jujpkfm6H6ZzbmTL&35l@BZ2)+ymY5IVMghWqSMr1V8aM!WJ(MOZPLEDG*>;ctN zPKnVlf9HlxctVVt1G4@LPDu3S6(YnMz-(vNM-N-SH>aN_0+C{p_F#>`AaHO_U>0Yt z1$ek@2F;Y3X9};Z#Ti$X%DgL?2jb5(Q-B9g0Cn2ODpNHiWmg=o9Ht2S>i_8>?gz5` zmjVdb&X`~fQ3e}F9+o(G(JXC_0YVX&zUrYH^I!I30x@hmJ_BbBY}4|Pd9T+kJn@bR z{LNG(fZHv4AV^lge(B9^-m~%%Zcm^+>cb z(NmS2+3+8(cv-q$?=qD?+lpF-Te?^y+~}#>xrG zB+Eb{2P>!c3de~Bxk=95ch+FzddRlND~Hg@e&sw+bt*&Z z95Io^7rwzu@fB%)-883bGQ6?x<9FAjvd9XQ%r#+G7~jZV)Cp~vM{BI0Z{z$q@!5v~09)*yBUelS zxq4aw`~19R&Mmq6P)GuT`VA7bOkYTbeEt(>WfJ`PSz1YHi%$)BrG-|jl?fNi3b0fd zCW-bLsvz|IBlb(ZQi-$T66mK{Qs-0B&bMeywo(<6*cs51rCUP1$MI%Yk0T+E`GWDME`7)l&W>RvcmT%V zg}?@1c7|D@!LM;+6K1B29RtF1OoGJ{`>YbPN+zswqa%KNeZ3^CZV}hBz=aH{uo1V& zrw+xs^+3%o(}tQ_{z!9cZtg5ITGcvx!=-No3@8F#W(>aoZV0paU;PUNY(avl%k~0! zw&-*509DiXyfxY>u>tH5JhH9dwdwW^`$MpL21^Z`i-V@}^D*bgWFH9n%6K69`{tYo z+EVQAS=2AV+^4E8xtLe@34=+U|57`*djrs;3E=f0=NC%{$8&qPwf6&d8-2!KZ*D*9 z@ydCN*Wa!E=fy>Qa|5rXycezGZF&o)hscNg^mzIjbjO0Pz!Syk;pmx4@|1_V57Hf} zE`SfauLHC$fCtEhqz|$lTkmH1Lw8MGtOa1=x&N=a5KYoFQIcw4gC^p{H5h+7n=j+% z@kipv!TRP<^FKJy6$RF|lyig?syz*n$-VdAvWkUV<-gegG|MylRQ5*!G}E#ARH^`5 z_G9~WAXX)4!7e+0udHte&fVP}__naB&3XW9Vu1{!(VfTmY`Q!i$biMrd$58W+DR=Q zfxXe%R<)cqj||@iWJ&Yn_P=ANdZ99isBq7$%v2%qfSCpblRVi5_U20mrYygjBkTqr zknu0%*2BP=esop za)e$jGDKTpwO{4N@TUg$;8Vi`9EH*_nB$ZLS66qdOXhKRh7dox zeRV!PeCpWwaQ7UP`KsW}V}uG9@-y3_2O?Wy;D52s8*&e9@IE(NA$(sX4fCze>a)=} z(NM8ck&clfP4OAys+m3AVWZ}C#v4_H-!>;=`kZ!%+b&@@=T z>)Ev9y~<1}HqlbERyr(MBBidl;-KzWY-Vdv-*xRAp(oWx7~wz}!7^sI?0qw5nzwLb zzg8T|hzLPj_U)qoxO3dsaF#=sn^$M0@gC_7)0^gSvOL$(n-w}WV3u~>P!TLL7u?E| zqoOITyS?hN*PVq$DKhx}+q%vrd(lgFCuDOJ^7{-y->fNFEEXPawv`_=tocNfKUE`DS%p-jVY@n&hI82tL5ieFfuH# zRyVWpjsd!?;=?gn3{sgOSc}J2=Q!tXL&;YaltT1ms7va__90;dl-8CQ))*I=ZcUSX z)ihQZSpY4LDI6q!&1L7!hys#LhZkqb>iy;C?dOf|9Uoq7ZEdNEK<*9QovFos1HFO9 zNzMe`0PS)X?pxV0n{}ZuNrbI^LR0R?`Cwk3BBG4>EL6uC;YxPbdk4=GGcKoVb_^L* zuF?7ov9h+;UI@2QjxFbzpcx8B&2NDndJv`^)>Bq*ao64UHxzG}*%{m2_?M)S#{iw7 zFIi*E)YQiUztTD8H?^e%*=968lBFh$!;V7PkK5CX{+r6mG}u#o*~PXzh^J@s`x9ar zf+9T8T%>n~Tx2J)(AP6_g*i#Dt{y4Iuot{XBc{Nc^SuzsuC&aagD#7LyIdkBemr!mj5`m>h~zt6u{Q9ouT3z#(oRHm86+5arqg+5~#CKjqrM)gcM=H zG%A#De;nN&eqFSic?A-p!{~3AfujfwuF5bo!xi@1RsyJi_206!`Vl*`$B}o!DEs7p zz+)0mA$Uv1dWZQG-<;Y$@_haEeL>DB9Y_LJ1r}0ESR$JZJM73EQO!YzVOvPSWiw+i z9@1w1o7?FG@Q^Z#F|BU~L0V=k|`Kfw-P307or?0}ZzQA$ibW?Br1I(V2yk#goL_ClbE)@q=PvqMQ za*nv~_%S88_BwC_^&j^`v?tJBhP3&aIHatMLCE(*<|^!VkRj2oDHAQy59RYnpkOHE z)6dld-Hxk>usXqI7%2Vq=(I41p$`^Jh2$qN|HJgP#PbQ;>%%hcep~^krs@_tyFkU8Sfs;(zE*7=Qg;>G5q1EbzIxA?f&?oy=?<$c3%VZSY04 znAn(Y@DtIF zzYUIqkg*#lzKpS(6TYaijj@Bilew)8zKpG+yc7kUqO*a8v7r+=1)bn8)zj&BF)4i| zV>NtNb0@Rk8TGAy7c;cdcXY&eF?MkLp97g_8R;qLw%awRi!NBrOCzw)8RSNZRB z8JHPZI2c)J7-^aRcbdQ9zcoskyBOpD=EO*WZ)vCRWaenB|KC-z(lXG}Q~YvZ@r`Ya zevbo^iGhvv|2UcdyK`jy?H2#5ab#g*{oia`d`2cl*8ktev08n@21^{)dqwr1VGw^o zje)j5{$ElV*35bwS#GYzNPgTTwOjDI>b?Z9PTyXm_@x?^=5=xG*M8*8VaKr!oaUx* z5$6fw)Ff7Z4mnaz6aos%Xa|wEnO!6_Qh;gRr&J573 zID3R1NX}QUJ5HJSjA;CLj&W@x0*js3)eT z1jb$Jclx1K*fWdIn?Rr_7c~eylAgkaTRsz^byBt1@;ZTl{w!@TZ2R^p{Vu>8=~^9?S~pKn%o z8$Uf&|MsVkP1rQEcD&b*Vh{f{4$n?rMdXwXS2m`a+WLH)9ey5(ryZRZE8hY1%SVq>@OxDxscmaRTZxrh8eBUjey}vJR zJsUYXemc7Gi` ze(u~nzv7(g`g!|2ZSMEWFGBH!YHYA)Q*s|auE#ZeZ6HAzEQ@QPEIbl zw75053yQFRTe)`%P~}#;f6`q)a`_B22LBv2mk7+1o`UE9{Ex=I0xFJeSsMv% z0YY$h3GN;w$e@EeLvRTW!QB$vNpN=tcb6c+2~G$kxFmRxfq#gdbKiOQynn5|)_lFC zYR^n{)mPQstBsGhVpfs5)GE_yTqDG$yWiZk!jX26)5sE1I@TZu+`U`YN%Ds<3g_Yo zKO&HJZ`*VpQyC*6k<9PtD%zr2R+ zcUbhnRWHv`m=JzaC?i|Q{LJHlCVCk;Y|{5sx-(TA0N`ksub+WqQVdaEliP)plAohL zFM$9^RvPsUqB5}%KOoKF{S>)Bd_&c!Ni6Bl6zc)XyB0~JCE?ZxCpEnxqc_R z@tfVXw(%PAQ5k;)@8qI3P`)XdW6V5nadat$dKzX=X9ZwKglOiXO*xS+2a*Y-0+0PI>-( z<%>4Rx#h}!+&p#gJmOTHDxp*=FR~?mFt|iYa3&&K(bPK&88Kp5c9RSEdWX1ldV4U^ zN?!*k{Dm9foCVE{HXYwMwgrB#XpOR7_;`iM_is zE!y?a&hgi?4X4JB%a$&S0}G=^&#_4pET(IpsLSL~dy zGm$SnlCsl&v){OggM_G)w(~3IobjgDks57NdWH1G7mG=uZ%D`QlJR(#3wSYjNLuL9 zHRCdiyGFw%aq(czh&uy$9?sbFtrz)*VT+v!MSZVcEw0fObK(vZGDP4Y#!O{`Cw}qe zoH(*4^mF~JtyEWN-ZLBMD~v8Th{|uYrCZ5uQ-Y?YFnl}sjB^po7)iM+YC>-sbPyg7 zu96ug>t=eZ)w(XMmU9By0c{%tBNXPnuxe&1BQi=@Z}mQAKILr`=23fU+geD7=@rdc zXBCO(GWp|C8O^YLqKeg~G0$rH`*KHY2x>TjLTwpfbakm^xi1Yn5yLLZi* zut+v&IXCUcvr&Gm6r`%dmA06$0dxjm6#LA;n&@a^P}JlSiGx#1)8Z&fks=-wHEAQJ zIhuof$$7^VzD&U+CB;`5u*C0*zM3LLH;wyjgTF^CBp(C52E(6HMX^bQ8zC{I@Hg^zVi9lAp<2Yo_m6h$ zZWd39mjbNN&oZmn%TJQ<7{n2~_DWktRtdr#_6{^hP?e0}aR966Cn?XI@Skun1e!^$ zD5^gETtU4rYMXATN#u$qWjgbO!Ur~^awtN!c&J*Gz$LXH;NaO%^Ck5Az0i5u^z_+d zELT2hKJ?;mD`E~u^+s6l`EI|rwPY^mJRjTQ#c*SefSWLAN0r7#SGm-zqBmkaZRvDM ziK&I^*oP76IN3|0n)C57-FVx(DOvtw=F1TAKFC8cx=CNTj^0+;&4_Ff&~ z;R{Cw$Ra#5%>82I-_PF9AokJaJRqSYgY+s#8}ZsC*rczdd0zQt-J*%Yt#tEc#O?)zP3GOaCmwB6LTEQqyj{p~ zJeL|bYMWT#v`n*w)s21fI(Z~na>QaJ53dGq;?=?{%K}^4;hrE>-<;82o;3ocY%ZLl ziC{DS2s-XwEAF)bv$qeQuA|`6WU4?v=A7h09V#A4Hzkj72HT{)rPLp}#8}hav_hWa zRF-T?c7z@b@C4fs&ONMru1}%=u1UN}X;H2z+A+X^^s~ev>u0z%!2yIG*GRPBJpz2> zIS$r`l@|JdCc}&A9YwJ$vMZFchAdSh#T`hxZy!R_%R4jIlVdJBE3@mA-aDkPXKPje zD?#S^2MyB(nwg`r$-OW&dr6_kPQk^=!EJ!bre@`7_5-7`X;J8LP;gOjKzo7q_Ad9m z98f91`$gvV_lNha`~FahLQj~T^Qjc4gyd662|jL4$!Ag=l2V+~l3e^!&vECl&rYfQxMsr^g< zMZH5U2{1jDG%xKfp30EV%JN*_C{yufhwq`@z$j61NL}U$GCf%>ZdH({WxRIzfNwBj zXn*&bIW@~?^T3SCFNGPg8CFQ#fcI&UN831j2Qu|GV7L}zJQsNu-x$(7V$D~!Vgw1= zintdWQ(Y(<`>`T8fXW*BtWTm!oO4~HhTB0OCa~byktNyDslkZPKnf;jofCOHO3Wjo z72FVME1kOMKCxJ2r*%!+a4XZmLtowQWw+ zsxim}3(zUCVk)HQ!==(Rb28v>#iZCup{C+B%Nw(PDGeZuEyLR?%bI!aZLE~VqNXrb zf&+#;!EHVlTpA%eeEvphVKP-yU{f#p(Ag#H`R*pNh|IP?;nPZ7Sy7qe<`>xR>M?H9 zVTm!KRX33G<7%%1g7-BUp`M?cV%)XX?%|U+WQJ|i3q#-gmp=m+G%di&PM&qp@p4|0*#)voJ)WyWbNo{?qBdp!rhpS03a&nN?gN_6T)G=|Oe0s`$fFnN!nhN4ZY#?fJFjH|T)a1Em zp0+1)?|opfx|AuXkhJnkskyNddIrzk!)Y04ZW*9y8RVwTN}KW4Wgqo?3J)o&EWb6o z{3gC;H$~pQb*kvK!qD#CJ^?9kihN$PC=vapt3gwC=#$@~W=bOZ+>&NvVr1mfth_dY z$OM`XnCJ=wg9wt9pJmyeeC9gzgs@drXB;IetHA&RFx1DmL=+bfQJ$YAV$_+p)yo6o z7@F%n$Ehl>uc!xO&h{eCBfm9<+I3b^Wq*+FRC) z>!Z#|9pcWyxzGiwT6}Y3^7lQysX_1#4>7wz{BSaB1SDa&>}&-wY&(Zletrt_cbr`u zRBlAo(}QmH3`ZBswpb3X)R>P(kH#{;Ox8MJj`bomA*cA)P!ls7liO+wbw0vdm<-|zi|6D4ORMjmpUaD;LRd^fqarB^2Y4Z1?jy$2JD1((-lzy)m zr*}4q%HxdghIz|pu}&9$3=3{cfT+H&A|`tEIGtZH8j_N~L&(7uf)Re3qD!SI-z`oW z`h&w$A7bNDnMg<}gomSGb5K&zN%aMXCj)K*R<|cbR||#b3%uiSJ-Vqkw3OA1IRbtE;O_hoPIs5e$o=NEt-2Ben{OCBP&XE8U7`Yk{}eD5z_15 zQFq6ae^dSbyawu<(6}nO|*~e_WQ^UtLf<}P|Q>?8H@epi{txpD`g{`ml991 z>Omh=;Ok>U1&hNFErZP_9*j=FRZJirfJp>tjtWz3$Gwc%-b=*Lur@5hPqV{cXX9TP z^PKj=pv$jE$84v4^hj{Jcx$`=5WN?P@c3?kv} zeqb9aHxH)=BDM`91>+VP(c7Va` zq2x!Gp*bqkI#uwiAiuz6yPa3Mxc9XVaGPs1>4DSn-w*Iz`@Xu?&>LQXG4%Yoz{nPB zBSI7Q|b^5*5Kn9PN^aXRWuL*$S$kvFlX8(=%f{ISd=>NKo(bCvdC)i>Z>7R=GYVa|*7a>~W}uXCdD? z6S<2mOIr2)ASPN`uf*ohd39>>1RJzYUIBTDgbnFUEs>*$I%sXuU0(D|=t$jtbm#Q68nueM^K2a0s=S&ar_p*Ag zw!pUn<$g*ohVggHMMc*^z8hf$Zew)=RNG)d!ATsiYDrXn6{?}_$D~JGkj>be3+DaF zro{HL_YLxtuyPDRPO?uC)FtrLB{60sh<3Bdh-fauQV(3vY(q%17u89PS|C)n?iZ<{B4DjyR<>!b zcB+E5gDqY+#Pe>J{V)N37^Jn>#CDM)>W?{DFvFF%!5Bing8FYm1H)Jt|BB@KHyTJgiOv*ry_~8Wg4*lT{j+|>RC*Y-K zLR0}*IAnv7MH%FQI-;hX*>h~g=(Q_NdUSv$f9u5?`RVvUiam_EawbZ$Mc_u7%;jUt z5MGK};k1n*7G-k}&Jp*gjfs#wvL!C4R=jcNj1%2y_o97R!x-TziCdW3+v0{rxdl^ zm>ZveNz?P#)Xelqv>@9^GrPAtl z#ZnjNnJ*K+*Ep?_S$XV|Bu2S`RyECK;GO66qBDc_&-N33Zb6KB1K-o7Pa3kW-jP@b z`k@#BywJNm%;resruox*1^BUND9c-G4P(hPvK6D>XH_p_bZD?E zhLTYKXWEF0z*~Wg!VN4CA zRQGZAryUh1igAFvL=lQW*mZ?6Z}tNc?*DFFg)Z~d;3r^>;n!CPIXB8;YKFI~@(tZ? z^RPlc?J4~0$tT3xMn{3_j`J3l^X=K9rBxDWMh#`0k<>DX&RAv?J?prxS zG_M;sQb+C*lIai**P9fmt)M>8l7+1;>RM)EZ$y2cCvks{4VH_WBXBau>IA$;RTS4k zU}98}3*be~h<{@QjzKH%epg*3{6&o-3vTjJc%e8`2$`J0ZnauoP9S8dGlS^z(O?lf zYEZoAXS8!+YbF)7fHa_S;iFW>5DvNa%O`I7USwPaT?&j7DgmLW-0Imma2R+EKSgmv zRYd}JE3}pj8H&Uy5a1YNr9rwtEzO0zQ{X&($pwUy4iE3OXGW(%nO?0s!(kGXof{*# z1Q?`4;#;iwu-?-(R}t^G{MfmvCPgh=8eX*QE;ghg!SmF7qby~~v7}Pm6`_<_#Q;Q> zDuS@7xmK6&_y_nO{yw4HikB0phyr!LJww5G&xRl&lTV7Re}S5ItLWV{Q(&_h(5 zKz}lUYBzy7k^?UoU?VnCpS2-4UKy-00pC7>RF*@IX#6lV-{jruPIr-L{=RQ}MmKw8 z7ZE`Shc?=tal88dLK*eBXz4z21Blp|I4VBb-qun zmQ95SesujA)22^SbQR3KY?mJa@Y;&R8j5?u?jYpj{|itt5O;TDI)gWv1hATxYX3cK#-~9zXrK*o*&0y1K0hR3QLH7&(to$c1uIj-_5uww_)7$64 zamaqKu7ZkEa?|9iQE~Gn`?w@uMBop53bZb1Qxx-6_q;)N7dGp)&VD?lf^;?k69q

    BiR?Y*ID`X4XaU|Df`} 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%0DAx>33|-=Dzk?H3?lrfiTe1H`6KOWj(V5*w`j`- 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%0AvJT^p$Vj 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

    -|Mib@elZUh;#Q6|} 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 ID~9&}040100RR91 literal 0 HcmV?d00001 diff --git a/doc/c/client/hello-world.c b/doc/c/client/hello-world.c index ca19e1cce..e0182b032 100644 --- a/doc/c/client/hello-world.c +++ b/doc/c/client/hello-world.c @@ -2,44 +2,38 @@ /* HyperDex Includes */ #include int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - struct hyperdex_client* client = NULL; - struct hyperdex_client_attribute attr; - struct hyperdex_client_attribute* attrs; - size_t attrs_sz = 0; - int64_t op_id; - enum hyperdex_client_returncode op_status; - int64_t loop_id; - enum hyperdex_client_returncode loop_status; - size_t i; - - client = hyperdex_client_create("127.0.0.1", 1982); - - attr.attr = "v"; - attr.value = "Hello World!"; - attr.value_sz = strlen(attr.value); - attr.datatype = HYPERDATATYPE_STRING; - - /* perform the "put" */ - op_id = hyperdex_client_put(client, "kv", "some key", 8, - &attr, 1, &op_status); - loop_id = hyperdex_client_loop(client, -1, &loop_status); - printf("put \"Hello World!\"\n"); - - /* perform the "get" */ - op_id = hyperdex_client_get(client, "kv", "some key", 8, - &op_status, &attrs, &attrs_sz); - loop_id = hyperdex_client_loop(client, -1, &loop_status); - printf("get done\n"); - - for (i = 0; i < attrs_sz; ++i) - { - printf("got attribute \"%s\" = \"%.*s\"\n", - attrs[i].attr, attrs[i].value_sz, attrs[i].value); - } - - hyperdex_client_destroy_attrs(attrs, attrs_sz); - hyperdex_client_destroy(client); - return EXIT_SUCCESS; + struct hyperdex_client *client = NULL; + struct hyperdex_client_attribute attr; + struct hyperdex_client_attribute *attrs; + size_t attrs_sz = 0; + int64_t op_id; + enum hyperdex_client_returncode op_status; + int64_t loop_id; + enum hyperdex_client_returncode loop_status; + size_t i; + client = hyperdex_client_create("127.0.0.1", 1982); + attr.attr = "v"; + attr.value = "Hello World!"; + attr.value_sz = strlen(attr.value); + attr.datatype = HYPERDATATYPE_STRING; + /* perform the "put" */ + op_id = hyperdex_client_put(client, "kv", "some key", 8, + &attr, 1, &op_status); + loop_id = hyperdex_client_loop(client, -1, &loop_status); + printf("put \"Hello World!\"\n"); + /* perform the "get" */ + op_id = hyperdex_client_get(client, "kv", "some key", 8, + &op_status, &attrs, &attrs_sz); + loop_id = hyperdex_client_loop(client, -1, &loop_status); + printf("get done\n"); + for (i = 0; i < attrs_sz; ++i) + { + printf("got attribute \"%s\" = \"%.*s\"\n", + attrs[i].attr, attrs[i].value_sz, attrs[i].value); + } + hyperdex_client_destroy_attrs(attrs, attrs_sz); + hyperdex_client_destroy(client); + return EXIT_SUCCESS; } diff --git a/doc/c/client/iterate.c b/doc/c/client/iterate.c index 3954f0aea..629b345e4 100644 --- a/doc/c/client/iterate.c +++ b/doc/c/client/iterate.c @@ -6,26 +6,23 @@ #include int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - int64_t num; - const char* value = "\x01\x00\x00\x00\x00\x00\x00\x00" - "\xff\xff\xff\xff\xff\xff\xff\xff" - "\xef\xbe\xad\xde\x00\x00\x00\x00"; - size_t value_sz = 24; - int status = 0; - hyperdex_ds_iterator iter; - hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_INT64, value, value_sz); - - while ((status = hyperdex_ds_iterate_list_int_next(&iter, &num)) > 0) - { - printf("%ld\n", num); - } - - if (status < 0) - { - printf("error: corrupt list\n"); - } - - return EXIT_SUCCESS; + int64_t num; + const char *value = "\x01\x00\x00\x00\x00\x00\x00\x00" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xef\xbe\xad\xde\x00\x00\x00\x00"; + size_t value_sz = 24; + int status = 0; + hyperdex_ds_iterator iter; + hyperdex_ds_iterator_init(&iter, HYPERDATATYPE_LIST_INT64, value, value_sz); + while ((status = hyperdex_ds_iterate_list_int_next(&iter, &num)) > 0) + { + printf("%ld\n", num); + } + if (status < 0) + { + printf("error: corrupt list\n"); + } + return EXIT_SUCCESS; } diff --git a/doc/warp.pdf b/doc/warp.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c36ececc583d63202c6e0dade07ec792a1499577 GIT binary patch literal 435717 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�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 !YlUgGje5q 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≪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 int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - std::vector cmds; - cmds.push_back(e::subcommand("coordinator", "Start a new HyperDex coordinator")); - cmds.push_back(e::subcommand("daemon", "Start a new HyperDex daemon")); - cmds.push_back(e::subcommand("add-space", "Create a new HyperDex space")); - cmds.push_back(e::subcommand("rm-space", "Remove an existing HyperDex space")); - cmds.push_back(e::subcommand("mv-space", "Rename a HyperDex space")); - cmds.push_back(e::subcommand("add-index", "Create a new index on an existing space")); - cmds.push_back(e::subcommand("rm-index", "Remove an existing index")); - cmds.push_back(e::subcommand("list-spaces", "List the names of all spaces")); - cmds.push_back(e::subcommand("validate-space", "Validate a HyperDex space description")); - cmds.push_back(e::subcommand("server-register", "Manually register a new HyperDex server")); - cmds.push_back(e::subcommand("server-offline", "Manually take a daemon offline")); - cmds.push_back(e::subcommand("server-online", "Manually bring a daemon online")); - cmds.push_back(e::subcommand("server-kill", "Manually and permanently kill a daemon")); - cmds.push_back(e::subcommand("server-forget", "Manually remove all trace that a daemon exists")); - cmds.push_back(e::subcommand("show-config", "Output a human-readable version of the cluster configuration")); - cmds.push_back(e::subcommand("perf-counters", "Collect performance counters from a cluster")); - cmds.push_back(e::subcommand("set-read-only", "Put the cluster into read-only mode, blocking writes")); - cmds.push_back(e::subcommand("set-read-write", "Put the cluster into read-write mode, permitting writes")); - cmds.push_back(e::subcommand("set-fault-tolerance", "Set the fault-tolerance for the specified space")); - cmds.push_back(e::subcommand("backup", "Take a backup of the entire HyperDex cluster")); - cmds.push_back(e::subcommand("backup-manager", "Manage incremental backups of the entire HyperDex cluster")); - cmds.push_back(e::subcommand("raw-backup", "Take a raw backup of a single HyperDex daemon")); - cmds.push_back(e::subcommand("wait-until-stable", "Wait for the cluster to become stable on the new configuration")); - return dispatch_to_subcommands(argc, argv, - "hyperdex", "HyperDex", - PACKAGE_VERSION, - "hyperdex-", - "HYPERDEX_EXEC_PATH", HYPERDEX_EXEC_DIR, - &cmds.front(), cmds.size()); + std::vector cmds; + cmds.push_back(e::subcommand("coordinator", "Start a new HyperDex coordinator")); + cmds.push_back(e::subcommand("daemon", "Start a new HyperDex daemon")); + cmds.push_back(e::subcommand("add-space", "Create a new HyperDex space")); + cmds.push_back(e::subcommand("rm-space", "Remove an existing HyperDex space")); + cmds.push_back(e::subcommand("mv-space", "Rename a HyperDex space")); + cmds.push_back(e::subcommand("add-index", "Create a new index on an existing space")); + cmds.push_back(e::subcommand("rm-index", "Remove an existing index")); + cmds.push_back(e::subcommand("list-spaces", "List the names of all spaces")); + cmds.push_back(e::subcommand("validate-space", "Validate a HyperDex space description")); + cmds.push_back(e::subcommand("server-register", "Manually register a new HyperDex server")); + cmds.push_back(e::subcommand("server-offline", "Manually take a daemon offline")); + cmds.push_back(e::subcommand("server-online", "Manually bring a daemon online")); + cmds.push_back(e::subcommand("server-kill", "Manually and permanently kill a daemon")); + cmds.push_back(e::subcommand("server-forget", "Manually remove all trace that a daemon exists")); + cmds.push_back(e::subcommand("show-config", "Output a human-readable version of the cluster configuration")); + cmds.push_back(e::subcommand("perf-counters", "Collect performance counters from a cluster")); + cmds.push_back(e::subcommand("set-read-only", "Put the cluster into read-only mode, blocking writes")); + cmds.push_back(e::subcommand("set-read-write", "Put the cluster into read-write mode, permitting writes")); + cmds.push_back(e::subcommand("set-fault-tolerance", "Set the fault-tolerance for the specified space")); + cmds.push_back(e::subcommand("backup", "Take a backup of the entire HyperDex cluster")); + cmds.push_back(e::subcommand("backup-manager", "Manage incremental backups of the entire HyperDex cluster")); + cmds.push_back(e::subcommand("raw-backup", "Take a raw backup of a single HyperDex daemon")); + cmds.push_back(e::subcommand("wait-until-stable", "Wait for the cluster to become stable on the new configuration")); + return dispatch_to_subcommands(argc, argv, + "hyperdex", "HyperDex", + PACKAGE_VERSION, + "hyperdex-", + "HYPERDEX_EXEC_PATH", HYPERDEX_EXEC_DIR, + &cmds.front(), cmds.size()); } diff --git a/include/hyperdex.h b/include/hyperdex.h index 936c9f66b..a94cc97e4 100644 --- a/include/hyperdex.h +++ b/include/hyperdex.h @@ -52,72 +52,72 @@ extern "C" enum hyperdatatype { - /* Primitive types */ - HYPERDATATYPE_GENERIC = 9216, - HYPERDATATYPE_STRING = 9217, - HYPERDATATYPE_INT64 = 9218, - HYPERDATATYPE_FLOAT = 9219, - HYPERDATATYPE_DOCUMENT = 9223, - - /* List types */ - HYPERDATATYPE_LIST_GENERIC = 9280, - HYPERDATATYPE_LIST_STRING = 9281, - HYPERDATATYPE_LIST_INT64 = 9282, - HYPERDATATYPE_LIST_FLOAT = 9283, - - /* Set types */ - HYPERDATATYPE_SET_GENERIC = 9344, - HYPERDATATYPE_SET_STRING = 9345, - HYPERDATATYPE_SET_INT64 = 9346, - HYPERDATATYPE_SET_FLOAT = 9347, - - /* Map types */ - HYPERDATATYPE_MAP_GENERIC = 9408, - HYPERDATATYPE_MAP_STRING_KEYONLY = 9416, - HYPERDATATYPE_MAP_STRING_STRING = 9417, - HYPERDATATYPE_MAP_STRING_INT64 = 9418, - HYPERDATATYPE_MAP_STRING_FLOAT = 9419, - HYPERDATATYPE_MAP_INT64_KEYONLY = 9424, - HYPERDATATYPE_MAP_INT64_STRING = 9425, - HYPERDATATYPE_MAP_INT64_INT64 = 9426, - HYPERDATATYPE_MAP_INT64_FLOAT = 9427, - HYPERDATATYPE_MAP_FLOAT_KEYONLY = 9432, - HYPERDATATYPE_MAP_FLOAT_STRING = 9433, - HYPERDATATYPE_MAP_FLOAT_INT64 = 9434, - HYPERDATATYPE_MAP_FLOAT_FLOAT = 9435, - - /*Timestamp types */ - HYPERDATATYPE_TIMESTAMP_GENERIC = 9472, - HYPERDATATYPE_TIMESTAMP_SECOND = 9473, - HYPERDATATYPE_TIMESTAMP_MINUTE = 9474, - HYPERDATATYPE_TIMESTAMP_HOUR = 9475, - HYPERDATATYPE_TIMESTAMP_DAY = 9476, - HYPERDATATYPE_TIMESTAMP_WEEK = 9477, - HYPERDATATYPE_TIMESTAMP_MONTH = 9478, - - /* Special (internal) types */ - HYPERDATATYPE_MACAROON_SECRET = 9664, - - /* Returned if the server acts up */ - HYPERDATATYPE_GARBAGE = 9727 + /* Primitive types */ + HYPERDATATYPE_GENERIC = 9216, + HYPERDATATYPE_STRING = 9217, + HYPERDATATYPE_INT64 = 9218, + HYPERDATATYPE_FLOAT = 9219, + HYPERDATATYPE_DOCUMENT = 9223, + + /* List types */ + HYPERDATATYPE_LIST_GENERIC = 9280, + HYPERDATATYPE_LIST_STRING = 9281, + HYPERDATATYPE_LIST_INT64 = 9282, + HYPERDATATYPE_LIST_FLOAT = 9283, + + /* Set types */ + HYPERDATATYPE_SET_GENERIC = 9344, + HYPERDATATYPE_SET_STRING = 9345, + HYPERDATATYPE_SET_INT64 = 9346, + HYPERDATATYPE_SET_FLOAT = 9347, + + /* Map types */ + HYPERDATATYPE_MAP_GENERIC = 9408, + HYPERDATATYPE_MAP_STRING_KEYONLY = 9416, + HYPERDATATYPE_MAP_STRING_STRING = 9417, + HYPERDATATYPE_MAP_STRING_INT64 = 9418, + HYPERDATATYPE_MAP_STRING_FLOAT = 9419, + HYPERDATATYPE_MAP_INT64_KEYONLY = 9424, + HYPERDATATYPE_MAP_INT64_STRING = 9425, + HYPERDATATYPE_MAP_INT64_INT64 = 9426, + HYPERDATATYPE_MAP_INT64_FLOAT = 9427, + HYPERDATATYPE_MAP_FLOAT_KEYONLY = 9432, + HYPERDATATYPE_MAP_FLOAT_STRING = 9433, + HYPERDATATYPE_MAP_FLOAT_INT64 = 9434, + HYPERDATATYPE_MAP_FLOAT_FLOAT = 9435, + + /*Timestamp types */ + HYPERDATATYPE_TIMESTAMP_GENERIC = 9472, + HYPERDATATYPE_TIMESTAMP_SECOND = 9473, + HYPERDATATYPE_TIMESTAMP_MINUTE = 9474, + HYPERDATATYPE_TIMESTAMP_HOUR = 9475, + HYPERDATATYPE_TIMESTAMP_DAY = 9476, + HYPERDATATYPE_TIMESTAMP_WEEK = 9477, + HYPERDATATYPE_TIMESTAMP_MONTH = 9478, + + /* Special (internal) types */ + HYPERDATATYPE_MACAROON_SECRET = 9664, + + /* Returned if the server acts up */ + HYPERDATATYPE_GARBAGE = 9727 }; /* Predicate occupies [9728, 9856) */ enum hyperpredicate { - HYPERPREDICATE_FAIL = 9728, - HYPERPREDICATE_EQUALS = 9729, - HYPERPREDICATE_LESS_THAN = 9738, - HYPERPREDICATE_LESS_EQUAL = 9730, - HYPERPREDICATE_GREATER_EQUAL = 9731, - HYPERPREDICATE_GREATER_THAN = 9739, - HYPERPREDICATE_CONTAINS_LESS_THAN = 9732, /* alias of HYPERPREDICATE_LENGTH_LESS_EQUAL */ - HYPERPREDICATE_REGEX = 9733, - HYPERPREDICATE_LENGTH_EQUALS = 9734, - HYPERPREDICATE_LENGTH_LESS_EQUAL = 9735, - HYPERPREDICATE_LENGTH_GREATER_EQUAL = 9736, - HYPERPREDICATE_CONTAINS = 9737 - /* NEXT = 9740 */ + HYPERPREDICATE_FAIL = 9728, + HYPERPREDICATE_EQUALS = 9729, + HYPERPREDICATE_LESS_THAN = 9738, + HYPERPREDICATE_LESS_EQUAL = 9730, + HYPERPREDICATE_GREATER_EQUAL = 9731, + HYPERPREDICATE_GREATER_THAN = 9739, + HYPERPREDICATE_CONTAINS_LESS_THAN = 9732, /* alias of HYPERPREDICATE_LENGTH_LESS_EQUAL */ + HYPERPREDICATE_REGEX = 9733, + HYPERPREDICATE_LENGTH_EQUALS = 9734, + HYPERPREDICATE_LENGTH_LESS_EQUAL = 9735, + HYPERPREDICATE_LENGTH_GREATER_EQUAL = 9736, + HYPERPREDICATE_CONTAINS = 9737 + /* NEXT = 9740 */ }; #ifdef __cplusplus @@ -126,10 +126,10 @@ enum hyperpredicate /* C++ */ #include -std::ostream& -operator << (std::ostream& lhs, hyperdatatype rhs); -std::ostream& -operator << (std::ostream& lhs, hyperpredicate rhs); +std::ostream & +operator << (std::ostream &lhs, hyperdatatype rhs); +std::ostream & +operator << (std::ostream &lhs, hyperpredicate rhs); #endif /* __cplusplus */ #endif /* hyperdex_h_ */ diff --git a/include/hyperdex/admin.h b/include/hyperdex/admin.h index 1b7a33fb5..28453b244 100644 --- a/include/hyperdex/admin.h +++ b/include/hyperdex/admin.h @@ -45,165 +45,165 @@ struct hyperdex_admin; struct hyperdex_admin_perf_counter { - uint64_t id; - uint64_t time; - const char* property; - uint64_t measurement; + uint64_t id; + uint64_t time; + const char *property; + uint64_t measurement; }; /* hyperdex_admin_returncode occupies [8704, 8832) */ enum hyperdex_admin_returncode { - HYPERDEX_ADMIN_SUCCESS = 8704, - - /* Error conditions */ - HYPERDEX_ADMIN_NOMEM = 8768, - HYPERDEX_ADMIN_NONEPENDING = 8769, - HYPERDEX_ADMIN_POLLFAILED = 8770, - HYPERDEX_ADMIN_TIMEOUT = 8771, - HYPERDEX_ADMIN_INTERRUPTED = 8772, - HYPERDEX_ADMIN_SERVERERROR = 8773, - HYPERDEX_ADMIN_COORDFAIL = 8774, - HYPERDEX_ADMIN_BADSPACE = 8775, - HYPERDEX_ADMIN_DUPLICATE = 8776, - HYPERDEX_ADMIN_NOTFOUND = 8777, - HYPERDEX_ADMIN_LOCALERROR = 8778, - - /* This should never happen. It indicates a bug */ - HYPERDEX_ADMIN_INTERNAL = 8829, - HYPERDEX_ADMIN_EXCEPTION = 8830, - HYPERDEX_ADMIN_GARBAGE = 8831 + HYPERDEX_ADMIN_SUCCESS = 8704, + + /* Error conditions */ + HYPERDEX_ADMIN_NOMEM = 8768, + HYPERDEX_ADMIN_NONEPENDING = 8769, + HYPERDEX_ADMIN_POLLFAILED = 8770, + HYPERDEX_ADMIN_TIMEOUT = 8771, + HYPERDEX_ADMIN_INTERRUPTED = 8772, + HYPERDEX_ADMIN_SERVERERROR = 8773, + HYPERDEX_ADMIN_COORDFAIL = 8774, + HYPERDEX_ADMIN_BADSPACE = 8775, + HYPERDEX_ADMIN_DUPLICATE = 8776, + HYPERDEX_ADMIN_NOTFOUND = 8777, + HYPERDEX_ADMIN_LOCALERROR = 8778, + + /* This should never happen. It indicates a bug */ + HYPERDEX_ADMIN_INTERNAL = 8829, + HYPERDEX_ADMIN_EXCEPTION = 8830, + HYPERDEX_ADMIN_GARBAGE = 8831 }; -struct hyperdex_admin* -hyperdex_admin_create(const char* coordinator, uint16_t port); +struct hyperdex_admin * +hyperdex_admin_create(const char *coordinator, uint16_t port); void -hyperdex_admin_destroy(struct hyperdex_admin* admin); +hyperdex_admin_destroy(struct hyperdex_admin *admin); int64_t -hyperdex_admin_dump_config(struct hyperdex_admin* admin, - enum hyperdex_admin_returncode* status, - const char** config); +hyperdex_admin_dump_config(struct hyperdex_admin *admin, + enum hyperdex_admin_returncode *status, + const char **config); int64_t -hyperdex_admin_read_only(struct hyperdex_admin* admin, +hyperdex_admin_read_only(struct hyperdex_admin *admin, int ro, - enum hyperdex_admin_returncode* status); + enum hyperdex_admin_returncode *status); int64_t -hyperdex_admin_wait_until_stable(struct hyperdex_admin* admin, - enum hyperdex_admin_returncode* status); +hyperdex_admin_wait_until_stable(struct hyperdex_admin *admin, + enum hyperdex_admin_returncode *status); int64_t -hyperdex_admin_fault_tolerance(struct hyperdex_admin* admin, - const char* space, +hyperdex_admin_fault_tolerance(struct hyperdex_admin *admin, + const char *space, uint64_t ft, - enum hyperdex_admin_returncode* status); + enum hyperdex_admin_returncode *status); int -hyperdex_admin_validate_space(struct hyperdex_admin* admin, - const char* description, - enum hyperdex_admin_returncode* status); +hyperdex_admin_validate_space(struct hyperdex_admin *admin, + const char *description, + enum hyperdex_admin_returncode *status); int64_t -hyperdex_admin_add_space(struct hyperdex_admin* admin, - const char* description, - enum hyperdex_admin_returncode* status); +hyperdex_admin_add_space(struct hyperdex_admin *admin, + const char *description, + enum hyperdex_admin_returncode *status); int64_t -hyperdex_admin_rm_space(struct hyperdex_admin* admin, - const char* space, - enum hyperdex_admin_returncode* status); +hyperdex_admin_rm_space(struct hyperdex_admin *admin, + const char *space, + enum hyperdex_admin_returncode *status); int64_t -hyperdex_admin_mv_space(struct hyperdex_admin* admin, - const char* source, - const char* target, - enum hyperdex_admin_returncode* status); +hyperdex_admin_mv_space(struct hyperdex_admin *admin, + const char *source, + const char *target, + enum hyperdex_admin_returncode *status); int64_t -hyperdex_admin_list_spaces(struct hyperdex_admin* admin, - enum hyperdex_admin_returncode* status, - const char** spaces); +hyperdex_admin_list_spaces(struct hyperdex_admin *admin, + enum hyperdex_admin_returncode *status, + const char **spaces); int64_t -hyperdex_admin_list_indices(struct hyperdex_admin* admin, - const char* space, - enum hyperdex_admin_returncode* status, - const char** indexes); +hyperdex_admin_list_indices(struct hyperdex_admin *admin, + const char *space, + enum hyperdex_admin_returncode *status, + const char **indexes); int64_t -hyperdex_admin_list_subspaces(struct hyperdex_admin* admin, - const char* space, - enum hyperdex_admin_returncode* status, - const char** subspaces); +hyperdex_admin_list_subspaces(struct hyperdex_admin *admin, + const char *space, + enum hyperdex_admin_returncode *status, + const char **subspaces); int64_t -hyperdex_admin_add_index(struct hyperdex_admin* admin, - const char* space, - const char* attribute, - enum hyperdex_admin_returncode* status); +hyperdex_admin_add_index(struct hyperdex_admin *admin, + const char *space, + const char *attribute, + enum hyperdex_admin_returncode *status); int64_t -hyperdex_admin_rm_index(struct hyperdex_admin* admin, +hyperdex_admin_rm_index(struct hyperdex_admin *admin, uint64_t idxid, - enum hyperdex_admin_returncode* status); + enum hyperdex_admin_returncode *status); int64_t -hyperdex_admin_server_register(struct hyperdex_admin* admin, +hyperdex_admin_server_register(struct hyperdex_admin *admin, uint64_t token, - const char* address, - enum hyperdex_admin_returncode* status); + const char *address, + enum hyperdex_admin_returncode *status); int64_t -hyperdex_admin_server_online(struct hyperdex_admin* admin, +hyperdex_admin_server_online(struct hyperdex_admin *admin, uint64_t token, - enum hyperdex_admin_returncode* status); + enum hyperdex_admin_returncode *status); int64_t -hyperdex_admin_server_offline(struct hyperdex_admin* admin, +hyperdex_admin_server_offline(struct hyperdex_admin *admin, uint64_t token, - enum hyperdex_admin_returncode* status); + enum hyperdex_admin_returncode *status); int64_t -hyperdex_admin_server_forget(struct hyperdex_admin* admin, +hyperdex_admin_server_forget(struct hyperdex_admin *admin, uint64_t token, - enum hyperdex_admin_returncode* status); + enum hyperdex_admin_returncode *status); int64_t -hyperdex_admin_server_kill(struct hyperdex_admin* admin, +hyperdex_admin_server_kill(struct hyperdex_admin *admin, uint64_t token, - enum hyperdex_admin_returncode* status); + enum hyperdex_admin_returncode *status); int64_t -hyperdex_admin_backup(struct hyperdex_admin* admin, - const char* backup, - enum hyperdex_admin_returncode* status, - const char** backups); +hyperdex_admin_backup(struct hyperdex_admin *admin, + const char *backup, + enum hyperdex_admin_returncode *status, + const char **backups); int64_t -hyperdex_admin_enable_perf_counters(struct hyperdex_admin* admin, - enum hyperdex_admin_returncode* status, - struct hyperdex_admin_perf_counter* pc); +hyperdex_admin_enable_perf_counters(struct hyperdex_admin *admin, + enum hyperdex_admin_returncode *status, + struct hyperdex_admin_perf_counter *pc); void -hyperdex_admin_disable_perf_counters(struct hyperdex_admin* admin); +hyperdex_admin_disable_perf_counters(struct hyperdex_admin *admin); int64_t -hyperdex_admin_loop(struct hyperdex_admin* admin, int timeout, - enum hyperdex_admin_returncode* status); +hyperdex_admin_loop(struct hyperdex_admin *admin, int timeout, + enum hyperdex_admin_returncode *status); int -hyperdex_admin_raw_backup(const char* host, uint16_t port, - const char* name, - enum hyperdex_admin_returncode* status); +hyperdex_admin_raw_backup(const char *host, uint16_t port, + const char *name, + enum hyperdex_admin_returncode *status); -const char* -hyperdex_admin_error_message(struct hyperdex_admin* admin); -const char* -hyperdex_admin_error_location(struct hyperdex_admin* admin); +const char * +hyperdex_admin_error_message(struct hyperdex_admin *admin); +const char * +hyperdex_admin_error_location(struct hyperdex_admin *admin); -const char* +const char * hyperdex_admin_returncode_to_string(enum hyperdex_admin_returncode); #ifdef __cplusplus diff --git a/include/hyperdex/admin.hpp b/include/hyperdex/admin.hpp index adbe39775..2b8981d0c 100644 --- a/include/hyperdex/admin.hpp +++ b/include/hyperdex/admin.hpp @@ -39,89 +39,89 @@ namespace hyperdex class Admin { - public: - Admin(const char* coordinator, uint16_t port) - : m_adm(hyperdex_admin_create(coordinator, port)) - { - if (!m_adm) - { - throw std::bad_alloc(); - } - } - ~Admin() throw () - { - hyperdex_admin_destroy(m_adm); - } +public: + Admin(const char *coordinator, uint16_t port) + : m_adm(hyperdex_admin_create(coordinator, port)) + { + if (!m_adm) + { + throw std::bad_alloc(); + } + } + ~Admin() throw () + { + hyperdex_admin_destroy(m_adm); + } - public: - int64_t dump_config(enum hyperdex_admin_returncode* status, - const char** config) - { return hyperdex_admin_dump_config(m_adm, status, config); } - int64_t read_only(int ro, enum hyperdex_admin_returncode* status) - { return hyperdex_admin_read_only(m_adm, ro, status); } - int64_t wait_until_stable(enum hyperdex_admin_returncode* status) - { return hyperdex_admin_wait_until_stable(m_adm, status); } - int64_t fault_tolerance(const char* space, uint64_t ft, - enum hyperdex_admin_returncode* status) - { return hyperdex_admin_fault_tolerance(m_adm, space, ft, status); } - int validate_space(const char* description, - enum hyperdex_admin_returncode* status) - { return hyperdex_admin_validate_space(m_adm, description, status); } - int64_t add_space(const char* description, - enum hyperdex_admin_returncode* status) - { return hyperdex_admin_add_space(m_adm, description, status); } - int64_t rm_space(const char* name, - enum hyperdex_admin_returncode* status) - { return hyperdex_admin_rm_space(m_adm, name, status); } - int64_t mv_space(const char* source, const char* target, - enum hyperdex_admin_returncode* status) - { return hyperdex_admin_mv_space(m_adm, source, target, status); } - int64_t list_spaces(enum hyperdex_admin_returncode* status, - const char** spaces) - { return hyperdex_admin_list_spaces(m_adm, status, spaces); } - int64_t add_index(const char* space, const char* attr, - enum hyperdex_admin_returncode* status) - { return hyperdex_admin_add_index(m_adm, space, attr, status); } - int64_t rm_index(uint64_t idxid, enum hyperdex_admin_returncode* status) - { return hyperdex_admin_rm_index(m_adm, idxid, status); } - int64_t server_register(uint64_t token, const char* address, - enum hyperdex_admin_returncode* status) - { return hyperdex_admin_server_register(m_adm, token, address, status); } - int64_t server_online(uint64_t token, enum hyperdex_admin_returncode* status) - { return hyperdex_admin_server_online(m_adm, token, status); } - int64_t server_offline(uint64_t token, enum hyperdex_admin_returncode* status) - { return hyperdex_admin_server_offline(m_adm, token, status); } - int64_t server_forget(uint64_t token, enum hyperdex_admin_returncode* status) - { return hyperdex_admin_server_forget(m_adm, token, status); } - int64_t server_kill(uint64_t token, enum hyperdex_admin_returncode* status) - { return hyperdex_admin_server_kill(m_adm, token, status); } - int64_t backup(const char* name, enum hyperdex_admin_returncode* status, const char** backups) - { return hyperdex_admin_backup(m_adm, name, status, backups); } - int64_t enable_perf_counters(enum hyperdex_admin_returncode* status, - struct hyperdex_admin_perf_counter* pc) - { return hyperdex_admin_enable_perf_counters(m_adm, status, pc); } - void disable_perf_counters() - { return hyperdex_admin_disable_perf_counters(m_adm); } +public: + int64_t dump_config(enum hyperdex_admin_returncode *status, + const char **config) + { return hyperdex_admin_dump_config(m_adm, status, config); } + int64_t read_only(int ro, enum hyperdex_admin_returncode *status) + { return hyperdex_admin_read_only(m_adm, ro, status); } + int64_t wait_until_stable(enum hyperdex_admin_returncode *status) + { return hyperdex_admin_wait_until_stable(m_adm, status); } + int64_t fault_tolerance(const char *space, uint64_t ft, + enum hyperdex_admin_returncode *status) + { return hyperdex_admin_fault_tolerance(m_adm, space, ft, status); } + int validate_space(const char *description, + enum hyperdex_admin_returncode *status) + { return hyperdex_admin_validate_space(m_adm, description, status); } + int64_t add_space(const char *description, + enum hyperdex_admin_returncode *status) + { return hyperdex_admin_add_space(m_adm, description, status); } + int64_t rm_space(const char *name, + enum hyperdex_admin_returncode *status) + { return hyperdex_admin_rm_space(m_adm, name, status); } + int64_t mv_space(const char *source, const char *target, + enum hyperdex_admin_returncode *status) + { return hyperdex_admin_mv_space(m_adm, source, target, status); } + int64_t list_spaces(enum hyperdex_admin_returncode *status, + const char **spaces) + { return hyperdex_admin_list_spaces(m_adm, status, spaces); } + int64_t add_index(const char *space, const char *attr, + enum hyperdex_admin_returncode *status) + { return hyperdex_admin_add_index(m_adm, space, attr, status); } + int64_t rm_index(uint64_t idxid, enum hyperdex_admin_returncode *status) + { return hyperdex_admin_rm_index(m_adm, idxid, status); } + int64_t server_register(uint64_t token, const char *address, + enum hyperdex_admin_returncode *status) + { return hyperdex_admin_server_register(m_adm, token, address, status); } + int64_t server_online(uint64_t token, enum hyperdex_admin_returncode *status) + { return hyperdex_admin_server_online(m_adm, token, status); } + int64_t server_offline(uint64_t token, enum hyperdex_admin_returncode *status) + { return hyperdex_admin_server_offline(m_adm, token, status); } + int64_t server_forget(uint64_t token, enum hyperdex_admin_returncode *status) + { return hyperdex_admin_server_forget(m_adm, token, status); } + int64_t server_kill(uint64_t token, enum hyperdex_admin_returncode *status) + { return hyperdex_admin_server_kill(m_adm, token, status); } + int64_t backup(const char *name, enum hyperdex_admin_returncode *status, const char **backups) + { return hyperdex_admin_backup(m_adm, name, status, backups); } + int64_t enable_perf_counters(enum hyperdex_admin_returncode *status, + struct hyperdex_admin_perf_counter *pc) + { return hyperdex_admin_enable_perf_counters(m_adm, status, pc); } + void disable_perf_counters() + { return hyperdex_admin_disable_perf_counters(m_adm); } - public: - int64_t loop(int timeout, enum hyperdex_admin_returncode* status) - { return hyperdex_admin_loop(m_adm, timeout, status); } - std::string error_message() - { return hyperdex_admin_error_message(m_adm); } - std::string error_location() - { return hyperdex_admin_error_location(m_adm); } +public: + int64_t loop(int timeout, enum hyperdex_admin_returncode *status) + { return hyperdex_admin_loop(m_adm, timeout, status); } + std::string error_message() + { return hyperdex_admin_error_message(m_adm); } + std::string error_location() + { return hyperdex_admin_error_location(m_adm); } - private: - Admin(const Admin&); - Admin& operator = (const Admin&); +private: + Admin(const Admin &); + Admin &operator = (const Admin &); - private: - hyperdex_admin* m_adm; +private: + hyperdex_admin *m_adm; }; } // namespace hyperdex -std::ostream& -operator << (std::ostream& lhs, hyperdex_admin_returncode rhs); +std::ostream & +operator << (std::ostream &lhs, hyperdex_admin_returncode rhs); #endif // hyperdex_admin_hpp_ diff --git a/include/hyperdex/client.h b/include/hyperdex/client.h index f2b4a76ab..8e7f7cc34 100644 --- a/include/hyperdex/client.h +++ b/include/hyperdex/client.h @@ -45,1156 +45,1156 @@ struct hyperdex_client_microtransaction; struct hyperdex_client_attribute { - const char* attr; /* NULL-terminated */ - const char* value; - size_t value_sz; - enum hyperdatatype datatype; + const char *attr; /* NULL-terminated */ + const char *value; + size_t value_sz; + enum hyperdatatype datatype; }; struct hyperdex_client_map_attribute { - const char* attr; /* NULL-terminated */ - const char* map_key; - size_t map_key_sz; - enum hyperdatatype map_key_datatype; - const char* value; - size_t value_sz; - enum hyperdatatype value_datatype; + const char *attr; /* NULL-terminated */ + const char *map_key; + size_t map_key_sz; + enum hyperdatatype map_key_datatype; + const char *value; + size_t value_sz; + enum hyperdatatype value_datatype; }; struct hyperdex_client_attribute_check { - const char* attr; /* NULL-terminated */ - const char* value; - size_t value_sz; - enum hyperdatatype datatype; - enum hyperpredicate predicate; + const char *attr; /* NULL-terminated */ + const char *value; + size_t value_sz; + enum hyperdatatype datatype; + enum hyperpredicate predicate; }; /* hyperdex_client_returncode occupies [8448, 8576) */ enum hyperdex_client_returncode { - HYPERDEX_CLIENT_SUCCESS = 8448, - HYPERDEX_CLIENT_NOTFOUND = 8449, - HYPERDEX_CLIENT_SEARCHDONE = 8450, - HYPERDEX_CLIENT_CMPFAIL = 8451, - HYPERDEX_CLIENT_READONLY = 8452, - - /* Error conditions */ - HYPERDEX_CLIENT_UNKNOWNSPACE = 8512, - HYPERDEX_CLIENT_COORDFAIL = 8513, - HYPERDEX_CLIENT_SERVERERROR = 8514, - HYPERDEX_CLIENT_POLLFAILED = 8515, - HYPERDEX_CLIENT_OVERFLOW = 8516, - HYPERDEX_CLIENT_RECONFIGURE = 8517, - HYPERDEX_CLIENT_TIMEOUT = 8519, - HYPERDEX_CLIENT_UNKNOWNATTR = 8520, - HYPERDEX_CLIENT_DUPEATTR = 8521, - HYPERDEX_CLIENT_NONEPENDING = 8523, - HYPERDEX_CLIENT_DONTUSEKEY = 8524, - HYPERDEX_CLIENT_WRONGTYPE = 8525, - HYPERDEX_CLIENT_NOMEM = 8526, - HYPERDEX_CLIENT_INTERRUPTED = 8530, - HYPERDEX_CLIENT_CLUSTER_JUMP = 8531, - HYPERDEX_CLIENT_OFFLINE = 8533, - HYPERDEX_CLIENT_UNAUTHORIZED = 8534, - - /* This should never happen. It indicates a bug */ - HYPERDEX_CLIENT_INTERNAL = 8573, - HYPERDEX_CLIENT_EXCEPTION = 8574, - HYPERDEX_CLIENT_GARBAGE = 8575 + HYPERDEX_CLIENT_SUCCESS = 8448, + HYPERDEX_CLIENT_NOTFOUND = 8449, + HYPERDEX_CLIENT_SEARCHDONE = 8450, + HYPERDEX_CLIENT_CMPFAIL = 8451, + HYPERDEX_CLIENT_READONLY = 8452, + + /* Error conditions */ + HYPERDEX_CLIENT_UNKNOWNSPACE = 8512, + HYPERDEX_CLIENT_COORDFAIL = 8513, + HYPERDEX_CLIENT_SERVERERROR = 8514, + HYPERDEX_CLIENT_POLLFAILED = 8515, + HYPERDEX_CLIENT_OVERFLOW = 8516, + HYPERDEX_CLIENT_RECONFIGURE = 8517, + HYPERDEX_CLIENT_TIMEOUT = 8519, + HYPERDEX_CLIENT_UNKNOWNATTR = 8520, + HYPERDEX_CLIENT_DUPEATTR = 8521, + HYPERDEX_CLIENT_NONEPENDING = 8523, + HYPERDEX_CLIENT_DONTUSEKEY = 8524, + HYPERDEX_CLIENT_WRONGTYPE = 8525, + HYPERDEX_CLIENT_NOMEM = 8526, + HYPERDEX_CLIENT_INTERRUPTED = 8530, + HYPERDEX_CLIENT_CLUSTER_JUMP = 8531, + HYPERDEX_CLIENT_OFFLINE = 8533, + HYPERDEX_CLIENT_UNAUTHORIZED = 8534, + + /* This should never happen. It indicates a bug */ + HYPERDEX_CLIENT_INTERNAL = 8573, + HYPERDEX_CLIENT_EXCEPTION = 8574, + HYPERDEX_CLIENT_GARBAGE = 8575 }; #define HYPERDEX_ATTRIBUTE_SECRET "__secret" -struct hyperdex_client* -hyperdex_client_create(const char* coordinator, uint16_t port); -struct hyperdex_client* -hyperdex_client_create_conn_str(const char* conn_str); +struct hyperdex_client * +hyperdex_client_create(const char *coordinator, uint16_t port); +struct hyperdex_client * +hyperdex_client_create_conn_str(const char *conn_str); void -hyperdex_client_destroy(struct hyperdex_client* client); +hyperdex_client_destroy(struct hyperdex_client *client); struct macaroon; void -hyperdex_client_clear_auth_context(struct hyperdex_client* client); +hyperdex_client_clear_auth_context(struct hyperdex_client *client); void -hyperdex_client_set_auth_context(struct hyperdex_client* client, - const char** macaroons, size_t macaroons_sz); +hyperdex_client_set_auth_context(struct hyperdex_client *client, + const char **macaroons, size_t macaroons_sz); -struct hyperdex_client_microtransaction* -hyperdex_client_uxact_init(struct hyperdex_client* _cl, - const char* space, - enum hyperdex_client_returncode *status); +struct hyperdex_client_microtransaction * +hyperdex_client_uxact_init(struct hyperdex_client *_cl, + const char *space, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_commit(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction *transaction, - const char* key, size_t key_sz); - +hyperdex_client_uxact_commit(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *transaction, + const char *key, size_t key_sz); + int64_t -hyperdex_client_uxact_group_commit(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction *transaction, - const struct hyperdex_client_attribute_check *chks, size_t chks_sz, - uint64_t *count); - +hyperdex_client_uxact_group_commit(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *transaction, + const struct hyperdex_client_attribute_check *chks, size_t chks_sz, + uint64_t *count); + int64_t -hyperdex_client_uxact_cond_commit(struct hyperdex_client* _cl, - struct hyperdex_client_microtransaction *transaction, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check *chks, size_t chks_sz); +hyperdex_client_uxact_cond_commit(struct hyperdex_client *_cl, + struct hyperdex_client_microtransaction *transaction, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *chks, size_t chks_sz); int64_t -hyperdex_client_get(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - enum hyperdex_client_returncode* status, - const struct hyperdex_client_attribute** attrs, size_t* attrs_sz); +hyperdex_client_get(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + enum hyperdex_client_returncode *status, + const struct hyperdex_client_attribute **attrs, size_t *attrs_sz); int64_t -hyperdex_client_get_partial(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const char** attrnames, size_t attrnames_sz, - enum hyperdex_client_returncode* status, - const struct hyperdex_client_attribute** attrs, size_t* attrs_sz); +hyperdex_client_get_partial(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const char **attrnames, size_t attrnames_sz, + enum hyperdex_client_returncode *status, + const struct hyperdex_client_attribute **attrs, size_t *attrs_sz); int64_t -hyperdex_client_put(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_put(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_put(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_put(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_put(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_put(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_put_or_create(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_put_or_create(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_put(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_put(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_put_if_not_exist(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_put_if_not_exist(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_del(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_del(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_del(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_del(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_del(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_del(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_atomic_add(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_atomic_add(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_atomic_add(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_atomic_add(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_atomic_add(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_atomic_add(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_atomic_add(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_atomic_add(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_atomic_sub(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_atomic_sub(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_atomic_sub(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_atomic_sub(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_atomic_sub(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_atomic_sub(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_atomic_sub(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_atomic_sub(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_atomic_mul(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_atomic_mul(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_atomic_mul(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_atomic_mul(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_atomic_mul(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_atomic_mul(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_atomic_mul(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_atomic_mul(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_atomic_div(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_atomic_div(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_atomic_div(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_atomic_div(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_atomic_div(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_atomic_div(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_atomic_div(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_atomic_div(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_atomic_mod(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_atomic_mod(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_atomic_mod(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_atomic_mod(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_atomic_mod(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_atomic_mod(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_atomic_and(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_atomic_and(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_atomic_and(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_atomic_and(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_atomic_and(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_atomic_and(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_atomic_and(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_atomic_and(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_atomic_or(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_atomic_or(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_atomic_or(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_atomic_or(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_atomic_or(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_atomic_or(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_atomic_or(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_atomic_or(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_atomic_xor(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_atomic_xor(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_atomic_xor(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_atomic_xor(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_atomic_xor(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_atomic_xor(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_atomic_min(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_atomic_min(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_atomic_min(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_atomic_min(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_atomic_min(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_atomic_min(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_atomic_max(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_atomic_max(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_atomic_max(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_atomic_max(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_atomic_max(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_atomic_max(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_string_prepend(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_string_prepend(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_string_prepend(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_string_prepend(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_string_prepend(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_string_prepend(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_string_prepend(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_string_prepend(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_string_append(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_string_append(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_string_append(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_string_append(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_string_append(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_string_append(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_string_append(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_string_append(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_string_ltrim(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_string_ltrim(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_string_ltrim(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_string_ltrim(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_string_ltrim(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_string_ltrim(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_string_ltrim(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_string_ltrim(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_string_rtrim(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_string_rtrim(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_string_rtrim(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_string_rtrim(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_string_rtrim(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_string_rtrim(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_string_rtrim(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_string_rtrim(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_list_lpush(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_list_lpush(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_list_lpush(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_list_lpush(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_list_lpush(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_list_lpush(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_list_lpush(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_list_lpush(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_list_rpush(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_list_rpush(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_list_rpush(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_list_rpush(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_list_rpush(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_list_rpush(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_list_rpush(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_list_rpush(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_set_add(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_set_add(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_set_add(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_set_add(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_set_add(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_set_add(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_set_remove(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_set_remove(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_set_remove(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_set_remove(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_set_remove(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_set_remove(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_set_intersect(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_set_intersect(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_set_intersect(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_set_intersect(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_set_intersect(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_set_intersect(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_set_union(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_set_union(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_set_union(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_set_union(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_set_union(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_set_union(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_document_rename(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_document_rename(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_document_rename(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_document_rename(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_document_rename(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_document_rename(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_document_rename(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_document_rename(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_document_unset(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_document_unset(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_uxact_document_unset(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_document_unset(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_cond_document_unset(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_document_unset(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_document_unset(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_document_unset(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_map_add(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_map_add(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_map_add(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_map_add(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_map_add(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_map_add(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_map_remove(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_map_remove(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_map_remove(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_map_remove(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_map_remove(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_map_remove(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_map_atomic_add(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_map_atomic_add(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_map_atomic_add(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_map_atomic_add(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_map_atomic_add(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_map_atomic_add(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_map_atomic_sub(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_map_atomic_sub(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_map_atomic_sub(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_map_atomic_sub(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_map_atomic_sub(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_map_atomic_sub(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_map_atomic_mul(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_map_atomic_mul(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_map_atomic_mul(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_map_atomic_mul(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_map_atomic_mul(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_map_atomic_mul(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_map_atomic_div(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_map_atomic_div(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_map_atomic_div(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_map_atomic_div(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_map_atomic_div(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_map_atomic_div(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_map_atomic_mod(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_map_atomic_mod(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_map_atomic_mod(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_map_atomic_mod(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_map_atomic_mod(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_map_atomic_mod(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_map_atomic_and(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_map_atomic_and(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_map_atomic_and(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_map_atomic_and(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_map_atomic_and(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_map_atomic_and(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_map_atomic_or(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_map_atomic_or(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_map_atomic_or(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_map_atomic_or(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_map_atomic_or(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_map_atomic_or(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_map_atomic_xor(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_map_atomic_xor(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_map_atomic_xor(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_map_atomic_xor(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_map_atomic_xor(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_map_atomic_xor(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_map_string_prepend(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_map_string_prepend(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_map_string_prepend(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_map_string_prepend(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_map_string_prepend(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_map_string_prepend(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_map_string_append(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_map_string_append(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_map_string_append(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_map_string_append(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_map_string_append(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_map_string_append(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_map_atomic_min(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_map_atomic_min(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_map_atomic_min(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_map_atomic_min(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_map_atomic_min(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_map_atomic_min(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_uxact_atomic_min(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_atomic_min(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_map_atomic_max(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_map_atomic_max(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_cond_map_atomic_max(struct hyperdex_client* client, - const char* space, - const char* key, size_t key_sz, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status); +hyperdex_client_cond_map_atomic_max(struct hyperdex_client *client, + const char *space, + const char *key, size_t key_sz, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status); int64_t -hyperdex_client_group_map_atomic_max(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const struct hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_group_map_atomic_max(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const struct hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_uxact_atomic_max(struct hyperdex_client* client, - struct hyperdex_client_microtransaction* microtransaction, - const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_uxact_atomic_max(struct hyperdex_client *client, + struct hyperdex_client_microtransaction *microtransaction, + const struct hyperdex_client_attribute *attrs, size_t attrs_sz); int64_t -hyperdex_client_search(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - enum hyperdex_client_returncode* status, - const struct hyperdex_client_attribute** attrs, size_t* attrs_sz); +hyperdex_client_search(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + enum hyperdex_client_returncode *status, + const struct hyperdex_client_attribute **attrs, size_t *attrs_sz); int64_t -hyperdex_client_search_describe(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - enum hyperdex_client_returncode* status, - const char** description); +hyperdex_client_search_describe(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + enum hyperdex_client_returncode *status, + const char **description); int64_t -hyperdex_client_sorted_search(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const char* sort_by, +hyperdex_client_sorted_search(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const char *sort_by, uint64_t limit, int maxmin, - enum hyperdex_client_returncode* status, - const struct hyperdex_client_attribute** attrs, size_t* attrs_sz); + enum hyperdex_client_returncode *status, + const struct hyperdex_client_attribute **attrs, size_t *attrs_sz); int64_t -hyperdex_client_count(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - enum hyperdex_client_returncode* status, - uint64_t* count); +hyperdex_client_count(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + enum hyperdex_client_returncode *status, + uint64_t *count); int64_t -hyperdex_client_sum(struct hyperdex_client* client, - const char* space, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const char* sum_key, - enum hyperdex_client_returncode* status, - uint64_t* sum_count); +hyperdex_client_sum(struct hyperdex_client *client, + const char *space, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const char *sum_key, + enum hyperdex_client_returncode *status, + uint64_t *sum_count); int64_t -hyperdex_client_loop(struct hyperdex_client* client, int timeout, - enum hyperdex_client_returncode* status); +hyperdex_client_loop(struct hyperdex_client *client, int timeout, + enum hyperdex_client_returncode *status); int -hyperdex_client_poll_fd(struct hyperdex_client* client); +hyperdex_client_poll_fd(struct hyperdex_client *client); int -hyperdex_client_block(struct hyperdex_client* client, int timeout); +hyperdex_client_block(struct hyperdex_client *client, int timeout); enum hyperdatatype -hyperdex_client_attribute_type(struct hyperdex_client* client, - const char* space, const char* name, - enum hyperdex_client_returncode* status); +hyperdex_client_attribute_type(struct hyperdex_client *client, + const char *space, const char *name, + enum hyperdex_client_returncode *status); -const char* -hyperdex_client_error_message(struct hyperdex_client* client); +const char * +hyperdex_client_error_message(struct hyperdex_client *client); -const char* -hyperdex_client_error_location(struct hyperdex_client* client); +const char * +hyperdex_client_error_location(struct hyperdex_client *client); -const char* +const char * hyperdex_client_returncode_to_string(enum hyperdex_client_returncode); void -hyperdex_client_destroy_attrs(const struct hyperdex_client_attribute* attrs, size_t attrs_sz); +hyperdex_client_destroy_attrs(const struct hyperdex_client_attribute *attrs, size_t attrs_sz); #ifdef __cplusplus } /* extern "C" */ diff --git a/include/hyperdex/client.hpp b/include/hyperdex/client.hpp index f4233f337..54e4c3a58 100644 --- a/include/hyperdex/client.hpp +++ b/include/hyperdex/client.hpp @@ -38,753 +38,753 @@ namespace hyperdex class Client { - public: - Client(const char* coordinator, uint16_t port) - : m_cl(hyperdex_client_create(coordinator, port)) - { - if (!m_cl) - { - throw std::bad_alloc(); - } - } - Client(const char* conn_str) - : m_cl(hyperdex_client_create_conn_str(conn_str)) - { - if (!m_cl) - { - throw std::bad_alloc(); - } - } - ~Client() throw () - { - hyperdex_client_destroy(m_cl); - } +public: + Client(const char *coordinator, uint16_t port) + : m_cl(hyperdex_client_create(coordinator, port)) + { + if (!m_cl) + { + throw std::bad_alloc(); + } + } + Client(const char *conn_str) + : m_cl(hyperdex_client_create_conn_str(conn_str)) + { + if (!m_cl) + { + throw std::bad_alloc(); + } + } + ~Client() throw () + { + hyperdex_client_destroy(m_cl); + } - public: - int64_t get(const char* space, - const char* key, size_t key_sz, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz) - { return hyperdex_client_get(m_cl, space, key, key_sz, status, attrs, attrs_sz); } - int64_t get_partial(const char* space, - const char* key, size_t key_sz, - const char** attrnames, size_t attrnames_sz, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz) - { return hyperdex_client_get_partial(m_cl, space, key, key_sz, attrnames, attrnames_sz, status, attrs, attrs_sz); } - int64_t put(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_put(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_put(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_put(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t cond_put_or_create(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_put_or_create(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_put(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_put(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t put_if_not_exist(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_put_if_not_exist(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t del(const char* space, - const char* key, size_t key_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_del(m_cl, space, key, key_sz, status); } - int64_t cond_del(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_del(m_cl, space, key, key_sz, checks, checks_sz, status); } - int64_t group_del(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_del(m_cl, space, checks, checks_sz, status, count); } - int64_t atomic_add(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_atomic_add(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_atomic_add(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_atomic_add(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_atomic_add(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_atomic_add(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t atomic_sub(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_atomic_sub(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_atomic_sub(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_atomic_sub(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_atomic_sub(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_atomic_sub(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t atomic_mul(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_atomic_mul(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_atomic_mul(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_atomic_mul(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_atomic_mul(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_atomic_mul(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t atomic_div(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_atomic_div(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_atomic_div(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_atomic_div(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_atomic_div(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_atomic_div(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t atomic_mod(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_atomic_mod(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_atomic_mod(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_atomic_mod(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_atomic_mod(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_atomic_mod(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t atomic_and(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_atomic_and(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_atomic_and(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_atomic_and(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_atomic_and(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_atomic_and(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t atomic_or(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_atomic_or(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_atomic_or(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_atomic_or(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_atomic_or(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_atomic_or(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t atomic_xor(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_atomic_xor(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_atomic_xor(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_atomic_xor(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_atomic_xor(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_atomic_xor(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t atomic_min(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_atomic_min(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_atomic_min(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_atomic_min(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_atomic_min(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_atomic_min(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t atomic_max(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_atomic_max(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_atomic_max(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_atomic_max(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_atomic_max(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_atomic_max(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t string_prepend(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_string_prepend(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_string_prepend(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_string_prepend(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_string_prepend(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_string_prepend(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t string_append(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_string_append(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_string_append(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_string_append(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_string_append(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_string_append(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t string_ltrim(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_string_ltrim(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_string_ltrim(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_string_ltrim(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_string_ltrim(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_string_ltrim(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t string_rtrim(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_string_rtrim(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_string_rtrim(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_string_rtrim(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_string_rtrim(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_string_rtrim(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t list_lpush(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_list_lpush(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_list_lpush(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_list_lpush(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_list_lpush(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_list_lpush(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t list_rpush(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_list_rpush(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_list_rpush(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_list_rpush(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_list_rpush(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_list_rpush(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t set_add(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_set_add(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_set_add(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_set_add(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_set_add(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_set_add(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t set_remove(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_set_remove(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_set_remove(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_set_remove(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_set_remove(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_set_remove(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t set_intersect(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_set_intersect(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_set_intersect(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_set_intersect(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_set_intersect(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_set_intersect(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t set_union(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_set_union(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_set_union(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_set_union(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_set_union(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_set_union(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t document_rename(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_document_rename(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_document_rename(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_document_rename(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_document_rename(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_document_rename(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t document_unset(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_document_unset(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_document_unset(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_document_unset(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_document_unset(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_document_unset(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t map_add(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_map_add(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } - int64_t cond_map_add(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_map_add(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } - int64_t group_map_add(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_map_add(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } - int64_t map_remove(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_map_remove(m_cl, space, key, key_sz, attrs, attrs_sz, status); } - int64_t cond_map_remove(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_map_remove(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } - int64_t group_map_remove(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_attribute* attrs, size_t attrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_map_remove(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } - int64_t map_atomic_add(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_map_atomic_add(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } - int64_t cond_map_atomic_add(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_map_atomic_add(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } - int64_t group_map_atomic_add(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_map_atomic_add(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } - int64_t map_atomic_sub(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_map_atomic_sub(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } - int64_t cond_map_atomic_sub(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_map_atomic_sub(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } - int64_t group_map_atomic_sub(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_map_atomic_sub(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } - int64_t map_atomic_mul(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_map_atomic_mul(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } - int64_t cond_map_atomic_mul(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_map_atomic_mul(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } - int64_t group_map_atomic_mul(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_map_atomic_mul(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } - int64_t map_atomic_div(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_map_atomic_div(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } - int64_t cond_map_atomic_div(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_map_atomic_div(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } - int64_t group_map_atomic_div(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_map_atomic_div(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } - int64_t map_atomic_mod(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_map_atomic_mod(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } - int64_t cond_map_atomic_mod(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_map_atomic_mod(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } - int64_t group_map_atomic_mod(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_map_atomic_mod(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } - int64_t map_atomic_and(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_map_atomic_and(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } - int64_t cond_map_atomic_and(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_map_atomic_and(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } - int64_t group_map_atomic_and(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_map_atomic_and(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } - int64_t map_atomic_or(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_map_atomic_or(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } - int64_t cond_map_atomic_or(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_map_atomic_or(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } - int64_t group_map_atomic_or(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_map_atomic_or(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } - int64_t map_atomic_xor(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_map_atomic_xor(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } - int64_t cond_map_atomic_xor(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_map_atomic_xor(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } - int64_t group_map_atomic_xor(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_map_atomic_xor(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } - int64_t map_string_prepend(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_map_string_prepend(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } - int64_t cond_map_string_prepend(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_map_string_prepend(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } - int64_t group_map_string_prepend(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_map_string_prepend(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } - int64_t map_string_append(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_map_string_append(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } - int64_t cond_map_string_append(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_map_string_append(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } - int64_t group_map_string_append(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_map_string_append(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } - int64_t map_atomic_min(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_map_atomic_min(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } - int64_t cond_map_atomic_min(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_map_atomic_min(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } - int64_t group_map_atomic_min(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_map_atomic_min(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } - int64_t map_atomic_max(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_map_atomic_max(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } - int64_t cond_map_atomic_max(const char* space, - const char* key, size_t key_sz, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status) - { return hyperdex_client_cond_map_atomic_max(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } - int64_t group_map_atomic_max(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const hyperdex_client_map_attribute* mapattrs, size_t mapattrs_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_group_map_atomic_max(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } - int64_t search(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz) - { return hyperdex_client_search(m_cl, space, checks, checks_sz, status, attrs, attrs_sz); } - int64_t search_describe(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - hyperdex_client_returncode* status, - const char** description) - { return hyperdex_client_search_describe(m_cl, space, checks, checks_sz, status, description); } - int64_t sorted_search(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const char* sort_by, - uint64_t limit, - int maxmin, - hyperdex_client_returncode* status, - const hyperdex_client_attribute** attrs, size_t* attrs_sz) - { return hyperdex_client_sorted_search(m_cl, space, checks, checks_sz, sort_by, limit, maxmin, status, attrs, attrs_sz); } - int64_t count(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_count(m_cl, space, checks, checks_sz, status, count); } - int64_t sum(const char* space, - const hyperdex_client_attribute_check* checks, size_t checks_sz, - const char* sum_key, - hyperdex_client_returncode* status, - uint64_t* count) - { return hyperdex_client_sum(m_cl, space, checks, checks_sz, sum_key, status, count); } +public: + int64_t get(const char *space, + const char *key, size_t key_sz, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz) + { return hyperdex_client_get(m_cl, space, key, key_sz, status, attrs, attrs_sz); } + int64_t get_partial(const char *space, + const char *key, size_t key_sz, + const char **attrnames, size_t attrnames_sz, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz) + { return hyperdex_client_get_partial(m_cl, space, key, key_sz, attrnames, attrnames_sz, status, attrs, attrs_sz); } + int64_t put(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_put(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_put(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_put(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t cond_put_or_create(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_put_or_create(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_put(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_put(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t put_if_not_exist(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_put_if_not_exist(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t del(const char *space, + const char *key, size_t key_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_del(m_cl, space, key, key_sz, status); } + int64_t cond_del(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_del(m_cl, space, key, key_sz, checks, checks_sz, status); } + int64_t group_del(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_del(m_cl, space, checks, checks_sz, status, count); } + int64_t atomic_add(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_atomic_add(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_atomic_add(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_atomic_add(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_atomic_add(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_atomic_add(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t atomic_sub(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_atomic_sub(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_atomic_sub(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_atomic_sub(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_atomic_sub(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_atomic_sub(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t atomic_mul(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_atomic_mul(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_atomic_mul(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_atomic_mul(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_atomic_mul(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_atomic_mul(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t atomic_div(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_atomic_div(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_atomic_div(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_atomic_div(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_atomic_div(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_atomic_div(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t atomic_mod(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_atomic_mod(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_atomic_mod(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_atomic_mod(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_atomic_mod(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_atomic_mod(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t atomic_and(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_atomic_and(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_atomic_and(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_atomic_and(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_atomic_and(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_atomic_and(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t atomic_or(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_atomic_or(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_atomic_or(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_atomic_or(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_atomic_or(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_atomic_or(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t atomic_xor(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_atomic_xor(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_atomic_xor(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_atomic_xor(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_atomic_xor(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_atomic_xor(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t atomic_min(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_atomic_min(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_atomic_min(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_atomic_min(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_atomic_min(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_atomic_min(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t atomic_max(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_atomic_max(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_atomic_max(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_atomic_max(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_atomic_max(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_atomic_max(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t string_prepend(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_string_prepend(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_string_prepend(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_string_prepend(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_string_prepend(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_string_prepend(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t string_append(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_string_append(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_string_append(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_string_append(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_string_append(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_string_append(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t string_ltrim(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_string_ltrim(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_string_ltrim(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_string_ltrim(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_string_ltrim(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_string_ltrim(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t string_rtrim(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_string_rtrim(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_string_rtrim(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_string_rtrim(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_string_rtrim(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_string_rtrim(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t list_lpush(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_list_lpush(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_list_lpush(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_list_lpush(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_list_lpush(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_list_lpush(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t list_rpush(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_list_rpush(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_list_rpush(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_list_rpush(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_list_rpush(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_list_rpush(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t set_add(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_set_add(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_set_add(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_set_add(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_set_add(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_set_add(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t set_remove(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_set_remove(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_set_remove(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_set_remove(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_set_remove(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_set_remove(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t set_intersect(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_set_intersect(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_set_intersect(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_set_intersect(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_set_intersect(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_set_intersect(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t set_union(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_set_union(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_set_union(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_set_union(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_set_union(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_set_union(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t document_rename(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_document_rename(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_document_rename(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_document_rename(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_document_rename(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_document_rename(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t document_unset(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_document_unset(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_document_unset(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_document_unset(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_document_unset(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_document_unset(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t map_add(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_map_add(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } + int64_t cond_map_add(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_map_add(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } + int64_t group_map_add(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_map_add(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } + int64_t map_remove(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_map_remove(m_cl, space, key, key_sz, attrs, attrs_sz, status); } + int64_t cond_map_remove(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_map_remove(m_cl, space, key, key_sz, checks, checks_sz, attrs, attrs_sz, status); } + int64_t group_map_remove(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_attribute *attrs, size_t attrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_map_remove(m_cl, space, checks, checks_sz, attrs, attrs_sz, status, count); } + int64_t map_atomic_add(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_map_atomic_add(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } + int64_t cond_map_atomic_add(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_map_atomic_add(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } + int64_t group_map_atomic_add(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_map_atomic_add(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } + int64_t map_atomic_sub(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_map_atomic_sub(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } + int64_t cond_map_atomic_sub(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_map_atomic_sub(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } + int64_t group_map_atomic_sub(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_map_atomic_sub(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } + int64_t map_atomic_mul(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_map_atomic_mul(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } + int64_t cond_map_atomic_mul(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_map_atomic_mul(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } + int64_t group_map_atomic_mul(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_map_atomic_mul(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } + int64_t map_atomic_div(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_map_atomic_div(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } + int64_t cond_map_atomic_div(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_map_atomic_div(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } + int64_t group_map_atomic_div(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_map_atomic_div(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } + int64_t map_atomic_mod(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_map_atomic_mod(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } + int64_t cond_map_atomic_mod(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_map_atomic_mod(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } + int64_t group_map_atomic_mod(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_map_atomic_mod(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } + int64_t map_atomic_and(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_map_atomic_and(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } + int64_t cond_map_atomic_and(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_map_atomic_and(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } + int64_t group_map_atomic_and(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_map_atomic_and(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } + int64_t map_atomic_or(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_map_atomic_or(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } + int64_t cond_map_atomic_or(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_map_atomic_or(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } + int64_t group_map_atomic_or(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_map_atomic_or(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } + int64_t map_atomic_xor(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_map_atomic_xor(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } + int64_t cond_map_atomic_xor(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_map_atomic_xor(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } + int64_t group_map_atomic_xor(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_map_atomic_xor(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } + int64_t map_string_prepend(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_map_string_prepend(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } + int64_t cond_map_string_prepend(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_map_string_prepend(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } + int64_t group_map_string_prepend(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_map_string_prepend(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } + int64_t map_string_append(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_map_string_append(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } + int64_t cond_map_string_append(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_map_string_append(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } + int64_t group_map_string_append(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_map_string_append(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } + int64_t map_atomic_min(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_map_atomic_min(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } + int64_t cond_map_atomic_min(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_map_atomic_min(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } + int64_t group_map_atomic_min(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_map_atomic_min(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } + int64_t map_atomic_max(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_map_atomic_max(m_cl, space, key, key_sz, mapattrs, mapattrs_sz, status); } + int64_t cond_map_atomic_max(const char *space, + const char *key, size_t key_sz, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status) + { return hyperdex_client_cond_map_atomic_max(m_cl, space, key, key_sz, checks, checks_sz, mapattrs, mapattrs_sz, status); } + int64_t group_map_atomic_max(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const hyperdex_client_map_attribute *mapattrs, size_t mapattrs_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_group_map_atomic_max(m_cl, space, checks, checks_sz, mapattrs, mapattrs_sz, status, count); } + int64_t search(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz) + { return hyperdex_client_search(m_cl, space, checks, checks_sz, status, attrs, attrs_sz); } + int64_t search_describe(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + hyperdex_client_returncode *status, + const char **description) + { return hyperdex_client_search_describe(m_cl, space, checks, checks_sz, status, description); } + int64_t sorted_search(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const char *sort_by, + uint64_t limit, + int maxmin, + hyperdex_client_returncode *status, + const hyperdex_client_attribute **attrs, size_t *attrs_sz) + { return hyperdex_client_sorted_search(m_cl, space, checks, checks_sz, sort_by, limit, maxmin, status, attrs, attrs_sz); } + int64_t count(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_count(m_cl, space, checks, checks_sz, status, count); } + int64_t sum(const char *space, + const hyperdex_client_attribute_check *checks, size_t checks_sz, + const char *sum_key, + hyperdex_client_returncode *status, + uint64_t *count) + { return hyperdex_client_sum(m_cl, space, checks, checks_sz, sum_key, status, count); } - public: - void clear_auth_context() - { return hyperdex_client_clear_auth_context(m_cl); } - void set_auth_context(const char** macaroons, size_t macaroons_sz) - { return hyperdex_client_set_auth_context(m_cl, macaroons, macaroons_sz); } +public: + void clear_auth_context() + { return hyperdex_client_clear_auth_context(m_cl); } + void set_auth_context(const char **macaroons, size_t macaroons_sz) + { return hyperdex_client_set_auth_context(m_cl, macaroons, macaroons_sz); } - public: - int64_t loop(int timeout, hyperdex_client_returncode* status) - { return hyperdex_client_loop(m_cl, timeout, status); } - int poll_fd() - { return hyperdex_client_poll_fd(m_cl); } - int block(int timeout) - { return hyperdex_client_block(m_cl, timeout); } - std::string error_message() - { return hyperdex_client_error_message(m_cl); } - std::string error_location() - { return hyperdex_client_error_location(m_cl); } +public: + int64_t loop(int timeout, hyperdex_client_returncode *status) + { return hyperdex_client_loop(m_cl, timeout, status); } + int poll_fd() + { return hyperdex_client_poll_fd(m_cl); } + int block(int timeout) + { return hyperdex_client_block(m_cl, timeout); } + std::string error_message() + { return hyperdex_client_error_message(m_cl); } + std::string error_location() + { return hyperdex_client_error_location(m_cl); } - private: - Client(const Client&); - Client& operator = (const Client&); +private: + Client(const Client &); + Client &operator = (const Client &); - private: - hyperdex_client* m_cl; +private: + hyperdex_client *m_cl; }; } // namespace hyperdex -std::ostream& -operator << (std::ostream& lhs, hyperdex_client_returncode rhs); +std::ostream & +operator << (std::ostream &lhs, hyperdex_client_returncode rhs); #endif // hyperdex_client_hpp_ diff --git a/include/hyperdex/datastructures.h b/include/hyperdex/datastructures.h index 5949ae134..5fa8c406d 100644 --- a/include/hyperdex/datastructures.h +++ b/include/hyperdex/datastructures.h @@ -46,197 +46,197 @@ struct hyperdex_ds_map; struct hyperdex_ds_iterator { - enum hyperdatatype datatype; - const char* value; - const char* value_end; - const char* progress; + enum hyperdatatype datatype; + const char *value; + const char *value_end; + const char *progress; }; /* errors */ enum hyperdex_ds_returncode { - HYPERDEX_DS_SUCCESS, - HYPERDEX_DS_NOMEM, - HYPERDEX_DS_MIXED_TYPES, - HYPERDEX_DS_WRONG_STATE, - HYPERDEX_DS_STRING_TOO_LONG + HYPERDEX_DS_SUCCESS, + HYPERDEX_DS_NOMEM, + HYPERDEX_DS_MIXED_TYPES, + HYPERDEX_DS_WRONG_STATE, + HYPERDEX_DS_STRING_TOO_LONG }; /* arena manipulation */ -struct hyperdex_ds_arena* +struct hyperdex_ds_arena * hyperdex_ds_arena_create(); void -hyperdex_ds_arena_destroy(struct hyperdex_ds_arena* arena); +hyperdex_ds_arena_destroy(struct hyperdex_ds_arena *arena); -void* -hyperdex_ds_malloc(struct hyperdex_ds_arena* arena, size_t sz); +void * +hyperdex_ds_malloc(struct hyperdex_ds_arena *arena, size_t sz); /* client parameters */ -struct hyperdex_client_attribute* -hyperdex_ds_allocate_attribute(struct hyperdex_ds_arena* arena, size_t sz); +struct hyperdex_client_attribute * +hyperdex_ds_allocate_attribute(struct hyperdex_ds_arena *arena, size_t sz); -struct hyperdex_client_attribute_check* -hyperdex_ds_allocate_attribute_check(struct hyperdex_ds_arena* arena, size_t sz); +struct hyperdex_client_attribute_check * +hyperdex_ds_allocate_attribute_check(struct hyperdex_ds_arena *arena, size_t sz); -struct hyperdex_client_map_attribute* -hyperdex_ds_allocate_map_attribute(struct hyperdex_ds_arena* arena, size_t sz); +struct hyperdex_client_map_attribute * +hyperdex_ds_allocate_map_attribute(struct hyperdex_ds_arena *arena, size_t sz); /* pack/unpack ints/floats */ void -hyperdex_ds_pack_int(int64_t num, char* buf); +hyperdex_ds_pack_int(int64_t num, char *buf); int -hyperdex_ds_unpack_int(const char* buf, size_t buf_sz, int64_t* num); +hyperdex_ds_unpack_int(const char *buf, size_t buf_sz, int64_t *num); void -hyperdex_ds_pack_float(double num, char* buf); +hyperdex_ds_pack_float(double num, char *buf); int -hyperdex_ds_unpack_float(const char* buf, size_t buf_sz, double* num); +hyperdex_ds_unpack_float(const char *buf, size_t buf_sz, double *num); /* copy strings/ints/floats */ int -hyperdex_ds_copy_string(struct hyperdex_ds_arena* arena, - const char* str, size_t str_sz, - enum hyperdex_ds_returncode* status, - const char** value, size_t* value_sz); +hyperdex_ds_copy_string(struct hyperdex_ds_arena *arena, + const char *str, size_t str_sz, + enum hyperdex_ds_returncode *status, + const char **value, size_t *value_sz); int -hyperdex_ds_copy_int(struct hyperdex_ds_arena* arena, int64_t num, - enum hyperdex_ds_returncode* status, - const char** value, size_t* value_sz); +hyperdex_ds_copy_int(struct hyperdex_ds_arena *arena, int64_t num, + enum hyperdex_ds_returncode *status, + const char **value, size_t *value_sz); int -hyperdex_ds_copy_float(struct hyperdex_ds_arena* arena, double num, - enum hyperdex_ds_returncode* status, - const char** value, size_t* value_sz); +hyperdex_ds_copy_float(struct hyperdex_ds_arena *arena, double num, + enum hyperdex_ds_returncode *status, + const char **value, size_t *value_sz); /* pack lists */ -struct hyperdex_ds_list* -hyperdex_ds_allocate_list(struct hyperdex_ds_arena* arena); +struct hyperdex_ds_list * +hyperdex_ds_allocate_list(struct hyperdex_ds_arena *arena); int -hyperdex_ds_list_append_string(struct hyperdex_ds_list* list, - const char* str, size_t str_sz, - enum hyperdex_ds_returncode* status); +hyperdex_ds_list_append_string(struct hyperdex_ds_list *list, + const char *str, size_t str_sz, + enum hyperdex_ds_returncode *status); int -hyperdex_ds_list_append_int(struct hyperdex_ds_list* list, +hyperdex_ds_list_append_int(struct hyperdex_ds_list *list, int64_t num, - enum hyperdex_ds_returncode* status); + enum hyperdex_ds_returncode *status); int -hyperdex_ds_list_append_float(struct hyperdex_ds_list* list, +hyperdex_ds_list_append_float(struct hyperdex_ds_list *list, double num, - enum hyperdex_ds_returncode* status); + enum hyperdex_ds_returncode *status); int -hyperdex_ds_list_finalize(struct hyperdex_ds_list* list, - enum hyperdex_ds_returncode* status, - const char** value, size_t* value_sz, - enum hyperdatatype* datatype); +hyperdex_ds_list_finalize(struct hyperdex_ds_list *list, + enum hyperdex_ds_returncode *status, + const char **value, size_t *value_sz, + enum hyperdatatype *datatype); /* pack sets */ -struct hyperdex_ds_set* -hyperdex_ds_allocate_set(struct hyperdex_ds_arena* arena); +struct hyperdex_ds_set * +hyperdex_ds_allocate_set(struct hyperdex_ds_arena *arena); int -hyperdex_ds_set_insert_string(struct hyperdex_ds_set* set, const char* str, size_t str_sz, - enum hyperdex_ds_returncode* status); +hyperdex_ds_set_insert_string(struct hyperdex_ds_set *set, const char *str, size_t str_sz, + enum hyperdex_ds_returncode *status); int -hyperdex_ds_set_insert_int(struct hyperdex_ds_set* set, int64_t num, - enum hyperdex_ds_returncode* status); +hyperdex_ds_set_insert_int(struct hyperdex_ds_set *set, int64_t num, + enum hyperdex_ds_returncode *status); int -hyperdex_ds_set_insert_float(struct hyperdex_ds_set* set, double num, - enum hyperdex_ds_returncode* status); +hyperdex_ds_set_insert_float(struct hyperdex_ds_set *set, double num, + enum hyperdex_ds_returncode *status); int -hyperdex_ds_set_finalize(struct hyperdex_ds_set*, - enum hyperdex_ds_returncode* status, - const char** value, size_t* value_sz, - enum hyperdatatype* datatype); +hyperdex_ds_set_finalize(struct hyperdex_ds_set *, + enum hyperdex_ds_returncode *status, + const char **value, size_t *value_sz, + enum hyperdatatype *datatype); /* pack maps */ -struct hyperdex_ds_map* -hyperdex_ds_allocate_map(struct hyperdex_ds_arena* arena); +struct hyperdex_ds_map * +hyperdex_ds_allocate_map(struct hyperdex_ds_arena *arena); int -hyperdex_ds_map_insert_key_string(struct hyperdex_ds_map* map, - const char* str, size_t str_sz, - enum hyperdex_ds_returncode* status); +hyperdex_ds_map_insert_key_string(struct hyperdex_ds_map *map, + const char *str, size_t str_sz, + enum hyperdex_ds_returncode *status); int -hyperdex_ds_map_insert_val_string(struct hyperdex_ds_map* map, - const char* str, size_t str_sz, - enum hyperdex_ds_returncode* status); +hyperdex_ds_map_insert_val_string(struct hyperdex_ds_map *map, + const char *str, size_t str_sz, + enum hyperdex_ds_returncode *status); int -hyperdex_ds_map_insert_key_int(struct hyperdex_ds_map* map, int64_t num, - enum hyperdex_ds_returncode* status); +hyperdex_ds_map_insert_key_int(struct hyperdex_ds_map *map, int64_t num, + enum hyperdex_ds_returncode *status); int -hyperdex_ds_map_insert_val_int(struct hyperdex_ds_map* map, int64_t num, - enum hyperdex_ds_returncode* status); +hyperdex_ds_map_insert_val_int(struct hyperdex_ds_map *map, int64_t num, + enum hyperdex_ds_returncode *status); int -hyperdex_ds_map_insert_key_float(struct hyperdex_ds_map* map, double num, - enum hyperdex_ds_returncode* status); +hyperdex_ds_map_insert_key_float(struct hyperdex_ds_map *map, double num, + enum hyperdex_ds_returncode *status); int -hyperdex_ds_map_insert_val_float(struct hyperdex_ds_map* map, double num, - enum hyperdex_ds_returncode* status); +hyperdex_ds_map_insert_val_float(struct hyperdex_ds_map *map, double num, + enum hyperdex_ds_returncode *status); int -hyperdex_ds_map_finalize(struct hyperdex_ds_map*, - enum hyperdex_ds_returncode* status, - const char** value, size_t* value_sz, - enum hyperdatatype* datatype); +hyperdex_ds_map_finalize(struct hyperdex_ds_map *, + enum hyperdex_ds_returncode *status, + const char **value, size_t *value_sz, + enum hyperdatatype *datatype); /* iterate datatypes */ void -hyperdex_ds_iterator_init(struct hyperdex_ds_iterator* iter, +hyperdex_ds_iterator_init(struct hyperdex_ds_iterator *iter, enum hyperdatatype datatype, - const char* value, + const char *value, size_t value_sz); /* list */ int -hyperdex_ds_iterate_list_string_next(struct hyperdex_ds_iterator* iter, - const char** str, size_t* str_sz); +hyperdex_ds_iterate_list_string_next(struct hyperdex_ds_iterator *iter, + const char **str, size_t *str_sz); int -hyperdex_ds_iterate_list_int_next(struct hyperdex_ds_iterator* iter, int64_t* num); +hyperdex_ds_iterate_list_int_next(struct hyperdex_ds_iterator *iter, int64_t *num); int -hyperdex_ds_iterate_list_float_next(struct hyperdex_ds_iterator* iter, double* num); +hyperdex_ds_iterate_list_float_next(struct hyperdex_ds_iterator *iter, double *num); /* set */ int -hyperdex_ds_iterate_set_string_next(struct hyperdex_ds_iterator* iter, - const char** str, size_t* str_sz); +hyperdex_ds_iterate_set_string_next(struct hyperdex_ds_iterator *iter, + const char **str, size_t *str_sz); int -hyperdex_ds_iterate_set_int_next(struct hyperdex_ds_iterator* iter, int64_t* num); +hyperdex_ds_iterate_set_int_next(struct hyperdex_ds_iterator *iter, int64_t *num); int -hyperdex_ds_iterate_set_float_next(struct hyperdex_ds_iterator* iter, double* num); +hyperdex_ds_iterate_set_float_next(struct hyperdex_ds_iterator *iter, double *num); /* map(string, *) */ int -hyperdex_ds_iterate_map_string_string_next(struct hyperdex_ds_iterator* iter, - const char** key, size_t* key_sz, - const char** val, size_t* val_sz); +hyperdex_ds_iterate_map_string_string_next(struct hyperdex_ds_iterator *iter, + const char **key, size_t *key_sz, + const char **val, size_t *val_sz); int -hyperdex_ds_iterate_map_string_int_next(struct hyperdex_ds_iterator* iter, - const char** key, size_t* key_sz, - int64_t* val); +hyperdex_ds_iterate_map_string_int_next(struct hyperdex_ds_iterator *iter, + const char **key, size_t *key_sz, + int64_t *val); int -hyperdex_ds_iterate_map_string_float_next(struct hyperdex_ds_iterator* iter, - const char** key, size_t* key_sz, - double* val); +hyperdex_ds_iterate_map_string_float_next(struct hyperdex_ds_iterator *iter, + const char **key, size_t *key_sz, + double *val); /* map(int, *) */ int -hyperdex_ds_iterate_map_int_string_next(struct hyperdex_ds_iterator* iter, - int64_t* key, - const char** val, size_t* val_sz); +hyperdex_ds_iterate_map_int_string_next(struct hyperdex_ds_iterator *iter, + int64_t *key, + const char **val, size_t *val_sz); int -hyperdex_ds_iterate_map_int_int_next(struct hyperdex_ds_iterator* iter, - int64_t* key, - int64_t* val); +hyperdex_ds_iterate_map_int_int_next(struct hyperdex_ds_iterator *iter, + int64_t *key, + int64_t *val); int -hyperdex_ds_iterate_map_int_float_next(struct hyperdex_ds_iterator* iter, - int64_t* key, - double* val); +hyperdex_ds_iterate_map_int_float_next(struct hyperdex_ds_iterator *iter, + int64_t *key, + double *val); /* map(float, *) */ int -hyperdex_ds_iterate_map_float_string_next(struct hyperdex_ds_iterator* iter, - double* key, - const char** val, size_t* val_sz); +hyperdex_ds_iterate_map_float_string_next(struct hyperdex_ds_iterator *iter, + double *key, + const char **val, size_t *val_sz); int -hyperdex_ds_iterate_map_float_int_next(struct hyperdex_ds_iterator* iter, - double* key, - int64_t* val); +hyperdex_ds_iterate_map_float_int_next(struct hyperdex_ds_iterator *iter, + double *key, + int64_t *val); int -hyperdex_ds_iterate_map_float_float_next(struct hyperdex_ds_iterator* iter, - double* key, - double* val); +hyperdex_ds_iterate_map_float_float_next(struct hyperdex_ds_iterator *iter, + double *key, + double *val); #ifdef __cplusplus } /* extern "C" */ @@ -244,8 +244,8 @@ hyperdex_ds_iterate_map_float_float_next(struct hyperdex_ds_iterator* iter, /* C++ */ #include -std::ostream& -operator << (std::ostream& lhs, hyperdex_ds_returncode rhs); +std::ostream & +operator << (std::ostream &lhs, hyperdex_ds_returncode rhs); #endif /* __cplusplus */ #endif /* hyperdex_datastructures_h_ */ diff --git a/include/hyperdex/hyperspace_builder.h b/include/hyperdex/hyperspace_builder.h index adddfdee8..198ed7bfd 100644 --- a/include/hyperdex/hyperspace_builder.h +++ b/include/hyperdex/hyperspace_builder.h @@ -45,59 +45,59 @@ struct hyperspace; /* hyperspace_returncode occupies [8576, 8704) */ enum hyperspace_returncode { - HYPERSPACE_SUCCESS = 8576, - HYPERSPACE_INVALID_NAME = 8577, - HYPERSPACE_INVALID_TYPE = 8578, - HYPERSPACE_DUPLICATE = 8579, - HYPERSPACE_IS_KEY = 8580, - HYPERSPACE_UNKNOWN_ATTR = 8581, - HYPERSPACE_NO_SUBSPACE = 8582, - HYPERSPACE_OUT_OF_BOUNDS = 8583, - HYPERSPACE_UNINDEXABLE = 8584, - - HYPERSPACE_GARBAGE = 8703 + HYPERSPACE_SUCCESS = 8576, + HYPERSPACE_INVALID_NAME = 8577, + HYPERSPACE_INVALID_TYPE = 8578, + HYPERSPACE_DUPLICATE = 8579, + HYPERSPACE_IS_KEY = 8580, + HYPERSPACE_UNKNOWN_ATTR = 8581, + HYPERSPACE_NO_SUBSPACE = 8582, + HYPERSPACE_OUT_OF_BOUNDS = 8583, + HYPERSPACE_UNINDEXABLE = 8584, + + HYPERSPACE_GARBAGE = 8703 }; -struct hyperspace* +struct hyperspace * hyperspace_create(); -struct hyperspace* -hyperspace_parse(const char* desc); +struct hyperspace * +hyperspace_parse(const char *desc); void -hyperspace_destroy(struct hyperspace* space); +hyperspace_destroy(struct hyperspace *space); -const char* -hyperspace_error(struct hyperspace* space); +const char * +hyperspace_error(struct hyperspace *space); enum hyperspace_returncode -hyperspace_set_name(struct hyperspace* space, const char* name); +hyperspace_set_name(struct hyperspace *space, const char *name); enum hyperspace_returncode -hyperspace_set_key(struct hyperspace* space, - const char* attr, +hyperspace_set_key(struct hyperspace *space, + const char *attr, enum hyperdatatype datatype); enum hyperspace_returncode -hyperspace_add_attribute(struct hyperspace* space, - const char* attr, +hyperspace_add_attribute(struct hyperspace *space, + const char *attr, enum hyperdatatype datatype); enum hyperspace_returncode -hyperspace_add_subspace(struct hyperspace* space); +hyperspace_add_subspace(struct hyperspace *space); enum hyperspace_returncode -hyperspace_add_subspace_attribute(struct hyperspace* space, const char* attr); +hyperspace_add_subspace_attribute(struct hyperspace *space, const char *attr); enum hyperspace_returncode -hyperspace_add_index(struct hyperspace* space, const char* attr); +hyperspace_add_index(struct hyperspace *space, const char *attr); enum hyperspace_returncode -hyperspace_set_fault_tolerance(struct hyperspace* space, uint64_t num); +hyperspace_set_fault_tolerance(struct hyperspace *space, uint64_t num); enum hyperspace_returncode -hyperspace_set_number_of_partitions(struct hyperspace* space, uint64_t num); +hyperspace_set_number_of_partitions(struct hyperspace *space, uint64_t num); enum hyperspace_returncode -hyperspace_use_authorization(struct hyperspace* space); +hyperspace_use_authorization(struct hyperspace *space); #ifdef __cplusplus } /* extern "C" */ diff --git a/maint/generate-test-packages.py b/maint/generate-test-packages.py new file mode 100644 index 000000000..909af9609 --- /dev/null +++ b/maint/generate-test-packages.py @@ -0,0 +1,160 @@ +# Copyright (c) 2013, Cornell University +# 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 HyperDex nor the names of its 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. + +import argparse +import os +import re +import subprocess +import tarfile +import tempfile + +def add_from_content(tar, name, content, mode=0644): + tmp = tempfile.TemporaryFile() + tmp.write(content) + tmp.flush() + tmp.seek(0) + os.fchmod(tmp.fileno(), mode) + tinfo = tar.gettarinfo(arcname=name, fileobj=tmp) + tar.addfile(tinfo, tmp) + +def generate_test_tarball(version, name, tests): + archive = 'test-hyperdex-' + name + '-' + str(version) + tar = tarfile.open(archive + '.tar.gz', 'w:gz') + version = subprocess.check_output('grep AC_INIT configure.ac', + shell=True).split(' ')[1].strip('[,] ') + makefile = '''CLASSPATH := /usr/share/java/*:test/java:. +export CLASSPATH +export HYPERDEX_SRCDIR=. +export HYPERDEX_BUILDDIR=. + +check: +{rules} +'''.format(version=version, rules=''.join(['\t%s\n' % s for s, t in tests])) + add_from_content(tar, archive + '/Makefile', makefile, 0644) + for sh, test in tests: + tar.add(sh, archive + '/' + sh) + tar.add(test, archive + '/' + test) + tar.add('test/runner.py', archive + '/test/runner.py') + tar.add('test/doctest-runner.py', archive + '/test/doctest-runner.py') + if argparse.__file__.endswith('.pyc'): + tar.add(argparse.__file__[:-1], archive + '/argparse.py') + tar.close() + +version = re.search('^AC_INIT\(\[.*\], \[(.*)\], \[.*\]\)$', + open('configure.ac').read(), re.MULTILINE).group(1) + +generate_test_tarball(version, 'doc', [ + ('test/sh/doc.async-ops.sh', 'test/doc.async-ops.py'), + ('test/sh/doc.atomic-ops.sh', 'test/doc.atomic-ops.py'), + ('test/sh/doc.data-types.sh', 'test/doc.data-types.py'), + ('test/sh/doc.documents.sh', 'test/doc.documents.py'), + ('test/sh/doc.quick-start.sh', 'test/doc.quick-start.py'), +]) + +generate_test_tarball(version, 'java', [ + ('test/sh/bindings.java.BasicSearch.sh', 'test/java/BasicSearch.java'), + ('test/sh/bindings.java.Basic.sh', 'test/java/Basic.java'), + ('test/sh/bindings.java.DataTypeFloat.sh', 'test/java/DataTypeFloat.java'), + ('test/sh/bindings.java.DataTypeInt.sh', 'test/java/DataTypeInt.java'), + ('test/sh/bindings.java.DataTypeListFloat.sh', 'test/java/DataTypeListFloat.java'), + ('test/sh/bindings.java.DataTypeListInt.sh', 'test/java/DataTypeListInt.java'), + ('test/sh/bindings.java.DataTypeListString.sh', 'test/java/DataTypeListString.java'), + ('test/sh/bindings.java.DataTypeMapFloatFloat.sh', 'test/java/DataTypeMapFloatFloat.java'), + ('test/sh/bindings.java.DataTypeMapFloatInt.sh', 'test/java/DataTypeMapFloatInt.java'), + ('test/sh/bindings.java.DataTypeMapFloatString.sh', 'test/java/DataTypeMapFloatString.java'), + ('test/sh/bindings.java.DataTypeMapIntFloat.sh', 'test/java/DataTypeMapIntFloat.java'), + ('test/sh/bindings.java.DataTypeMapIntInt.sh', 'test/java/DataTypeMapIntInt.java'), + ('test/sh/bindings.java.DataTypeMapIntString.sh', 'test/java/DataTypeMapIntString.java'), + ('test/sh/bindings.java.DataTypeMapStringFloat.sh', 'test/java/DataTypeMapStringFloat.java'), + ('test/sh/bindings.java.DataTypeMapStringInt.sh', 'test/java/DataTypeMapStringInt.java'), + ('test/sh/bindings.java.DataTypeMapStringString.sh', 'test/java/DataTypeMapStringString.java'), + ('test/sh/bindings.java.DataTypeSetFloat.sh', 'test/java/DataTypeSetFloat.java'), + ('test/sh/bindings.java.DataTypeSetInt.sh', 'test/java/DataTypeSetInt.java'), + ('test/sh/bindings.java.DataTypeSetString.sh', 'test/java/DataTypeSetString.java'), + ('test/sh/bindings.java.DataTypeString.sh', 'test/java/DataTypeString.java'), + ('test/sh/bindings.java.LengthString.sh', 'test/java/LengthString.java'), + ('test/sh/bindings.java.MultiAttribute.sh', 'test/java/MultiAttribute.java'), + ('test/sh/bindings.java.RangeSearchInt.sh', 'test/java/RangeSearchInt.java'), + ('test/sh/bindings.java.RangeSearchString.sh', 'test/java/RangeSearchString.java'), + ('test/sh/bindings.java.RegexSearch.sh', 'test/java/RegexSearch.java'), +]) + +generate_test_tarball(version, 'python', [ + ('test/sh/bindings.python.BasicSearch.sh', 'test/python/BasicSearch.py'), + ('test/sh/bindings.python.Basic.sh', 'test/python/Basic.py'), + ('test/sh/bindings.python.DataTypeFloat.sh', 'test/python/DataTypeFloat.py'), + ('test/sh/bindings.python.DataTypeInt.sh', 'test/python/DataTypeInt.py'), + ('test/sh/bindings.python.DataTypeListFloat.sh', 'test/python/DataTypeListFloat.py'), + ('test/sh/bindings.python.DataTypeListInt.sh', 'test/python/DataTypeListInt.py'), + ('test/sh/bindings.python.DataTypeListString.sh', 'test/python/DataTypeListString.py'), + ('test/sh/bindings.python.DataTypeMapFloatFloat.sh', 'test/python/DataTypeMapFloatFloat.py'), + ('test/sh/bindings.python.DataTypeMapFloatInt.sh', 'test/python/DataTypeMapFloatInt.py'), + ('test/sh/bindings.python.DataTypeMapFloatString.sh', 'test/python/DataTypeMapFloatString.py'), + ('test/sh/bindings.python.DataTypeMapIntFloat.sh', 'test/python/DataTypeMapIntFloat.py'), + ('test/sh/bindings.python.DataTypeMapIntInt.sh', 'test/python/DataTypeMapIntInt.py'), + ('test/sh/bindings.python.DataTypeMapIntString.sh', 'test/python/DataTypeMapIntString.py'), + ('test/sh/bindings.python.DataTypeMapStringFloat.sh', 'test/python/DataTypeMapStringFloat.py'), + ('test/sh/bindings.python.DataTypeMapStringInt.sh', 'test/python/DataTypeMapStringInt.py'), + ('test/sh/bindings.python.DataTypeMapStringString.sh', 'test/python/DataTypeMapStringString.py'), + ('test/sh/bindings.python.DataTypeSetFloat.sh', 'test/python/DataTypeSetFloat.py'), + ('test/sh/bindings.python.DataTypeSetInt.sh', 'test/python/DataTypeSetInt.py'), + ('test/sh/bindings.python.DataTypeSetString.sh', 'test/python/DataTypeSetString.py'), + ('test/sh/bindings.python.DataTypeString.sh', 'test/python/DataTypeString.py'), + ('test/sh/bindings.python.LengthString.sh', 'test/python/LengthString.py'), + ('test/sh/bindings.python.MultiAttribute.sh', 'test/python/MultiAttribute.py'), + ('test/sh/bindings.python.RangeSearchInt.sh', 'test/python/RangeSearchInt.py'), + ('test/sh/bindings.python.RangeSearchString.sh', 'test/python/RangeSearchString.py'), + ('test/sh/bindings.python.RegexSearch.sh', 'test/python/RegexSearch.py'), +]) + +generate_test_tarball(version, 'ruby', [ + ('test/sh/bindings.ruby.BasicSearch.sh', 'test/ruby/BasicSearch.rb'), + ('test/sh/bindings.ruby.Basic.sh', 'test/ruby/Basic.rb'), + ('test/sh/bindings.ruby.DataTypeFloat.sh', 'test/ruby/DataTypeFloat.rb'), + ('test/sh/bindings.ruby.DataTypeInt.sh', 'test/ruby/DataTypeInt.rb'), + ('test/sh/bindings.ruby.DataTypeListFloat.sh', 'test/ruby/DataTypeListFloat.rb'), + ('test/sh/bindings.ruby.DataTypeListInt.sh', 'test/ruby/DataTypeListInt.rb'), + ('test/sh/bindings.ruby.DataTypeListString.sh', 'test/ruby/DataTypeListString.rb'), + ('test/sh/bindings.ruby.DataTypeMapFloatFloat.sh', 'test/ruby/DataTypeMapFloatFloat.rb'), + ('test/sh/bindings.ruby.DataTypeMapFloatInt.sh', 'test/ruby/DataTypeMapFloatInt.rb'), + ('test/sh/bindings.ruby.DataTypeMapFloatString.sh', 'test/ruby/DataTypeMapFloatString.rb'), + ('test/sh/bindings.ruby.DataTypeMapIntFloat.sh', 'test/ruby/DataTypeMapIntFloat.rb'), + ('test/sh/bindings.ruby.DataTypeMapIntInt.sh', 'test/ruby/DataTypeMapIntInt.rb'), + ('test/sh/bindings.ruby.DataTypeMapIntString.sh', 'test/ruby/DataTypeMapIntString.rb'), + ('test/sh/bindings.ruby.DataTypeMapStringFloat.sh', 'test/ruby/DataTypeMapStringFloat.rb'), + ('test/sh/bindings.ruby.DataTypeMapStringInt.sh', 'test/ruby/DataTypeMapStringInt.rb'), + ('test/sh/bindings.ruby.DataTypeMapStringString.sh', 'test/ruby/DataTypeMapStringString.rb'), + ('test/sh/bindings.ruby.DataTypeSetFloat.sh', 'test/ruby/DataTypeSetFloat.rb'), + ('test/sh/bindings.ruby.DataTypeSetInt.sh', 'test/ruby/DataTypeSetInt.rb'), + ('test/sh/bindings.ruby.DataTypeSetString.sh', 'test/ruby/DataTypeSetString.rb'), + ('test/sh/bindings.ruby.DataTypeString.sh', 'test/ruby/DataTypeString.rb'), + ('test/sh/bindings.ruby.LengthString.sh', 'test/ruby/LengthString.rb'), + ('test/sh/bindings.ruby.MultiAttribute.sh', 'test/ruby/MultiAttribute.rb'), + ('test/sh/bindings.ruby.RangeSearchInt.sh', 'test/ruby/RangeSearchInt.rb'), + ('test/sh/bindings.ruby.RangeSearchString.sh', 'test/ruby/RangeSearchString.rb'), + ('test/sh/bindings.ruby.RegexSearch.sh', 'test/ruby/RegexSearch.rb'), +]) diff --git a/maint/lib-check.c b/maint/lib-check.c index a682afb88..cb7bbfcea 100644 --- a/maint/lib-check.c +++ b/maint/lib-check.c @@ -31,27 +31,23 @@ #include int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - int i = 0; - void* ptr = NULL; - - if (argc < 2) - { - fprintf(stderr, "specify a library\n"); - return EXIT_FAILURE; - } - - for (i = 1; i < argc; ++i) - { - ptr = dlopen(argv[i], RTLD_NOW|RTLD_GLOBAL); - - if (!ptr) - { - fprintf(stderr, "%s\n", dlerror()); - continue; - } - } - - return EXIT_SUCCESS; + int i = 0; + void *ptr = NULL; + if (argc < 2) + { + fprintf(stderr, "specify a library\n"); + return EXIT_FAILURE; + } + for (i = 1; i < argc; ++i) + { + ptr = dlopen(argv[i], RTLD_NOW | RTLD_GLOBAL); + if (!ptr) + { + fprintf(stderr, "%s\n", dlerror()); + continue; + } + } + return EXIT_SUCCESS; } diff --git a/namespace.h b/namespace.h index 9a402a159..97a196b1f 100644 --- a/namespace.h +++ b/namespace.h @@ -29,7 +29,7 @@ #define hyperdex_namespace_h_ #define BEGIN_HYPERDEX_NAMESPACE \ - namespace hyperdex __attribute__ ((visibility ("hidden"))) { + namespace hyperdex __attribute__ ((visibility ("hidden"))) { #define END_HYPERDEX_NAMESPACE } diff --git a/osx/ieee754.h b/osx/ieee754.h index 94d22c8a9..b979a43b6 100644 --- a/osx/ieee754.h +++ b/osx/ieee754.h @@ -8,171 +8,171 @@ #include union ieee754_float - { - float f; +{ + float f; - /* This is the IEEE 754 single-precision format. */ - struct - { + /* This is the IEEE 754 single-precision format. */ + struct + { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:8; - unsigned int mantissa:23; + unsigned int negative: 1; + unsigned int exponent: 8; + unsigned int mantissa: 23; #endif /* Big endian. */ #if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned int mantissa:23; - unsigned int exponent:8; - unsigned int negative:1; + unsigned int mantissa: 23; + unsigned int exponent: 8; + unsigned int negative: 1; #endif /* Little endian. */ - } ieee; + } ieee; - /* This format makes it easier to see if a NaN is a signalling NaN. */ - struct - { + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct + { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:8; - unsigned int quiet_nan:1; - unsigned int mantissa:22; + unsigned int negative: 1; + unsigned int exponent: 8; + unsigned int quiet_nan: 1; + unsigned int mantissa: 22; #endif /* Big endian. */ #if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned int mantissa:22; - unsigned int quiet_nan:1; - unsigned int exponent:8; - unsigned int negative:1; + unsigned int mantissa: 22; + unsigned int quiet_nan: 1; + unsigned int exponent: 8; + unsigned int negative: 1; #endif /* Little endian. */ - } ieee_nan; - }; + } ieee_nan; +}; #define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */ union ieee754_double - { - double d; +{ + double d; - /* This is the IEEE 754 double-precision format. */ - struct - { + /* This is the IEEE 754 double-precision format. */ + struct + { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:11; - /* Together these comprise the mantissa. */ - unsigned int mantissa0:20; - unsigned int mantissa1:32; + unsigned int negative: 1; + unsigned int exponent: 11; + /* Together these comprise the mantissa. */ + unsigned int mantissa0: 20; + unsigned int mantissa1: 32; #endif /* Big endian. */ #if __BYTE_ORDER == __LITTLE_ENDIAN # if __FLOAT_WORD_ORDER == BIG_ENDIAN - unsigned int mantissa0:20; - unsigned int exponent:11; - unsigned int negative:1; - unsigned int mantissa1:32; + unsigned int mantissa0: 20; + unsigned int exponent: 11; + unsigned int negative: 1; + unsigned int mantissa1: 32; # else - /* Together these comprise the mantissa. */ - unsigned int mantissa1:32; - unsigned int mantissa0:20; - unsigned int exponent:11; - unsigned int negative:1; + /* Together these comprise the mantissa. */ + unsigned int mantissa1: 32; + unsigned int mantissa0: 20; + unsigned int exponent: 11; + unsigned int negative: 1; # endif #endif /* Little endian. */ - } ieee; + } ieee; - /* This format makes it easier to see if a NaN is a signalling NaN. */ - struct - { + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct + { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:11; - unsigned int quiet_nan:1; - /* Together these comprise the mantissa. */ - unsigned int mantissa0:19; - unsigned int mantissa1:32; + unsigned int negative: 1; + unsigned int exponent: 11; + unsigned int quiet_nan: 1; + /* Together these comprise the mantissa. */ + unsigned int mantissa0: 19; + unsigned int mantissa1: 32; #else # if __FLOAT_WORD_ORDER == BIG_ENDIAN - unsigned int mantissa0:19; - unsigned int quiet_nan:1; - unsigned int exponent:11; - unsigned int negative:1; - unsigned int mantissa1:32; + unsigned int mantissa0: 19; + unsigned int quiet_nan: 1; + unsigned int exponent: 11; + unsigned int negative: 1; + unsigned int mantissa1: 32; # else - /* Together these comprise the mantissa. */ - unsigned int mantissa1:32; - unsigned int mantissa0:19; - unsigned int quiet_nan:1; - unsigned int exponent:11; - unsigned int negative:1; + /* Together these comprise the mantissa. */ + unsigned int mantissa1: 32; + unsigned int mantissa0: 19; + unsigned int quiet_nan: 1; + unsigned int exponent: 11; + unsigned int negative: 1; # endif #endif - } ieee_nan; - }; + } ieee_nan; +}; #define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */ union ieee854_long_double - { - long double d; +{ + long double d; - /* This is the IEEE 854 double-extended-precision format. */ - struct - { + /* This is the IEEE 854 double-extended-precision format. */ + struct + { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:15; - unsigned int empty:16; - unsigned int mantissa0:32; - unsigned int mantissa1:32; + unsigned int negative: 1; + unsigned int exponent: 15; + unsigned int empty: 16; + unsigned int mantissa0: 32; + unsigned int mantissa1: 32; #endif #if __BYTE_ORDER == __LITTLE_ENDIAN # if __FLOAT_WORD_ORDER == BIG_ENDIAN - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; - unsigned int mantissa0:32; - unsigned int mantissa1:32; + unsigned int exponent: 15; + unsigned int negative: 1; + unsigned int empty: 16; + unsigned int mantissa0: 32; + unsigned int mantissa1: 32; # else - unsigned int mantissa1:32; - unsigned int mantissa0:32; - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; + unsigned int mantissa1: 32; + unsigned int mantissa0: 32; + unsigned int exponent: 15; + unsigned int negative: 1; + unsigned int empty: 16; # endif #endif - } ieee; + } ieee; - /* This is for NaNs in the IEEE 854 double-extended-precision format. */ - struct - { + /* This is for NaNs in the IEEE 854 double-extended-precision format. */ + struct + { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:15; - unsigned int empty:16; - unsigned int one:1; - unsigned int quiet_nan:1; - unsigned int mantissa0:30; - unsigned int mantissa1:32; + unsigned int negative: 1; + unsigned int exponent: 15; + unsigned int empty: 16; + unsigned int one: 1; + unsigned int quiet_nan: 1; + unsigned int mantissa0: 30; + unsigned int mantissa1: 32; #endif #if __BYTE_ORDER == __LITTLE_ENDIAN # if __FLOAT_WORD_ORDER == BIG_ENDIAN - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; - unsigned int mantissa0:30; - unsigned int quiet_nan:1; - unsigned int one:1; - unsigned int mantissa1:32; + unsigned int exponent: 15; + unsigned int negative: 1; + unsigned int empty: 16; + unsigned int mantissa0: 30; + unsigned int quiet_nan: 1; + unsigned int one: 1; + unsigned int mantissa1: 32; # else - unsigned int mantissa1:32; - unsigned int mantissa0:30; - unsigned int quiet_nan:1; - unsigned int one:1; - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; + unsigned int mantissa1: 32; + unsigned int mantissa0: 30; + unsigned int quiet_nan: 1; + unsigned int one: 1; + unsigned int exponent: 15; + unsigned int negative: 1; + unsigned int empty: 16; # endif #endif - } ieee_nan; - }; + } ieee_nan; +}; #define IEEE854_LONG_DOUBLE_BIAS 0x3fff diff --git a/test/replication-stress-test.cc b/test/replication-stress-test.cc index 812a71d00..dcdbacc70 100644 --- a/test/replication-stress-test.cc +++ b/test/replication-stress-test.cc @@ -46,11 +46,11 @@ static bool _continuous = false; static long _partitions = 4; -const char* _space = "replication"; +const char *_space = "replication"; static bool _quiet = false; static int _testno = 0; -static hyperdex::Client* _cl = NULL; +static hyperdex::Client *_cl = NULL; static std::map > _incompleteops; static void @@ -67,299 +67,261 @@ static void test4(); int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser st; - st.arg().name('c', "continuous") - .description("run the test continuously (default: no)") - .set_true(&_continuous); - st.arg().name('n', "partitions") - .description("assume each subspace is partitioned into N pieces (default: 4)") - .metavar("N").as_long(&_partitions); - st.arg().name('s', "space") - .description("perform all operations on the specified space (default: \"replication\")") - .metavar("space").as_string(&_space); - st.arg().name('q', "quiet") - .description("silence all output") - .set_true(&_quiet); - - e::argparser ap; - ap.autohelp(); - ap.add("Connect to a cluster:", conn.parser()); - ap.add("Replication stress test:", st); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 0) - { - std::cerr << "command takes no arguments" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - hyperdex::Client cl(conn.host(), conn.port()); - _cl = &cl; - - do - { - wipe(); - test0(); - test1(); - test2(); - test3(); - test4(); - } - while (_continuous); - - return EXIT_SUCCESS; + hyperdex::connect_opts conn; + e::argparser st; + st.arg().name('c', "continuous") + .description("run the test continuously (default: no)") + .set_true(&_continuous); + st.arg().name('n', "partitions") + .description("assume each subspace is partitioned into N pieces (default: 4)") + .metavar("N").as_long(&_partitions); + st.arg().name('s', "space") + .description("perform all operations on the specified space (default: \"replication\")") + .metavar("space").as_string(&_space); + st.arg().name('q', "quiet") + .description("silence all output") + .set_true(&_quiet); + e::argparser ap; + ap.autohelp(); + ap.add("Connect to a cluster:", conn.parser()); + ap.add("Replication stress test:", st); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 0) + { + std::cerr << "command takes no arguments" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + hyperdex::Client cl(conn.host(), conn.port()); + _cl = &cl; + do + { + wipe(); + test0(); + test1(); + test2(); + test3(); + test4(); + } + while (_continuous); + return EXIT_SUCCESS; } static void success() { - if (!_quiet) std::cout << "Test " << _testno << ": [\x1b[32mOK\x1b[0m]\n"; + if (!_quiet) std::cout << "Test " << _testno << ": [\x1b[32mOK\x1b[0m]\n"; } #define FAIL(REASON) \ - do { \ - if (!_quiet) std::cout << "Test " << _testno << ": [\x1b[31mFAIL\x1b[0m]\n" \ - << "location: " << __FILE__ << ":" << __LINE__ << "\n" \ - << "reason: " << REASON << "\n"; \ - abort(); \ - } while (0) + do { \ + if (!_quiet) std::cout << "Test " << _testno << ": [\x1b[31mFAIL\x1b[0m]\n" \ + << "location: " << __FILE__ << ":" << __LINE__ << "\n" \ + << "reason: " << REASON << "\n"; \ + abort(); \ + } while (0) static uint64_t generate_attr(size_t idx) { - uint64_t partition_size = UINT64_MAX / _partitions; - return partition_size * idx + partition_size / 2; + uint64_t partition_size = UINT64_MAX / _partitions; + return partition_size * idx + partition_size / 2; } static void put(uint64_t A, uint64_t B, uint64_t C) { - char buf[3 * sizeof(uint64_t)]; - e::pack64le(A, buf + 0 * sizeof(uint64_t)); - e::pack64le(B, buf + 1 * sizeof(uint64_t)); - e::pack64le(C, buf + 2 * sizeof(uint64_t)); - hyperdex_client_attribute attrs[2]; - attrs[0].attr = "B"; - attrs[0].value = buf + 1 * sizeof(uint64_t); - attrs[0].value_sz = sizeof(uint64_t); - attrs[0].datatype = HYPERDATATYPE_INT64; - attrs[1].attr = "C"; - attrs[1].value = buf + 2 * sizeof(uint64_t); - attrs[1].value_sz = sizeof(uint64_t); - attrs[1].datatype = HYPERDATATYPE_INT64; - e::compat::shared_ptr status(new hyperdex_client_returncode()); - int64_t id = _cl->put(_space, buf, sizeof(uint64_t), attrs, 2, status.get()); - - if (id < 0) - { - FAIL("put encountered error " << *status); - } - - std::pair >::iterator, bool> res; - res = _incompleteops.insert(std::make_pair(id, status)); - - if (res.second != true) - { - FAIL("put could not insert into incompleteops"); - } + char buf[3 * sizeof(uint64_t)]; + e::pack64le(A, buf + 0 * sizeof(uint64_t)); + e::pack64le(B, buf + 1 * sizeof(uint64_t)); + e::pack64le(C, buf + 2 * sizeof(uint64_t)); + hyperdex_client_attribute attrs[2]; + attrs[0].attr = "B"; + attrs[0].value = buf + 1 * sizeof(uint64_t); + attrs[0].value_sz = sizeof(uint64_t); + attrs[0].datatype = HYPERDATATYPE_INT64; + attrs[1].attr = "C"; + attrs[1].value = buf + 2 * sizeof(uint64_t); + attrs[1].value_sz = sizeof(uint64_t); + attrs[1].datatype = HYPERDATATYPE_INT64; + e::compat::shared_ptr status(new hyperdex_client_returncode()); + int64_t id = _cl->put(_space, buf, sizeof(uint64_t), attrs, 2, status.get()); + if (id < 0) + { + FAIL("put encountered error " << *status); + } + std::pair >::iterator, bool> res; + res = _incompleteops.insert(std::make_pair(id, status)); + if (res.second != true) + { + FAIL("put could not insert into incompleteops"); + } } static void del(uint64_t A) { - char buf[sizeof(uint64_t)]; - e::pack64le(A, buf); - e::compat::shared_ptr status(new hyperdex_client_returncode()); - int64_t id = _cl->del(_space, buf, sizeof(uint64_t), status.get()); - - if (id < 0) - { - FAIL("del encountered error " << status); - } - - std::pair >::iterator, bool> res; - res = _incompleteops.insert(std::make_pair(id, status)); - - if (res.second != true) - { - FAIL("del could not insert into incompleteops"); - } + char buf[sizeof(uint64_t)]; + e::pack64le(A, buf); + e::compat::shared_ptr status(new hyperdex_client_returncode()); + int64_t id = _cl->del(_space, buf, sizeof(uint64_t), status.get()); + if (id < 0) + { + FAIL("del encountered error " << status); + } + std::pair >::iterator, bool> res; + res = _incompleteops.insert(std::make_pair(id, status)); + if (res.second != true) + { + FAIL("del could not insert into incompleteops"); + } } static void flush() { - while (!_incompleteops.empty()) - { - hyperdex_client_returncode status; - int64_t id = _cl->loop(10000, &status); - - if (id < 0) - { - FAIL("loop returned error " << status); - } - else - { - std::map >::iterator incomplete; - incomplete = _incompleteops.find(id); - - if (incomplete == _incompleteops.end()) - { - FAIL("loop returned unknown id " << id); - } - - if (*(incomplete->second) != HYPERDEX_CLIENT_SUCCESS) - { - FAIL("operation " << id << " returned " << *(incomplete->second)); - } - - _incompleteops.erase(incomplete); - } - } + while (!_incompleteops.empty()) + { + hyperdex_client_returncode status; + int64_t id = _cl->loop(10000, &status); + if (id < 0) + { + FAIL("loop returned error " << status); + } + else + { + std::map >::iterator incomplete; + incomplete = _incompleteops.find(id); + if (incomplete == _incompleteops.end()) + { + FAIL("loop returned unknown id " << id); + } + if (*(incomplete->second) != HYPERDEX_CLIENT_SUCCESS) + { + FAIL("operation " << id << " returned " << * (incomplete->second)); + } + _incompleteops.erase(incomplete); + } + } } static void present(uint64_t A, uint64_t B, uint64_t C) { - flush(); - - char buf[3 * sizeof(uint64_t)]; - e::pack64le(A, buf + 0 * sizeof(uint64_t)); - e::pack64le(B, buf + 1 * sizeof(uint64_t)); - e::pack64le(C, buf + 2 * sizeof(uint64_t)); - hyperdex_client_returncode gstatus; - hyperdex_client_returncode lstatus; - const hyperdex_client_attribute* attrs; - size_t attrs_sz; - int64_t gid = _cl->get(_space, buf, sizeof(uint64_t), &gstatus, &attrs, &attrs_sz); - - if (gid < 0) - { - FAIL("get encountered error " << gstatus); - } - - int64_t lid = _cl->loop(10000, &lstatus); - - if (lid < 0) - { - FAIL("loop encountered error " << lstatus); - } - - if (gid != lid) - { - FAIL("loop id (" << lid << ") does not match get id (" << gid << ")"); - } - - if (gstatus != HYPERDEX_CLIENT_SUCCESS) - { - FAIL("operation " << gid << " (a presence check) returned " << gstatus); - } - - if (attrs_sz != 2) - { - FAIL("presence check: " << attrs_sz << " attributes instead of 2 attributes"); - } - - if (strcmp(attrs[0].attr, "B") != 0) - { - FAIL("presence check: first attribute is \"" << attrs[0].attr << "\" instead of \"B\""); - } - - if (attrs[0].datatype != HYPERDATATYPE_INT64) - { - FAIL("presence check: first attribute is not of datatype \"int\""); - } - - if (e::slice(attrs[0].value, attrs[0].value_sz) != e::slice(buf + sizeof(uint64_t), sizeof(uint64_t))) - { - FAIL("presence check: first attribute does not match " << B - << " (" << e::slice(attrs[0].value, attrs[0].value_sz).hex() << " vs. " - << e::slice(buf + sizeof(uint64_t), sizeof(uint64_t)).hex() << ")"); - } - - if (strcmp(attrs[1].attr, "C") != 0) - { - FAIL("presence check: second attribute is \"" << attrs[1].attr << "\" instead of \"C\""); - } - - if (attrs[1].datatype != HYPERDATATYPE_INT64) - { - FAIL("presence check: second attribute is not of datatype \"int\""); - } - - if (e::slice(attrs[1].value, attrs[1].value_sz) != e::slice(buf + 2 * sizeof(uint64_t), sizeof(uint64_t))) - { - FAIL("presence check: second attribute does not match " << C - << " (" << e::slice(attrs[1].value, attrs[1].value_sz).hex() << " vs. " - << e::slice(buf + 2 * sizeof(uint64_t), sizeof(uint64_t)).hex() << ")"); - } - - hyperdex_client_destroy_attrs(attrs, attrs_sz); + flush(); + char buf[3 * sizeof(uint64_t)]; + e::pack64le(A, buf + 0 * sizeof(uint64_t)); + e::pack64le(B, buf + 1 * sizeof(uint64_t)); + e::pack64le(C, buf + 2 * sizeof(uint64_t)); + hyperdex_client_returncode gstatus; + hyperdex_client_returncode lstatus; + const hyperdex_client_attribute *attrs; + size_t attrs_sz; + int64_t gid = _cl->get(_space, buf, sizeof(uint64_t), &gstatus, &attrs, &attrs_sz); + if (gid < 0) + { + FAIL("get encountered error " << gstatus); + } + int64_t lid = _cl->loop(10000, &lstatus); + if (lid < 0) + { + FAIL("loop encountered error " << lstatus); + } + if (gid != lid) + { + FAIL("loop id (" << lid << ") does not match get id (" << gid << ")"); + } + if (gstatus != HYPERDEX_CLIENT_SUCCESS) + { + FAIL("operation " << gid << " (a presence check) returned " << gstatus); + } + if (attrs_sz != 2) + { + FAIL("presence check: " << attrs_sz << " attributes instead of 2 attributes"); + } + if (strcmp(attrs[0].attr, "B") != 0) + { + FAIL("presence check: first attribute is \"" << attrs[0].attr << "\" instead of \"B\""); + } + if (attrs[0].datatype != HYPERDATATYPE_INT64) + { + FAIL("presence check: first attribute is not of datatype \"int\""); + } + if (e::slice(attrs[0].value, attrs[0].value_sz) != e::slice(buf + sizeof(uint64_t), sizeof(uint64_t))) + { + FAIL("presence check: first attribute does not match " << B + << " (" << e::slice(attrs[0].value, attrs[0].value_sz).hex() << " vs. " + << e::slice(buf + sizeof(uint64_t), sizeof(uint64_t)).hex() << ")"); + } + if (strcmp(attrs[1].attr, "C") != 0) + { + FAIL("presence check: second attribute is \"" << attrs[1].attr << "\" instead of \"C\""); + } + if (attrs[1].datatype != HYPERDATATYPE_INT64) + { + FAIL("presence check: second attribute is not of datatype \"int\""); + } + if (e::slice(attrs[1].value, attrs[1].value_sz) != e::slice(buf + 2 * sizeof(uint64_t), sizeof(uint64_t))) + { + FAIL("presence check: second attribute does not match " << C + << " (" << e::slice(attrs[1].value, attrs[1].value_sz).hex() << " vs. " + << e::slice(buf + 2 * sizeof(uint64_t), sizeof(uint64_t)).hex() << ")"); + } + hyperdex_client_destroy_attrs(attrs, attrs_sz); } static void absent(uint64_t A) { - flush(); - - char buf[sizeof(uint64_t)]; - e::pack64le(A, buf); - hyperdex_client_returncode gstatus; - hyperdex_client_returncode lstatus; - const hyperdex_client_attribute* attrs = NULL; - size_t attrs_sz = 0; - int64_t gid = _cl->get(_space, buf, sizeof(uint64_t), &gstatus, &attrs, &attrs_sz); - - if (gid < 0) - { - FAIL("get encountered error " << gstatus); - } - - int64_t lid = _cl->loop(10000, &lstatus); - - if (lid < 0) - { - FAIL("loop returned error " << lstatus); - } - - if (gid != lid) - { - FAIL("loop id (" << lid << ") does not match get id (" << gid << ")"); - } - - if (gstatus != HYPERDEX_CLIENT_NOTFOUND) - { - FAIL("operation " << gid << " (an absence check) returned " << gstatus); - } - - assert(!attrs && !attrs_sz); + flush(); + char buf[sizeof(uint64_t)]; + e::pack64le(A, buf); + hyperdex_client_returncode gstatus; + hyperdex_client_returncode lstatus; + const hyperdex_client_attribute *attrs = NULL; + size_t attrs_sz = 0; + int64_t gid = _cl->get(_space, buf, sizeof(uint64_t), &gstatus, &attrs, &attrs_sz); + if (gid < 0) + { + FAIL("get encountered error " << gstatus); + } + int64_t lid = _cl->loop(10000, &lstatus); + if (lid < 0) + { + FAIL("loop returned error " << lstatus); + } + if (gid != lid) + { + FAIL("loop id (" << lid << ") does not match get id (" << gid << ")"); + } + if (gstatus != HYPERDEX_CLIENT_NOTFOUND) + { + FAIL("operation " << gid << " (an absence check) returned " << gstatus); + } + assert(!attrs && !attrs_sz); } void wipe() { - for (long i = 0; i < _partitions; ++i) - { - uint64_t A = generate_attr(i); - put(A, A, A); - del(A); - flush(); - } + for (long i = 0; i < _partitions; ++i) + { + uint64_t A = generate_attr(i); + put(A, A, A); + del(A); + flush(); + } } // This test continually puts keys, ensuring that every way in which one could @@ -367,33 +329,28 @@ wipe() void test0() { - _testno = 0; - uint64_t A; - uint64_t B; - uint64_t C; - - for (long i = 0; i < _partitions; ++i) - { - A = generate_attr(i); - absent(A); - - for (long j = 0; j < _partitions; ++j) - { - B = generate_attr(j); - - for (long k = 0; k < _partitions; ++k) - { - C = generate_attr(k); - put(A, B, C); - } - } - - present(A, B, C); - del(A); - absent(A); - } - - success(); + _testno = 0; + uint64_t A; + uint64_t B; + uint64_t C; + for (long i = 0; i < _partitions; ++i) + { + A = generate_attr(i); + absent(A); + for (long j = 0; j < _partitions; ++j) + { + B = generate_attr(j); + for (long k = 0; k < _partitions; ++k) + { + C = generate_attr(k); + put(A, B, C); + } + } + present(A, B, C); + del(A); + absent(A); + } + success(); } // This test continually puts/deletes keys, ensuring that a [PUT, DEL] sequence @@ -402,32 +359,27 @@ test0() void test1() { - _testno = 1; - uint64_t A; - uint64_t B; - uint64_t C; - - for (long i = 0; i < _partitions; ++i) - { - A = generate_attr(i); - absent(A); - - for (long j = 0; j < _partitions; ++j) - { - B = generate_attr(j); - - for (long k = 0; k < _partitions; ++k) - { - C = generate_attr(k); - put(A, B, C); - del(A); - } - } - - absent(A); - } - - success(); + _testno = 1; + uint64_t A; + uint64_t B; + uint64_t C; + for (long i = 0; i < _partitions; ++i) + { + A = generate_attr(i); + absent(A); + for (long j = 0; j < _partitions; ++j) + { + B = generate_attr(j); + for (long k = 0; k < _partitions; ++k) + { + C = generate_attr(k); + put(A, B, C); + del(A); + } + } + absent(A); + } + success(); } // This test puts keys such that A and B are fixed, but every choice of C for @@ -437,66 +389,56 @@ test1() void test2() { - _testno = 2; - uint64_t A = 0; - uint64_t B = 0; - uint64_t C = 0; - - for (long i = 0; i < _partitions; ++i) - { - A = generate_attr(i); - - for (long j = 0; j < _partitions; ++j) - { - B = generate_attr(j); - absent(A); - - for (long k = 0; k < _partitions; ++k) - { - C = generate_attr(k); - put(A, B, C); - } - - present(A, B, C); - del(A); - absent(A); - } - } - - success(); + _testno = 2; + uint64_t A = 0; + uint64_t B = 0; + uint64_t C = 0; + for (long i = 0; i < _partitions; ++i) + { + A = generate_attr(i); + for (long j = 0; j < _partitions; ++j) + { + B = generate_attr(j); + absent(A); + for (long k = 0; k < _partitions; ++k) + { + C = generate_attr(k); + put(A, B, C); + } + present(A, B, C); + del(A); + absent(A); + } + } + success(); } // This is similar to test2 except that columns A and C are fixed. void test3() { - _testno = 3; - uint64_t A = 0; - uint64_t B = 0; - uint64_t C = 0; - - for (long i = 0; i < _partitions; ++i) - { - A = generate_attr(i); - - for (long j = 0; j < _partitions; ++j) - { - C = generate_attr(j); - absent(A); - - for (long k = 0; k < _partitions; ++k) - { - B = generate_attr(k); - put(A, B, C); - } - - present(A, B, C); - del(A); - absent(A); - } - } - - success(); + _testno = 3; + uint64_t A = 0; + uint64_t B = 0; + uint64_t C = 0; + for (long i = 0; i < _partitions; ++i) + { + A = generate_attr(i); + for (long j = 0; j < _partitions; ++j) + { + C = generate_attr(j); + absent(A); + for (long k = 0; k < _partitions; ++k) + { + B = generate_attr(k); + put(A, B, C); + } + present(A, B, C); + del(A); + absent(A); + } + } + success(); } // This test stresses the interaction of CHAIN_SUBSPACE with DELETE messages. @@ -506,42 +448,35 @@ test3() void test4() { - _testno = 4; - uint64_t A; - uint64_t B; - uint64_t BP; - uint64_t C; - uint64_t CP; - - for (long h = 0; h < _partitions; ++h) - { - A = generate_attr(h); - - for (long i = 0; i < _partitions; ++i) - { - B = generate_attr(i); - - for (long j = 0; j < _partitions; ++j) - { - C = generate_attr(j); - - for (long k = 0; k < _partitions; ++k) - { - BP = generate_attr(k); - - for (long l = 0; l < _partitions; ++l) - { - CP = generate_attr(l); - put(A, B, C); - put(A, BP, CP); - del(A); - } - } - - absent(A); - } - } - } - - success(); + _testno = 4; + uint64_t A; + uint64_t B; + uint64_t BP; + uint64_t C; + uint64_t CP; + for (long h = 0; h < _partitions; ++h) + { + A = generate_attr(h); + for (long i = 0; i < _partitions; ++i) + { + B = generate_attr(i); + for (long j = 0; j < _partitions; ++j) + { + C = generate_attr(j); + for (long k = 0; k < _partitions; ++k) + { + BP = generate_attr(k); + for (long l = 0; l < _partitions; ++l) + { + CP = generate_attr(l); + put(A, B, C); + put(A, BP, CP); + del(A); + } + } + absent(A); + } + } + } + success(); } diff --git a/test/search-stress-test.cc b/test/search-stress-test.cc index 3e3d10622..54a3ff8fc 100644 --- a/test/search-stress-test.cc +++ b/test/search-stress-test.cc @@ -36,738 +36,652 @@ #include #include "tools/common.h" -const char* _colnames[] = {"bit01", "bit02", "bit03", "bit04", "bit05", "bit06", +const char *_colnames[] = {"bit01", "bit02", "bit03", "bit04", "bit05", "bit06", "bit07", "bit08", "bit09", "bit10", "bit11", "bit12", "bit13", "bit14", "bit15", "bit16", "bit17", "bit18", "bit19", "bit20", "bit21", "bit22", "bit23", "bit24", "bit25", "bit26", "bit27", "bit28", "bit29", "bit30", - "bit31", "bit32"}; + "bit31", "bit32" + }; static bool _quiet = false; -static const char* _space = "search"; +static const char *_space = "search"; static unsigned long _random_iters = 16; -static const char* _key_type_s = "int"; +static const char *_key_type_s = "int"; static hyperdatatype _key_type = HYPERDATATYPE_INT64; static int -test(hyperdex::Client* cl); +test(hyperdex::Client *cl); int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser st; - st.arg().name('s', "space") - .description("perform all operations on the specified space (default: \"search\")") - .metavar("space").as_string(&_space); - st.arg().name('k', "key-type") - .description("one of \"int\", \"string\" (default: \"int\")") - .metavar("type").as_string(&_key_type_s); - st.arg().name('q', "quiet") - .description("silence all output") - .set_true(&_quiet); - - e::argparser ap; - ap.autohelp(); - ap.add("Connect to a cluster:", conn.parser()); - ap.add("Search stress test:", st); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (strcmp(_key_type_s, "int") == 0) - { - _key_type = HYPERDATATYPE_INT64; - } - else if (strcmp(_key_type_s, "string") == 0) - { - _key_type = HYPERDATATYPE_STRING; - } - else - { - std::cerr << "unsupported key type \"" << _key_type_s << "\"" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 0) - { - std::cerr << "command takes no arguments" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Client cl(conn.host(), conn.port()); - return test(&cl); - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what(); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; + hyperdex::connect_opts conn; + e::argparser st; + st.arg().name('s', "space") + .description("perform all operations on the specified space (default: \"search\")") + .metavar("space").as_string(&_space); + st.arg().name('k', "key-type") + .description("one of \"int\", \"string\" (default: \"int\")") + .metavar("type").as_string(&_key_type_s); + st.arg().name('q', "quiet") + .description("silence all output") + .set_true(&_quiet); + e::argparser ap; + ap.autohelp(); + ap.add("Connect to a cluster:", conn.parser()); + ap.add("Search stress test:", st); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (strcmp(_key_type_s, "int") == 0) + { + _key_type = HYPERDATATYPE_INT64; + } + else if (strcmp(_key_type_s, "string") == 0) + { + _key_type = HYPERDATATYPE_STRING; + } + else + { + std::cerr << "unsupported key type \"" << _key_type_s << "\"" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 0) + { + std::cerr << "command takes no arguments" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Client cl(conn.host(), conn.port()); + return test(&cl); + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what(); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; } #define HYPERDEX_TEST_SUCCESS(TESTNO) \ - do { \ - if (!_quiet) std::cout << "Test " << TESTNO << ": [\x1b[32mOK\x1b[0m]" << std::endl; \ - } while (0) + do { \ + if (!_quiet) std::cout << "Test " << TESTNO << ": [\x1b[32mOK\x1b[0m]" << std::endl; \ + } while (0) #define HYPERDEX_TEST_FAIL(TESTNO, REASON) \ - do { \ - if (!_quiet) std::cout << "Test " << TESTNO << ": [\x1b[31mFAIL\x1b[0m]\n" \ - << "location: " << __FILE__ << ":" << __LINE__ << "\n" \ - << "reason: " << REASON << std::endl; \ - abort(); \ - } while (0) + do { \ + if (!_quiet) std::cout << "Test " << TESTNO << ": [\x1b[31mFAIL\x1b[0m]\n" \ + << "location: " << __FILE__ << ":" << __LINE__ << "\n" \ + << "reason: " << REASON << std::endl; \ + abort(); \ + } while (0) #define SEARCH_STRESS_TIMEOUT(testno) (25000 * (1 + testno)) static void empty(size_t testno, - hyperdex::Client* cl); + hyperdex::Client *cl); static void populate(size_t testno, - hyperdex::Client* cl); + hyperdex::Client *cl); static void search(size_t testno, - hyperdex::Client* cl, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const std::vector& expected); + hyperdex::Client *cl, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const std::vector &expected); static void sorted_search(size_t testno, - hyperdex::Client* cl, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const std::vector& expected); + hyperdex::Client *cl, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const std::vector &expected); static void group_del(size_t testno, - hyperdex::Client* cl, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz); + hyperdex::Client *cl, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz); static void count(size_t testno, - hyperdex::Client* cl, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, + hyperdex::Client *cl, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, size_t expected); static void all_search_tests(size_t testno, - hyperdex::Client* cl, - const std::vector& expecting); + hyperdex::Client *cl, + const std::vector &expecting); int -test(hyperdex::Client* cl) +test(hyperdex::Client *cl) { - group_del(16, cl, NULL, 0); // clear everything - srand(0xdeadbeef); // yes, I know rand+mod is suboptimal - hyperdex_client_attribute_check chk; - chk.datatype = HYPERDATATYPE_STRING; - chk.predicate = HYPERPREDICATE_EQUALS; - - for (size_t testno = 0; testno < 10; ++testno) - { - // Check that we start out clean - empty(testno, cl); - // Populate with all items we expect - populate(testno, cl); - std::vector expecting(1ULL << testno, true); - all_search_tests(testno, cl, expecting); - // group_del everything that is even - chk.attr = _colnames[0]; - chk.value = "0"; - chk.value_sz = 1; - group_del(testno, cl, &chk, 1); - - for (size_t i = 0; i < expecting.size(); ++i) - { - if (!(i & 1)) - { - expecting[i] = false; - } - } - - all_search_tests(testno, cl, expecting); - // take out the upper half of the objects - chk.attr = _colnames[testno > 0 ? testno - 1 : 0]; - chk.value = "1"; - chk.value_sz = 1; - group_del(testno, cl, &chk, 1); - - for (size_t i = expecting.size() / 2; i < expecting.size(); ++i) - { - expecting[i] = false; - } - - all_search_tests(testno, cl, expecting); - // take out the lower quarter of the objects - chk.attr = _colnames[testno > 1 ? testno - 2 : 0]; - chk.value = "0"; - chk.value_sz = 1; - group_del(testno, cl, &chk, 1); - - for (size_t i = 0; i < expecting.size() / 4; ++i) - { - expecting[i] = false; - } - - all_search_tests(testno, cl, expecting); - // Blow it all away - group_del(testno, cl, NULL, 0); - // Check to make sure everything is gone. - empty(testno, cl); - HYPERDEX_TEST_SUCCESS(testno); - } - - return 0; + group_del(16, cl, NULL, 0); // clear everything + srand(0xdeadbeef); // yes, I know rand+mod is suboptimal + hyperdex_client_attribute_check chk; + chk.datatype = HYPERDATATYPE_STRING; + chk.predicate = HYPERPREDICATE_EQUALS; + for (size_t testno = 0; testno < 10; ++testno) + { + // Check that we start out clean + empty(testno, cl); + // Populate with all items we expect + populate(testno, cl); + std::vector expecting(1ULL << testno, true); + all_search_tests(testno, cl, expecting); + // group_del everything that is even + chk.attr = _colnames[0]; + chk.value = "0"; + chk.value_sz = 1; + group_del(testno, cl, &chk, 1); + for (size_t i = 0; i < expecting.size(); ++i) + { + if (!(i & 1)) + { + expecting[i] = false; + } + } + all_search_tests(testno, cl, expecting); + // take out the upper half of the objects + chk.attr = _colnames[testno > 0 ? testno - 1 : 0]; + chk.value = "1"; + chk.value_sz = 1; + group_del(testno, cl, &chk, 1); + for (size_t i = expecting.size() / 2; i < expecting.size(); ++i) + { + expecting[i] = false; + } + all_search_tests(testno, cl, expecting); + // take out the lower quarter of the objects + chk.attr = _colnames[testno > 1 ? testno - 2 : 0]; + chk.value = "0"; + chk.value_sz = 1; + group_del(testno, cl, &chk, 1); + for (size_t i = 0; i < expecting.size() / 4; ++i) + { + expecting[i] = false; + } + all_search_tests(testno, cl, expecting); + // Blow it all away + group_del(testno, cl, NULL, 0); + // Check to make sure everything is gone. + empty(testno, cl); + HYPERDEX_TEST_SUCCESS(testno); + } + return 0; } void empty(size_t testno, - hyperdex::Client* cl) + hyperdex::Client *cl) { - count(testno, cl, NULL, 0, 0); - std::vector expected(1ULL << testno, false); - search(testno, cl, NULL, 0, expected); - sorted_search(testno, cl, NULL, 0, expected); + count(testno, cl, NULL, 0, 0); + std::vector expected(1ULL << testno, false); + search(testno, cl, NULL, 0, expected); + sorted_search(testno, cl, NULL, 0, expected); } static void populate(size_t testno, - hyperdex::Client* cl) + hyperdex::Client *cl) { - for (int64_t number = 0; number < (1LL << testno); ++number) - { - hyperdex_client_attribute attrs[32]; - - for (size_t i = 0; i < 32; ++i) - { - attrs[i].attr = _colnames[i]; - attrs[i].datatype = HYPERDATATYPE_STRING; - - if ((number & (1ULL << i))) - { - attrs[i].value = "1"; - attrs[i].value_sz = 1; - } - else - { - attrs[i].value = "0"; - attrs[i].value_sz = 1; - } - } - - char buf[sizeof(uint64_t)]; - - if (_key_type == HYPERDATATYPE_STRING) - { - e::pack64be(number, buf); - } - else if (_key_type == HYPERDATATYPE_INT64) - { - e::pack64le(number, buf); - } - else - { - HYPERDEX_TEST_FAIL(testno, "unknown key datatype"); - } - - hyperdex_client_returncode pstatus; - int64_t pid = cl->put(_space, buf, sizeof(uint64_t), attrs, 32, &pstatus); - - if (pid < 0) - { - HYPERDEX_TEST_FAIL(testno, "put encountered error " << pstatus << " (pid=" << pid << "): " << cl->error_message() << " at " << cl->error_location()); - } - - hyperdex_client_returncode lstatus; - int64_t lid = cl->loop(SEARCH_STRESS_TIMEOUT(testno), &lstatus); - - if (lid < 0) - { - HYPERDEX_TEST_FAIL(testno, "loop returned error " << lstatus << ": " << cl->error_message() << " at " << cl->error_location()); - } - - if (pid != lid) - { - HYPERDEX_TEST_FAIL(testno, "loop id (" << lid << ") does not match put id (" << pid << ")"); - } - - if (pstatus != HYPERDEX_CLIENT_SUCCESS) - { - HYPERDEX_TEST_FAIL(testno, "operation " << pid << " (populate) returned " << pstatus << ": " << cl->error_message() << " at " << cl->error_location()); - } - } + for (int64_t number = 0; number < (1LL << testno); ++number) + { + hyperdex_client_attribute attrs[32]; + for (size_t i = 0; i < 32; ++i) + { + attrs[i].attr = _colnames[i]; + attrs[i].datatype = HYPERDATATYPE_STRING; + if ((number & (1ULL << i))) + { + attrs[i].value = "1"; + attrs[i].value_sz = 1; + } + else + { + attrs[i].value = "0"; + attrs[i].value_sz = 1; + } + } + char buf[sizeof(uint64_t)]; + if (_key_type == HYPERDATATYPE_STRING) + { + e::pack64be(number, buf); + } + else if (_key_type == HYPERDATATYPE_INT64) + { + e::pack64le(number, buf); + } + else + { + HYPERDEX_TEST_FAIL(testno, "unknown key datatype"); + } + hyperdex_client_returncode pstatus; + int64_t pid = cl->put(_space, buf, sizeof(uint64_t), attrs, 32, &pstatus); + if (pid < 0) + { + HYPERDEX_TEST_FAIL(testno, "put encountered error " << pstatus << " (pid=" << pid << "): " << cl->error_message() << " at " << cl->error_location()); + } + hyperdex_client_returncode lstatus; + int64_t lid = cl->loop(SEARCH_STRESS_TIMEOUT(testno), &lstatus); + if (lid < 0) + { + HYPERDEX_TEST_FAIL(testno, "loop returned error " << lstatus << ": " << cl->error_message() << " at " << cl->error_location()); + } + if (pid != lid) + { + HYPERDEX_TEST_FAIL(testno, "loop id (" << lid << ") does not match put id (" << pid << ")"); + } + if (pstatus != HYPERDEX_CLIENT_SUCCESS) + { + HYPERDEX_TEST_FAIL(testno, "operation " << pid << " (populate) returned " << pstatus << ": " << cl->error_message() << " at " << cl->error_location()); + } + } } void search(size_t testno, - hyperdex::Client* cl, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const std::vector& expected) + hyperdex::Client *cl, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const std::vector &expected) { - std::vector seen(expected.size(), false); - const hyperdex_client_attribute* attrs; - size_t attrs_sz; - hyperdex_client_returncode sstatus = HYPERDEX_CLIENT_SUCCESS; - int64_t sid = cl->search(_space, checks, checks_sz, &sstatus, &attrs, &attrs_sz); - - if (sid < 0) - { - HYPERDEX_TEST_FAIL(testno, "search encountered error " << sstatus << ": " << cl->error_message() << " at " << cl->error_location()); - } - - while (true) - { - hyperdex_client_returncode lstatus; - int64_t lid = cl->loop(SEARCH_STRESS_TIMEOUT(testno), &lstatus); - - if (lid < 0) - { - HYPERDEX_TEST_FAIL(testno, "loop returned error " << lstatus << ": " << cl->error_message() << " at " << cl->error_location()); - } - - if (sid != lid) - { - HYPERDEX_TEST_FAIL(testno, "loop id (" << lid << ") does not match search id (" << sid << ")"); - } - - if (sstatus != HYPERDEX_CLIENT_SUCCESS && sstatus != HYPERDEX_CLIENT_SEARCHDONE) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) returned " << sstatus << ": " << cl->error_message() << " at " << cl->error_location()); - } - - if (sstatus == HYPERDEX_CLIENT_SUCCESS) - { - if (attrs_sz != 33) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) returned " << attrs_sz - << " attributes instead of 33"); - } - - if (strcmp(attrs[0].attr, "number") != 0) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) key was field \"" - << attrs[0].attr << "\" but should have been field \"number\""); - } - - if (attrs[0].value_sz != sizeof(uint64_t)) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) key has size " - << attrs[0].value_sz << " bytes, but should be sizeof(int64_t)"); - } - - int64_t num = 0; - - if (_key_type == HYPERDATATYPE_STRING) - { - e::unpack64be(attrs[0].value, &num); - } - else if (_key_type == HYPERDATATYPE_INT64) - { - e::unpack64le(attrs[0].value, &num); - } - else - { - HYPERDEX_TEST_FAIL(testno, "unknown key datatype"); - } - - if (num >= (1LL << testno)) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) number " << num << " outside range"); - } - - if (seen[num]) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) number " << num << " already seen"); - } - - seen[num] = true; - - if (!expected[num]) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) number " << num << " not expected"); - } - - for (size_t i = 0; i < 32; ++i) - { - if (strcmp(attrs[i + 1].attr, _colnames[i]) != 0) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) key was field \"" - << attrs[i + 1].attr << "\" but should have been field \"" - << _colnames[i] << "\""); - } - - if (attrs[i + 1].value_sz != 1) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) attribute has size " - << attrs[i + 1].value_sz << " bytes, but should be 1"); - } - - if (*attrs[i + 1].value == '1') - { - if (!(num & (1ULL << i))) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) bit " << i - << " not set for number " << num); - } - } - else if (*attrs[i + 1].value == '0') - { - if ((num & (1ULL << i))) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) bit " << i - << " set for number " << num); - } - } - else - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) bit not '0' or '1' (is " << (int)*attrs[i + 1].value << "d)"); - } - } - } - - if (sstatus == HYPERDEX_CLIENT_SEARCHDONE) - { - break; - } - } - - for (size_t i = 0; i < expected.size(); ++i) - { - if (expected[i] && !seen[i]) - { - HYPERDEX_TEST_FAIL(testno, "search should have returned " << i << " but did not"); - } - } + std::vector seen(expected.size(), false); + const hyperdex_client_attribute *attrs; + size_t attrs_sz; + hyperdex_client_returncode sstatus = HYPERDEX_CLIENT_SUCCESS; + int64_t sid = cl->search(_space, checks, checks_sz, &sstatus, &attrs, &attrs_sz); + if (sid < 0) + { + HYPERDEX_TEST_FAIL(testno, "search encountered error " << sstatus << ": " << cl->error_message() << " at " << cl->error_location()); + } + while (true) + { + hyperdex_client_returncode lstatus; + int64_t lid = cl->loop(SEARCH_STRESS_TIMEOUT(testno), &lstatus); + if (lid < 0) + { + HYPERDEX_TEST_FAIL(testno, "loop returned error " << lstatus << ": " << cl->error_message() << " at " << cl->error_location()); + } + if (sid != lid) + { + HYPERDEX_TEST_FAIL(testno, "loop id (" << lid << ") does not match search id (" << sid << ")"); + } + if (sstatus != HYPERDEX_CLIENT_SUCCESS && sstatus != HYPERDEX_CLIENT_SEARCHDONE) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) returned " << sstatus << ": " << cl->error_message() << " at " << cl->error_location()); + } + if (sstatus == HYPERDEX_CLIENT_SUCCESS) + { + if (attrs_sz != 33) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) returned " << attrs_sz + << " attributes instead of 33"); + } + if (strcmp(attrs[0].attr, "number") != 0) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) key was field \"" + << attrs[0].attr << "\" but should have been field \"number\""); + } + if (attrs[0].value_sz != sizeof(uint64_t)) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) key has size " + << attrs[0].value_sz << " bytes, but should be sizeof(int64_t)"); + } + int64_t num = 0; + if (_key_type == HYPERDATATYPE_STRING) + { + e::unpack64be(attrs[0].value, &num); + } + else if (_key_type == HYPERDATATYPE_INT64) + { + e::unpack64le(attrs[0].value, &num); + } + else + { + HYPERDEX_TEST_FAIL(testno, "unknown key datatype"); + } + if (num >= (1LL << testno)) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) number " << num << " outside range"); + } + if (seen[num]) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) number " << num << " already seen"); + } + seen[num] = true; + if (!expected[num]) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) number " << num << " not expected"); + } + for (size_t i = 0; i < 32; ++i) + { + if (strcmp(attrs[i + 1].attr, _colnames[i]) != 0) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) key was field \"" + << attrs[i + 1].attr << "\" but should have been field \"" + << _colnames[i] << "\""); + } + if (attrs[i + 1].value_sz != 1) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) attribute has size " + << attrs[i + 1].value_sz << " bytes, but should be 1"); + } + if (*attrs[i + 1].value == '1') + { + if (!(num & (1ULL << i))) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) bit " << i + << " not set for number " << num); + } + } + else if (*attrs[i + 1].value == '0') + { + if ((num & (1ULL << i))) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) bit " << i + << " set for number " << num); + } + } + else + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (search) bit not '0' or '1' (is " << (int)*attrs[i + 1].value << "d)"); + } + } + } + if (sstatus == HYPERDEX_CLIENT_SEARCHDONE) + { + break; + } + } + for (size_t i = 0; i < expected.size(); ++i) + { + if (expected[i] && !seen[i]) + { + HYPERDEX_TEST_FAIL(testno, "search should have returned " << i << " but did not"); + } + } } void sorted_search(size_t testno, - hyperdex::Client* cl, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, - const std::vector& expected) + hyperdex::Client *cl, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, + const std::vector &expected) { - std::vector seen(expected.size(), false); - const hyperdex_client_attribute* attrs; - size_t attrs_sz; - hyperdex_client_returncode sstatus = HYPERDEX_CLIENT_SUCCESS; - int64_t sid = cl->sorted_search(_space, checks, checks_sz, "number", 1ULL << testno, false, &sstatus, &attrs, &attrs_sz); - - if (sid < 0) - { - HYPERDEX_TEST_FAIL(testno, "sorted_search encountered error " << sstatus << ": " << cl->error_message() << " at " << cl->error_location()); - } - - int64_t old_num = 0; - - while (true) - { - hyperdex_client_returncode lstatus; - int64_t lid = cl->loop(SEARCH_STRESS_TIMEOUT(testno), &lstatus); - - if (lid < 0) - { - HYPERDEX_TEST_FAIL(testno, "loop returned error " << lstatus << ": " << cl->error_message() << " at " << cl->error_location()); - } - - if (sid != lid) - { - HYPERDEX_TEST_FAIL(testno, "loop id (" << lid << ") does not match sorted_search id (" << sid << ")"); - } - - if (sstatus != HYPERDEX_CLIENT_SUCCESS && sstatus != HYPERDEX_CLIENT_SEARCHDONE) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) returned " << sstatus << ": " << cl->error_message() << " at " << cl->error_location()); - } - - if (sstatus == HYPERDEX_CLIENT_SUCCESS) - { - if (attrs_sz != 33) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) returned " << attrs_sz - << " attributes instead of 33"); - } - - if (strcmp(attrs[0].attr, "number") != 0) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) key was field \"" - << attrs[0].attr << "\" but should have been field \"number\""); - } - - if (attrs[0].value_sz != sizeof(uint64_t)) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) key has size " - << attrs[0].value_sz << " bytes, but should be sizeof(int64_t)"); - } - - int64_t num = 0; - - if (_key_type == HYPERDATATYPE_STRING) - { - e::unpack64be(attrs[0].value, &num); - } - else if (_key_type == HYPERDATATYPE_INT64) - { - e::unpack64le(attrs[0].value, &num); - } - else - { - HYPERDEX_TEST_FAIL(testno, "unknown key datatype"); - } - - if (num >= (1LL << testno)) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) number " << num << " outside range"); - } - - if (num < old_num) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) number " << num << " out of order (prev was " << old_num << ")"); - } - - old_num = num; - - if (seen[num]) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) number " << num << " already seen"); - } - - seen[num] = true; - - if (!expected[num]) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) number " << num << " not expected"); - } - - for (size_t i = 0; i < 32; ++i) - { - if (strcmp(attrs[i + 1].attr, _colnames[i]) != 0) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) key was field \"" - << attrs[i + 1].attr << "\" but should have been field \"" - << _colnames[i] << "\""); - } - - if (attrs[i + 1].value_sz != 1) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) attribute has size " - << attrs[i + 1].value_sz << " bytes, but should be 1"); - } - - if (*attrs[i + 1].value == '1') - { - if (!(num & (1ULL << i))) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) bit " << i - << " not set for number " << num); - } - } - else if (*attrs[i + 1].value == '0') - { - if ((num & (1ULL << i))) - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) bit " << i - << " set for number " << num); - } - } - else - { - HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) bit not '0' or '1' (is " << (int)*attrs[i + 1].value << "d)"); - } - } - } - - if (sstatus == HYPERDEX_CLIENT_SEARCHDONE) - { - break; - } - } - - for (size_t i = 0; i < expected.size(); ++i) - { - if (expected[i] && !seen[i]) - { - HYPERDEX_TEST_FAIL(testno, "sorted_search should have returned " << i << " but did not"); - } - } + std::vector seen(expected.size(), false); + const hyperdex_client_attribute *attrs; + size_t attrs_sz; + hyperdex_client_returncode sstatus = HYPERDEX_CLIENT_SUCCESS; + int64_t sid = cl->sorted_search(_space, checks, checks_sz, "number", 1ULL << testno, false, &sstatus, &attrs, &attrs_sz); + if (sid < 0) + { + HYPERDEX_TEST_FAIL(testno, "sorted_search encountered error " << sstatus << ": " << cl->error_message() << " at " << cl->error_location()); + } + int64_t old_num = 0; + while (true) + { + hyperdex_client_returncode lstatus; + int64_t lid = cl->loop(SEARCH_STRESS_TIMEOUT(testno), &lstatus); + if (lid < 0) + { + HYPERDEX_TEST_FAIL(testno, "loop returned error " << lstatus << ": " << cl->error_message() << " at " << cl->error_location()); + } + if (sid != lid) + { + HYPERDEX_TEST_FAIL(testno, "loop id (" << lid << ") does not match sorted_search id (" << sid << ")"); + } + if (sstatus != HYPERDEX_CLIENT_SUCCESS && sstatus != HYPERDEX_CLIENT_SEARCHDONE) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) returned " << sstatus << ": " << cl->error_message() << " at " << cl->error_location()); + } + if (sstatus == HYPERDEX_CLIENT_SUCCESS) + { + if (attrs_sz != 33) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) returned " << attrs_sz + << " attributes instead of 33"); + } + if (strcmp(attrs[0].attr, "number") != 0) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) key was field \"" + << attrs[0].attr << "\" but should have been field \"number\""); + } + if (attrs[0].value_sz != sizeof(uint64_t)) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) key has size " + << attrs[0].value_sz << " bytes, but should be sizeof(int64_t)"); + } + int64_t num = 0; + if (_key_type == HYPERDATATYPE_STRING) + { + e::unpack64be(attrs[0].value, &num); + } + else if (_key_type == HYPERDATATYPE_INT64) + { + e::unpack64le(attrs[0].value, &num); + } + else + { + HYPERDEX_TEST_FAIL(testno, "unknown key datatype"); + } + if (num >= (1LL << testno)) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) number " << num << " outside range"); + } + if (num < old_num) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) number " << num << " out of order (prev was " << old_num << ")"); + } + old_num = num; + if (seen[num]) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) number " << num << " already seen"); + } + seen[num] = true; + if (!expected[num]) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) number " << num << " not expected"); + } + for (size_t i = 0; i < 32; ++i) + { + if (strcmp(attrs[i + 1].attr, _colnames[i]) != 0) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) key was field \"" + << attrs[i + 1].attr << "\" but should have been field \"" + << _colnames[i] << "\""); + } + if (attrs[i + 1].value_sz != 1) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) attribute has size " + << attrs[i + 1].value_sz << " bytes, but should be 1"); + } + if (*attrs[i + 1].value == '1') + { + if (!(num & (1ULL << i))) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) bit " << i + << " not set for number " << num); + } + } + else if (*attrs[i + 1].value == '0') + { + if ((num & (1ULL << i))) + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) bit " << i + << " set for number " << num); + } + } + else + { + HYPERDEX_TEST_FAIL(testno, "operation " << sid << " (sorted_search) bit not '0' or '1' (is " << (int)*attrs[i + 1].value << "d)"); + } + } + } + if (sstatus == HYPERDEX_CLIENT_SEARCHDONE) + { + break; + } + } + for (size_t i = 0; i < expected.size(); ++i) + { + if (expected[i] && !seen[i]) + { + HYPERDEX_TEST_FAIL(testno, "sorted_search should have returned " << i << " but did not"); + } + } } static void group_del(size_t testno, - hyperdex::Client* cl, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz) + hyperdex::Client *cl, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz) { - hyperdex_client_returncode gstatus; - uint64_t count; - int64_t gid = cl->group_del(_space, checks, checks_sz, &gstatus, &count); - - if (gid < 0) - { - HYPERDEX_TEST_FAIL(testno, "group_del encountered error " << gstatus << ": " << cl->error_message() << " at " << cl->error_location()); - } - - hyperdex_client_returncode lstatus; - int64_t lid = cl->loop(SEARCH_STRESS_TIMEOUT(testno), &lstatus); - - if (lid < 0) - { - HYPERDEX_TEST_FAIL(testno, "loop returned error " << lstatus << ": " << cl->error_message() << " at " << cl->error_location()); - } - - if (gid != lid) - { - HYPERDEX_TEST_FAIL(testno, "loop id (" << lid << ") does not match group_del id (" << gid << ")"); - } - - if (gstatus != HYPERDEX_CLIENT_SUCCESS) - { - HYPERDEX_TEST_FAIL(testno, "operation " << gid << " (group_del) returned " << gstatus << ": " << cl->error_message() << " at " << cl->error_location()); - } - - uint64_t sleep = 10000000ULL; - sleep *= (1 + testno); - struct timespec ts; - ts.tv_sec = sleep / 1000000000ULL; - ts.tv_nsec = sleep % 1000000000ULL; - nanosleep(&ts, NULL); + hyperdex_client_returncode gstatus; + uint64_t count; + int64_t gid = cl->group_del(_space, checks, checks_sz, &gstatus, &count); + if (gid < 0) + { + HYPERDEX_TEST_FAIL(testno, "group_del encountered error " << gstatus << ": " << cl->error_message() << " at " << cl->error_location()); + } + hyperdex_client_returncode lstatus; + int64_t lid = cl->loop(SEARCH_STRESS_TIMEOUT(testno), &lstatus); + if (lid < 0) + { + HYPERDEX_TEST_FAIL(testno, "loop returned error " << lstatus << ": " << cl->error_message() << " at " << cl->error_location()); + } + if (gid != lid) + { + HYPERDEX_TEST_FAIL(testno, "loop id (" << lid << ") does not match group_del id (" << gid << ")"); + } + if (gstatus != HYPERDEX_CLIENT_SUCCESS) + { + HYPERDEX_TEST_FAIL(testno, "operation " << gid << " (group_del) returned " << gstatus << ": " << cl->error_message() << " at " << cl->error_location()); + } + uint64_t sleep = 10000000ULL; + sleep *= (1 + testno); + struct timespec ts; + ts.tv_sec = sleep / 1000000000ULL; + ts.tv_nsec = sleep % 1000000000ULL; + nanosleep(&ts, NULL); } static void count(size_t testno, - hyperdex::Client* cl, - const struct hyperdex_client_attribute_check* checks, size_t checks_sz, + hyperdex::Client *cl, + const struct hyperdex_client_attribute_check *checks, size_t checks_sz, size_t expected) { - uint64_t c = 0; - hyperdex_client_returncode cstatus; - int64_t cid = cl->count(_space, checks, checks_sz, &cstatus, &c); - - if (cid < 0) - { - HYPERDEX_TEST_FAIL(testno, "count encountered error " << cstatus << ": " << cl->error_message() << " at " << cl->error_location()); - } - - hyperdex_client_returncode lstatus; - int64_t lid = cl->loop(SEARCH_STRESS_TIMEOUT(testno), &lstatus); - - if (lid < 0) - { - HYPERDEX_TEST_FAIL(testno, "loop returned error " << lstatus << ": " << cl->error_message() << " at " << cl->error_location()); - } - - if (cid != lid) - { - HYPERDEX_TEST_FAIL(testno, "loop id (" << lid << ") does not match count id (" << cid << ")"); - } - - if (cstatus != HYPERDEX_CLIENT_SUCCESS) - { - HYPERDEX_TEST_FAIL(testno, "operation " << cid << " (count) returned " << cstatus << ": " << cl->error_message() << " at " << cl->error_location()); - } - - if (c != expected) - { - HYPERDEX_TEST_FAIL(testno, "counted " << c << " objects when we should have counted " << expected << " objects"); - } + uint64_t c = 0; + hyperdex_client_returncode cstatus; + int64_t cid = cl->count(_space, checks, checks_sz, &cstatus, &c); + if (cid < 0) + { + HYPERDEX_TEST_FAIL(testno, "count encountered error " << cstatus << ": " << cl->error_message() << " at " << cl->error_location()); + } + hyperdex_client_returncode lstatus; + int64_t lid = cl->loop(SEARCH_STRESS_TIMEOUT(testno), &lstatus); + if (lid < 0) + { + HYPERDEX_TEST_FAIL(testno, "loop returned error " << lstatus << ": " << cl->error_message() << " at " << cl->error_location()); + } + if (cid != lid) + { + HYPERDEX_TEST_FAIL(testno, "loop id (" << lid << ") does not match count id (" << cid << ")"); + } + if (cstatus != HYPERDEX_CLIENT_SUCCESS) + { + HYPERDEX_TEST_FAIL(testno, "operation " << cid << " (count) returned " << cstatus << ": " << cl->error_message() << " at " << cl->error_location()); + } + if (c != expected) + { + HYPERDEX_TEST_FAIL(testno, "counted " << c << " objects when we should have counted " << expected << " objects"); + } } static void setup_random_search(size_t, - hyperdex_client_attribute_check* chks, - size_t* chks_sz, - std::vector* expecting) + hyperdex_client_attribute_check *chks, + size_t *chks_sz, + std::vector *expecting) { - uint32_t mask = rand(); - uint32_t bits = rand(); - *chks_sz = 0; - - for (size_t i = 0; i < 32; ++i) - { - if ((mask & (1ULL << i))) - { - chks[*chks_sz].attr = _colnames[i]; - - if ((bits & (1ULL << i))) - { - chks[*chks_sz].value = "1"; - } - else - { - chks[*chks_sz].value = "0"; - } - - chks[*chks_sz].value_sz = 1; - chks[*chks_sz].datatype = HYPERDATATYPE_STRING; - chks[*chks_sz].predicate = HYPERPREDICATE_EQUALS; - ++(*chks_sz); - } - } - - for (uint32_t i = 0; i < expecting->size(); ++i) - { - if ((mask & i) != (mask & bits)) - { - (*expecting)[i] = false; - } - } + uint32_t mask = rand(); + uint32_t bits = rand(); + *chks_sz = 0; + for (size_t i = 0; i < 32; ++i) + { + if ((mask & (1ULL << i))) + { + chks[*chks_sz].attr = _colnames[i]; + if ((bits & (1ULL << i))) + { + chks[*chks_sz].value = "1"; + } + else + { + chks[*chks_sz].value = "0"; + } + chks[*chks_sz].value_sz = 1; + chks[*chks_sz].datatype = HYPERDATATYPE_STRING; + chks[*chks_sz].predicate = HYPERPREDICATE_EQUALS; + ++(*chks_sz); + } + } + for (uint32_t i = 0; i < expecting->size(); ++i) + { + if ((mask & i) != (mask & bits)) + { + (*expecting)[i] = false; + } + } } void all_search_tests(size_t testno, - hyperdex::Client* cl, - const std::vector& expecting) + hyperdex::Client *cl, + const std::vector &expecting) { - struct timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 100 * 1000ULL * 1000ULL; - nanosleep(&ts, NULL); - search(testno, cl, NULL, 0, expecting); - sorted_search(testno, cl, NULL, 0, expecting); - size_t num = 0; - - for (size_t i = 0; i < expecting.size(); ++i) - { - if (expecting[i]) - { - ++num; - } - } - - count(testno, cl, NULL, 0, num); - hyperdex_client_attribute_check chks[32]; - - for (size_t i = 0; i < _random_iters; ++i) - { - size_t chks_sz; - std::vector subset_expecting(expecting); - setup_random_search(testno, chks, &chks_sz, &subset_expecting); - search(testno, cl, chks, chks_sz, subset_expecting); - sorted_search(testno, cl, chks, chks_sz, subset_expecting); - num = 0; - - for (size_t j = 0; j < subset_expecting.size(); ++j) - { - if (subset_expecting[j]) - { - ++num; - } - } - - count(testno, cl, chks, chks_sz, num); - } + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 100 * 1000ULL * 1000ULL; + nanosleep(&ts, NULL); + search(testno, cl, NULL, 0, expecting); + sorted_search(testno, cl, NULL, 0, expecting); + size_t num = 0; + for (size_t i = 0; i < expecting.size(); ++i) + { + if (expecting[i]) + { + ++num; + } + } + count(testno, cl, NULL, 0, num); + hyperdex_client_attribute_check chks[32]; + for (size_t i = 0; i < _random_iters; ++i) + { + size_t chks_sz; + std::vector subset_expecting(expecting); + setup_random_search(testno, chks, &chks_sz, &subset_expecting); + search(testno, cl, chks, chks_sz, subset_expecting); + sorted_search(testno, cl, chks, chks_sz, subset_expecting); + num = 0; + for (size_t j = 0; j < subset_expecting.size(); ++j) + { + if (subset_expecting[j]) + { + ++num; + } + } + count(testno, cl, chks, chks_sz, num); + } } diff --git a/test/sh/bindings.go.Basic.sh b/test/sh/bindings.go.Basic.sh new file mode 100755 index 000000000..a93b9a945 --- /dev/null +++ b/test/sh/bindings.go.Basic.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + go run test/go/Basic.go {HOST} {PORT} diff --git a/test/sh/bindings.go.BasicSearch.sh b/test/sh/bindings.go.BasicSearch.sh new file mode 100755 index 000000000..517ec4ed8 --- /dev/null +++ b/test/sh/bindings.go.BasicSearch.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + go run test/go/BasicSearch.go {HOST} {PORT} diff --git a/test/sh/bindings.go.CondPut.sh b/test/sh/bindings.go.CondPut.sh new file mode 100755 index 000000000..f8e2dd728 --- /dev/null +++ b/test/sh/bindings.go.CondPut.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + go run test/go/CondPut.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeFloat.sh b/test/sh/bindings.go.DataTypeFloat.sh new file mode 100755 index 000000000..fbd8666c4 --- /dev/null +++ b/test/sh/bindings.go.DataTypeFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes float v" --daemons=1 -- \ + go run test/go/DataTypeFloat.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeInt.sh b/test/sh/bindings.go.DataTypeInt.sh new file mode 100755 index 000000000..5494435e8 --- /dev/null +++ b/test/sh/bindings.go.DataTypeInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes int v" --daemons=1 -- \ + go run test/go/DataTypeInt.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeListFloat.sh b/test/sh/bindings.go.DataTypeListFloat.sh new file mode 100755 index 000000000..3391ad545 --- /dev/null +++ b/test/sh/bindings.go.DataTypeListFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes list(float) v" --daemons=1 -- \ + go run test/go/DataTypeListFloat.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeListInt.sh b/test/sh/bindings.go.DataTypeListInt.sh new file mode 100755 index 000000000..2e863b151 --- /dev/null +++ b/test/sh/bindings.go.DataTypeListInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes list(int) v" --daemons=1 -- \ + go run test/go/DataTypeListInt.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeListString.sh b/test/sh/bindings.go.DataTypeListString.sh new file mode 100755 index 000000000..8e0b8663f --- /dev/null +++ b/test/sh/bindings.go.DataTypeListString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes list(string) v" --daemons=1 -- \ + go run test/go/DataTypeListString.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeMapFloatFloat.sh b/test/sh/bindings.go.DataTypeMapFloatFloat.sh new file mode 100755 index 000000000..514e4c78c --- /dev/null +++ b/test/sh/bindings.go.DataTypeMapFloatFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(float, float) v" --daemons=1 -- \ + go run test/go/DataTypeMapFloatFloat.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeMapFloatInt.sh b/test/sh/bindings.go.DataTypeMapFloatInt.sh new file mode 100755 index 000000000..5c0482c4f --- /dev/null +++ b/test/sh/bindings.go.DataTypeMapFloatInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(float, int) v" --daemons=1 -- \ + go run test/go/DataTypeMapFloatInt.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeMapFloatString.sh b/test/sh/bindings.go.DataTypeMapFloatString.sh new file mode 100755 index 000000000..7abd3bea4 --- /dev/null +++ b/test/sh/bindings.go.DataTypeMapFloatString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(float, string) v" --daemons=1 -- \ + go run test/go/DataTypeMapFloatString.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeMapIntFloat.sh b/test/sh/bindings.go.DataTypeMapIntFloat.sh new file mode 100755 index 000000000..434320d98 --- /dev/null +++ b/test/sh/bindings.go.DataTypeMapIntFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(int, float) v" --daemons=1 -- \ + go run test/go/DataTypeMapIntFloat.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeMapIntInt.sh b/test/sh/bindings.go.DataTypeMapIntInt.sh new file mode 100755 index 000000000..6fdb202ff --- /dev/null +++ b/test/sh/bindings.go.DataTypeMapIntInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(int, int) v" --daemons=1 -- \ + go run test/go/DataTypeMapIntInt.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeMapIntString.sh b/test/sh/bindings.go.DataTypeMapIntString.sh new file mode 100755 index 000000000..f0380edb2 --- /dev/null +++ b/test/sh/bindings.go.DataTypeMapIntString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(int, string) v" --daemons=1 -- \ + go run test/go/DataTypeMapIntString.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeMapStringFloat.sh b/test/sh/bindings.go.DataTypeMapStringFloat.sh new file mode 100755 index 000000000..271a107fa --- /dev/null +++ b/test/sh/bindings.go.DataTypeMapStringFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(string, float) v" --daemons=1 -- \ + go run test/go/DataTypeMapStringFloat.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeMapStringInt.sh b/test/sh/bindings.go.DataTypeMapStringInt.sh new file mode 100755 index 000000000..c898b5737 --- /dev/null +++ b/test/sh/bindings.go.DataTypeMapStringInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(string, int) v" --daemons=1 -- \ + go run test/go/DataTypeMapStringInt.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeMapStringString.sh b/test/sh/bindings.go.DataTypeMapStringString.sh new file mode 100755 index 000000000..90b90815a --- /dev/null +++ b/test/sh/bindings.go.DataTypeMapStringString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(string, string) v" --daemons=1 -- \ + go run test/go/DataTypeMapStringString.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeSetFloat.sh b/test/sh/bindings.go.DataTypeSetFloat.sh new file mode 100755 index 000000000..cc015ac6b --- /dev/null +++ b/test/sh/bindings.go.DataTypeSetFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes set(float) v" --daemons=1 -- \ + go run test/go/DataTypeSetFloat.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeSetInt.sh b/test/sh/bindings.go.DataTypeSetInt.sh new file mode 100755 index 000000000..2f1b803dc --- /dev/null +++ b/test/sh/bindings.go.DataTypeSetInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes set(int) v" --daemons=1 -- \ + go run test/go/DataTypeSetInt.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeSetString.sh b/test/sh/bindings.go.DataTypeSetString.sh new file mode 100755 index 000000000..f8f148254 --- /dev/null +++ b/test/sh/bindings.go.DataTypeSetString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes set(string) v" --daemons=1 -- \ + go run test/go/DataTypeSetString.go {HOST} {PORT} diff --git a/test/sh/bindings.go.DataTypeString.sh b/test/sh/bindings.go.DataTypeString.sh new file mode 100755 index 000000000..df3d02011 --- /dev/null +++ b/test/sh/bindings.go.DataTypeString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes v" --daemons=1 -- \ + go run test/go/DataTypeString.go {HOST} {PORT} diff --git a/test/sh/bindings.go.LengthString.sh b/test/sh/bindings.go.LengthString.sh new file mode 100755 index 000000000..ec32fd8e4 --- /dev/null +++ b/test/sh/bindings.go.LengthString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k" --daemons=1 -- \ + go run test/go/LengthString.go {HOST} {PORT} diff --git a/test/sh/bindings.go.MultiAttribute.sh b/test/sh/bindings.go.MultiAttribute.sh new file mode 100755 index 000000000..981219cfe --- /dev/null +++ b/test/sh/bindings.go.MultiAttribute.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes v1, v2" --daemons=1 -- \ + go run test/go/MultiAttribute.go {HOST} {PORT} diff --git a/test/sh/bindings.go.RangeSearchInt.sh b/test/sh/bindings.go.RangeSearchInt.sh new file mode 100755 index 000000000..08e51dabe --- /dev/null +++ b/test/sh/bindings.go.RangeSearchInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key int k attribute int v" --daemons=1 -- \ + go run test/go/RangeSearchInt.go {HOST} {PORT} diff --git a/test/sh/bindings.go.RangeSearchString.sh b/test/sh/bindings.go.RangeSearchString.sh new file mode 100755 index 000000000..8a4312eef --- /dev/null +++ b/test/sh/bindings.go.RangeSearchString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + go run test/go/RangeSearchString.go {HOST} {PORT} diff --git a/test/sh/bindings.go.RegexSearch.sh b/test/sh/bindings.go.RegexSearch.sh new file mode 100755 index 000000000..9d75e80c0 --- /dev/null +++ b/test/sh/bindings.go.RegexSearch.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k" --daemons=1 -- \ + go run test/go/RegexSearch.go {HOST} {PORT} diff --git a/test/sh/bindings.java.Basic.sh b/test/sh/bindings.java.Basic.sh new file mode 100755 index 000000000..b8fd055d4 --- /dev/null +++ b/test/sh/bindings.java.Basic.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/Basic.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 Basic {HOST} {PORT} diff --git a/test/sh/bindings.java.BasicSearch.sh b/test/sh/bindings.java.BasicSearch.sh new file mode 100755 index 000000000..ed14dfaa4 --- /dev/null +++ b/test/sh/bindings.java.BasicSearch.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/BasicSearch.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 BasicSearch {HOST} {PORT} diff --git a/test/sh/bindings.java.CondPut.sh b/test/sh/bindings.java.CondPut.sh new file mode 100755 index 000000000..6c21589d8 --- /dev/null +++ b/test/sh/bindings.java.CondPut.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/CondPut.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 CondPut {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeFloat.sh b/test/sh/bindings.java.DataTypeFloat.sh new file mode 100755 index 000000000..da1197208 --- /dev/null +++ b/test/sh/bindings.java.DataTypeFloat.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeFloat.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes float v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeFloat {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeInt.sh b/test/sh/bindings.java.DataTypeInt.sh new file mode 100755 index 000000000..563abce98 --- /dev/null +++ b/test/sh/bindings.java.DataTypeInt.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeInt.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes int v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeInt {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeListFloat.sh b/test/sh/bindings.java.DataTypeListFloat.sh new file mode 100755 index 000000000..a3157af7a --- /dev/null +++ b/test/sh/bindings.java.DataTypeListFloat.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeListFloat.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes list(float) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeListFloat {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeListInt.sh b/test/sh/bindings.java.DataTypeListInt.sh new file mode 100755 index 000000000..c23687e03 --- /dev/null +++ b/test/sh/bindings.java.DataTypeListInt.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeListInt.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes list(int) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeListInt {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeListString.sh b/test/sh/bindings.java.DataTypeListString.sh new file mode 100755 index 000000000..800ed7b19 --- /dev/null +++ b/test/sh/bindings.java.DataTypeListString.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeListString.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes list(string) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeListString {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeMapFloatFloat.sh b/test/sh/bindings.java.DataTypeMapFloatFloat.sh new file mode 100755 index 000000000..c3eb66b91 --- /dev/null +++ b/test/sh/bindings.java.DataTypeMapFloatFloat.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeMapFloatFloat.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(float, float) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeMapFloatFloat {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeMapFloatInt.sh b/test/sh/bindings.java.DataTypeMapFloatInt.sh new file mode 100755 index 000000000..0762bb1b2 --- /dev/null +++ b/test/sh/bindings.java.DataTypeMapFloatInt.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeMapFloatInt.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(float, int) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeMapFloatInt {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeMapFloatString.sh b/test/sh/bindings.java.DataTypeMapFloatString.sh new file mode 100755 index 000000000..cb919c298 --- /dev/null +++ b/test/sh/bindings.java.DataTypeMapFloatString.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeMapFloatString.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(float, string) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeMapFloatString {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeMapIntFloat.sh b/test/sh/bindings.java.DataTypeMapIntFloat.sh new file mode 100755 index 000000000..d68d67a35 --- /dev/null +++ b/test/sh/bindings.java.DataTypeMapIntFloat.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeMapIntFloat.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(int, float) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeMapIntFloat {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeMapIntInt.sh b/test/sh/bindings.java.DataTypeMapIntInt.sh new file mode 100755 index 000000000..3106313f1 --- /dev/null +++ b/test/sh/bindings.java.DataTypeMapIntInt.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeMapIntInt.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(int, int) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeMapIntInt {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeMapIntString.sh b/test/sh/bindings.java.DataTypeMapIntString.sh new file mode 100755 index 000000000..814293097 --- /dev/null +++ b/test/sh/bindings.java.DataTypeMapIntString.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeMapIntString.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(int, string) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeMapIntString {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeMapStringFloat.sh b/test/sh/bindings.java.DataTypeMapStringFloat.sh new file mode 100755 index 000000000..ca6041030 --- /dev/null +++ b/test/sh/bindings.java.DataTypeMapStringFloat.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeMapStringFloat.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(string, float) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeMapStringFloat {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeMapStringInt.sh b/test/sh/bindings.java.DataTypeMapStringInt.sh new file mode 100755 index 000000000..e1b77eb33 --- /dev/null +++ b/test/sh/bindings.java.DataTypeMapStringInt.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeMapStringInt.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(string, int) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeMapStringInt {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeMapStringString.sh b/test/sh/bindings.java.DataTypeMapStringString.sh new file mode 100755 index 000000000..7767fee3d --- /dev/null +++ b/test/sh/bindings.java.DataTypeMapStringString.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeMapStringString.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(string, string) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeMapStringString {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeSetFloat.sh b/test/sh/bindings.java.DataTypeSetFloat.sh new file mode 100755 index 000000000..1243976e0 --- /dev/null +++ b/test/sh/bindings.java.DataTypeSetFloat.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeSetFloat.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes set(float) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeSetFloat {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeSetInt.sh b/test/sh/bindings.java.DataTypeSetInt.sh new file mode 100755 index 000000000..53fcabb2a --- /dev/null +++ b/test/sh/bindings.java.DataTypeSetInt.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeSetInt.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes set(int) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeSetInt {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeSetString.sh b/test/sh/bindings.java.DataTypeSetString.sh new file mode 100755 index 000000000..2765a3afb --- /dev/null +++ b/test/sh/bindings.java.DataTypeSetString.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeSetString.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes set(string) v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeSetString {HOST} {PORT} diff --git a/test/sh/bindings.java.DataTypeString.sh b/test/sh/bindings.java.DataTypeString.sh new file mode 100755 index 000000000..ccd8f4825 --- /dev/null +++ b/test/sh/bindings.java.DataTypeString.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/DataTypeString.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 DataTypeString {HOST} {PORT} diff --git a/test/sh/bindings.java.LengthString.sh b/test/sh/bindings.java.LengthString.sh new file mode 100755 index 000000000..c8544d72e --- /dev/null +++ b/test/sh/bindings.java.LengthString.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/LengthString.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 LengthString {HOST} {PORT} diff --git a/test/sh/bindings.java.MultiAttribute.sh b/test/sh/bindings.java.MultiAttribute.sh new file mode 100755 index 000000000..49a37f844 --- /dev/null +++ b/test/sh/bindings.java.MultiAttribute.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/MultiAttribute.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes v1, v2" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 MultiAttribute {HOST} {PORT} diff --git a/test/sh/bindings.java.RangeSearchInt.sh b/test/sh/bindings.java.RangeSearchInt.sh new file mode 100755 index 000000000..16b046036 --- /dev/null +++ b/test/sh/bindings.java.RangeSearchInt.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/RangeSearchInt.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key int k attribute int v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 RangeSearchInt {HOST} {PORT} diff --git a/test/sh/bindings.java.RangeSearchString.sh b/test/sh/bindings.java.RangeSearchString.sh new file mode 100755 index 000000000..16ed9a013 --- /dev/null +++ b/test/sh/bindings.java.RangeSearchString.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/RangeSearchString.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 RangeSearchString {HOST} {PORT} diff --git a/test/sh/bindings.java.RegexSearch.sh b/test/sh/bindings.java.RegexSearch.sh new file mode 100755 index 000000000..69d31b020 --- /dev/null +++ b/test/sh/bindings.java.RegexSearch.sh @@ -0,0 +1,5 @@ +#!/bin/sh +javac -d "${HYPERDEX_BUILDDIR}"/test/java "${HYPERDEX_SRCDIR}"/test/java/RegexSearch.java + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k" --daemons=1 -- \ + java -ea -Djava.library.path="${HYPERDEX_BUILDDIR}"/.libs:/usr/local/lib:/usr/local/lib64:/usr/lib:/usr/lib64 RegexSearch {HOST} {PORT} diff --git a/test/sh/bindings.python.Admin.sh b/test/sh/bindings.python.Admin.sh new file mode 100755 index 000000000..982873e43 --- /dev/null +++ b/test/sh/bindings.python.Admin.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/Admin.py {HOST} {PORT} diff --git a/test/sh/bindings.python.Basic.sh b/test/sh/bindings.python.Basic.sh new file mode 100755 index 000000000..1a1d82e7f --- /dev/null +++ b/test/sh/bindings.python.Basic.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/Basic.py {HOST} {PORT} diff --git a/test/sh/bindings.python.BasicSearch.sh b/test/sh/bindings.python.BasicSearch.sh new file mode 100755 index 000000000..325aaea11 --- /dev/null +++ b/test/sh/bindings.python.BasicSearch.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/BasicSearch.py {HOST} {PORT} diff --git a/test/sh/bindings.python.CondPut.sh b/test/sh/bindings.python.CondPut.sh new file mode 100755 index 000000000..f4d5ab48d --- /dev/null +++ b/test/sh/bindings.python.CondPut.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/CondPut.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeDocument.sh b/test/sh/bindings.python.DataTypeDocument.sh new file mode 100755 index 000000000..dc916aa21 --- /dev/null +++ b/test/sh/bindings.python.DataTypeDocument.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes document v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeDocument.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeFloat.sh b/test/sh/bindings.python.DataTypeFloat.sh new file mode 100755 index 000000000..9b3970d9b --- /dev/null +++ b/test/sh/bindings.python.DataTypeFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes float v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeFloat.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeInt.sh b/test/sh/bindings.python.DataTypeInt.sh new file mode 100755 index 000000000..855a394d8 --- /dev/null +++ b/test/sh/bindings.python.DataTypeInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes int v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeInt.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeListFloat.sh b/test/sh/bindings.python.DataTypeListFloat.sh new file mode 100755 index 000000000..5897e35ca --- /dev/null +++ b/test/sh/bindings.python.DataTypeListFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes list(float) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeListFloat.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeListInt.sh b/test/sh/bindings.python.DataTypeListInt.sh new file mode 100755 index 000000000..5b62385e7 --- /dev/null +++ b/test/sh/bindings.python.DataTypeListInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes list(int) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeListInt.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeListString.sh b/test/sh/bindings.python.DataTypeListString.sh new file mode 100755 index 000000000..f0771b901 --- /dev/null +++ b/test/sh/bindings.python.DataTypeListString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes list(string) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeListString.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeMapFloatFloat.sh b/test/sh/bindings.python.DataTypeMapFloatFloat.sh new file mode 100755 index 000000000..ffaf2c163 --- /dev/null +++ b/test/sh/bindings.python.DataTypeMapFloatFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(float, float) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeMapFloatFloat.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeMapFloatInt.sh b/test/sh/bindings.python.DataTypeMapFloatInt.sh new file mode 100755 index 000000000..4ed578128 --- /dev/null +++ b/test/sh/bindings.python.DataTypeMapFloatInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(float, int) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeMapFloatInt.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeMapFloatString.sh b/test/sh/bindings.python.DataTypeMapFloatString.sh new file mode 100755 index 000000000..49c253c09 --- /dev/null +++ b/test/sh/bindings.python.DataTypeMapFloatString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(float, string) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeMapFloatString.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeMapIntFloat.sh b/test/sh/bindings.python.DataTypeMapIntFloat.sh new file mode 100755 index 000000000..a361a6168 --- /dev/null +++ b/test/sh/bindings.python.DataTypeMapIntFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(int, float) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeMapIntFloat.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeMapIntInt.sh b/test/sh/bindings.python.DataTypeMapIntInt.sh new file mode 100755 index 000000000..50ff44862 --- /dev/null +++ b/test/sh/bindings.python.DataTypeMapIntInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(int, int) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeMapIntInt.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeMapIntString.sh b/test/sh/bindings.python.DataTypeMapIntString.sh new file mode 100755 index 000000000..adca5145c --- /dev/null +++ b/test/sh/bindings.python.DataTypeMapIntString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(int, string) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeMapIntString.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeMapStringFloat.sh b/test/sh/bindings.python.DataTypeMapStringFloat.sh new file mode 100755 index 000000000..39e48b462 --- /dev/null +++ b/test/sh/bindings.python.DataTypeMapStringFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(string, float) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeMapStringFloat.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeMapStringInt.sh b/test/sh/bindings.python.DataTypeMapStringInt.sh new file mode 100755 index 000000000..bb90e981b --- /dev/null +++ b/test/sh/bindings.python.DataTypeMapStringInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(string, int) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeMapStringInt.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeMapStringString.sh b/test/sh/bindings.python.DataTypeMapStringString.sh new file mode 100755 index 000000000..814258f27 --- /dev/null +++ b/test/sh/bindings.python.DataTypeMapStringString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(string, string) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeMapStringString.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeSetFloat.sh b/test/sh/bindings.python.DataTypeSetFloat.sh new file mode 100755 index 000000000..51f7c431e --- /dev/null +++ b/test/sh/bindings.python.DataTypeSetFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes set(float) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeSetFloat.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeSetInt.sh b/test/sh/bindings.python.DataTypeSetInt.sh new file mode 100755 index 000000000..b0d61bfd0 --- /dev/null +++ b/test/sh/bindings.python.DataTypeSetInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes set(int) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeSetInt.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeSetString.sh b/test/sh/bindings.python.DataTypeSetString.sh new file mode 100755 index 000000000..b69acd76b --- /dev/null +++ b/test/sh/bindings.python.DataTypeSetString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes set(string) v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeSetString.py {HOST} {PORT} diff --git a/test/sh/bindings.python.DataTypeString.sh b/test/sh/bindings.python.DataTypeString.sh new file mode 100755 index 000000000..afdbe2360 --- /dev/null +++ b/test/sh/bindings.python.DataTypeString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/DataTypeString.py {HOST} {PORT} diff --git a/test/sh/bindings.python.GroupAtomic.sh b/test/sh/bindings.python.GroupAtomic.sh new file mode 100755 index 000000000..f6187c303 --- /dev/null +++ b/test/sh/bindings.python.GroupAtomic.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes document v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/GroupAtomic.py {HOST} {PORT} diff --git a/test/sh/bindings.python.HyperMongo.sh b/test/sh/bindings.python.HyperMongo.sh new file mode 100755 index 000000000..a4f67b32a --- /dev/null +++ b/test/sh/bindings.python.HyperMongo.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes document v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/HyperMongo.py {HOST} {PORT} + diff --git a/test/sh/bindings.python.LengthString.sh b/test/sh/bindings.python.LengthString.sh new file mode 100755 index 000000000..e6fe7d8cd --- /dev/null +++ b/test/sh/bindings.python.LengthString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/LengthString.py {HOST} {PORT} diff --git a/test/sh/bindings.python.MultiAttribute.sh b/test/sh/bindings.python.MultiAttribute.sh new file mode 100755 index 000000000..b464c3fb8 --- /dev/null +++ b/test/sh/bindings.python.MultiAttribute.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes v1, v2" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/MultiAttribute.py {HOST} {PORT} diff --git a/test/sh/bindings.python.RangeSearchInt.sh b/test/sh/bindings.python.RangeSearchInt.sh new file mode 100755 index 000000000..9ee43aa4f --- /dev/null +++ b/test/sh/bindings.python.RangeSearchInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key int k attribute int v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/RangeSearchInt.py {HOST} {PORT} diff --git a/test/sh/bindings.python.RangeSearchString.sh b/test/sh/bindings.python.RangeSearchString.sh new file mode 100755 index 000000000..cf238c07e --- /dev/null +++ b/test/sh/bindings.python.RangeSearchString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/RangeSearchString.py {HOST} {PORT} diff --git a/test/sh/bindings.python.RegexSearch.sh b/test/sh/bindings.python.RegexSearch.sh new file mode 100755 index 000000000..a0d21ab1f --- /dev/null +++ b/test/sh/bindings.python.RegexSearch.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k" --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/python/RegexSearch.py {HOST} {PORT} diff --git a/test/sh/bindings.ruby.Basic.sh b/test/sh/bindings.ruby.Basic.sh new file mode 100755 index 000000000..c4a181299 --- /dev/null +++ b/test/sh/bindings.ruby.Basic.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/Basic.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.BasicSearch.sh b/test/sh/bindings.ruby.BasicSearch.sh new file mode 100755 index 000000000..2c561b8ca --- /dev/null +++ b/test/sh/bindings.ruby.BasicSearch.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/BasicSearch.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.CondPut.sh b/test/sh/bindings.ruby.CondPut.sh new file mode 100755 index 000000000..90b5c218e --- /dev/null +++ b/test/sh/bindings.ruby.CondPut.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/CondPut.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeFloat.sh b/test/sh/bindings.ruby.DataTypeFloat.sh new file mode 100755 index 000000000..cbf0e59f0 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes float v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeFloat.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeInt.sh b/test/sh/bindings.ruby.DataTypeInt.sh new file mode 100755 index 000000000..c739dd005 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes int v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeInt.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeListFloat.sh b/test/sh/bindings.ruby.DataTypeListFloat.sh new file mode 100755 index 000000000..1ae8b1eca --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeListFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes list(float) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeListFloat.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeListInt.sh b/test/sh/bindings.ruby.DataTypeListInt.sh new file mode 100755 index 000000000..25e54664f --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeListInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes list(int) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeListInt.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeListString.sh b/test/sh/bindings.ruby.DataTypeListString.sh new file mode 100755 index 000000000..7500bdba3 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeListString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes list(string) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeListString.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeMapFloatFloat.sh b/test/sh/bindings.ruby.DataTypeMapFloatFloat.sh new file mode 100755 index 000000000..68b0b00e9 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeMapFloatFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(float, float) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeMapFloatFloat.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeMapFloatInt.sh b/test/sh/bindings.ruby.DataTypeMapFloatInt.sh new file mode 100755 index 000000000..6e7f34649 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeMapFloatInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(float, int) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeMapFloatInt.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeMapFloatString.sh b/test/sh/bindings.ruby.DataTypeMapFloatString.sh new file mode 100755 index 000000000..2e7547250 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeMapFloatString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(float, string) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeMapFloatString.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeMapIntFloat.sh b/test/sh/bindings.ruby.DataTypeMapIntFloat.sh new file mode 100755 index 000000000..4cf9d1f40 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeMapIntFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(int, float) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeMapIntFloat.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeMapIntInt.sh b/test/sh/bindings.ruby.DataTypeMapIntInt.sh new file mode 100755 index 000000000..33c9a64da --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeMapIntInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(int, int) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeMapIntInt.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeMapIntString.sh b/test/sh/bindings.ruby.DataTypeMapIntString.sh new file mode 100755 index 000000000..a5e8752c9 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeMapIntString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(int, string) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeMapIntString.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeMapStringFloat.sh b/test/sh/bindings.ruby.DataTypeMapStringFloat.sh new file mode 100755 index 000000000..d09ccd1b4 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeMapStringFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(string, float) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeMapStringFloat.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeMapStringInt.sh b/test/sh/bindings.ruby.DataTypeMapStringInt.sh new file mode 100755 index 000000000..3eaa052d9 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeMapStringInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(string, int) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeMapStringInt.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeMapStringString.sh b/test/sh/bindings.ruby.DataTypeMapStringString.sh new file mode 100755 index 000000000..13feeacc8 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeMapStringString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes map(string, string) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeMapStringString.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeSetFloat.sh b/test/sh/bindings.ruby.DataTypeSetFloat.sh new file mode 100755 index 000000000..2a1f409c6 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeSetFloat.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes set(float) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeSetFloat.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeSetInt.sh b/test/sh/bindings.ruby.DataTypeSetInt.sh new file mode 100755 index 000000000..33fe21ec9 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeSetInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes set(int) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeSetInt.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeSetString.sh b/test/sh/bindings.ruby.DataTypeSetString.sh new file mode 100755 index 000000000..5d8682f96 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeSetString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes set(string) v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeSetString.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.DataTypeString.sh b/test/sh/bindings.ruby.DataTypeString.sh new file mode 100755 index 000000000..ecbab5326 --- /dev/null +++ b/test/sh/bindings.ruby.DataTypeString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/DataTypeString.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.LengthString.sh b/test/sh/bindings.ruby.LengthString.sh new file mode 100755 index 000000000..8303c4448 --- /dev/null +++ b/test/sh/bindings.ruby.LengthString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/LengthString.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.MultiAttribute.sh b/test/sh/bindings.ruby.MultiAttribute.sh new file mode 100755 index 000000000..f51c85b64 --- /dev/null +++ b/test/sh/bindings.ruby.MultiAttribute.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attributes v1, v2" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/MultiAttribute.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.RangeSearchInt.sh b/test/sh/bindings.ruby.RangeSearchInt.sh new file mode 100755 index 000000000..26a6423eb --- /dev/null +++ b/test/sh/bindings.ruby.RangeSearchInt.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key int k attribute int v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/RangeSearchInt.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.RangeSearchString.sh b/test/sh/bindings.ruby.RangeSearchString.sh new file mode 100755 index 000000000..3889fef70 --- /dev/null +++ b/test/sh/bindings.ruby.RangeSearchString.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k attribute v" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/RangeSearchString.rb {HOST} {PORT} diff --git a/test/sh/bindings.ruby.RegexSearch.sh b/test/sh/bindings.ruby.RegexSearch.sh new file mode 100755 index 000000000..43e3cd2ee --- /dev/null +++ b/test/sh/bindings.ruby.RegexSearch.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --space="space kv key k" --daemons=1 -- \ + ruby "${HYPERDEX_SRCDIR}"/test/ruby/RegexSearch.rb {HOST} {PORT} diff --git a/test/sh/doc.async-ops.sh b/test/sh/doc.async-ops.sh new file mode 100755 index 000000000..4e27123fa --- /dev/null +++ b/test/sh/doc.async-ops.sh @@ -0,0 +1,4 @@ +#!/bin/sh +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/doctest-runner.py \ + "${HYPERDEX_SRCDIR}"/test/doc.async-ops.py {HOST} {PORT} diff --git a/test/sh/doc.atomic-ops.sh b/test/sh/doc.atomic-ops.sh new file mode 100755 index 000000000..b55b7b6e5 --- /dev/null +++ b/test/sh/doc.atomic-ops.sh @@ -0,0 +1,4 @@ +#!/bin/sh +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/doctest-runner.py \ + "${HYPERDEX_SRCDIR}"/test/doc.atomic-ops.py {HOST} {PORT} diff --git a/test/sh/doc.authorization.sh b/test/sh/doc.authorization.sh new file mode 100755 index 000000000..d7520bb1d --- /dev/null +++ b/test/sh/doc.authorization.sh @@ -0,0 +1,4 @@ +#!/bin/sh +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/doctest-runner.py \ + "${HYPERDEX_SRCDIR}"/test/doc.authorization.py {HOST} {PORT} diff --git a/test/sh/doc.data-types.sh b/test/sh/doc.data-types.sh new file mode 100755 index 000000000..e9b51c23e --- /dev/null +++ b/test/sh/doc.data-types.sh @@ -0,0 +1,4 @@ +#!/bin/sh +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/doctest-runner.py \ + "${HYPERDEX_SRCDIR}"/test/doc.data-types.py {HOST} {PORT} diff --git a/test/sh/doc.documents.sh b/test/sh/doc.documents.sh new file mode 100755 index 000000000..9a3dc510a --- /dev/null +++ b/test/sh/doc.documents.sh @@ -0,0 +1,4 @@ +#!/bin/sh +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/doctest-runner.py \ + "${HYPERDEX_SRCDIR}"/test/doc.documents.py {HOST} {PORT} diff --git a/test/sh/doc.quick-start.sh b/test/sh/doc.quick-start.sh new file mode 100755 index 000000000..a9efc5799 --- /dev/null +++ b/test/sh/doc.quick-start.sh @@ -0,0 +1,4 @@ +#!/bin/sh +python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 -- \ + python2 "${HYPERDEX_SRCDIR}"/test/doctest-runner.py \ + "${HYPERDEX_SRCDIR}"/test/doc.quick-start.py {HOST} {PORT} diff --git a/test/sh/replication.composite.daemons=1.fault-tolerance=0.sh b/test/sh/replication.composite.daemons=1.fault-tolerance=0.sh new file mode 100755 index 000000000..021da6b98 --- /dev/null +++ b/test/sh/replication.composite.daemons=1.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space replication key int A attributes int B, int C subspace B, C create 1 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/replication-stress-test --quiet -n 1 -h {HOST} -p {PORT} diff --git a/test/sh/replication.composite.daemons=4.fault-tolerance=0.sh b/test/sh/replication.composite.daemons=4.fault-tolerance=0.sh new file mode 100755 index 000000000..4a72b90c8 --- /dev/null +++ b/test/sh/replication.composite.daemons=4.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space replication key int A attributes int B, int C subspace B, C create 4 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/replication-stress-test --quiet -n 4 -h {HOST} -p {PORT} diff --git a/test/sh/replication.composite.daemons=4.fault-tolerance=1.sh b/test/sh/replication.composite.daemons=4.fault-tolerance=1.sh new file mode 100755 index 000000000..039132e88 --- /dev/null +++ b/test/sh/replication.composite.daemons=4.fault-tolerance=1.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space replication key int A attributes int B, int C subspace B, C create 4 partitions tolerate 1 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/replication-stress-test --quiet -n 4 -h {HOST} -p {PORT} diff --git a/test/sh/replication.composite.daemons=4.fault-tolerance=2.sh b/test/sh/replication.composite.daemons=4.fault-tolerance=2.sh new file mode 100755 index 000000000..c1a04745d --- /dev/null +++ b/test/sh/replication.composite.daemons=4.fault-tolerance=2.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space replication key int A attributes int B, int C subspace B, C create 4 partitions tolerate 2 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/replication-stress-test --quiet -n 4 -h {HOST} -p {PORT} diff --git a/test/sh/replication.reverse.daemons=1.fault-tolerance=0.sh b/test/sh/replication.reverse.daemons=1.fault-tolerance=0.sh new file mode 100755 index 000000000..b0bb4b707 --- /dev/null +++ b/test/sh/replication.reverse.daemons=1.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space replication key int A attributes int B, int C subspace C subspace B create 1 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/replication-stress-test --quiet -n 1 -h {HOST} -p {PORT} diff --git a/test/sh/replication.reverse.daemons=4.fault-tolerance=0.sh b/test/sh/replication.reverse.daemons=4.fault-tolerance=0.sh new file mode 100755 index 000000000..4e35ede03 --- /dev/null +++ b/test/sh/replication.reverse.daemons=4.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space replication key int A attributes int B, int C subspace C subspace B create 4 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/replication-stress-test --quiet -n 4 -h {HOST} -p {PORT} diff --git a/test/sh/replication.reverse.daemons=4.fault-tolerance=1.sh b/test/sh/replication.reverse.daemons=4.fault-tolerance=1.sh new file mode 100755 index 000000000..7f451c8d7 --- /dev/null +++ b/test/sh/replication.reverse.daemons=4.fault-tolerance=1.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space replication key int A attributes int B, int C subspace C subspace B create 4 partitions tolerate 1 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/replication-stress-test --quiet -n 4 -h {HOST} -p {PORT} diff --git a/test/sh/replication.reverse.daemons=4.fault-tolerance=2.sh b/test/sh/replication.reverse.daemons=4.fault-tolerance=2.sh new file mode 100755 index 000000000..ecdae4f87 --- /dev/null +++ b/test/sh/replication.reverse.daemons=4.fault-tolerance=2.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space replication key int A attributes int B, int C subspace C subspace B create 4 partitions tolerate 2 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/replication-stress-test --quiet -n 4 -h {HOST} -p {PORT} diff --git a/test/sh/replication.simple.daemons=1.fault-tolerance=0.sh b/test/sh/replication.simple.daemons=1.fault-tolerance=0.sh new file mode 100755 index 000000000..e1380dec9 --- /dev/null +++ b/test/sh/replication.simple.daemons=1.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space replication key int A attributes int B, int C subspace B subspace C create 1 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/replication-stress-test --quiet -n 1 -h {HOST} -p {PORT} diff --git a/test/sh/replication.simple.daemons=4.fault-tolerance=0.sh b/test/sh/replication.simple.daemons=4.fault-tolerance=0.sh new file mode 100755 index 000000000..ce3135a0d --- /dev/null +++ b/test/sh/replication.simple.daemons=4.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space replication key int A attributes int B, int C subspace B subspace C create 4 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/replication-stress-test --quiet -n 4 -h {HOST} -p {PORT} diff --git a/test/sh/replication.simple.daemons=4.fault-tolerance=1.sh b/test/sh/replication.simple.daemons=4.fault-tolerance=1.sh new file mode 100755 index 000000000..412475ae0 --- /dev/null +++ b/test/sh/replication.simple.daemons=4.fault-tolerance=1.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space replication key int A attributes int B, int C subspace B subspace C create 4 partitions tolerate 1 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/replication-stress-test --quiet -n 4 -h {HOST} -p {PORT} diff --git a/test/sh/replication.simple.daemons=4.fault-tolerance=2.sh b/test/sh/replication.simple.daemons=4.fault-tolerance=2.sh new file mode 100755 index 000000000..348e23170 --- /dev/null +++ b/test/sh/replication.simple.daemons=4.fault-tolerance=2.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space replication key int A attributes int B, int C subspace B subspace C create 4 partitions tolerate 2 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/replication-stress-test --quiet -n 4 -h {HOST} -p {PORT} diff --git a/test/sh/search.combination.keytype=int,daemons=1.fault-tolerance=0.sh b/test/sh/search.combination.keytype=int,daemons=1.fault-tolerance=0.sh new file mode 100755 index 000000000..91ba3bf67 --- /dev/null +++ b/test/sh/search.combination.keytype=int,daemons=1.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key int number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 subspace bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08 subspace bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16 subspace bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24 subspace bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 index bit09 index bit10 index bit11 index bit12 index bit13 index bit14 index bit15 index bit16 index bit17 index bit18 index bit19 index bit20 index bit21 index bit22 index bit23 index bit24 index bit25 index bit26 index bit27 index bit28 index bit29 index bit30 index bit31 index bit32 index bit01 index bit02 index bit03 index bit04 index bit05 index bit06 index bit07 index bit08 create 1 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k int diff --git a/test/sh/search.combination.keytype=int,daemons=4.fault-tolerance=0.sh b/test/sh/search.combination.keytype=int,daemons=4.fault-tolerance=0.sh new file mode 100755 index 000000000..0f5b53a1b --- /dev/null +++ b/test/sh/search.combination.keytype=int,daemons=4.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key int number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 subspace bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08 subspace bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16 subspace bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24 subspace bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 index bit09 index bit10 index bit11 index bit12 index bit13 index bit14 index bit15 index bit16 index bit17 index bit18 index bit19 index bit20 index bit21 index bit22 index bit23 index bit24 index bit25 index bit26 index bit27 index bit28 index bit29 index bit30 index bit31 index bit32 index bit01 index bit02 index bit03 index bit04 index bit05 index bit06 index bit07 index bit08 create 4 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k int diff --git a/test/sh/search.combination.keytype=int,daemons=4.fault-tolerance=1.sh b/test/sh/search.combination.keytype=int,daemons=4.fault-tolerance=1.sh new file mode 100755 index 000000000..6c1d3bb8f --- /dev/null +++ b/test/sh/search.combination.keytype=int,daemons=4.fault-tolerance=1.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key int number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 subspace bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08 subspace bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16 subspace bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24 subspace bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 index bit09 index bit10 index bit11 index bit12 index bit13 index bit14 index bit15 index bit16 index bit17 index bit18 index bit19 index bit20 index bit21 index bit22 index bit23 index bit24 index bit25 index bit26 index bit27 index bit28 index bit29 index bit30 index bit31 index bit32 index bit01 index bit02 index bit03 index bit04 index bit05 index bit06 index bit07 index bit08 create 4 partitions tolerate 1 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k int diff --git a/test/sh/search.combination.keytype=string,daemons=1.fault-tolerance=0.sh b/test/sh/search.combination.keytype=string,daemons=1.fault-tolerance=0.sh new file mode 100755 index 000000000..8c895461d --- /dev/null +++ b/test/sh/search.combination.keytype=string,daemons=1.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key string number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 subspace bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08 subspace bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16 subspace bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24 subspace bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 index bit09 index bit10 index bit11 index bit12 index bit13 index bit14 index bit15 index bit16 index bit17 index bit18 index bit19 index bit20 index bit21 index bit22 index bit23 index bit24 index bit25 index bit26 index bit27 index bit28 index bit29 index bit30 index bit31 index bit32 index bit01 index bit02 index bit03 index bit04 index bit05 index bit06 index bit07 index bit08 create 1 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k string diff --git a/test/sh/search.combination.keytype=string,daemons=4.fault-tolerance=0.sh b/test/sh/search.combination.keytype=string,daemons=4.fault-tolerance=0.sh new file mode 100755 index 000000000..9f16728af --- /dev/null +++ b/test/sh/search.combination.keytype=string,daemons=4.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key string number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 subspace bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08 subspace bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16 subspace bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24 subspace bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 index bit09 index bit10 index bit11 index bit12 index bit13 index bit14 index bit15 index bit16 index bit17 index bit18 index bit19 index bit20 index bit21 index bit22 index bit23 index bit24 index bit25 index bit26 index bit27 index bit28 index bit29 index bit30 index bit31 index bit32 index bit01 index bit02 index bit03 index bit04 index bit05 index bit06 index bit07 index bit08 create 4 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k string diff --git a/test/sh/search.combination.keytype=string,daemons=4.fault-tolerance=1.sh b/test/sh/search.combination.keytype=string,daemons=4.fault-tolerance=1.sh new file mode 100755 index 000000000..62d7f91bd --- /dev/null +++ b/test/sh/search.combination.keytype=string,daemons=4.fault-tolerance=1.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key string number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 subspace bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08 subspace bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16 subspace bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24 subspace bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 index bit09 index bit10 index bit11 index bit12 index bit13 index bit14 index bit15 index bit16 index bit17 index bit18 index bit19 index bit20 index bit21 index bit22 index bit23 index bit24 index bit25 index bit26 index bit27 index bit28 index bit29 index bit30 index bit31 index bit32 index bit01 index bit02 index bit03 index bit04 index bit05 index bit06 index bit07 index bit08 create 4 partitions tolerate 1 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k string diff --git a/test/sh/search.index.keytype=int,daemons=1.fault-tolerance=0.sh b/test/sh/search.index.keytype=int,daemons=1.fault-tolerance=0.sh new file mode 100755 index 000000000..c88998a18 --- /dev/null +++ b/test/sh/search.index.keytype=int,daemons=1.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key int number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 index bit01 index bit02 index bit03 index bit04 index bit05 index bit06 index bit07 index bit08 index bit09 index bit10 index bit11 index bit12 index bit13 index bit14 index bit15 index bit16 index bit17 index bit18 index bit19 index bit20 index bit21 index bit22 index bit23 index bit24 index bit25 index bit26 index bit27 index bit28 index bit29 index bit30 index bit31 index bit32 create 1 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k int diff --git a/test/sh/search.index.keytype=int,daemons=4.fault-tolerance=0.sh b/test/sh/search.index.keytype=int,daemons=4.fault-tolerance=0.sh new file mode 100755 index 000000000..a2adbe399 --- /dev/null +++ b/test/sh/search.index.keytype=int,daemons=4.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key int number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 index bit01 index bit02 index bit03 index bit04 index bit05 index bit06 index bit07 index bit08 index bit09 index bit10 index bit11 index bit12 index bit13 index bit14 index bit15 index bit16 index bit17 index bit18 index bit19 index bit20 index bit21 index bit22 index bit23 index bit24 index bit25 index bit26 index bit27 index bit28 index bit29 index bit30 index bit31 index bit32 create 4 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k int diff --git a/test/sh/search.index.keytype=int,daemons=4.fault-tolerance=1.sh b/test/sh/search.index.keytype=int,daemons=4.fault-tolerance=1.sh new file mode 100755 index 000000000..213eef0c6 --- /dev/null +++ b/test/sh/search.index.keytype=int,daemons=4.fault-tolerance=1.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key int number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 index bit01 index bit02 index bit03 index bit04 index bit05 index bit06 index bit07 index bit08 index bit09 index bit10 index bit11 index bit12 index bit13 index bit14 index bit15 index bit16 index bit17 index bit18 index bit19 index bit20 index bit21 index bit22 index bit23 index bit24 index bit25 index bit26 index bit27 index bit28 index bit29 index bit30 index bit31 index bit32 create 4 partitions tolerate 1 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k int diff --git a/test/sh/search.index.keytype=string,daemons=1.fault-tolerance=0.sh b/test/sh/search.index.keytype=string,daemons=1.fault-tolerance=0.sh new file mode 100755 index 000000000..18c6910f9 --- /dev/null +++ b/test/sh/search.index.keytype=string,daemons=1.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key string number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 index bit01 index bit02 index bit03 index bit04 index bit05 index bit06 index bit07 index bit08 index bit09 index bit10 index bit11 index bit12 index bit13 index bit14 index bit15 index bit16 index bit17 index bit18 index bit19 index bit20 index bit21 index bit22 index bit23 index bit24 index bit25 index bit26 index bit27 index bit28 index bit29 index bit30 index bit31 index bit32 create 1 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k string diff --git a/test/sh/search.index.keytype=string,daemons=4.fault-tolerance=0.sh b/test/sh/search.index.keytype=string,daemons=4.fault-tolerance=0.sh new file mode 100755 index 000000000..4002c1e5c --- /dev/null +++ b/test/sh/search.index.keytype=string,daemons=4.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key string number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 index bit01 index bit02 index bit03 index bit04 index bit05 index bit06 index bit07 index bit08 index bit09 index bit10 index bit11 index bit12 index bit13 index bit14 index bit15 index bit16 index bit17 index bit18 index bit19 index bit20 index bit21 index bit22 index bit23 index bit24 index bit25 index bit26 index bit27 index bit28 index bit29 index bit30 index bit31 index bit32 create 4 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k string diff --git a/test/sh/search.index.keytype=string,daemons=4.fault-tolerance=1.sh b/test/sh/search.index.keytype=string,daemons=4.fault-tolerance=1.sh new file mode 100755 index 000000000..2dab27a0a --- /dev/null +++ b/test/sh/search.index.keytype=string,daemons=4.fault-tolerance=1.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key string number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 index bit01 index bit02 index bit03 index bit04 index bit05 index bit06 index bit07 index bit08 index bit09 index bit10 index bit11 index bit12 index bit13 index bit14 index bit15 index bit16 index bit17 index bit18 index bit19 index bit20 index bit21 index bit22 index bit23 index bit24 index bit25 index bit26 index bit27 index bit28 index bit29 index bit30 index bit31 index bit32 create 4 partitions tolerate 1 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k string diff --git a/test/sh/search.simple.keytype=int,daemons=1.fault-tolerance=0.sh b/test/sh/search.simple.keytype=int,daemons=1.fault-tolerance=0.sh new file mode 100755 index 000000000..922706aca --- /dev/null +++ b/test/sh/search.simple.keytype=int,daemons=1.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key int number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 create 1 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k int diff --git a/test/sh/search.simple.keytype=int,daemons=4.fault-tolerance=0.sh b/test/sh/search.simple.keytype=int,daemons=4.fault-tolerance=0.sh new file mode 100755 index 000000000..90bb275ae --- /dev/null +++ b/test/sh/search.simple.keytype=int,daemons=4.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key int number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 create 4 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k int diff --git a/test/sh/search.simple.keytype=int,daemons=4.fault-tolerance=1.sh b/test/sh/search.simple.keytype=int,daemons=4.fault-tolerance=1.sh new file mode 100755 index 000000000..f999e358f --- /dev/null +++ b/test/sh/search.simple.keytype=int,daemons=4.fault-tolerance=1.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key int number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 create 4 partitions tolerate 1 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k int diff --git a/test/sh/search.simple.keytype=string,daemons=1.fault-tolerance=0.sh b/test/sh/search.simple.keytype=string,daemons=1.fault-tolerance=0.sh new file mode 100755 index 000000000..20c4487fe --- /dev/null +++ b/test/sh/search.simple.keytype=string,daemons=1.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key string number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 create 1 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k string diff --git a/test/sh/search.simple.keytype=string,daemons=4.fault-tolerance=0.sh b/test/sh/search.simple.keytype=string,daemons=4.fault-tolerance=0.sh new file mode 100755 index 000000000..98ddb961c --- /dev/null +++ b/test/sh/search.simple.keytype=string,daemons=4.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key string number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 create 4 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k string diff --git a/test/sh/search.simple.keytype=string,daemons=4.fault-tolerance=1.sh b/test/sh/search.simple.keytype=string,daemons=4.fault-tolerance=1.sh new file mode 100755 index 000000000..76fb05096 --- /dev/null +++ b/test/sh/search.simple.keytype=string,daemons=4.fault-tolerance=1.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key string number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 create 4 partitions tolerate 1 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k string diff --git a/test/sh/search.subspace.keytype=int,daemons=1.fault-tolerance=0.sh b/test/sh/search.subspace.keytype=int,daemons=1.fault-tolerance=0.sh new file mode 100755 index 000000000..349f01899 --- /dev/null +++ b/test/sh/search.subspace.keytype=int,daemons=1.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key int number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 subspace bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08 subspace bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16 subspace bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24 subspace bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 create 1 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k int diff --git a/test/sh/search.subspace.keytype=int,daemons=4.fault-tolerance=0.sh b/test/sh/search.subspace.keytype=int,daemons=4.fault-tolerance=0.sh new file mode 100755 index 000000000..5c75ab2d8 --- /dev/null +++ b/test/sh/search.subspace.keytype=int,daemons=4.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key int number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 subspace bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08 subspace bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16 subspace bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24 subspace bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 create 4 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k int diff --git a/test/sh/search.subspace.keytype=int,daemons=4.fault-tolerance=1.sh b/test/sh/search.subspace.keytype=int,daemons=4.fault-tolerance=1.sh new file mode 100755 index 000000000..918567ad4 --- /dev/null +++ b/test/sh/search.subspace.keytype=int,daemons=4.fault-tolerance=1.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key int number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 subspace bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08 subspace bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16 subspace bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24 subspace bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 create 4 partitions tolerate 1 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k int diff --git a/test/sh/search.subspace.keytype=string,daemons=1.fault-tolerance=0.sh b/test/sh/search.subspace.keytype=string,daemons=1.fault-tolerance=0.sh new file mode 100755 index 000000000..c75097565 --- /dev/null +++ b/test/sh/search.subspace.keytype=string,daemons=1.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key string number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 subspace bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08 subspace bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16 subspace bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24 subspace bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 create 1 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=1 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k string diff --git a/test/sh/search.subspace.keytype=string,daemons=4.fault-tolerance=0.sh b/test/sh/search.subspace.keytype=string,daemons=4.fault-tolerance=0.sh new file mode 100755 index 000000000..7b48f8204 --- /dev/null +++ b/test/sh/search.subspace.keytype=string,daemons=4.fault-tolerance=0.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key string number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 subspace bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08 subspace bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16 subspace bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24 subspace bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 create 4 partitions tolerate 0 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k string diff --git a/test/sh/search.subspace.keytype=string,daemons=4.fault-tolerance=1.sh b/test/sh/search.subspace.keytype=string,daemons=4.fault-tolerance=1.sh new file mode 100755 index 000000000..6011ed191 --- /dev/null +++ b/test/sh/search.subspace.keytype=string,daemons=4.fault-tolerance=1.sh @@ -0,0 +1,4 @@ +#!/bin/sh +SPACE="space search key string number attributes bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08, bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16, bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24, bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 subspace bit01, bit02, bit03, bit04, bit05, bit06, bit07, bit08 subspace bit09, bit10, bit11, bit12, bit13, bit14, bit15, bit16 subspace bit17, bit18, bit19, bit20, bit21, bit22, bit23, bit24 subspace bit25, bit26, bit27, bit28, bit29, bit30, bit31, bit32 create 4 partitions tolerate 1 failures" +exec python2 "${HYPERDEX_SRCDIR}"/test/runner.py --daemons=4 --space="${SPACE}" -- \ + "${HYPERDEX_BUILDDIR}"/test/search-stress-test --quiet -h {HOST} -p {PORT} -k string diff --git a/test/simple-consistency-stress-test.cc b/test/simple-consistency-stress-test.cc index 84b34143e..645104513 100644 --- a/test/simple-consistency-stress-test.cc +++ b/test/simple-consistency-stress-test.cc @@ -64,8 +64,8 @@ static long window = 128; static long repetitions = 1024; static int64_t threads = 16; -static const char* space = "consistency"; -static const char* host = "127.0.0.1"; +static const char *space = "consistency"; +static const char *host = "127.0.0.1"; static po6::net::ipaddr coord(host); static long port = 1982; static std::auto_ptr barrier; @@ -80,28 +80,40 @@ static uint64_t inconsistencies = 0; extern "C" { -static struct poptOption popts[] = { - POPT_AUTOHELP - {"window-size", 'w', POPT_ARG_LONG, &window, 'w', - "the number of sequential keys which will be used for the test", - "keys"}, - {"repetitiions", 'r', POPT_ARG_LONG, &repetitions, 'r', - "the number of tests which will be run before exiting", - "number"}, - {"threads", 't', POPT_ARG_LONG, &threads, 't', - "the number of threads which will check for inconsistencies", - "number"}, - {"space", 's', POPT_ARG_STRING, &space, 's', - "the HyperDex space to use", - "space"}, - {"host", 'h', POPT_ARG_STRING, &host, 'h', - "the IP address of the coordinator", - "IP"}, - {"port", 'p', POPT_ARG_LONG, &port, 'p', - "the port number of the coordinator", - "port"}, - POPT_TABLEEND -}; + static struct poptOption popts[] = + { + POPT_AUTOHELP + { + "window-size", 'w', POPT_ARG_LONG, &window, 'w', + "the number of sequential keys which will be used for the test", + "keys"}, + { + "repetitiions", 'r', POPT_ARG_LONG, &repetitions, 'r', + "the number of tests which will be run before exiting", + "number" + }, + { + "threads", 't', POPT_ARG_LONG, &threads, 't', + "the number of threads which will check for inconsistencies", + "number" + }, + { + "space", 's', POPT_ARG_STRING, &space, 's', + "the HyperDex space to use", + "space" + }, + { + "host", 'h', POPT_ARG_STRING, &host, 'h', + "the IP address of the coordinator", + "IP" + }, + { + "port", 'p', POPT_ARG_LONG, &port, 'p', + "the port number of the coordinator", + "port" + }, + POPT_TABLEEND + }; } // extern "C" @@ -111,347 +123,288 @@ static void reader_thread(); int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - poptContext poptcon; - poptcon = poptGetContext(NULL, argc, argv, popts, POPT_CONTEXT_POSIXMEHARDER); - e::guard g = e::makeguard(poptFreeContext, poptcon); - g.use_variable(); - int rc; - - while ((rc = poptGetNextOpt(poptcon)) != -1) - { - switch (rc) - { - case 'w': - if (window < 0) - { - std::cerr << "window-size must be >= 0" << std::endl; - return EXIT_FAILURE; - } - - break; - case 'r': - if (repetitions < 0) - { - std::cerr << "repetitions must be >= 0" << std::endl; - return EXIT_FAILURE; - } - - break; - case 't': - if (threads < 0) - { - std::cerr << "threads must be >= 0" << std::endl; - return EXIT_FAILURE; - } - - break; - case 's': - break; - case 'h': - try - { - coord = po6::net::ipaddr(host); - } - catch (std::invalid_argument& e) - { - std::cerr << "cannot parse coordinator address" << std::endl; - return EXIT_FAILURE; - } - - break; - case 'p': - if (port >= (1 << 16)) - { - std::cerr << "port number out of range for TCP" << std::endl; - return EXIT_FAILURE; - } - - break; - case POPT_ERROR_NOARG: - case POPT_ERROR_BADOPT: - case POPT_ERROR_BADNUMBER: - case POPT_ERROR_OVERFLOW: - std::cerr << poptStrerror(rc) << " " << poptBadOption(poptcon, 0) << std::endl; - return EXIT_FAILURE; - case POPT_ERROR_OPTSTOODEEP: - case POPT_ERROR_BADQUOTE: - case POPT_ERROR_ERRNO: - default: - std::cerr << "logic error in argument parsing" << std::endl; - return EXIT_FAILURE; - } - } - - barrier.reset(new po6::threads::barrier(threads + 1)); - po6::threads::thread writer(writer_thread); - writer.start(); - std::vector > readers; - - for (int64_t i = 0; i < threads; ++i) - { - e::compat::shared_ptr tptr(new po6::threads::thread(reader_thread)); - readers.push_back(tptr); - tptr->start(); - } - - writer.join(); - - bool success = __sync_bool_compare_and_swap(&done, 0, 1); - assert(success); - - for (int64_t i = 0; i < threads; ++i) - { - readers[i]->join(); - } - - po6::threads::mutex::hold hold(&results_lock); - typedef std::map::iterator result_iter_t; - std::cout << "Failed puts:" << std::endl; - - for (result_iter_t o = failed_puts.begin(); o != failed_puts.end(); ++o) - { - std::cout << o->first << "\t" << o->second << std::endl; - } - - std::cout << std::endl << "Failed loops:" << std::endl; - - for (result_iter_t o = failed_loops.begin(); o != failed_loops.end(); ++o) - { - std::cout << o->first << "\t" << o->second << std::endl; - } - - std::cout << std::endl << "Normal ops:" << std::endl; - - for (result_iter_t o = ops.begin(); o != ops.end(); ++o) - { - std::cout << o->first << "\t" << o->second << std::endl; - } - - std::cout << std::endl << "failed writes: " << failed_writes << std::endl - << "Inconsistencies: " << inconsistencies << std::endl; - return EXIT_SUCCESS; + poptContext poptcon; + poptcon = poptGetContext(NULL, argc, argv, popts, POPT_CONTEXT_POSIXMEHARDER); + e::guard g = e::makeguard(poptFreeContext, poptcon); + g.use_variable(); + int rc; + while ((rc = poptGetNextOpt(poptcon)) != -1) + { + switch (rc) + { + case 'w': + if (window < 0) + { + std::cerr << "window-size must be >= 0" << std::endl; + return EXIT_FAILURE; + } + break; + case 'r': + if (repetitions < 0) + { + std::cerr << "repetitions must be >= 0" << std::endl; + return EXIT_FAILURE; + } + break; + case 't': + if (threads < 0) + { + std::cerr << "threads must be >= 0" << std::endl; + return EXIT_FAILURE; + } + break; + case 's': + break; + case 'h': + try + { + coord = po6::net::ipaddr(host); + } + catch (std::invalid_argument &e) + { + std::cerr << "cannot parse coordinator address" << std::endl; + return EXIT_FAILURE; + } + break; + case 'p': + if (port >= (1 << 16)) + { + std::cerr << "port number out of range for TCP" << std::endl; + return EXIT_FAILURE; + } + break; + case POPT_ERROR_NOARG: + case POPT_ERROR_BADOPT: + case POPT_ERROR_BADNUMBER: + case POPT_ERROR_OVERFLOW: + std::cerr << poptStrerror(rc) << " " << poptBadOption(poptcon, 0) << std::endl; + return EXIT_FAILURE; + case POPT_ERROR_OPTSTOODEEP: + case POPT_ERROR_BADQUOTE: + case POPT_ERROR_ERRNO: + default: + std::cerr << "logic error in argument parsing" << std::endl; + return EXIT_FAILURE; + } + } + barrier.reset(new po6::threads::barrier(threads + 1)); + po6::threads::thread writer(writer_thread); + writer.start(); + std::vector > readers; + for (int64_t i = 0; i < threads; ++i) + { + e::compat::shared_ptr tptr(new po6::threads::thread(reader_thread)); + readers.push_back(tptr); + tptr->start(); + } + writer.join(); + bool success = __sync_bool_compare_and_swap(&done, 0, 1); + assert(success); + for (int64_t i = 0; i < threads; ++i) + { + readers[i]->join(); + } + po6::threads::mutex::hold hold(&results_lock); + typedef std::map::iterator result_iter_t; + std::cout << "Failed puts:" << std::endl; + for (result_iter_t o = failed_puts.begin(); o != failed_puts.end(); ++o) + { + std::cout << o->first << "\t" << o->second << std::endl; + } + std::cout << std::endl << "Failed loops:" << std::endl; + for (result_iter_t o = failed_loops.begin(); o != failed_loops.end(); ++o) + { + std::cout << o->first << "\t" << o->second << std::endl; + } + std::cout << std::endl << "Normal ops:" << std::endl; + for (result_iter_t o = ops.begin(); o != ops.end(); ++o) + { + std::cout << o->first << "\t" << o->second << std::endl; + } + std::cout << std::endl << "failed writes: " << failed_writes << std::endl + << "Inconsistencies: " << inconsistencies << std::endl; + return EXIT_SUCCESS; } static void writer_thread() { - std::map lfailed_puts; - std::map lfailed_loops; - std::map lops; - uint64_t lfailed_writes = 0; - hyperdex::Client cl(host, port); - bool fail = false; - - for (int64_t i = 0; i < window; ++i) - { - int64_t key = i; - int64_t did; - hyperdex_client_returncode dstatus; - - const char* keystr = reinterpret_cast(&key); - did = cl.del(space, keystr, sizeof(key), &dstatus); - - if (did < 0) - { - std::cerr << "delete failed with " << dstatus << std::endl; - fail = true; - break; - } - - int64_t lid; - hyperdex_client_returncode lstatus; - lid = cl.loop(-1, &lstatus); - - if (lid < 0) - { - std::cerr << "loop failed with " << lstatus << std::endl; - fail = true; - break; - } - - assert(lid == did); - - if (dstatus != HYPERDEX_CLIENT_SUCCESS && dstatus != HYPERDEX_CLIENT_NOTFOUND) - { - std::cerr << "delete returned " << dstatus << std::endl; - fail = true; - break; - } - } - - barrier->wait(); - - if (fail) - { - std::cerr << "the above errors are fatal" << std::endl; - return; - } - - std::cout << "starting the consistency stress test" << std::endl; - - for (int64_t r = 0; r < repetitions; ++r) - { - for (int64_t i = 0; i < window; ++i) - { - uint64_t count = 0; - - for (count = 0; count < 65536; ++count) - { - int64_t key = i; - int64_t val = r; - int64_t pid; - hyperdex_client_attribute attr; - hyperdex_client_returncode pstatus; - - const char* keystr = reinterpret_cast(&key); - attr.attr = "repetition"; - attr.value = reinterpret_cast(&val); - attr.value_sz = sizeof(val); - attr.datatype = HYPERDATATYPE_STRING; - pid = cl.put(space, keystr, sizeof(key), &attr, 1, &pstatus); - - if (pid < 0) - { - ++lfailed_puts[pstatus]; - continue; - } - - int64_t lid; - hyperdex_client_returncode lstatus; - lid = cl.loop(-1, &lstatus); - - if (lid < 0) - { - ++lfailed_loops[lstatus]; - continue; - } - - assert(lid == pid); - ++lops[pstatus]; - break; - } - - if (count == 65536) - { - ++lfailed_writes; - } - } - - std::cout << "done " << r << "/" << repetitions << std::endl; - } - - po6::threads::mutex::hold hold(&results_lock); - typedef std::map::iterator result_iter_t; - - for (result_iter_t o = lfailed_puts.begin(); o != lfailed_puts.end(); ++o) - { - failed_puts[o->first] += o->second; - } - - for (result_iter_t o = lfailed_loops.begin(); o != lfailed_loops.end(); ++o) - { - failed_loops[o->first] += o->second; - } - - for (result_iter_t o = lops.begin(); o != lops.end(); ++o) - { - ops[o->first] += o->second; - } - - failed_writes = lfailed_writes; + std::map lfailed_puts; + std::map lfailed_loops; + std::map lops; + uint64_t lfailed_writes = 0; + hyperdex::Client cl(host, port); + bool fail = false; + for (int64_t i = 0; i < window; ++i) + { + int64_t key = i; + int64_t did; + hyperdex_client_returncode dstatus; + const char *keystr = reinterpret_cast(&key); + did = cl.del(space, keystr, sizeof(key), &dstatus); + if (did < 0) + { + std::cerr << "delete failed with " << dstatus << std::endl; + fail = true; + break; + } + int64_t lid; + hyperdex_client_returncode lstatus; + lid = cl.loop(-1, &lstatus); + if (lid < 0) + { + std::cerr << "loop failed with " << lstatus << std::endl; + fail = true; + break; + } + assert(lid == did); + if (dstatus != HYPERDEX_CLIENT_SUCCESS && dstatus != HYPERDEX_CLIENT_NOTFOUND) + { + std::cerr << "delete returned " << dstatus << std::endl; + fail = true; + break; + } + } + barrier->wait(); + if (fail) + { + std::cerr << "the above errors are fatal" << std::endl; + return; + } + std::cout << "starting the consistency stress test" << std::endl; + for (int64_t r = 0; r < repetitions; ++r) + { + for (int64_t i = 0; i < window; ++i) + { + uint64_t count = 0; + for (count = 0; count < 65536; ++count) + { + int64_t key = i; + int64_t val = r; + int64_t pid; + hyperdex_client_attribute attr; + hyperdex_client_returncode pstatus; + const char *keystr = reinterpret_cast(&key); + attr.attr = "repetition"; + attr.value = reinterpret_cast(&val); + attr.value_sz = sizeof(val); + attr.datatype = HYPERDATATYPE_STRING; + pid = cl.put(space, keystr, sizeof(key), &attr, 1, &pstatus); + if (pid < 0) + { + ++lfailed_puts[pstatus]; + continue; + } + int64_t lid; + hyperdex_client_returncode lstatus; + lid = cl.loop(-1, &lstatus); + if (lid < 0) + { + ++lfailed_loops[lstatus]; + continue; + } + assert(lid == pid); + ++lops[pstatus]; + break; + } + if (count == 65536) + { + ++lfailed_writes; + } + } + std::cout << "done " << r << "/" << repetitions << std::endl; + } + po6::threads::mutex::hold hold(&results_lock); + typedef std::map::iterator result_iter_t; + for (result_iter_t o = lfailed_puts.begin(); o != lfailed_puts.end(); ++o) + { + failed_puts[o->first] += o->second; + } + for (result_iter_t o = lfailed_loops.begin(); o != lfailed_loops.end(); ++o) + { + failed_loops[o->first] += o->second; + } + for (result_iter_t o = lops.begin(); o != lops.end(); ++o) + { + ops[o->first] += o->second; + } + failed_writes = lfailed_writes; } static void reader_thread() { - std::map lfailed_puts; - std::map lfailed_loops; - std::map lops; - uint64_t linconsistencies = 0; - hyperdex::Client cl(host, port); - barrier->wait(); - - while (!__sync_bool_compare_and_swap(&done, 1, 1)) - { - for (int64_t i = window - 1; i >= 0; --i) - { - int64_t oldval = 0; - - while (true) - { - int64_t key = i; - int64_t gid; - const hyperdex_client_attribute* attrs = NULL; - size_t attrs_sz = 0; - hyperdex_client_returncode gstatus; - - const char* keystr = reinterpret_cast(&key); - gid = cl.get(space, keystr, sizeof(key), &gstatus, &attrs, &attrs_sz); - - if (gid < 0) - { - ++lfailed_puts[gstatus]; - continue; - } - - int64_t lid; - hyperdex_client_returncode lstatus; - lid = cl.loop(-1, &lstatus); - - if (lid < 0) - { - ++lfailed_loops[lstatus]; - continue; - } - - assert(lid == gid); - ++lops[gstatus]; - - if (gstatus == HYPERDEX_CLIENT_SUCCESS) - { - assert(attrs_sz == 1); - assert(strcmp(attrs[0].attr, "repetition") == 0); - int64_t val = 0; - memmove(&val, attrs[0].value, attrs[0].value_sz); - assert(attrs[0].datatype == HYPERDATATYPE_STRING); - - if (val < oldval) - { - ++inconsistencies; - } - - oldval = val; - } - - if (attrs) - { - hyperdex_client_destroy_attrs(attrs, attrs_sz); - } - - break; - } - } - } - - po6::threads::mutex::hold hold(&results_lock); - typedef std::map::iterator result_iter_t; - - for (result_iter_t o = lfailed_puts.begin(); o != lfailed_puts.end(); ++o) - { - failed_puts[o->first] += o->second; - } - - for (result_iter_t o = lfailed_loops.begin(); o != lfailed_loops.end(); ++o) - { - failed_loops[o->first] += o->second; - } - - for (result_iter_t o = lops.begin(); o != lops.end(); ++o) - { - ops[o->first] += o->second; - } - - inconsistencies += linconsistencies; + std::map lfailed_puts; + std::map lfailed_loops; + std::map lops; + uint64_t linconsistencies = 0; + hyperdex::Client cl(host, port); + barrier->wait(); + while (!__sync_bool_compare_and_swap(&done, 1, 1)) + { + for (int64_t i = window - 1; i >= 0; --i) + { + int64_t oldval = 0; + while (true) + { + int64_t key = i; + int64_t gid; + const hyperdex_client_attribute *attrs = NULL; + size_t attrs_sz = 0; + hyperdex_client_returncode gstatus; + const char *keystr = reinterpret_cast(&key); + gid = cl.get(space, keystr, sizeof(key), &gstatus, &attrs, &attrs_sz); + if (gid < 0) + { + ++lfailed_puts[gstatus]; + continue; + } + int64_t lid; + hyperdex_client_returncode lstatus; + lid = cl.loop(-1, &lstatus); + if (lid < 0) + { + ++lfailed_loops[lstatus]; + continue; + } + assert(lid == gid); + ++lops[gstatus]; + if (gstatus == HYPERDEX_CLIENT_SUCCESS) + { + assert(attrs_sz == 1); + assert(strcmp(attrs[0].attr, "repetition") == 0); + int64_t val = 0; + memmove(&val, attrs[0].value, attrs[0].value_sz); + assert(attrs[0].datatype == HYPERDATATYPE_STRING); + if (val < oldval) + { + ++inconsistencies; + } + oldval = val; + } + if (attrs) + { + hyperdex_client_destroy_attrs(attrs, attrs_sz); + } + break; + } + } + } + po6::threads::mutex::hold hold(&results_lock); + typedef std::map::iterator result_iter_t; + for (result_iter_t o = lfailed_puts.begin(); o != lfailed_puts.end(); ++o) + { + failed_puts[o->first] += o->second; + } + for (result_iter_t o = lfailed_loops.begin(); o != lfailed_loops.end(); ++o) + { + failed_loops[o->first] += o->second; + } + for (result_iter_t o = lops.begin(); o != lops.end(); ++o) + { + ops[o->first] += o->second; + } + inconsistencies += linconsistencies; } diff --git a/test/th.cc b/test/th.cc index 3f4c20e66..7847300e4 100644 --- a/test/th.cc +++ b/test/th.cc @@ -38,173 +38,159 @@ // th #include "th.h" -static std::vector* _th_tests = NULL; +static std::vector *_th_tests = NULL; class escape_from_test_failure { - public: - escape_from_test_failure() {} +public: + escape_from_test_failure() {} }; -th :: test_base :: test_base(const char* group, - const char* name, - const char* file, +th :: test_base :: test_base(const char *group, + const char *name, + const char *file, size_t line) - : m_group(group) - , m_name(name) - , m_file(file) - , m_line(line) + : m_group(group) + , m_name(name) + , m_file(file) + , m_line(line) { - if (_th_tests == NULL) - { - _th_tests = new std::vector(); - } - - _th_tests->push_back(this); + if (_th_tests == NULL) + { + _th_tests = new std::vector(); + } + _th_tests->push_back(this); } void -th :: test_base :: run(bool quiet, bool* failed) +th :: test_base :: run(bool quiet, bool *failed) { - if (!quiet) std::cerr << "===== Test " << m_group << "::" << m_name << " @ " << m_file << ":" << m_line << std::endl; - - try - { - this->_run(); - *failed = false; - } - catch (escape_from_test_failure& ttotf) - { - *failed = true; - } + if (!quiet) std::cerr << "===== Test " << m_group << "::" << m_name << " @ " << m_file << ":" << m_line << std::endl; + try + { + this->_run(); + *failed = false; + } + catch (escape_from_test_failure &ttotf) + { + *failed = true; + } } bool -th :: test_base :: operator < (const test_base& rhs) const +th :: test_base :: operator < (const test_base &rhs) const { - return compare(rhs) < 0; + return compare(rhs) < 0; } int -th :: test_base :: compare(const test_base& rhs) const +th :: test_base :: compare(const test_base &rhs) const { - const test_base& lhs(*this); - int cmp; - - // Compare file - cmp = strcmp(lhs.m_file, rhs.m_file); - - if (cmp < 0) - { - return -1; - } - if (cmp > 0) - { - return 1; - } - - // Compare line - if (lhs.m_line < rhs.m_line) - { - return -1; - } - if (lhs.m_line > rhs.m_line) - { - return 1; - } - - // Compare group - cmp = strcmp(lhs.m_group, rhs.m_group); - - if (cmp < 0) - { - return -1; - } - if (cmp > 0) - { - return 1; - } - - // Compare name - cmp = strcmp(lhs.m_name, rhs.m_name); - - if (cmp < 0) - { - return -1; - } - if (cmp > 0) - { - return 1; - } - - return 0; + const test_base &lhs(*this); + int cmp; + // Compare file + cmp = strcmp(lhs.m_file, rhs.m_file); + if (cmp < 0) + { + return -1; + } + if (cmp > 0) + { + return 1; + } + // Compare line + if (lhs.m_line < rhs.m_line) + { + return -1; + } + if (lhs.m_line > rhs.m_line) + { + return 1; + } + // Compare group + cmp = strcmp(lhs.m_group, rhs.m_group); + if (cmp < 0) + { + return -1; + } + if (cmp > 0) + { + return 1; + } + // Compare name + cmp = strcmp(lhs.m_name, rhs.m_name); + if (cmp < 0) + { + return -1; + } + if (cmp > 0) + { + return 1; + } + return 0; } -th :: predicate :: predicate(const char* file, size_t line, const char* a, const char* b) - : m_file(file) - , m_line(line) - , m_a(a) - , m_b(b) +th :: predicate :: predicate(const char *file, size_t line, const char *a, const char *b) + : m_file(file) + , m_line(line) + , m_a(a) + , m_b(b) { } void th :: predicate :: assert_true(bool T) { - if (!T) - { - std::cerr << "FAIL @ " << m_file << ":" << m_line << ": tested " << m_a << "; expected true, but got false" << std::endl; - th::fail(); - } + if (!T) + { + std::cerr << "FAIL @ " << m_file << ":" << m_line << ": tested " << m_a << "; expected true, but got false" << std::endl; + th::fail(); + } } void th :: predicate :: assert_false(bool F) { - if (F) - { - std::cerr << "FAIL @ " << m_file << ":" << m_line << ": tested " << m_a << "; expected false, but got true" << std::endl; - th::fail(); - } + if (F) + { + std::cerr << "FAIL @ " << m_file << ":" << m_line << ": tested " << m_a << "; expected false, but got true" << std::endl; + th::fail(); + } } void th :: predicate :: fail() { - std::cerr << "FAIL @ " << m_file << ":" << m_line << ": forced fail" << std::endl; - th::fail(); + std::cerr << "FAIL @ " << m_file << ":" << m_line << ": forced fail" << std::endl; + th::fail(); } static bool -compare_test_base_ptrs(const th::test_base* lhs, const th::test_base* rhs) +compare_test_base_ptrs(const th::test_base *lhs, const th::test_base *rhs) { - return *lhs < *rhs; + return *lhs < *rhs; } int th :: run_tests(bool quiet) { - if (!_th_tests) - { - return 0; - } - - std::sort(_th_tests->begin(), _th_tests->end(), compare_test_base_ptrs); - const std::vector& th_tests(*_th_tests); - int failures = 0; - - for (size_t i = 0; i < th_tests.size(); ++i) - { - bool fail = false; - th_tests[i]->run(quiet, &fail); - - if (fail) - { - ++failures; - } - } - - return failures; + if (!_th_tests) + { + return 0; + } + std::sort(_th_tests->begin(), _th_tests->end(), compare_test_base_ptrs); + const std::vector &th_tests(*_th_tests); + int failures = 0; + for (size_t i = 0; i < th_tests.size(); ++i) + { + bool fail = false; + th_tests[i]->run(quiet, &fail); + if (fail) + { + ++failures; + } + } + return failures; } #pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn" @@ -212,6 +198,6 @@ th :: run_tests(bool quiet) void th :: fail() { - escape_from_test_failure eftf; - throw eftf; + escape_from_test_failure eftf; + throw eftf; } diff --git a/test/th.h b/test/th.h index dca6ef724..15888fb04 100644 --- a/test/th.h +++ b/test/th.h @@ -50,68 +50,68 @@ fail(); class test_base { - public: - test_base(const char* group, - const char* name, - const char* file, - size_t line); - virtual ~test_base() throw () {} - - public: - void run(bool quiet, bool* failed); - - public: - bool operator < (const test_base& rhs) const; - - private: - virtual void _run() = 0; - int compare(const test_base& rhs) const; - - private: - test_base(const test_base&); - test_base& operator = (const test_base&); - - private: - const char* m_group; - const char* m_name; - const char* m_file; - size_t m_line; +public: + test_base(const char *group, + const char *name, + const char *file, + size_t line); + virtual ~test_base() throw () {} + +public: + void run(bool quiet, bool *failed); + +public: + bool operator < (const test_base &rhs) const; + +private: + virtual void _run() = 0; + int compare(const test_base &rhs) const; + +private: + test_base(const test_base &); + test_base &operator = (const test_base &); + +private: + const char *m_group; + const char *m_name; + const char *m_file; + size_t m_line; }; #define BINARY_PREDICATE(english, compiler) \ - template \ - void \ - assert_ ## english(const A& a, const B& b) \ - { \ - if (!(a compiler b)) \ - { \ - std::cerr << "FAIL @ " << m_file << ":" << m_line << ": tested " << m_a << " " TH_XSTR(compiler) " " << m_b << "; got " << a << " " TH_XSTR(compiler) " " << b << std::endl; \ - th::fail(); \ - } \ - } + template \ + void \ + assert_ ## english(const A& a, const B& b) \ + { \ + if (!(a compiler b)) \ + { \ + std::cerr << "FAIL @ " << m_file << ":" << m_line << ": tested " << m_a << " " TH_XSTR(compiler) " " << m_b << "; got " << a << " " TH_XSTR(compiler) " " << b << std::endl; \ + th::fail(); \ + } \ + } class predicate { - public: - predicate(const char* file, - size_t line, - const char* a, - const char* b); - void assert_true(bool T); - void assert_false(bool F); - BINARY_PREDICATE(lt, <) - BINARY_PREDICATE(le, <=) - BINARY_PREDICATE(eq, ==) - BINARY_PREDICATE(ne, !=) - BINARY_PREDICATE(ge, >=) - BINARY_PREDICATE(gt, >) - void fail(); - - private: - const char* m_file; - size_t m_line; - const char* m_a; - const char* m_b; +public: + predicate(const char *file, + size_t line, + const char *a, + const char *b); + void assert_true(bool T); + void assert_false(bool F); + BINARY_PREDICATE(lt, < ) + BINARY_PREDICATE(le, <= ) + BINARY_PREDICATE(eq, == ) + BINARY_PREDICATE(ne, != ) + BINARY_PREDICATE(ge, >= ) + BINARY_PREDICATE(gt, > ) + void fail(); + +private: + const char *m_file; + size_t m_line; + const char *m_a; + const char *m_b; }; #undef BINARY_PREDICATE @@ -119,17 +119,17 @@ class predicate } // namespace th #define TEST(GROUP, NAME) \ - class TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__)))) : public th::test_base \ - { \ - public: \ - TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__))))() \ - : test_base(TH_STR(GROUP), TH_STR(NAME), __FILE__, __LINE__) {} \ - protected: \ - virtual void _run(); \ - }; \ - TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__)))) \ - TH_CONCAT(_test_instance_, TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__))))); \ - void TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__)))) :: _run() + class TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__)))) : public th::test_base \ + { \ + public: \ + TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__))))() \ + : test_base(TH_STR(GROUP), TH_STR(NAME), __FILE__, __LINE__) {} \ + protected: \ + virtual void _run(); \ + }; \ + TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__)))) \ + TH_CONCAT(_test_instance_, TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__))))); \ + void TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__)))) :: _run() #define ASSERT_TRUE(P) th::predicate(__FILE__, __LINE__, TH_STR(P), NULL).assert_true(P) #define ASSERT_FALSE(P) th::predicate(__FILE__, __LINE__, TH_STR(P), NULL).assert_false(P) diff --git a/test/th_main.cc b/test/th_main.cc index df15ad215..980c30b12 100644 --- a/test/th_main.cc +++ b/test/th_main.cc @@ -32,14 +32,12 @@ #include "th.h" int -main(int argc, char* argv[]) +main(int argc, char *argv[]) { - bool quiet = false; - - for (int i = 1; i < argc; ++i) - { - quiet = quiet || strcmp(argv[i], "--quiet") == 0; - } - - return th::run_tests(quiet); + bool quiet = false; + for (int i = 1; i < argc; ++i) + { + quiet = quiet || strcmp(argv[i], "--quiet") == 0; + } + return th::run_tests(quiet); } diff --git a/tools/add-index.cc b/tools/add-index.cc index ebc6f94ff..0626fdf43 100644 --- a/tools/add-index.cc +++ b/tools/add-index.cc @@ -33,66 +33,56 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (ap.args_sz() != 2) - { - std::cerr << "please specify the space and attribute to index\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - int64_t rid = h.add_index(ap.args()[0], ap.args()[1], &rrc); - - if (rid < 0) - { - std::cerr << "could not add index: " << rrc << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not add index: " << lrc << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not add index: " << rrc << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (ap.args_sz() != 2) + { + std::cerr << "please specify the space and attribute to index\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + int64_t rid = h.add_index(ap.args()[0], ap.args()[1], &rrc); + if (rid < 0) + { + std::cerr << "could not add index: " << rrc << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not add index: " << lrc << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not add index: " << rrc << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/add-space.cc b/tools/add-space.cc index 15e8dfcc6..130143466 100644 --- a/tools/add-space.cc +++ b/tools/add-space.cc @@ -33,81 +33,69 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 0) - { - std::cerr << "command takes no arguments" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - std::string description; - std::string s; - - while (std::cin >> s) - { - if (!description.empty()) - { - description += " " + s; - } - else - { - description += s; - } - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - int64_t rid = h.add_space(description.c_str(), &rrc); - - if (rid < 0) - { - std::cerr << "could not add space: " << h.error_message() << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not add space: " << h.error_message() << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not add space: " << h.error_message() << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 0) + { + std::cerr << "command takes no arguments" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + std::string description; + std::string s; + while (std::cin >> s) + { + if (!description.empty()) + { + description += " " + s; + } + else + { + description += s; + } + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + int64_t rid = h.add_space(description.c_str(), &rrc); + if (rid < 0) + { + std::cerr << "could not add space: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not add space: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not add space: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/backup-manager.cc b/tools/backup-manager.cc index c30fa8a60..570d7c9dd 100644 --- a/tools/backup-manager.cc +++ b/tools/backup-manager.cc @@ -47,399 +47,341 @@ using hyperdex::connect_opts; struct daemon_backup { - daemon_backup() : sid(), addr(), path() {} - daemon_backup(uint64_t s, - const std::string& a, - const std::string& p) - : sid(s), addr(a), path(p) {} - ~daemon_backup() {} - uint64_t sid; - std::string addr; - std::string path; + daemon_backup() : sid(), addr(), path() {} + daemon_backup(uint64_t s, + const std::string &a, + const std::string &p) + : sid(s), addr(a), path(p) {} + ~daemon_backup() {} + uint64_t sid; + std::string addr; + std::string path; }; static bool -get_time(std::string* now) +get_time(std::string *now) { - time_t tmp_t; - struct tm* tmp_tm; - - tmp_t = time(NULL); - tmp_tm = localtime(&tmp_t); - - if (tmp_tm == NULL) - { - perror("could not read time"); - return false; - } - - char tmp[1024]; - - if (strftime(tmp, 1024, "%Y-%m-%dT%H:%M:%S", tmp_tm) == 0) - { - std::cerr << "could not read time" << std::endl; - return false; - } - - *now = std::string(tmp); - return true; + time_t tmp_t; + struct tm *tmp_tm; + tmp_t = time(NULL); + tmp_tm = localtime(&tmp_t); + if (tmp_tm == NULL) + { + perror("could not read time"); + return false; + } + char tmp[1024]; + if (strftime(tmp, 1024, "%Y-%m-%dT%H:%M:%S", tmp_tm) == 0) + { + std::cerr << "could not read time" << std::endl; + return false; + } + *now = std::string(tmp); + return true; } static bool -take_backup(const connect_opts& conn, - const char* name, - std::vector* daemons) +take_backup(const connect_opts &conn, + const char *name, + std::vector *daemons) { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - const char* backups = NULL; - int64_t rid = h.backup(name, &rrc, &backups); - - if (rid < 0) - { - std::cerr << "Backup failed.\n" - << "Please read the above messages for the cause and potential solutions\n"; - return false; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "Backup failed.\n" - << "Please read the above messages for the cause and potential solutions\n"; - return false; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "backup failed: " << h.error_message() << std::endl; - return false; - } - - if (!backups) - { - return true; - } - - const char* ptr = backups; - const char* end = ptr + strlen(ptr); - - while (ptr < end) - { - const char* eol = strchr(ptr, '\n'); - eol = eol ? eol : end; - std::string line(ptr, eol); - ptr = eol + 1; - long long unsigned int num; - std::vector loc_buf(line.size()); - std::vector path_buf(line.size()); - - if (sscanf(line.c_str(), "%llu %s %[^\t\n]", - &num, &loc_buf[0], &path_buf[0]) < 3) - { - std::cerr << "could not parse backup information for daemons:\n" - << backups << std::flush; - return false; - } - - daemons->push_back(daemon_backup(num, - std::string(&loc_buf[0]), - std::string(&path_buf[0]))); - } - - return true; + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + const char *backups = NULL; + int64_t rid = h.backup(name, &rrc, &backups); + if (rid < 0) + { + std::cerr << "Backup failed.\n" + << "Please read the above messages for the cause and potential solutions\n"; + return false; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "Backup failed.\n" + << "Please read the above messages for the cause and potential solutions\n"; + return false; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "backup failed: " << h.error_message() << std::endl; + return false; + } + if (!backups) + { + return true; + } + const char *ptr = backups; + const char *end = ptr + strlen(ptr); + while (ptr < end) + { + const char *eol = strchr(ptr, '\n'); + eol = eol ? eol : end; + std::string line(ptr, eol); + ptr = eol + 1; + long long unsigned int num; + std::vector loc_buf(line.size()); + std::vector path_buf(line.size()); + if (sscanf(line.c_str(), "%llu %s %[^\t\n]", + &num, &loc_buf[0], &path_buf[0]) < 3) + { + std::cerr << "could not parse backup information for daemons:\n" + << backups << std::flush; + return false; + } + daemons->push_back(daemon_backup(num, + std::string(&loc_buf[0]), + std::string(&path_buf[0]))); + } + return true; } static bool -read_latest(const std::string& base, bool* has_previous, std::string* previous) +read_latest(const std::string &base, bool *has_previous, std::string *previous) { - std::string latest_path = po6::path::join(base, "LATEST"); - po6::io::fd latest(open(latest_path.c_str(), O_RDONLY)); - - if (latest.get() < 0 && errno == ENOENT) - { - *has_previous = false; - return true; - } - else if (latest.get() < 0) - { - return false; - } - - std::vector buf(PATH_MAX); - ssize_t amt = latest.xread(&buf[0], buf.size()); - - if (amt < 0) - { - std::cerr << "could not read the LATEST backup: " - << strerror(errno) << std::endl; - return false; - } - - buf.resize(amt); - *has_previous = true; - *previous = po6::path::join(base, std::string(buf.begin(), buf.end())); - return true; + std::string latest_path = po6::path::join(base, "LATEST"); + po6::io::fd latest(open(latest_path.c_str(), O_RDONLY)); + if (latest.get() < 0 && errno == ENOENT) + { + *has_previous = false; + return true; + } + else if (latest.get() < 0) + { + return false; + } + std::vector buf(PATH_MAX); + ssize_t amt = latest.xread(&buf[0], buf.size()); + if (amt < 0) + { + std::cerr << "could not read the LATEST backup: " + << strerror(errno) << std::endl; + return false; + } + buf.resize(amt); + *has_previous = true; + *previous = po6::path::join(base, std::string(buf.begin(), buf.end())); + return true; } static bool -record_latest(const std::string& base, const std::string& now) +record_latest(const std::string &base, const std::string &now) { - std::string latest_path = po6::path::join(base, "LATEST"); - po6::io::fd latest(open(latest_path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)); - - if (latest.get() < 0) - { - std::cerr << "could not record the backup in LATEST: " - << strerror(errno) << std::endl; - return false; - } - - if (latest.xwrite(now.c_str(), now.size()) < static_cast(now.size())) - { - std::cerr << "could not record the backup in LATEST: " - << strerror(errno) << std::endl; - return false; - } - - latest.close(); - return true; + std::string latest_path = po6::path::join(base, "LATEST"); + po6::io::fd latest(open(latest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); + if (latest.get() < 0) + { + std::cerr << "could not record the backup in LATEST: " + << strerror(errno) << std::endl; + return false; + } + if (latest.xwrite(now.c_str(), now.size()) < static_cast(now.size())) + { + std::cerr << "could not record the backup in LATEST: " + << strerror(errno) << std::endl; + return false; + } + latest.close(); + return true; } static bool -fork_exec_wait(const std::vector& args) +fork_exec_wait(const std::vector &args) { - pid_t child = fork(); - - if (child > 0) - { - int status = 0; - - if (waitpid(child, &status, 0) < 0) - { - std::cerr << "could not wait for child: " << strerror(errno) << std::endl; - return false; - } - - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - { - std::cerr << "child process failed" << std::endl; - return false; - } - - return true; - } - else if (child == 0) - { - std::vector arg_ptrs; - arg_ptrs.reserve(args.size() + 1); - - for (size_t i = 0; i < args.size(); ++i) - { - arg_ptrs.push_back(args[i].c_str()); - } - - arg_ptrs.push_back(NULL); - execvp(arg_ptrs[0], const_cast(&arg_ptrs[0])); - std::cerr << "could not exec: " << strerror(errno) << std::endl; - exit(EXIT_FAILURE); - } - else - { - std::cerr << "could not fork: " << strerror(errno) << std::endl; - return false; - } + pid_t child = fork(); + if (child > 0) + { + int status = 0; + if (waitpid(child, &status, 0) < 0) + { + std::cerr << "could not wait for child: " << strerror(errno) << std::endl; + return false; + } + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + { + std::cerr << "child process failed" << std::endl; + return false; + } + return true; + } + else if (child == 0) + { + std::vector arg_ptrs; + arg_ptrs.reserve(args.size() + 1); + for (size_t i = 0; i < args.size(); ++i) + { + arg_ptrs.push_back(args[i].c_str()); + } + arg_ptrs.push_back(NULL); + execvp(arg_ptrs[0], const_cast(&arg_ptrs[0])); + std::cerr << "could not exec: " << strerror(errno) << std::endl; + exit(EXIT_FAILURE); + } + else + { + std::cerr << "could not fork: " << strerror(errno) << std::endl; + return false; + } } int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - bool _cleanup = true; - const char* _data = "."; - const char* _user = NULL; - connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.add("Connect to a cluster:", conn.parser()); - ap.arg().name('b', "backup-dir") - .description("store backups in this directory (default: .)") - .metavar("dir").as_string(&_data); - ap.arg().name('u', "user") - .description("username to use for ssh connections (default: this user)") - .metavar("user").as_string(&_user); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - using po6::path::join; - - try - { - bool success = true; - std::string base(_data); - - if (!po6::path::realpath(base, &base)) - { - std::cerr << "error: " << po6::strerror(errno) << std::endl; - return EXIT_FAILURE; - } - - if (chdir(base.c_str()) < 0) - { - std::cerr << "could not change directory to: " << _data << std::endl; - return EXIT_FAILURE; - } - - std::string now; - std::vector daemons; - - if (!get_time(&now)) - { - return EXIT_FAILURE; - } - - if (!take_backup(conn, now.c_str(), &daemons)) - { - return EXIT_FAILURE; - } - - bool has_previous = false; - std::string previous; - - if (!read_latest(base, &has_previous, &previous)) - { - return EXIT_FAILURE; - } - - std::string backupdir(join(base, now)); - - if (mkdir(backupdir.c_str(), S_IRWXU) < 0) - { - std::cerr << "could not make local directory for the backup: " - << strerror(errno) << std::endl; - return EXIT_FAILURE; - } - - if (rename(join(base, now + ".coordinator.bin").c_str(), - join(backupdir, "coordinator.bin").c_str()) < 0) - { - std::cerr << "could not rename coordinator backup: " - << strerror(errno) << std::endl; - return EXIT_FAILURE; - } - - for (size_t i = 0; i < daemons.size(); ++i) - { - char buf[21]; - sprintf(buf, "%lu", daemons[i].sid); - std::string daemon_dir(join(base, now, buf)); - bool prev = false; - std::string link_dest; - - if (has_previous) - { - struct stat stbuf; - std::string daemon_prev(join(previous, buf)); - int status = stat(daemon_prev.c_str(), &stbuf); - - if (status < 0 && errno == ENOENT) - { - prev = false; - } - else if (status < 0) - { - prev = false; - std::cerr << "could not stat prev backup for " << daemons[i].sid << ": " - << strerror(errno) << std::endl; - success = false; - } - else - { - prev = true; - link_dest = "--link-dest="; - link_dest += daemon_prev.c_str(); - } - } - - std::vector args; - args.push_back("rsync"); - args.push_back("-a"); - args.push_back("--delete"); - - if (prev) - { - args.push_back(link_dest); - } - - args.push_back("--"); - std::string rsync_url = daemons[i].addr + ":" + daemons[i].path + "/"; - - if (_user) - { - args.push_back(std::string(_user) + "@" + rsync_url); - } - else - { - args.push_back(rsync_url); - } - - args.push_back(daemon_dir.c_str()); - - if (!fork_exec_wait(args)) - { - success = false; - } - } - - if (success && _cleanup) - { - for (size_t i = 0; i < daemons.size(); ++i) - { - std::vector args; - args.push_back("ssh"); - - if (_user) - { - args.push_back("-l"); - args.push_back(_user); - } - - args.push_back(daemons[i].addr); - args.push_back("rm"); - args.push_back("-r"); - args.push_back("--"); - args.push_back(daemons[i].path); - - if (!fork_exec_wait(args)) - { - success = false; - } - } - } - - if (success && !record_latest(base, now)) - { - success = false; - } - - return success ? EXIT_SUCCESS : EXIT_FAILURE; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + bool _cleanup = true; + const char *_data = "."; + const char *_user = NULL; + connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.add("Connect to a cluster:", conn.parser()); + ap.arg().name('b', "backup-dir") + .description("store backups in this directory (default: .)") + .metavar("dir").as_string(&_data); + ap.arg().name('u', "user") + .description("username to use for ssh connections (default: this user)") + .metavar("user").as_string(&_user); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + using po6::path::join; + try + { + bool success = true; + std::string base(_data); + if (!po6::path::realpath(base, &base)) + { + std::cerr << "error: " << po6::strerror(errno) << std::endl; + return EXIT_FAILURE; + } + if (chdir(base.c_str()) < 0) + { + std::cerr << "could not change directory to: " << _data << std::endl; + return EXIT_FAILURE; + } + std::string now; + std::vector daemons; + if (!get_time(&now)) + { + return EXIT_FAILURE; + } + if (!take_backup(conn, now.c_str(), &daemons)) + { + return EXIT_FAILURE; + } + bool has_previous = false; + std::string previous; + if (!read_latest(base, &has_previous, &previous)) + { + return EXIT_FAILURE; + } + std::string backupdir(join(base, now)); + if (mkdir(backupdir.c_str(), S_IRWXU) < 0) + { + std::cerr << "could not make local directory for the backup: " + << strerror(errno) << std::endl; + return EXIT_FAILURE; + } + if (rename(join(base, now + ".coordinator.bin").c_str(), + join(backupdir, "coordinator.bin").c_str()) < 0) + { + std::cerr << "could not rename coordinator backup: " + << strerror(errno) << std::endl; + return EXIT_FAILURE; + } + for (size_t i = 0; i < daemons.size(); ++i) + { + char buf[21]; + sprintf(buf, "%lu", daemons[i].sid); + std::string daemon_dir(join(base, now, buf)); + bool prev = false; + std::string link_dest; + if (has_previous) + { + struct stat stbuf; + std::string daemon_prev(join(previous, buf)); + int status = stat(daemon_prev.c_str(), &stbuf); + if (status < 0 && errno == ENOENT) + { + prev = false; + } + else if (status < 0) + { + prev = false; + std::cerr << "could not stat prev backup for " << daemons[i].sid << ": " + << strerror(errno) << std::endl; + success = false; + } + else + { + prev = true; + link_dest = "--link-dest="; + link_dest += daemon_prev.c_str(); + } + } + std::vector args; + args.push_back("rsync"); + args.push_back("-a"); + args.push_back("--delete"); + if (prev) + { + args.push_back(link_dest); + } + args.push_back("--"); + std::string rsync_url = daemons[i].addr + ":" + daemons[i].path + "/"; + if (_user) + { + args.push_back(std::string(_user) + "@" + rsync_url); + } + else + { + args.push_back(rsync_url); + } + args.push_back(daemon_dir.c_str()); + if (!fork_exec_wait(args)) + { + success = false; + } + } + if (success && _cleanup) + { + for (size_t i = 0; i < daemons.size(); ++i) + { + std::vector args; + args.push_back("ssh"); + if (_user) + { + args.push_back("-l"); + args.push_back(_user); + } + args.push_back(daemons[i].addr); + args.push_back("rm"); + args.push_back("-r"); + args.push_back("--"); + args.push_back(daemons[i].path); + if (!fork_exec_wait(args)) + { + success = false; + } + } + } + if (success && !record_latest(base, now)) + { + success = false; + } + return success ? EXIT_SUCCESS : EXIT_FAILURE; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/backup.cc b/tools/backup.cc index 62ca3c438..ce790ff0c 100644 --- a/tools/backup.cc +++ b/tools/backup.cc @@ -33,74 +33,63 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 1) - { - std::cerr << "please specify the backup name" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - const char* backups = NULL; - int64_t rid = h.backup(ap.args()[0], &rrc, &backups); - - if (rid < 0) - { - std::cerr << "Backup failed.\n" - << "Please read the above messages for the cause and potential solutions\n"; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "Backup failed.\n" - << "Please read the above messages for the cause and potential solutions\n"; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "backup failed: " << h.error_message() << std::endl; - return EXIT_FAILURE; - } - - if (backups) - { - std::cout << backups; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 1) + { + std::cerr << "please specify the backup name" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + const char *backups = NULL; + int64_t rid = h.backup(ap.args()[0], &rrc, &backups); + if (rid < 0) + { + std::cerr << "Backup failed.\n" + << "Please read the above messages for the cause and potential solutions\n"; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "Backup failed.\n" + << "Please read the above messages for the cause and potential solutions\n"; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "backup failed: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + if (backups) + { + std::cout << backups; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/common.h b/tools/common.h index 337dac7da..837a03fd0 100644 --- a/tools/common.h +++ b/tools/common.h @@ -48,42 +48,41 @@ BEGIN_HYPERDEX_NAMESPACE class connect_opts { - public: - connect_opts() - : m_ap() , m_host("127.0.0.1") , m_port(1982) - { - m_ap.arg().name('h', "host") - .description("connect to the coordinator on an IP address or hostname (default: 127.0.0.1)") - .metavar("addr").as_string(&m_host); - m_ap.arg().name('p', "port") - .description("connect to the coordinator on an alternative port (default: 1982)") - .metavar("port").as_long(&m_port); - } - ~connect_opts() throw () {} - - public: - const e::argparser& parser() { return m_ap; } - const char* host() const { return m_host; } - uint16_t port() const { return m_port; } - bool validate() - { - if (m_port <= 0 || m_port >= (1 << 16)) - { - std::cerr << "port number to connect to is out of range" << std::endl; - return false; - } - - return true; - } - - private: - connect_opts(const connect_opts&); - connect_opts& operator = (const connect_opts&); - - private: - e::argparser m_ap; - const char* m_host; - long m_port; +public: + connect_opts() + : m_ap() , m_host("127.0.0.1") , m_port(1982) + { + m_ap.arg().name('h', "host") + .description("connect to the coordinator on an IP address or hostname (default: 127.0.0.1)") + .metavar("addr").as_string(&m_host); + m_ap.arg().name('p', "port") + .description("connect to the coordinator on an alternative port (default: 1982)") + .metavar("port").as_long(&m_port); + } + ~connect_opts() throw () {} + +public: + const e::argparser &parser() { return m_ap; } + const char *host() const { return m_host; } + uint16_t port() const { return m_port; } + bool validate() + { + if (m_port <= 0 || m_port >= (1 << 16)) + { + std::cerr << "port number to connect to is out of range" << std::endl; + return false; + } + return true; + } + +private: + connect_opts(const connect_opts &); + connect_opts &operator = (const connect_opts &); + +private: + e::argparser m_ap; + const char *m_host; + long m_port; }; #ifdef HYPERDEX_EXEC_DIR @@ -91,69 +90,58 @@ class connect_opts #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wlarger-than=" bool -locate_coordinator_lib(const char* argv0, std::string* path) +locate_coordinator_lib(const char *argv0, std::string *path) { - // find the right library - std::vector paths; - const char* env = getenv("HYPERDEX_COORD_LIB"); - static const char* exts[] = { "", ".so.0.0.0", ".so.0", ".so", ".dylib", 0 }; - - for (size_t i = 0; exts[i]; ++i) - { - std::string base(HYPERDEX_LIB_NAME); - base += exts[i]; - paths.push_back(po6::path::join(HYPERDEX_EXEC_DIR, base)); - paths.push_back(po6::path::join(po6::path::dirname(argv0), ".libs", base)); - - if (env) - { - std::string envlib(env); - envlib += exts[i]; - paths.push_back(envlib); - } - } - - // maybe we're running out of Git. make it "just work" - char selfbuf[PATH_MAX + 1]; - memset(selfbuf, 0, sizeof(selfbuf)); - - if (readlink("/proc/self/exe", selfbuf, PATH_MAX) >= 0) - { - std::string workdir(selfbuf); - workdir = po6::path::dirname(workdir); - std::string gitdir(po6::path::join(workdir, ".git")); - struct stat buf; - - if (stat(gitdir.c_str(), &buf) == 0 && - S_ISDIR(buf.st_mode)) - { - std::string libdir(po6::path::join(workdir, ".libs")); - - for (size_t i = 0; exts[i]; ++i) - { - std::string libname(HYPERDEX_LIB_NAME); - libname += exts[i]; - paths.push_back(po6::path::join(libdir, libname)); - } - } - } - - size_t idx = 0; - - while (idx < paths.size()) - { - struct stat buf; - - if (stat(paths[idx].c_str(), &buf) == 0) - { - *path = paths[idx]; - return true; - } - - ++idx; - } - - return false; + // find the right library + std::vector paths; + const char *env = getenv("HYPERDEX_COORD_LIB"); + static const char *exts[] = { "", ".so.0.0.0", ".so.0", ".so", ".dylib", 0 }; + for (size_t i = 0; exts[i]; ++i) + { + std::string base(HYPERDEX_LIB_NAME); + base += exts[i]; + paths.push_back(po6::path::join(HYPERDEX_EXEC_DIR, base)); + paths.push_back(po6::path::join(po6::path::dirname(argv0), ".libs", base)); + if (env) + { + std::string envlib(env); + envlib += exts[i]; + paths.push_back(envlib); + } + } + // maybe we're running out of Git. make it "just work" + char selfbuf[PATH_MAX + 1]; + memset(selfbuf, 0, sizeof(selfbuf)); + if (readlink("/proc/self/exe", selfbuf, PATH_MAX) >= 0) + { + std::string workdir(selfbuf); + workdir = po6::path::dirname(workdir); + std::string gitdir(po6::path::join(workdir, ".git")); + struct stat buf; + if (stat(gitdir.c_str(), &buf) == 0 && + S_ISDIR(buf.st_mode)) + { + std::string libdir(po6::path::join(workdir, ".libs")); + for (size_t i = 0; exts[i]; ++i) + { + std::string libname(HYPERDEX_LIB_NAME); + libname += exts[i]; + paths.push_back(po6::path::join(libdir, libname)); + } + } + } + size_t idx = 0; + while (idx < paths.size()) + { + struct stat buf; + if (stat(paths[idx].c_str(), &buf) == 0) + { + *path = paths[idx]; + return true; + } + ++idx; + } + return false; } #pragma GCC diagnostic pop #undef HYPERDEX_LIB_NAME diff --git a/tools/coordinator.cc b/tools/coordinator.cc index 15497254b..4a88a6f30 100644 --- a/tools/coordinator.cc +++ b/tools/coordinator.cc @@ -39,60 +39,50 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - std::string libpath; - - if (!hyperdex::locate_coordinator_lib(argv[0], &libpath)) - { - std::cerr << "cannot locate the HyperDex coordinator library" << std::endl; - return EXIT_FAILURE; - } - - // setup the environment - if (setenv("REPLICANT_WRAP", "hyperdex-coordinator", 1) < 0) - { - std::cerr << "could not setup the environment: " << strerror(errno) << std::endl; - return EXIT_FAILURE; - } - - // generate a random token - uint64_t token; - po6::io::fd sysrand(open("/dev/urandom", O_RDONLY)); - - if (sysrand.get() < 0 || - sysrand.read(&token, sizeof(token)) != sizeof(token)) - { - std::cerr << "could not generate random token for cluster" << std::endl; - return EXIT_FAILURE; - } - - char token_buf[21]; - snprintf(token_buf, 21, "%lu", (unsigned long) token); - - // exec replicant daemon - std::vector args; - args.push_back("replicant"); - args.push_back("daemon"); - - for (int i = 1; i < argc; ++i) - { - args.push_back(argv[i]); - } - - args.push_back("--object"); - args.push_back("hyperdex"); - args.push_back("--library"); - args.push_back(libpath.c_str()); - args.push_back("--init-string"); - args.push_back(token_buf); - args.push_back(NULL); - - if (execvp("replicant", const_cast(&args[0])) < 0) - { - perror("could not exec replicant"); - return EXIT_FAILURE; - } - - abort(); + std::string libpath; + if (!hyperdex::locate_coordinator_lib(argv[0], &libpath)) + { + std::cerr << "cannot locate the HyperDex coordinator library" << std::endl; + return EXIT_FAILURE; + } + // setup the environment + if (setenv("REPLICANT_WRAP", "hyperdex-coordinator", 1) < 0) + { + std::cerr << "could not setup the environment: " << strerror(errno) << std::endl; + return EXIT_FAILURE; + } + // generate a random token + uint64_t token; + po6::io::fd sysrand(open("/dev/urandom", O_RDONLY)); + if (sysrand.get() < 0 || + sysrand.read(&token, sizeof(token)) != sizeof(token)) + { + std::cerr << "could not generate random token for cluster" << std::endl; + return EXIT_FAILURE; + } + char token_buf[21]; + snprintf(token_buf, 21, "%lu", (unsigned long) token); + // exec replicant daemon + std::vector args; + args.push_back("replicant"); + args.push_back("daemon"); + for (int i = 1; i < argc; ++i) + { + args.push_back(argv[i]); + } + args.push_back("--object"); + args.push_back("hyperdex"); + args.push_back("--library"); + args.push_back(libpath.c_str()); + args.push_back("--init-string"); + args.push_back(token_buf); + args.push_back(NULL); + if (execvp("replicant", const_cast(&args[0])) < 0) + { + perror("could not exec replicant"); + return EXIT_FAILURE; + } + abort(); } diff --git a/tools/list-spaces.cc b/tools/list-spaces.cc index 08b1f7a9b..b66353115 100644 --- a/tools/list-spaces.cc +++ b/tools/list-spaces.cc @@ -34,68 +34,59 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - const char* spaces; - int64_t rid = h.list_spaces(&rrc, &spaces); - - if (rid < 0) - { - std::cerr << "could not list spaces: " << h.error_message() << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not list spaces: " << h.error_message() << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not list spaces: " << h.error_message() << std::endl; - return EXIT_FAILURE; - } - - if (strcmp(spaces, "") == 0) - { - std::cout << "No spaces are found." << std::endl; - } - else - { - std::cout << spaces; - return EXIT_SUCCESS; - } - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + const char *spaces; + int64_t rid = h.list_spaces(&rrc, &spaces); + if (rid < 0) + { + std::cerr << "could not list spaces: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not list spaces: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not list spaces: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + if (strcmp(spaces, "") == 0) + { + std::cout << "No spaces are found." << std::endl; + } + else + { + std::cout << spaces; + return EXIT_SUCCESS; + } + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/mv-space.cc b/tools/mv-space.cc index 864fe89be..783586bf7 100644 --- a/tools/mv-space.cc +++ b/tools/mv-space.cc @@ -33,67 +33,57 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.option_string("[OPTIONS] "); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 2) - { - std::cerr << "please specify the source and target space names\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - int64_t rid = h.mv_space(ap.args()[0], ap.args()[1], &rrc); - - if (rid < 0) - { - std::cerr << "could not rename space: " << rrc << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not rename space: " << lrc << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not rename space: " << rrc << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.option_string("[OPTIONS] "); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 2) + { + std::cerr << "please specify the source and target space names\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + int64_t rid = h.mv_space(ap.args()[0], ap.args()[1], &rrc); + if (rid < 0) + { + std::cerr << "could not rename space: " << rrc << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not rename space: " << lrc << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not rename space: " << rrc << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/perf-counters.cc b/tools/perf-counters.cc index 570799c19..c9140fbc7 100644 --- a/tools/perf-counters.cc +++ b/tools/perf-counters.cc @@ -36,60 +36,52 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 0) - { - std::cerr << "command takes no arguments" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode prc; - hyperdex_admin_perf_counter pc; - int64_t pid = h.enable_perf_counters(&prc, &pc); - assert(pid>=0); - - while(true) - { - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid != pid) - { - continue; - } - - assert(lid==pid); - assert(prc == HYPERDEX_ADMIN_SUCCESS); - std::cout << pc.id << " " << pc.time << " " << pc.property << " = " << pc.measurement << std::endl; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 0) + { + std::cerr << "command takes no arguments" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode prc; + hyperdex_admin_perf_counter pc; + int64_t pid = h.enable_perf_counters(&prc, &pc); + assert(pid >= 0); + while (true) + { + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid != pid) + { + continue; + } + assert(lid == pid); + assert(prc == HYPERDEX_ADMIN_SUCCESS); + std::cout << pc.id << " " << pc.time << " " << pc.property << " = " << pc.measurement << std::endl; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/raw-backup.cc b/tools/raw-backup.cc index e306ce700..a2b01fa9d 100644 --- a/tools/raw-backup.cc +++ b/tools/raw-backup.cc @@ -36,89 +36,81 @@ class connect_opts { - public: - connect_opts() - : m_ap() , m_host("127.0.0.1") , m_port(2012) - { - m_ap.arg().name('h', "host") - .description("connect to the daemon on an IP address or hostname (default: 127.0.0.1)") - .metavar("addr").as_string(&m_host); - m_ap.arg().name('p', "port") - .description("connect to the daemon on an alternative port (default: 2012)") - .metavar("port").as_long(&m_port); - } - ~connect_opts() throw () {} - - public: - const e::argparser& parser() { return m_ap; } - const char* host() { return m_host; } - uint16_t port() { return m_port; } - bool validate() - { - if (m_port <= 0 || m_port >= (1 << 16)) - { - std::cerr << "port number to connect to is out of range" << std::endl; - return false; - } - - return true; - } - - private: - connect_opts(const connect_opts&); - connect_opts& operator = (const connect_opts&); - - private: - e::argparser m_ap; - const char* m_host; - long m_port; +public: + connect_opts() + : m_ap() , m_host("127.0.0.1") , m_port(2012) + { + m_ap.arg().name('h', "host") + .description("connect to the daemon on an IP address or hostname (default: 127.0.0.1)") + .metavar("addr").as_string(&m_host); + m_ap.arg().name('p', "port") + .description("connect to the daemon on an alternative port (default: 2012)") + .metavar("port").as_long(&m_port); + } + ~connect_opts() throw () {} + +public: + const e::argparser &parser() { return m_ap; } + const char *host() { return m_host; } + uint16_t port() { return m_port; } + bool validate() + { + if (m_port <= 0 || m_port >= (1 << 16)) + { + std::cerr << "port number to connect to is out of range" << std::endl; + return false; + } + return true; + } + +private: + connect_opts(const connect_opts &); + connect_opts &operator = (const connect_opts &); + +private: + e::argparser m_ap; + const char *m_host; + long m_port; }; int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.option_string("[OPTIONS] "); - ap.add("Connect to a daemon:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 1) - { - std::cerr << "please specify a name for the backup" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - const char* name = ap.args()[0]; - - try - { - hyperdex_admin_returncode rc; - - if (hyperdex_admin_raw_backup(conn.host(), conn.port(), name, &rc) < 0) - { - std::cerr << "could not take raw backup: " << rc << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.option_string("[OPTIONS] "); + ap.add("Connect to a daemon:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 1) + { + std::cerr << "please specify a name for the backup" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + const char *name = ap.args()[0]; + try + { + hyperdex_admin_returncode rc; + if (hyperdex_admin_raw_backup(conn.host(), conn.port(), name, &rc) < 0) + { + std::cerr << "could not take raw backup: " << rc << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/rm-index.cc b/tools/rm-index.cc index 049853b89..729893f9d 100644 --- a/tools/rm-index.cc +++ b/tools/rm-index.cc @@ -33,76 +33,64 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (ap.args_sz() != 1) - { - std::cerr << "please specify the id of the index to remove\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - char* endptr = NULL; - uint64_t id = strtoull(ap.args()[0], &endptr, 10); - - if (id == 0 || *endptr != '\0') - { - std::cerr << "invalid index id\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - int64_t rid = h.rm_index(id, &rrc); - - if (rid < 0) - { - std::cerr << "could not rm index: " << rrc << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not rm index: " << lrc << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not rm index: " << rrc << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (ap.args_sz() != 1) + { + std::cerr << "please specify the id of the index to remove\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + char *endptr = NULL; + uint64_t id = strtoull(ap.args()[0], &endptr, 10); + if (id == 0 || *endptr != '\0') + { + std::cerr << "invalid index id\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + int64_t rid = h.rm_index(id, &rrc); + if (rid < 0) + { + std::cerr << "could not rm index: " << rrc << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not rm index: " << lrc << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not rm index: " << rrc << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/rm-space.cc b/tools/rm-space.cc index 456fd23d0..2fd5a3486 100644 --- a/tools/rm-space.cc +++ b/tools/rm-space.cc @@ -33,67 +33,57 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - bool failure = false; - - for (size_t i = 0; i < ap.args_sz(); ++i) - { - hyperdex_admin_returncode rrc; - int64_t rid = h.rm_space(ap.args()[i], &rrc); - - if (rid < 0) - { - std::cerr << "could not rm space: " << h.error_message() << std::endl; - failure = true; - continue; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not rm space: " << h.error_message() << std::endl; - failure = true; - continue; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not rm space: " << h.error_message() << std::endl; - failure = true; - continue; - } - } - - return failure ? EXIT_FAILURE : EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + bool failure = false; + for (size_t i = 0; i < ap.args_sz(); ++i) + { + hyperdex_admin_returncode rrc; + int64_t rid = h.rm_space(ap.args()[i], &rrc); + if (rid < 0) + { + std::cerr << "could not rm space: " << h.error_message() << std::endl; + failure = true; + continue; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not rm space: " << h.error_message() << std::endl; + failure = true; + continue; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not rm space: " << h.error_message() << std::endl; + failure = true; + continue; + } + } + return failure ? EXIT_FAILURE : EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/server-forget.cc b/tools/server-forget.cc index 146cd59ff..0f35d87a3 100644 --- a/tools/server-forget.cc +++ b/tools/server-forget.cc @@ -33,77 +33,65 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.option_string("[OPTIONS] "); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 1) - { - std::cerr << "please specify the server id" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - char* end = NULL; - uint64_t token = strtoull(ap.args()[0], &end, 0); - - if (*end != '\0' || ap.args()[0] == end) - { - std::cerr << "server id must be a number" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - int64_t rid = h.server_forget(token, &rrc); - - if (rid < 0) - { - std::cerr << "could not forget server: " << rrc << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not forget server: " << lrc << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not forget server: " << rrc << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.option_string("[OPTIONS] "); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 1) + { + std::cerr << "please specify the server id" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + char *end = NULL; + uint64_t token = strtoull(ap.args()[0], &end, 0); + if (*end != '\0' || ap.args()[0] == end) + { + std::cerr << "server id must be a number" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + int64_t rid = h.server_forget(token, &rrc); + if (rid < 0) + { + std::cerr << "could not forget server: " << rrc << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not forget server: " << lrc << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not forget server: " << rrc << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/server-kill.cc b/tools/server-kill.cc index 9683ff866..8fcf5f30f 100644 --- a/tools/server-kill.cc +++ b/tools/server-kill.cc @@ -33,77 +33,65 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.option_string("[OPTIONS] "); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 1) - { - std::cerr << "please specify the server id" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - char* end = NULL; - uint64_t token = strtoull(ap.args()[0], &end, 0); - - if (*end != '\0' || ap.args()[0] == end) - { - std::cerr << "server id must be a number" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - int64_t rid = h.server_kill(token, &rrc); - - if (rid < 0) - { - std::cerr << "could not kill server: " << rrc << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not kill server: " << lrc << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not kill server: " << rrc << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.option_string("[OPTIONS] "); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 1) + { + std::cerr << "please specify the server id" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + char *end = NULL; + uint64_t token = strtoull(ap.args()[0], &end, 0); + if (*end != '\0' || ap.args()[0] == end) + { + std::cerr << "server id must be a number" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + int64_t rid = h.server_kill(token, &rrc); + if (rid < 0) + { + std::cerr << "could not kill server: " << rrc << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not kill server: " << lrc << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not kill server: " << rrc << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/server-offline.cc b/tools/server-offline.cc index 0f23415e1..df7ffa761 100644 --- a/tools/server-offline.cc +++ b/tools/server-offline.cc @@ -33,77 +33,65 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.option_string("[OPTIONS] "); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 1) - { - std::cerr << "please specify the server id" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - char* end = NULL; - uint64_t token = strtoull(ap.args()[0], &end, 0); - - if (*end != '\0' || ap.args()[0] == end) - { - std::cerr << "server id must be a number" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - int64_t rid = h.server_offline(token, &rrc); - - if (rid < 0) - { - std::cerr << "could not mark server unavailable: " << rrc << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not mark server unavailable: " << lrc << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not mark server unavailable: " << rrc << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.option_string("[OPTIONS] "); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 1) + { + std::cerr << "please specify the server id" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + char *end = NULL; + uint64_t token = strtoull(ap.args()[0], &end, 0); + if (*end != '\0' || ap.args()[0] == end) + { + std::cerr << "server id must be a number" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + int64_t rid = h.server_offline(token, &rrc); + if (rid < 0) + { + std::cerr << "could not mark server unavailable: " << rrc << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not mark server unavailable: " << lrc << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not mark server unavailable: " << rrc << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/server-online.cc b/tools/server-online.cc index beb0a0f6d..7080d1e7e 100644 --- a/tools/server-online.cc +++ b/tools/server-online.cc @@ -33,77 +33,65 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.option_string("[OPTIONS] "); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 1) - { - std::cerr << "please specify the server id" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - char* end = NULL; - uint64_t token = strtoull(ap.args()[0], &end, 0); - - if (*end != '\0' || ap.args()[0] == end) - { - std::cerr << "server id must be a number" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - int64_t rid = h.server_online(token, &rrc); - - if (rid < 0) - { - std::cerr << "could not bring server online: " << rrc << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not bring server online: " << lrc << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not bring server online: " << rrc << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.option_string("[OPTIONS] "); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 1) + { + std::cerr << "please specify the server id" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + char *end = NULL; + uint64_t token = strtoull(ap.args()[0], &end, 0); + if (*end != '\0' || ap.args()[0] == end) + { + std::cerr << "server id must be a number" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + int64_t rid = h.server_online(token, &rrc); + if (rid < 0) + { + std::cerr << "could not bring server online: " << rrc << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not bring server online: " << lrc << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not bring server online: " << rrc << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/server-register.cc b/tools/server-register.cc index 0db89950a..91fa310ef 100644 --- a/tools/server-register.cc +++ b/tools/server-register.cc @@ -33,77 +33,65 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.option_string("[OPTIONS] "); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 2) - { - std::cerr << "please specify the server id and address:port" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - char* end = NULL; - uint64_t token = strtoull(ap.args()[0], &end, 0); - - if (*end != '\0' || ap.args()[0] == end) - { - std::cerr << "server id must be a number" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - int64_t rid = h.server_register(token, ap.args()[1], &rrc); - - if (rid < 0) - { - std::cerr << "could not register server: " << rrc << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not register server: " << lrc << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not register server: " << rrc << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.option_string("[OPTIONS] "); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 2) + { + std::cerr << "please specify the server id and address:port" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + char *end = NULL; + uint64_t token = strtoull(ap.args()[0], &end, 0); + if (*end != '\0' || ap.args()[0] == end) + { + std::cerr << "server id must be a number" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + int64_t rid = h.server_register(token, ap.args()[1], &rrc); + if (rid < 0) + { + std::cerr << "could not register server: " << rrc << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not register server: " << lrc << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not register server: " << rrc << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/set-fault-tolerance.cc b/tools/set-fault-tolerance.cc index 85f94ddc5..400415f9e 100644 --- a/tools/set-fault-tolerance.cc +++ b/tools/set-fault-tolerance.cc @@ -33,77 +33,65 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.option_string("[OPTIONS] "); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 2) - { - std::cerr << "specify the space and fault tolerance level" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - char* end = NULL; - long ft = strtol(ap.args()[1], &end, 0); - - if (*end != '\0' || ap.args()[1] == end || ft < 0) - { - std::cerr << "fault tolerance must be a number greater than 0" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - int64_t rid = h.fault_tolerance(ap.args()[0], ft, &rrc); - - if (rid < 0) - { - std::cerr << "could not set fault tolerance: " << rrc << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not set fault tolerance: " << lrc << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not set fault tolerance: " << rrc << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.option_string("[OPTIONS] "); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 2) + { + std::cerr << "specify the space and fault tolerance level" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + char *end = NULL; + long ft = strtol(ap.args()[1], &end, 0); + if (*end != '\0' || ap.args()[1] == end || ft < 0) + { + std::cerr << "fault tolerance must be a number greater than 0" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + int64_t rid = h.fault_tolerance(ap.args()[0], ft, &rrc); + if (rid < 0) + { + std::cerr << "could not set fault tolerance: " << rrc << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not set fault tolerance: " << lrc << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not set fault tolerance: " << rrc << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/set-read-only.cc b/tools/set-read-only.cc index bc4548fbc..18cb8e551 100644 --- a/tools/set-read-only.cc +++ b/tools/set-read-only.cc @@ -33,67 +33,57 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.option_string("[OPTIONS] "); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 0) - { - std::cerr << "command takes no arguments" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - int64_t rid = h.read_only(true, &rrc); - - if (rid < 0) - { - std::cerr << "could not make cluster read-only: " << rrc << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not make cluster read-only: " << lrc << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not make cluster read-only: " << rrc << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.option_string("[OPTIONS] "); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 0) + { + std::cerr << "command takes no arguments" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + int64_t rid = h.read_only(true, &rrc); + if (rid < 0) + { + std::cerr << "could not make cluster read-only: " << rrc << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not make cluster read-only: " << lrc << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not make cluster read-only: " << rrc << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/set-read-write.cc b/tools/set-read-write.cc index febdc9832..e266fdc92 100644 --- a/tools/set-read-write.cc +++ b/tools/set-read-write.cc @@ -33,67 +33,57 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.option_string("[OPTIONS] "); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 0) - { - std::cerr << "command takes no arguments" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - int64_t rid = h.read_only(false, &rrc); - - if (rid < 0) - { - std::cerr << "could not make cluster read-write: " << rrc << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not make cluster read-write: " << lrc << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not make cluster read-write: " << rrc << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.option_string("[OPTIONS] "); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 0) + { + std::cerr << "command takes no arguments" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + int64_t rid = h.read_only(false, &rrc); + if (rid < 0) + { + std::cerr << "could not make cluster read-write: " << rrc << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not make cluster read-write: " << lrc << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not make cluster read-write: " << rrc << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/show-config.cc b/tools/show-config.cc index 0fe9f8686..73f7d6548 100644 --- a/tools/show-config.cc +++ b/tools/show-config.cc @@ -33,68 +33,58 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 0) - { - std::cerr << "command takes no positional arguments" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - const char* config = NULL; - int64_t rid = h.dump_config(&rrc, &config); - - if (rid < 0) - { - std::cerr << "could not show config: " << h.error_message() << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not show config: " << h.error_message() << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not show config: " << h.error_message() << std::endl; - return EXIT_FAILURE; - } - - std::cout << config; - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 0) + { + std::cerr << "command takes no positional arguments" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + const char *config = NULL; + int64_t rid = h.dump_config(&rrc, &config); + if (rid < 0) + { + std::cerr << "could not show config: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not show config: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not show config: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + std::cout << config; + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/tools/validate-space.cc b/tools/validate-space.cc index 148be1d06..df49d33cc 100644 --- a/tools/validate-space.cc +++ b/tools/validate-space.cc @@ -38,52 +38,43 @@ #include int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - e::argparser ap; - ap.autohelp(); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (ap.args_sz() != 0) - { - std::cerr << "command takes no arguments" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - std::string description; - std::string s; - - while (std::cin >> s) - { - if (!description.empty()) - { - description += " " + s; - } - else - { - description += s; - } - } - - struct hyperspace* space = hyperspace_parse(description.c_str()); - - if (hyperspace_error(space)) - { - std::cerr << "invalid hyperspace: " << hyperspace_error(space) << std::endl; - - if (space) - { - hyperspace_destroy(space); - } - - return EXIT_FAILURE; - } - - hyperspace_destroy(space); - return EXIT_SUCCESS; + e::argparser ap; + ap.autohelp(); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (ap.args_sz() != 0) + { + std::cerr << "command takes no arguments" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + std::string description; + std::string s; + while (std::cin >> s) + { + if (!description.empty()) + { + description += " " + s; + } + else + { + description += s; + } + } + struct hyperspace *space = hyperspace_parse(description.c_str()); + if (hyperspace_error(space)) + { + std::cerr << "invalid hyperspace: " << hyperspace_error(space) << std::endl; + if (space) + { + hyperspace_destroy(space); + } + return EXIT_FAILURE; + } + hyperspace_destroy(space); + return EXIT_SUCCESS; } diff --git a/tools/wait-until-stable.cc b/tools/wait-until-stable.cc index 6ed5b02fe..75df5706e 100644 --- a/tools/wait-until-stable.cc +++ b/tools/wait-until-stable.cc @@ -33,66 +33,56 @@ #include "tools/common.h" int -main(int argc, const char* argv[]) +main(int argc, const char *argv[]) { - hyperdex::connect_opts conn; - e::argparser ap; - ap.autohelp(); - ap.add("Connect to a cluster:", conn.parser()); - - if (!ap.parse(argc, argv)) - { - return EXIT_FAILURE; - } - - if (!conn.validate()) - { - std::cerr << "invalid host:port specification\n" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - if (ap.args_sz() != 0) - { - std::cerr << "command takes no arguments" << std::endl; - ap.usage(); - return EXIT_FAILURE; - } - - try - { - hyperdex::Admin h(conn.host(), conn.port()); - hyperdex_admin_returncode rrc; - int64_t rid = h.wait_until_stable(&rrc); - - if (rid < 0) - { - std::cerr << "could not wait until stable: " << h.error_message() << std::endl; - return EXIT_FAILURE; - } - - hyperdex_admin_returncode lrc; - int64_t lid = h.loop(-1, &lrc); - - if (lid < 0) - { - std::cerr << "could not wait until stable: " << h.error_message() << std::endl; - return EXIT_FAILURE; - } - - assert(rid == lid); - - if (rrc != HYPERDEX_ADMIN_SUCCESS) - { - std::cerr << "could not wait until stable: " << h.error_message() << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - catch (std::exception& e) - { - std::cerr << "error: " << e.what() << std::endl; - return EXIT_FAILURE; - } + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.add("Connect to a cluster:", conn.parser()); + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + if (ap.args_sz() != 0) + { + std::cerr << "command takes no arguments" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + try + { + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + int64_t rid = h.wait_until_stable(&rrc); + if (rid < 0) + { + std::cerr << "could not wait until stable: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not wait until stable: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not wait until stable: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } } diff --git a/windows/hyperclientclr.cpp b/windows/hyperclientclr.cpp index 0e9e9446b..4ba48bdad 100644 --- a/windows/hyperclientclr.cpp +++ b/windows/hyperclientclr.cpp @@ -1,959 +1,898 @@ -// This is the main DLL file. - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace msclr::interop; -using namespace cliext; -using namespace System; -using namespace System::Collections::Generic; - -#define THROW_EXCEPTION(x) \ - do{ \ - HyperClientException^ ex = gcnew HyperClientException(); \ - ex->return_code = static_cast(x); \ - throw ex; \ - } while (0) - -namespace -HyperDex -{ - - Int64 unpack_int64(const char* val) - { - int64_t out; - e::unpack64le(val, &out); - return out; - } - - Double unpack_float(const char* val) - { - double out; - e::unpack64le(val, (int64_t*)&out); - return out; - } - - String^ unpack_string(const char* str, size_t sz) - { - char* tmp = (char*)malloc(sz + 1); - memcpy(tmp, str, sz); - tmp[sz] = '\0'; - String^ output = marshal_as(tmp); - free(tmp); - return output; - } - - Dictionary^ - unpack_map_string_string(const char* pos, size_t rem) - { - Dictionary^ dict = gcnew Dictionary(); - - while(rem >= 4) - { - uint32_t sz; - e::unpack32le(pos, &sz); - pos += 4; - rem -= 4; - - String^ key = unpack_string(pos, sz); - pos += sz; - rem -= sz; - - e::unpack32le(pos, &sz); - pos += 4; - rem -= 4; - - String^ val = unpack_string(pos, sz); - pos += sz; - rem -= sz; - - dict->Add(key, val); - } - return dict; - } - - Dictionary^ - unpack_map_string_int64(const char* pos, size_t rem) - { - Dictionary^ dict = gcnew Dictionary(); - - while(rem >= 4) - { - uint32_t sz; - e::unpack32le(pos, &sz); - pos += 4; - rem -= 4; - - String^ key = unpack_string(pos, sz); - pos += sz; - rem -= sz; - - Int64 val = unpack_int64(pos); - pos += 8; - rem -= 8; - - dict->Add(key, val); - } - return dict; - } - - Dictionary^ - unpack_map_string_float(const char* pos, size_t rem) - { - Dictionary^ dict = gcnew Dictionary(); - - while(rem >= 4) - { - uint32_t sz; - e::unpack32le(pos, &sz); - pos += 4; - rem -= 4; - - String^ key = unpack_string(pos, sz); - pos += sz; - rem -= sz; - - Double val = unpack_float(pos); - pos += 8; - rem -= 8; - - dict->Add(key, val); - } - return dict; - } - - Dictionary^ - unpack_map_int64_float(const char* pos, size_t rem) - { - Dictionary^ dict = gcnew Dictionary(); - - while(rem >= 8) - { - Int64 key = unpack_int64(pos); - pos += 8; - rem -= 8; - - Double val = unpack_float(pos); - pos += 8; - rem -= 8; - - dict->Add(key, val); - } - return dict; - } - - Dictionary^ - unpack_map_int64_int64(const char* pos, size_t rem) - { - Dictionary^ dict = gcnew Dictionary(); - - while(rem >= 8) - { - Int64 key = unpack_int64(pos); - pos += 8; - rem -= 8; - - Int64 val = unpack_int64(pos); - pos += 8; - rem -= 8; - - dict->Add(key, val); - } - return dict; - } - - - Dictionary^ - unpack_map_int64_string(const char* pos, size_t rem) - { - Dictionary^ dict = gcnew Dictionary(); - - while(rem >= 8) - { - Int64 key = unpack_int64(pos); - pos += 8; - rem -= 8; - - uint32_t sz; - e::unpack32le(pos, &sz); - pos += 4; - rem -= 4; - - String^ val = unpack_string(pos, sz); - pos += sz; - rem -= sz; - - dict->Add(key, val); - } - return dict; - } - - Dictionary^ - unpack_map_float_float(const char* pos, size_t rem) - { - Dictionary^ dict = gcnew Dictionary(); - - while(rem >= 8) - { - Double key = unpack_float(pos); - pos += 8; - rem -= 8; - - Double val = unpack_float(pos); - pos += 8; - rem -= 8; - - dict->Add(key, val); - } - return dict; - } - - Dictionary^ - unpack_map_float_int64(const char* pos, size_t rem) - { - Dictionary^ dict = gcnew Dictionary(); - - while(rem >= 8) - { - Double key = unpack_float(pos); - pos += 8; - rem -= 8; - - Int64 val = unpack_int64(pos); - pos += 8; - rem -= 8; - - dict->Add(key, val); - } - return dict; - } - - - Dictionary^ - unpack_map_float_string(const char* pos, size_t rem) - { - Dictionary^ dict = gcnew Dictionary(); - - while(rem >= 8) - { - Double key = unpack_float(pos); - pos += 8; - rem -= 8; - - uint32_t sz; - e::unpack32le(pos, &sz); - pos += 4; - rem -= 4; - - String^ val = unpack_string(pos, sz); - pos += sz; - rem -= sz; - - dict->Add(key, val); - } - return dict; - } - - - SortedSet^ - unpack_set_string(const char* pos, size_t rem) - { - SortedSet^ lst = gcnew SortedSet(); - - while(rem >= 4) - { - uint32_t sz; - e::unpack32le(pos, &sz); - pos += 4; - rem -= 4; - lst->Add(unpack_string(pos, sz)); - pos += sz; - rem -= sz; - } - return lst; - } - - SortedSet^ - unpack_set_float(const char* pos, size_t rem) - { - SortedSet^ lst = gcnew SortedSet(); - - while(rem >= 8) - { - lst->Add(unpack_float(pos)); - pos += 8; - rem -= 8; - } - return lst; - } - - SortedSet^ - unpack_set_int64(const char* pos, size_t rem) - { - SortedSet^ lst = gcnew SortedSet(); - - while(rem >= 8) - { - lst->Add(unpack_int64(pos)); - pos += 8; - rem -= 8; - } - return lst; - } - - - List^ - unpack_list_string(const char* pos, size_t rem) - { - List^ lst = gcnew List(); - - while(rem >= 4) - { - uint32_t sz; - e::unpack32le(pos, &sz); - pos += 4; - rem -= 4; - lst->Add(unpack_string(pos, sz)); - pos += sz; - rem -= sz; - } - return lst; - } - - List^ - unpack_list_float(const char* pos, size_t rem) - { - List^ lst = gcnew List(); - - while(rem >= 8) - { - lst->Add(unpack_float(pos)); - pos += 8; - rem -= 8; - } - return lst; - } - - List^ - unpack_list_int64(const char* pos, size_t rem) - { - List^ lst = gcnew List(); - - while(rem >= 8) - { - lst->Add(unpack_int64(pos)); - pos += 8; - rem -= 8; - } - return lst; - } - - - HyperClient::HyperClient(String^ coordinator, uint16_t port) - { - WSADATA wsa; - if(WSAStartup(MAKEWORD(2,2), &wsa)) - abort(); - const char* coord; - mc = gcnew marshal_context(); - coord = mc->marshal_as( coordinator ); - _hc = new hyperclient(coord, port); - } - - HyperClient::~HyperClient() - { - this->!HyperClient(); - } - - HyperClient::!HyperClient() - { - delete _hc; - _hc = nullptr; - } - - Dictionary ^ - HyperClient::get(String ^space, String ^key) - { - Dictionary ^output = gcnew Dictionary; - marshal_context context; - - hyperclient_returncode st; - hyperclient_attribute *attrs; - size_t attrs_sz; - int64_t ret = _hc->get(context.marshal_as(space), - context.marshal_as(key), - key->Length, &st, &attrs, &attrs_sz); - if(ret < 0) - { - THROW_EXCEPTION(st); - } - - while(1) - { - hyperclient_returncode rc; - int64_t lret = _hc->loop(-1, &rc); - if(lret == ret) - { - if(rc == HYPERCLIENT_SUCCESS) - { - for(int i = 0; i < attrs_sz; ++i) - { - if(attrs[i].value_sz == 0) - { - continue; - } - switch(attrs[i].datatype) - { - - case HYPERDATATYPE_STRING: - { - output->Add(marshal_as(attrs[i].attr), - unpack_string(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_INT64: - output->Add(marshal_as(attrs[i].attr), - unpack_int64(attrs[i].value)); - break; - case HYPERDATATYPE_FLOAT: - output->Add(marshal_as(attrs[i].attr), - unpack_float(attrs[i].value)); - break; - case HYPERDATATYPE_SET_STRING: - { - output->Add(marshal_as(attrs[i].attr), - unpack_set_string(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_LIST_STRING: - { - output->Add(marshal_as(attrs[i].attr), - unpack_list_string(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_SET_INT64: - { - output->Add(marshal_as(attrs[i].attr), - unpack_set_int64(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_LIST_INT64: - { - output->Add(marshal_as(attrs[i].attr), - unpack_list_int64(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_SET_FLOAT: - { - output->Add(marshal_as(attrs[i].attr), - unpack_set_float(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_LIST_FLOAT: - { - output->Add(marshal_as(attrs[i].attr), - unpack_list_float(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_STRING_STRING: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_string_string(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_STRING_INT64: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_string_int64(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_STRING_FLOAT: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_string_float(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_INT64_STRING: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_int64_string(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_INT64_INT64: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_int64_int64(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_INT64_FLOAT: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_int64_float(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_FLOAT_STRING: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_float_string(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_FLOAT_INT64: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_float_int64(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_FLOAT_FLOAT: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_float_float(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_STRING_KEYONLY: - default: - THROW_EXCEPTION(HYPERCLIENT_WRONGTYPE); - break; - } - } - } - else - { - THROW_EXCEPTION(rc); - } - break; - } - } - - return output; - } - -#define WAIT_FOR_STATUS \ - while(1) \ - { \ - hyperclient_returncode rc; \ - int64_t lret = _hc->loop(-1, &rc); \ - if(lret == ret) \ - { \ - if(rc == HYPERCLIENT_SUCCESS) \ - { \ - return true; \ - } \ - \ - THROW_EXCEPTION(rc); \ - } \ - } \ - \ - return false; \ - -#define HYPERCLIENT_CLRDEF(OPNAME) \ - bool \ - HyperClient:: ## OPNAME(String ^space, String ^key, Dictionary ^ attrs) \ - { \ - size_t size; \ - for each(KeyValuePair kvp in attrs) \ - { \ - if (kvp.Value->GetType()->IsGenericType \ - && kvp.Value->GetType()->GetGenericTypeDefinition() == List::typeid) \ - { \ - if(kvp.Value->GetType() == String::typeid) \ - size += 1 + ((List^)kvp.Value)->Count; \ - if(kvp.Value->GetType() == Int64::typeid) \ - size += 1 + ((List^)kvp.Value)->Count; \ - if(kvp.Value->GetType() == Double::typeid) \ - size += 1 + ((List^)kvp.Value)->Count; \ - } \ - else if (kvp.Value->GetType()->IsGenericType \ - && kvp.Value->GetType()->GetGenericTypeDefinition() == SortedSet::typeid) \ - { \ - if(kvp.Value->GetType() == String::typeid) \ - size += 1 + ((SortedSet^)kvp.Value)->Count; \ - if(kvp.Value->GetType() == Int64::typeid) \ - size += 1 + ((SortedSet^)kvp.Value)->Count; \ - if(kvp.Value->GetType() == Double::typeid) \ - size += 1 + ((SortedSet^)kvp.Value)->Count; \ - } \ - else \ - { \ - size ++; \ - } \ - } \ - marshal_context context; \ - hyperclient_returncode st; \ - int64_t ret = _hc->OPNAME(context.marshal_as(space), \ - context.marshal_as(key), \ - key->Length, \ - context.marshal_as(attrs), \ - size, &st); \ - if(ret < 0) \ - { \ - THROW_EXCEPTION(st); \ - } \ - WAIT_FOR_STATUS \ - } - - HYPERCLIENT_CLRDEF(put) - HYPERCLIENT_CLRDEF(put_if_not_exist) - HYPERCLIENT_CLRDEF(atomic_add) - HYPERCLIENT_CLRDEF(atomic_sub) - HYPERCLIENT_CLRDEF(atomic_mul) - HYPERCLIENT_CLRDEF(atomic_div) - HYPERCLIENT_CLRDEF(atomic_mod) - HYPERCLIENT_CLRDEF(atomic_and) - HYPERCLIENT_CLRDEF(atomic_or) - HYPERCLIENT_CLRDEF(atomic_xor) - HYPERCLIENT_CLRDEF(string_prepend) - HYPERCLIENT_CLRDEF(string_append) - HYPERCLIENT_CLRDEF(list_lpush) - HYPERCLIENT_CLRDEF(list_rpush) - HYPERCLIENT_CLRDEF(set_add) - HYPERCLIENT_CLRDEF(set_remove) - HYPERCLIENT_CLRDEF(set_intersect) - HYPERCLIENT_CLRDEF(set_union) - -#define HYPERCLIENT_MAP_CLRDEF(OPNAME) \ - bool \ - HyperClient:: map_ ## OPNAME(String ^space, String ^key, Dictionary^ > ^ attrs) \ - { \ - marshal_context context; \ - hyperclient_returncode st; \ - size_t size = 0; \ - for each(KeyValuePair^ > attrkvp in attrs) \ - { \ - size += attrkvp.Value->Count; \ - } \ - int64_t ret = _hc->map_ ## OPNAME(context.marshal_as(space), \ - context.marshal_as(key), \ - key->Length, \ - context.marshal_as(attrs), \ - size, &st); \ - if(ret < 0) \ - { \ - THROW_EXCEPTION(st); \ - } \ - WAIT_FOR_STATUS \ - } - - HYPERCLIENT_MAP_CLRDEF(add) - HYPERCLIENT_MAP_CLRDEF(remove) - HYPERCLIENT_MAP_CLRDEF(atomic_add) - HYPERCLIENT_MAP_CLRDEF(atomic_sub) - HYPERCLIENT_MAP_CLRDEF(atomic_mul) - HYPERCLIENT_MAP_CLRDEF(atomic_div) - HYPERCLIENT_MAP_CLRDEF(atomic_mod) - HYPERCLIENT_MAP_CLRDEF(atomic_and) - HYPERCLIENT_MAP_CLRDEF(atomic_or) - HYPERCLIENT_MAP_CLRDEF(atomic_xor) - HYPERCLIENT_MAP_CLRDEF(string_prepend) - HYPERCLIENT_MAP_CLRDEF(string_append) - - List^ >^ - HyperClient::search(String^ space, Dictionary^ checks) - { - List^ > ^toValue = gcnew List^ >(); - - marshal_context context; - hyperclient_returncode st; - struct hyperclient_attribute* attrs; - size_t attrs_sz; - size_t checks_sz; - - for each(KeyValuePair kvp in checks) - { - if (kvp.Value->GetType()->IsGenericType - && kvp.Value->GetType()->GetGenericTypeDefinition() == KeyValuePair::typeid) - { - ++checks_sz; - } - ++checks_sz; - } - - int64_t ret = _hc->search(context.marshal_as(space), - context.marshal_as(checks), - checks_sz, &st, &attrs, &attrs_sz); - if(ret < 0) - { - THROW_EXCEPTION(st); - } - - while(1) - { - hyperclient_returncode rc; - int64_t lret = _hc->loop(-1, &rc); - if(lret < 0) - { - THROW_EXCEPTION(rc); - } - else if(lret == ret) - { - Dictionary^ output = gcnew Dictionary(); - for(int i = 0; i < attrs_sz; ++i) - { - switch(attrs[i].datatype) - { - - case HYPERDATATYPE_STRING: - { - output->Add(marshal_as(attrs[i].attr), - unpack_string(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_INT64: - output->Add(marshal_as(attrs[i].attr), - unpack_int64(attrs[i].value)); - break; - case HYPERDATATYPE_FLOAT: - output->Add(marshal_as(attrs[i].attr), - unpack_float(attrs[i].value)); - break; - case HYPERDATATYPE_SET_STRING: - { - output->Add(marshal_as(attrs[i].attr), - unpack_set_string(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_LIST_STRING: - { - output->Add(marshal_as(attrs[i].attr), - unpack_list_string(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_SET_INT64: - { - output->Add(marshal_as(attrs[i].attr), - unpack_set_int64(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_LIST_INT64: - { - output->Add(marshal_as(attrs[i].attr), - unpack_list_int64(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_SET_FLOAT: - { - output->Add(marshal_as(attrs[i].attr), - unpack_set_float(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_LIST_FLOAT: - { - output->Add(marshal_as(attrs[i].attr), - unpack_list_float(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_STRING_STRING: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_string_string(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_STRING_INT64: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_string_int64(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_STRING_FLOAT: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_string_float(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_INT64_STRING: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_int64_string(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_INT64_INT64: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_int64_int64(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_INT64_FLOAT: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_int64_float(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_FLOAT_STRING: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_float_string(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_FLOAT_INT64: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_float_int64(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_FLOAT_FLOAT: - { - output->Add(marshal_as(attrs[i].attr), - unpack_map_float_float(attrs[i].value, attrs[i].value_sz)); - break; - } - case HYPERDATATYPE_MAP_STRING_KEYONLY: - default: - THROW_EXCEPTION(HYPERCLIENT_WRONGTYPE); - break; - } - } - - toValue->Add(output); - - if(rc == HYPERCLIENT_SEARCHDONE) - { - break; - } - } - } - return toValue; - } - - List^ >^ - HyperClient::sorted_search(String^ space, String ^sortby, - UInt64 limit, bool maximize, Dictionary^ checks) - { - List^ > ^toValue = gcnew List^ >(); - - marshal_context context; - hyperclient_returncode st; - struct hyperclient_attribute* attrs; - size_t attrs_sz; - size_t checks_sz; - - for each(KeyValuePair kvp in checks) - { - if (kvp.Value->GetType()->IsGenericType - && kvp.Value->GetType()->GetGenericTypeDefinition() == KeyValuePair::typeid) - { - ++checks_sz; - } - ++checks_sz; - } - - int64_t ret = _hc->sorted_search(context.marshal_as(space), - context.marshal_as(checks), - checks_sz, context.marshal_as(sortby), limit, maximize, - &st, &attrs, &attrs_sz); - - if(ret < 0) - { - THROW_EXCEPTION(st); - } - - while(1) - { - hyperclient_returncode rc; - int64_t lret = _hc->loop(-1, &rc); - if(lret < 0) - { - THROW_EXCEPTION(rc); - } - else if(lret == ret) - { - Dictionary^ output = gcnew Dictionary(); - for(int i = 0; i < attrs_sz; ++i) - { - switch(attrs[i].datatype) - { - case HYPERDATATYPE_STRING: - output->Add(marshal_as(attrs[i].attr), - marshal_as(attrs[i].value)); - break; - case HYPERDATATYPE_INT64: - output->Add(marshal_as(attrs[i].attr), - *(int64_t*)attrs[i].value); - break; - case HYPERDATATYPE_FLOAT: - output->Add(marshal_as(attrs[i].attr), - *(double*)attrs[i].value); - break; - default: - break; - } - } - - toValue->Add(output); - - if(rc == HYPERCLIENT_SEARCHDONE) - { - break; - } - } - } - return toValue; - } - - - UInt64 - HyperClient::count(String^ space, Dictionary^ checks) - { - marshal_context context; - hyperclient_returncode st; - size_t checks_sz; - uint64_t result; - - for each(KeyValuePair kvp in checks) - { - if (kvp.Value->GetType()->IsGenericType - && kvp.Value->GetType()->GetGenericTypeDefinition() == KeyValuePair::typeid) - { - ++checks_sz; - } - ++checks_sz; - } - - int64_t ret = _hc->count(context.marshal_as(space), - context.marshal_as(checks), - checks_sz, &st, &result); - if(ret < 0) - { - THROW_EXCEPTION(st); - } - - while(1) - { - hyperclient_returncode rc; - int64_t lret = _hc->loop(-1, &rc); - if(lret < 0) - { - THROW_EXCEPTION(rc); - } - else if(lret == ret) - { - if(rc == HYPERCLIENT_SUCCESS) - { - return result; - } - THROW_EXCEPTION(rc); - } - } - } - - - bool - HyperClient::del(String^ space, String^ key) - { - marshal_context context; - hyperclient_returncode st; - int64_t ret = _hc->del(context.marshal_as(space), - context.marshal_as(key), - key->Length, &st); - - if(ret < 0) - { - THROW_EXCEPTION(st); - } - WAIT_FOR_STATUS - } -} +// This is the main DLL file. + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace msclr::interop; +using namespace cliext; +using namespace System; +using namespace System::Collections::Generic; + +#define THROW_EXCEPTION(x) \ + do{ \ + HyperClientException^ ex = gcnew HyperClientException(); \ + ex->return_code = static_cast(x); \ + throw ex; \ + } while (0) + +namespace + HyperDex +{ + +Int64 unpack_int64(const char *val) +{ + int64_t out; + e::unpack64le(val, &out); + return out; +} + +Double unpack_float(const char *val) +{ + double out; + e::unpack64le(val, (int64_t *)&out); + return out; +} + +String ^unpack_string(const char *str, size_t sz) +{ + char *tmp = (char *)malloc(sz + 1); + memcpy(tmp, str, sz); + tmp[sz] = '\0'; + String ^output = marshal_as(tmp); + free(tmp); + return output; +} + +Dictionary ^ +unpack_map_string_string(const char *pos, size_t rem) +{ + Dictionary ^dict = gcnew Dictionary(); + while (rem >= 4) + { + uint32_t sz; + e::unpack32le(pos, &sz); + pos += 4; + rem -= 4; + String ^key = unpack_string(pos, sz); + pos += sz; + rem -= sz; + e::unpack32le(pos, &sz); + pos += 4; + rem -= 4; + String ^val = unpack_string(pos, sz); + pos += sz; + rem -= sz; + dict->Add(key, val); + } + return dict; +} + +Dictionary ^ +unpack_map_string_int64(const char *pos, size_t rem) +{ + Dictionary ^dict = gcnew Dictionary(); + while (rem >= 4) + { + uint32_t sz; + e::unpack32le(pos, &sz); + pos += 4; + rem -= 4; + String ^key = unpack_string(pos, sz); + pos += sz; + rem -= sz; + Int64 val = unpack_int64(pos); + pos += 8; + rem -= 8; + dict->Add(key, val); + } + return dict; +} + +Dictionary ^ +unpack_map_string_float(const char *pos, size_t rem) +{ + Dictionary ^dict = gcnew Dictionary(); + while (rem >= 4) + { + uint32_t sz; + e::unpack32le(pos, &sz); + pos += 4; + rem -= 4; + String ^key = unpack_string(pos, sz); + pos += sz; + rem -= sz; + Double val = unpack_float(pos); + pos += 8; + rem -= 8; + dict->Add(key, val); + } + return dict; +} + +Dictionary ^ +unpack_map_int64_float(const char *pos, size_t rem) +{ + Dictionary ^dict = gcnew Dictionary(); + while (rem >= 8) + { + Int64 key = unpack_int64(pos); + pos += 8; + rem -= 8; + Double val = unpack_float(pos); + pos += 8; + rem -= 8; + dict->Add(key, val); + } + return dict; +} + +Dictionary ^ +unpack_map_int64_int64(const char *pos, size_t rem) +{ + Dictionary ^dict = gcnew Dictionary(); + while (rem >= 8) + { + Int64 key = unpack_int64(pos); + pos += 8; + rem -= 8; + Int64 val = unpack_int64(pos); + pos += 8; + rem -= 8; + dict->Add(key, val); + } + return dict; +} + + +Dictionary ^ +unpack_map_int64_string(const char *pos, size_t rem) +{ + Dictionary ^dict = gcnew Dictionary(); + while (rem >= 8) + { + Int64 key = unpack_int64(pos); + pos += 8; + rem -= 8; + uint32_t sz; + e::unpack32le(pos, &sz); + pos += 4; + rem -= 4; + String ^val = unpack_string(pos, sz); + pos += sz; + rem -= sz; + dict->Add(key, val); + } + return dict; +} + +Dictionary ^ +unpack_map_float_float(const char *pos, size_t rem) +{ + Dictionary ^dict = gcnew Dictionary(); + while (rem >= 8) + { + Double key = unpack_float(pos); + pos += 8; + rem -= 8; + Double val = unpack_float(pos); + pos += 8; + rem -= 8; + dict->Add(key, val); + } + return dict; +} + +Dictionary ^ +unpack_map_float_int64(const char *pos, size_t rem) +{ + Dictionary ^dict = gcnew Dictionary(); + while (rem >= 8) + { + Double key = unpack_float(pos); + pos += 8; + rem -= 8; + Int64 val = unpack_int64(pos); + pos += 8; + rem -= 8; + dict->Add(key, val); + } + return dict; +} + + +Dictionary ^ +unpack_map_float_string(const char *pos, size_t rem) +{ + Dictionary ^dict = gcnew Dictionary(); + while (rem >= 8) + { + Double key = unpack_float(pos); + pos += 8; + rem -= 8; + uint32_t sz; + e::unpack32le(pos, &sz); + pos += 4; + rem -= 4; + String ^val = unpack_string(pos, sz); + pos += sz; + rem -= sz; + dict->Add(key, val); + } + return dict; +} + + +SortedSet ^ +unpack_set_string(const char *pos, size_t rem) +{ + SortedSet ^lst = gcnew SortedSet(); + while (rem >= 4) + { + uint32_t sz; + e::unpack32le(pos, &sz); + pos += 4; + rem -= 4; + lst->Add(unpack_string(pos, sz)); + pos += sz; + rem -= sz; + } + return lst; +} + +SortedSet ^ +unpack_set_float(const char *pos, size_t rem) +{ + SortedSet ^lst = gcnew SortedSet(); + while (rem >= 8) + { + lst->Add(unpack_float(pos)); + pos += 8; + rem -= 8; + } + return lst; +} + +SortedSet ^ +unpack_set_int64(const char *pos, size_t rem) +{ + SortedSet ^lst = gcnew SortedSet(); + while (rem >= 8) + { + lst->Add(unpack_int64(pos)); + pos += 8; + rem -= 8; + } + return lst; +} + + +List ^ +unpack_list_string(const char *pos, size_t rem) +{ + List ^lst = gcnew List(); + while (rem >= 4) + { + uint32_t sz; + e::unpack32le(pos, &sz); + pos += 4; + rem -= 4; + lst->Add(unpack_string(pos, sz)); + pos += sz; + rem -= sz; + } + return lst; +} + +List ^ +unpack_list_float(const char *pos, size_t rem) +{ + List ^lst = gcnew List(); + while (rem >= 8) + { + lst->Add(unpack_float(pos)); + pos += 8; + rem -= 8; + } + return lst; +} + +List ^ +unpack_list_int64(const char *pos, size_t rem) +{ + List ^lst = gcnew List(); + while (rem >= 8) + { + lst->Add(unpack_int64(pos)); + pos += 8; + rem -= 8; + } + return lst; +} + + +HyperClient::HyperClient(String ^coordinator, uint16_t port) +{ + WSADATA wsa; + if (WSAStartup(MAKEWORD(2, 2), &wsa)) + abort(); + const char *coord; + mc = gcnew marshal_context(); + coord = mc->marshal_as( coordinator ); + _hc = new hyperclient(coord, port); +} + +HyperClient::~HyperClient() +{ + this->!HyperClient(); +} + +HyperClient::!HyperClient() +{ + delete _hc; + _hc = nullptr; +} + +Dictionary ^ +HyperClient::get(String ^space, String ^key) +{ + Dictionary ^output = gcnew Dictionary; + marshal_context context; + hyperclient_returncode st; + hyperclient_attribute *attrs; + size_t attrs_sz; + int64_t ret = _hc->get(context.marshal_as(space), + context.marshal_as(key), + key->Length, &st, &attrs, &attrs_sz); + if (ret < 0) + { + THROW_EXCEPTION(st); + } + while (1) + { + hyperclient_returncode rc; + int64_t lret = _hc->loop(-1, &rc); + if (lret == ret) + { + if (rc == HYPERCLIENT_SUCCESS) + { + for (int i = 0; i < attrs_sz; ++i) + { + if (attrs[i].value_sz == 0) + { + continue; + } + switch (attrs[i].datatype) + { + case HYPERDATATYPE_STRING: + { + output->Add(marshal_as(attrs[i].attr), + unpack_string(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_INT64: + output->Add(marshal_as(attrs[i].attr), + unpack_int64(attrs[i].value)); + break; + case HYPERDATATYPE_FLOAT: + output->Add(marshal_as(attrs[i].attr), + unpack_float(attrs[i].value)); + break; + case HYPERDATATYPE_SET_STRING: + { + output->Add(marshal_as(attrs[i].attr), + unpack_set_string(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_LIST_STRING: + { + output->Add(marshal_as(attrs[i].attr), + unpack_list_string(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_SET_INT64: + { + output->Add(marshal_as(attrs[i].attr), + unpack_set_int64(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_LIST_INT64: + { + output->Add(marshal_as(attrs[i].attr), + unpack_list_int64(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_SET_FLOAT: + { + output->Add(marshal_as(attrs[i].attr), + unpack_set_float(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_LIST_FLOAT: + { + output->Add(marshal_as(attrs[i].attr), + unpack_list_float(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_STRING_STRING: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_string_string(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_STRING_INT64: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_string_int64(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_STRING_FLOAT: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_string_float(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_INT64_STRING: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_int64_string(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_INT64_INT64: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_int64_int64(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_INT64_FLOAT: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_int64_float(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_FLOAT_STRING: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_float_string(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_FLOAT_INT64: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_float_int64(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_FLOAT_FLOAT: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_float_float(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_STRING_KEYONLY: + default: + THROW_EXCEPTION(HYPERCLIENT_WRONGTYPE); + break; + } + } + } + else + { + THROW_EXCEPTION(rc); + } + break; + } + } + return output; +} + +#define WAIT_FOR_STATUS \ + while(1) \ + { \ + hyperclient_returncode rc; \ + int64_t lret = _hc->loop(-1, &rc); \ + if(lret == ret) \ + { \ + if(rc == HYPERCLIENT_SUCCESS) \ + { \ + return true; \ + } \ + \ + THROW_EXCEPTION(rc); \ + } \ + } \ + \ + return false; \ + +#define HYPERCLIENT_CLRDEF(OPNAME) \ + bool \ + HyperClient:: ## OPNAME(String ^space, String ^key, Dictionary ^ attrs) \ + { \ + size_t size; \ + for each(KeyValuePair kvp in attrs) \ + { \ + if (kvp.Value->GetType()->IsGenericType \ + && kvp.Value->GetType()->GetGenericTypeDefinition() == List::typeid) \ + { \ + if(kvp.Value->GetType() == String::typeid) \ + size += 1 + ((List^)kvp.Value)->Count; \ + if(kvp.Value->GetType() == Int64::typeid) \ + size += 1 + ((List^)kvp.Value)->Count; \ + if(kvp.Value->GetType() == Double::typeid) \ + size += 1 + ((List^)kvp.Value)->Count; \ + } \ + else if (kvp.Value->GetType()->IsGenericType \ + && kvp.Value->GetType()->GetGenericTypeDefinition() == SortedSet::typeid) \ + { \ + if(kvp.Value->GetType() == String::typeid) \ + size += 1 + ((SortedSet^)kvp.Value)->Count; \ + if(kvp.Value->GetType() == Int64::typeid) \ + size += 1 + ((SortedSet^)kvp.Value)->Count; \ + if(kvp.Value->GetType() == Double::typeid) \ + size += 1 + ((SortedSet^)kvp.Value)->Count; \ + } \ + else \ + { \ + size ++; \ + } \ + } \ + marshal_context context; \ + hyperclient_returncode st; \ + int64_t ret = _hc->OPNAME(context.marshal_as(space), \ + context.marshal_as(key), \ + key->Length, \ + context.marshal_as(attrs), \ + size, &st); \ + if(ret < 0) \ + { \ + THROW_EXCEPTION(st); \ + } \ + WAIT_FOR_STATUS \ + } + + HYPERCLIENT_CLRDEF(put) + HYPERCLIENT_CLRDEF(put_if_not_exist) + HYPERCLIENT_CLRDEF(atomic_add) + HYPERCLIENT_CLRDEF(atomic_sub) + HYPERCLIENT_CLRDEF(atomic_mul) + HYPERCLIENT_CLRDEF(atomic_div) + HYPERCLIENT_CLRDEF(atomic_mod) + HYPERCLIENT_CLRDEF(atomic_and) + HYPERCLIENT_CLRDEF(atomic_or) + HYPERCLIENT_CLRDEF(atomic_xor) + HYPERCLIENT_CLRDEF(string_prepend) + HYPERCLIENT_CLRDEF(string_append) + HYPERCLIENT_CLRDEF(list_lpush) + HYPERCLIENT_CLRDEF(list_rpush) + HYPERCLIENT_CLRDEF(set_add) + HYPERCLIENT_CLRDEF(set_remove) + HYPERCLIENT_CLRDEF(set_intersect) + HYPERCLIENT_CLRDEF(set_union) + +#define HYPERCLIENT_MAP_CLRDEF(OPNAME) \ + bool \ + HyperClient:: map_ ## OPNAME(String ^space, String ^key, Dictionary^ > ^ attrs) \ + { \ + marshal_context context; \ + hyperclient_returncode st; \ + size_t size = 0; \ + for each(KeyValuePair^ > attrkvp in attrs) \ + { \ + size += attrkvp.Value->Count; \ + } \ + int64_t ret = _hc->map_ ## OPNAME(context.marshal_as(space), \ + context.marshal_as(key), \ + key->Length, \ + context.marshal_as(attrs), \ + size, &st); \ + if(ret < 0) \ + { \ + THROW_EXCEPTION(st); \ + } \ + WAIT_FOR_STATUS \ + } + + HYPERCLIENT_MAP_CLRDEF(add) + HYPERCLIENT_MAP_CLRDEF(remove) + HYPERCLIENT_MAP_CLRDEF(atomic_add) + HYPERCLIENT_MAP_CLRDEF(atomic_sub) + HYPERCLIENT_MAP_CLRDEF(atomic_mul) + HYPERCLIENT_MAP_CLRDEF(atomic_div) + HYPERCLIENT_MAP_CLRDEF(atomic_mod) + HYPERCLIENT_MAP_CLRDEF(atomic_and) + HYPERCLIENT_MAP_CLRDEF(atomic_or) + HYPERCLIENT_MAP_CLRDEF(atomic_xor) + HYPERCLIENT_MAP_CLRDEF(string_prepend) + HYPERCLIENT_MAP_CLRDEF(string_append) + + List^ > ^ + HyperClient::search(String ^space, Dictionary ^checks) + { + List^ > ^toValue = gcnew List^ >(); + marshal_context context; + hyperclient_returncode st; + struct hyperclient_attribute *attrs; + size_t attrs_sz; + size_t checks_sz; + for each(KeyValuePair kvp in checks) + { + if (kvp.Value->GetType()->IsGenericType + && kvp.Value->GetType()->GetGenericTypeDefinition() == KeyValuePair::typeid) + { + ++checks_sz; + } + ++checks_sz; + } + int64_t ret = _hc->search(context.marshal_as(space), + context.marshal_as(checks), + checks_sz, &st, &attrs, &attrs_sz); + if (ret < 0) + { + THROW_EXCEPTION(st); + } + while (1) + { + hyperclient_returncode rc; + int64_t lret = _hc->loop(-1, &rc); + if (lret < 0) + { + THROW_EXCEPTION(rc); + } + else if (lret == ret) + { + Dictionary ^output = gcnew Dictionary(); + for (int i = 0; i < attrs_sz; ++i) + { + switch (attrs[i].datatype) + { + case HYPERDATATYPE_STRING: + { + output->Add(marshal_as(attrs[i].attr), + unpack_string(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_INT64: + output->Add(marshal_as(attrs[i].attr), + unpack_int64(attrs[i].value)); + break; + case HYPERDATATYPE_FLOAT: + output->Add(marshal_as(attrs[i].attr), + unpack_float(attrs[i].value)); + break; + case HYPERDATATYPE_SET_STRING: + { + output->Add(marshal_as(attrs[i].attr), + unpack_set_string(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_LIST_STRING: + { + output->Add(marshal_as(attrs[i].attr), + unpack_list_string(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_SET_INT64: + { + output->Add(marshal_as(attrs[i].attr), + unpack_set_int64(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_LIST_INT64: + { + output->Add(marshal_as(attrs[i].attr), + unpack_list_int64(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_SET_FLOAT: + { + output->Add(marshal_as(attrs[i].attr), + unpack_set_float(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_LIST_FLOAT: + { + output->Add(marshal_as(attrs[i].attr), + unpack_list_float(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_STRING_STRING: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_string_string(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_STRING_INT64: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_string_int64(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_STRING_FLOAT: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_string_float(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_INT64_STRING: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_int64_string(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_INT64_INT64: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_int64_int64(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_INT64_FLOAT: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_int64_float(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_FLOAT_STRING: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_float_string(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_FLOAT_INT64: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_float_int64(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_FLOAT_FLOAT: + { + output->Add(marshal_as(attrs[i].attr), + unpack_map_float_float(attrs[i].value, attrs[i].value_sz)); + break; + } + case HYPERDATATYPE_MAP_STRING_KEYONLY: + default: + THROW_EXCEPTION(HYPERCLIENT_WRONGTYPE); + break; + } + } + toValue->Add(output); + if (rc == HYPERCLIENT_SEARCHDONE) + { + break; + } + } + } + return toValue; + } + + List^ > ^ + HyperClient::sorted_search(String ^space, String ^sortby, + UInt64 limit, bool maximize, Dictionary ^checks) + { + List^ > ^toValue = gcnew List^ >(); + marshal_context context; + hyperclient_returncode st; + struct hyperclient_attribute *attrs; + size_t attrs_sz; + size_t checks_sz; + for each(KeyValuePair kvp in checks) + { + if (kvp.Value->GetType()->IsGenericType + && kvp.Value->GetType()->GetGenericTypeDefinition() == KeyValuePair::typeid) + { + ++checks_sz; + } + ++checks_sz; + } + int64_t ret = _hc->sorted_search(context.marshal_as(space), + context.marshal_as(checks), + checks_sz, context.marshal_as(sortby), limit, maximize, + &st, &attrs, &attrs_sz); + if (ret < 0) + { + THROW_EXCEPTION(st); + } + while (1) + { + hyperclient_returncode rc; + int64_t lret = _hc->loop(-1, &rc); + if (lret < 0) + { + THROW_EXCEPTION(rc); + } + else if (lret == ret) + { + Dictionary ^output = gcnew Dictionary(); + for (int i = 0; i < attrs_sz; ++i) + { + switch (attrs[i].datatype) + { + case HYPERDATATYPE_STRING: + output->Add(marshal_as(attrs[i].attr), + marshal_as(attrs[i].value)); + break; + case HYPERDATATYPE_INT64: + output->Add(marshal_as(attrs[i].attr), + *(int64_t *)attrs[i].value); + break; + case HYPERDATATYPE_FLOAT: + output->Add(marshal_as(attrs[i].attr), + *(double *)attrs[i].value); + break; + default: + break; + } + } + toValue->Add(output); + if (rc == HYPERCLIENT_SEARCHDONE) + { + break; + } + } + } + return toValue; + } + + + UInt64 + HyperClient::count(String ^space, Dictionary ^checks) + { + marshal_context context; + hyperclient_returncode st; + size_t checks_sz; + uint64_t result; + for each(KeyValuePair kvp in checks) + { + if (kvp.Value->GetType()->IsGenericType + && kvp.Value->GetType()->GetGenericTypeDefinition() == KeyValuePair::typeid) + { + ++checks_sz; + } + ++checks_sz; + } + int64_t ret = _hc->count(context.marshal_as(space), + context.marshal_as(checks), + checks_sz, &st, &result); + if (ret < 0) + { + THROW_EXCEPTION(st); + } + while (1) + { + hyperclient_returncode rc; + int64_t lret = _hc->loop(-1, &rc); + if (lret < 0) + { + THROW_EXCEPTION(rc); + } + else if (lret == ret) + { + if (rc == HYPERCLIENT_SUCCESS) + { + return result; + } + THROW_EXCEPTION(rc); + } + } + } + + + bool + HyperClient::del(String ^space, String ^key) + { + marshal_context context; + hyperclient_returncode st; + int64_t ret = _hc->del(context.marshal_as(space), + context.marshal_as(key), + key->Length, &st); + if (ret < 0) + { + THROW_EXCEPTION(st); + } + WAIT_FOR_STATUS + } + } diff --git a/windows/hyperclientclr.h b/windows/hyperclientclr.h index a59af0a61..4f4559971 100644 --- a/windows/hyperclientclr.h +++ b/windows/hyperclientclr.h @@ -12,123 +12,123 @@ using namespace System; using namespace System::Collections::Generic; #define THROW_EXCEPTION(x) \ - do{ \ - HyperClientException^ ex = gcnew HyperClientException(); \ - ex->return_code = static_cast(x); \ - throw ex; \ - } while (0) + do{ \ + HyperClientException^ ex = gcnew HyperClientException(); \ + ex->return_code = static_cast(x); \ + throw ex; \ + } while (0) namespace -HyperDex + HyperDex { - public enum class HyperClientReturnCode - { - HYPERDEX_CLIENT_SUCCESS = 8448, - HYPERDEX_CLIENT_NOTFOUND = 8449, - HYPERDEX_CLIENT_SEARCHDONE = 8450, - HYPERDEX_CLIENT_CMPFAIL = 8451, - HYPERDEX_CLIENT_READONLY = 8452, - - /* Error conditions */ - HYPERDEX_CLIENT_UNKNOWNSPACE = 8512, - HYPERDEX_CLIENT_COORDFAIL = 8513, - HYPERDEX_CLIENT_SERVERERROR = 8514, - HYPERDEX_CLIENT_POLLFAILED = 8515, - HYPERDEX_CLIENT_OVERFLOW = 8516, - HYPERDEX_CLIENT_RECONFIGURE = 8517, - HYPERDEX_CLIENT_TIMEOUT = 8519, - HYPERDEX_CLIENT_UNKNOWNATTR = 8520, - HYPERDEX_CLIENT_DUPEATTR = 8521, - HYPERDEX_CLIENT_NONEPENDING = 8523, - HYPERDEX_CLIENT_DONTUSEKEY = 8524, - HYPERDEX_CLIENT_WRONGTYPE = 8525, - HYPERDEX_CLIENT_NOMEM = 8526, - HYPERDEX_CLIENT_BADCONFIG = 8527, - HYPERDEX_CLIENT_BADSPACE = 8528, - HYPERDEX_CLIENT_DUPLICATE = 8529, - HYPERDEX_CLIENT_INTERRUPTED = 8530, - HYPERDEX_CLIENT_CLUSTER_JUMP = 8531, - HYPERDEX_CLIENT_COORD_LOGGED = 8532, - - /* This should never happen. It indicates a bug */ - HYPERDEX_CLIENT_INTERNAL = 8573, - HYPERDEX_CLIENT_EXCEPTION = 8574, - HYPERDEX_CLIENT_GARBAGE = 8575 - }; - - public ref struct HyperClientException : public System::Exception - { - public: - HyperClientReturnCode^ return_code; - }; - - public ref class HyperClient - { - - hyperclient* _hc; - marshal_context^ mc; - - public: - HyperClient(String^ coordinator, uint16_t port); - ~HyperClient(); - - protected: - !HyperClient(); - - public: - Dictionary ^get(String ^space, String ^key); +public enum class HyperClientReturnCode +{ + HYPERDEX_CLIENT_SUCCESS = 8448, + HYPERDEX_CLIENT_NOTFOUND = 8449, + HYPERDEX_CLIENT_SEARCHDONE = 8450, + HYPERDEX_CLIENT_CMPFAIL = 8451, + HYPERDEX_CLIENT_READONLY = 8452, + + /* Error conditions */ + HYPERDEX_CLIENT_UNKNOWNSPACE = 8512, + HYPERDEX_CLIENT_COORDFAIL = 8513, + HYPERDEX_CLIENT_SERVERERROR = 8514, + HYPERDEX_CLIENT_POLLFAILED = 8515, + HYPERDEX_CLIENT_OVERFLOW = 8516, + HYPERDEX_CLIENT_RECONFIGURE = 8517, + HYPERDEX_CLIENT_TIMEOUT = 8519, + HYPERDEX_CLIENT_UNKNOWNATTR = 8520, + HYPERDEX_CLIENT_DUPEATTR = 8521, + HYPERDEX_CLIENT_NONEPENDING = 8523, + HYPERDEX_CLIENT_DONTUSEKEY = 8524, + HYPERDEX_CLIENT_WRONGTYPE = 8525, + HYPERDEX_CLIENT_NOMEM = 8526, + HYPERDEX_CLIENT_BADCONFIG = 8527, + HYPERDEX_CLIENT_BADSPACE = 8528, + HYPERDEX_CLIENT_DUPLICATE = 8529, + HYPERDEX_CLIENT_INTERRUPTED = 8530, + HYPERDEX_CLIENT_CLUSTER_JUMP = 8531, + HYPERDEX_CLIENT_COORD_LOGGED = 8532, + + /* This should never happen. It indicates a bug */ + HYPERDEX_CLIENT_INTERNAL = 8573, + HYPERDEX_CLIENT_EXCEPTION = 8574, + HYPERDEX_CLIENT_GARBAGE = 8575 +}; + +public ref struct HyperClientException : public System::Exception +{ +public: + HyperClientReturnCode ^return_code; +}; + +public ref class HyperClient +{ + + hyperclient *_hc; + marshal_context ^mc; + +public: + HyperClient(String ^coordinator, uint16_t port); + ~HyperClient(); + +protected: + !HyperClient(); + +public: + Dictionary ^get(String ^space, String ^key); #define HYPERDEX_CLIENT_CLRDEC(OPNAME) \ - bool OPNAME(String ^space, String ^key, Dictionary ^ attrs); - - HYPERDEX_CLIENT_CLRDEC(put) - HYPERDEX_CLIENT_CLRDEC(put_if_not_exist) - HYPERDEX_CLIENT_CLRDEC(atomic_add) - HYPERDEX_CLIENT_CLRDEC(atomic_sub) - HYPERDEX_CLIENT_CLRDEC(atomic_mul) - HYPERDEX_CLIENT_CLRDEC(atomic_div) - HYPERDEX_CLIENT_CLRDEC(atomic_mod) - HYPERDEX_CLIENT_CLRDEC(atomic_and) - HYPERDEX_CLIENT_CLRDEC(atomic_or) - HYPERDEX_CLIENT_CLRDEC(atomic_xor) - HYPERDEX_CLIENT_CLRDEC(string_prepend) - HYPERDEX_CLIENT_CLRDEC(string_append) - HYPERDEX_CLIENT_CLRDEC(list_lpush) - HYPERDEX_CLIENT_CLRDEC(list_rpush) - HYPERDEX_CLIENT_CLRDEC(set_add) - HYPERDEX_CLIENT_CLRDEC(set_remove) - HYPERDEX_CLIENT_CLRDEC(set_intersect) - HYPERDEX_CLIENT_CLRDEC(set_union) + bool OPNAME(String ^space, String ^key, Dictionary ^ attrs); + + HYPERDEX_CLIENT_CLRDEC(put) + HYPERDEX_CLIENT_CLRDEC(put_if_not_exist) + HYPERDEX_CLIENT_CLRDEC(atomic_add) + HYPERDEX_CLIENT_CLRDEC(atomic_sub) + HYPERDEX_CLIENT_CLRDEC(atomic_mul) + HYPERDEX_CLIENT_CLRDEC(atomic_div) + HYPERDEX_CLIENT_CLRDEC(atomic_mod) + HYPERDEX_CLIENT_CLRDEC(atomic_and) + HYPERDEX_CLIENT_CLRDEC(atomic_or) + HYPERDEX_CLIENT_CLRDEC(atomic_xor) + HYPERDEX_CLIENT_CLRDEC(string_prepend) + HYPERDEX_CLIENT_CLRDEC(string_append) + HYPERDEX_CLIENT_CLRDEC(list_lpush) + HYPERDEX_CLIENT_CLRDEC(list_rpush) + HYPERDEX_CLIENT_CLRDEC(set_add) + HYPERDEX_CLIENT_CLRDEC(set_remove) + HYPERDEX_CLIENT_CLRDEC(set_intersect) + HYPERDEX_CLIENT_CLRDEC(set_union) #define HYPERDEX_CLIENT_MAP_CLRDEC(OPNAME) \ - bool map_ ## OPNAME(String ^space, String ^key, Dictionary^ > ^ attrs); + bool map_ ## OPNAME(String ^space, String ^key, Dictionary^ > ^ attrs); - HYPERDEX_CLIENT_MAP_CLRDEC(add) - HYPERDEX_CLIENT_MAP_CLRDEC(remove) - HYPERDEX_CLIENT_MAP_CLRDEC(atomic_add) - HYPERDEX_CLIENT_MAP_CLRDEC(atomic_sub) - HYPERDEX_CLIENT_MAP_CLRDEC(atomic_mul) - HYPERDEX_CLIENT_MAP_CLRDEC(atomic_div) - HYPERDEX_CLIENT_MAP_CLRDEC(atomic_mod) - HYPERDEX_CLIENT_MAP_CLRDEC(atomic_and) - HYPERDEX_CLIENT_MAP_CLRDEC(atomic_or) - HYPERDEX_CLIENT_MAP_CLRDEC(atomic_xor) - HYPERDEX_CLIENT_MAP_CLRDEC(string_prepend) - HYPERDEX_CLIENT_MAP_CLRDEC(string_append) + HYPERDEX_CLIENT_MAP_CLRDEC(add) + HYPERDEX_CLIENT_MAP_CLRDEC(remove) + HYPERDEX_CLIENT_MAP_CLRDEC(atomic_add) + HYPERDEX_CLIENT_MAP_CLRDEC(atomic_sub) + HYPERDEX_CLIENT_MAP_CLRDEC(atomic_mul) + HYPERDEX_CLIENT_MAP_CLRDEC(atomic_div) + HYPERDEX_CLIENT_MAP_CLRDEC(atomic_mod) + HYPERDEX_CLIENT_MAP_CLRDEC(atomic_and) + HYPERDEX_CLIENT_MAP_CLRDEC(atomic_or) + HYPERDEX_CLIENT_MAP_CLRDEC(atomic_xor) + HYPERDEX_CLIENT_MAP_CLRDEC(string_prepend) + HYPERDEX_CLIENT_MAP_CLRDEC(string_append) - List^ >^ - search(String^ space, Dictionary^ checks); + List^ > ^ + search(String ^space, Dictionary ^checks); - List^ >^ - sorted_search(String^ space, String ^sortby, - UInt64 limit, bool maximize, Dictionary^ checks); + List^ > ^ + sorted_search(String ^space, String ^sortby, + UInt64 limit, bool maximize, Dictionary ^checks); - UInt64 - count(String^ space, Dictionary^ checks); + UInt64 + count(String ^space, Dictionary ^checks); - bool - del(String^ space, String^ key); - }; + bool + del(String ^space, String ^key); +}; } diff --git a/windows/ieee754.h b/windows/ieee754.h index 20ba54d88..1d1e9b89b 100644 --- a/windows/ieee754.h +++ b/windows/ieee754.h @@ -8,171 +8,171 @@ #include union ieee754_float - { - float f; +{ + float f; - /* This is the IEEE 754 single-precision format. */ - struct - { + /* This is the IEEE 754 single-precision format. */ + struct + { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:8; - unsigned int mantissa:23; + unsigned int negative: 1; + unsigned int exponent: 8; + unsigned int mantissa: 23; #endif /* Big endian. */ #if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned int mantissa:23; - unsigned int exponent:8; - unsigned int negative:1; + unsigned int mantissa: 23; + unsigned int exponent: 8; + unsigned int negative: 1; #endif /* Little endian. */ - } ieee; + } ieee; - /* This format makes it easier to see if a NaN is a signalling NaN. */ - struct - { + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct + { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:8; - unsigned int quiet_nan:1; - unsigned int mantissa:22; + unsigned int negative: 1; + unsigned int exponent: 8; + unsigned int quiet_nan: 1; + unsigned int mantissa: 22; #endif /* Big endian. */ #if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned int mantissa:22; - unsigned int quiet_nan:1; - unsigned int exponent:8; - unsigned int negative:1; + unsigned int mantissa: 22; + unsigned int quiet_nan: 1; + unsigned int exponent: 8; + unsigned int negative: 1; #endif /* Little endian. */ - } ieee_nan; - }; + } ieee_nan; +}; #define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */ union ieee754_double - { - double d; +{ + double d; - /* This is the IEEE 754 double-precision format. */ - struct - { + /* This is the IEEE 754 double-precision format. */ + struct + { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:11; - /* Together these comprise the mantissa. */ - unsigned int mantissa0:20; - unsigned int mantissa1:32; + unsigned int negative: 1; + unsigned int exponent: 11; + /* Together these comprise the mantissa. */ + unsigned int mantissa0: 20; + unsigned int mantissa1: 32; #endif /* Big endian. */ #if __BYTE_ORDER == __LITTLE_ENDIAN # if __FLOAT_WORD_ORDER == BIG_ENDIAN - unsigned int mantissa0:20; - unsigned int exponent:11; - unsigned int negative:1; - unsigned int mantissa1:32; + unsigned int mantissa0: 20; + unsigned int exponent: 11; + unsigned int negative: 1; + unsigned int mantissa1: 32; # else - /* Together these comprise the mantissa. */ - unsigned int mantissa1:32; - unsigned int mantissa0:20; - unsigned int exponent:11; - unsigned int negative:1; + /* Together these comprise the mantissa. */ + unsigned int mantissa1: 32; + unsigned int mantissa0: 20; + unsigned int exponent: 11; + unsigned int negative: 1; # endif #endif /* Little endian. */ - } ieee; + } ieee; - /* This format makes it easier to see if a NaN is a signalling NaN. */ - struct - { + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct + { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:11; - unsigned int quiet_nan:1; - /* Together these comprise the mantissa. */ - unsigned int mantissa0:19; - unsigned int mantissa1:32; + unsigned int negative: 1; + unsigned int exponent: 11; + unsigned int quiet_nan: 1; + /* Together these comprise the mantissa. */ + unsigned int mantissa0: 19; + unsigned int mantissa1: 32; #else # if __FLOAT_WORD_ORDER == BIG_ENDIAN - unsigned int mantissa0:19; - unsigned int quiet_nan:1; - unsigned int exponent:11; - unsigned int negative:1; - unsigned int mantissa1:32; + unsigned int mantissa0: 19; + unsigned int quiet_nan: 1; + unsigned int exponent: 11; + unsigned int negative: 1; + unsigned int mantissa1: 32; # else - /* Together these comprise the mantissa. */ - unsigned int mantissa1:32; - unsigned int mantissa0:19; - unsigned int quiet_nan:1; - unsigned int exponent:11; - unsigned int negative:1; + /* Together these comprise the mantissa. */ + unsigned int mantissa1: 32; + unsigned int mantissa0: 19; + unsigned int quiet_nan: 1; + unsigned int exponent: 11; + unsigned int negative: 1; # endif #endif - } ieee_nan; - }; + } ieee_nan; +}; #define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */ union ieee854_long_double - { - long double d; +{ + long double d; - /* This is the IEEE 854 double-extended-precision format. */ - struct - { + /* This is the IEEE 854 double-extended-precision format. */ + struct + { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:15; - unsigned int empty:16; - unsigned int mantissa0:32; - unsigned int mantissa1:32; + unsigned int negative: 1; + unsigned int exponent: 15; + unsigned int empty: 16; + unsigned int mantissa0: 32; + unsigned int mantissa1: 32; #endif #if __BYTE_ORDER == __LITTLE_ENDIAN # if __FLOAT_WORD_ORDER == BIG_ENDIAN - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; - unsigned int mantissa0:32; - unsigned int mantissa1:32; + unsigned int exponent: 15; + unsigned int negative: 1; + unsigned int empty: 16; + unsigned int mantissa0: 32; + unsigned int mantissa1: 32; # else - unsigned int mantissa1:32; - unsigned int mantissa0:32; - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; + unsigned int mantissa1: 32; + unsigned int mantissa0: 32; + unsigned int exponent: 15; + unsigned int negative: 1; + unsigned int empty: 16; # endif #endif - } ieee; + } ieee; - /* This is for NaNs in the IEEE 854 double-extended-precision format. */ - struct - { + /* This is for NaNs in the IEEE 854 double-extended-precision format. */ + struct + { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:15; - unsigned int empty:16; - unsigned int one:1; - unsigned int quiet_nan:1; - unsigned int mantissa0:30; - unsigned int mantissa1:32; + unsigned int negative: 1; + unsigned int exponent: 15; + unsigned int empty: 16; + unsigned int one: 1; + unsigned int quiet_nan: 1; + unsigned int mantissa0: 30; + unsigned int mantissa1: 32; #endif #if __BYTE_ORDER == __LITTLE_ENDIAN # if __FLOAT_WORD_ORDER == BIG_ENDIAN - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; - unsigned int mantissa0:30; - unsigned int quiet_nan:1; - unsigned int one:1; - unsigned int mantissa1:32; + unsigned int exponent: 15; + unsigned int negative: 1; + unsigned int empty: 16; + unsigned int mantissa0: 30; + unsigned int quiet_nan: 1; + unsigned int one: 1; + unsigned int mantissa1: 32; # else - unsigned int mantissa1:32; - unsigned int mantissa0:30; - unsigned int quiet_nan:1; - unsigned int one:1; - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; + unsigned int mantissa1: 32; + unsigned int mantissa0: 30; + unsigned int quiet_nan: 1; + unsigned int one: 1; + unsigned int exponent: 15; + unsigned int negative: 1; + unsigned int empty: 16; # endif #endif - } ieee_nan; - }; + } ieee_nan; +}; #define IEEE854_LONG_DOUBLE_BIAS 0x3fff diff --git a/windows/marshal.cpp b/windows/marshal.cpp index 234f6e25c..5895d2341 100644 --- a/windows/marshal.cpp +++ b/windows/marshal.cpp @@ -15,443 +15,405 @@ using namespace cliext; using namespace System::Collections::Generic; #define THROW_EXCEPTION(x) \ - do{ \ - HyperClientException^ ex = gcnew HyperClientException(); \ - ex->return_code = static_cast(x); \ - throw ex; \ - } while (0) + do{ \ + HyperClientException^ ex = gcnew HyperClientException(); \ + ex->return_code = static_cast(x); \ + throw ex; \ + } while (0) -msclr::interop::context_node::context_node(const char*& toObject, Double ^fromObject) +msclr::interop::context_node::context_node(const char *&toObject, Double ^fromObject) { - toPtr = NULL; - toPtr = (const char*)(new double(*fromObject)); - toObject = toPtr; + toPtr = NULL; + toPtr = (const char *)(new double(*fromObject)); + toObject = toPtr; } -msclr::interop::context_node::~context_node() +msclr::interop::context_node::~context_node() { - this->!context_node(); + this->!context_node(); } -msclr::interop::context_node::!context_node() +msclr::interop::context_node::!context_node() { - if (toPtr != NULL) { - delete toPtr; - toPtr = NULL; - } + if (toPtr != NULL) + { + delete toPtr; + toPtr = NULL; + } } -msclr::interop::context_node::context_node(const char*& toObject, Int64 ^fromObject) +msclr::interop::context_node::context_node(const char *&toObject, Int64 ^fromObject) { - toPtr = NULL; - toPtr = (const char*)(new int64_t(*fromObject)); - toObject = toPtr; + toPtr = NULL; + toPtr = (const char *)(new int64_t(*fromObject)); + toObject = toPtr; } -msclr::interop::context_node::~context_node() +msclr::interop::context_node::~context_node() { - this->!context_node(); + this->!context_node(); } -msclr::interop::context_node::!context_node() +msclr::interop::context_node::!context_node() { - if (toPtr != NULL) { - delete toPtr; - toPtr = NULL; - } + if (toPtr != NULL) + { + delete toPtr; + toPtr = NULL; + } } -msclr::interop::context_node^ >::context_node(hyperclient_attribute*& toObject, Dictionary^ fromObject) +msclr::interop::context_node^ >::context_node(hyperclient_attribute *&toObject, Dictionary ^fromObject) { - size = fromObject->Count; - - toPtr = new hyperclient_attribute[size](); - - int i = 0; - for each(KeyValuePair kvp in fromObject) - { - if(kvp.Value->GetType() == String::typeid) - { - toPtr[i].value = context.marshal_as((String ^)kvp.Value); - toPtr[i].attr = context.marshal_as((String ^)kvp.Key); - toPtr[i].datatype = HYPERDATATYPE_STRING; - toPtr[i].value_sz = strlen(toPtr[i].value); - } - else if(kvp.Value->GetType() == Int64::typeid) - { - toPtr[i].value = context.marshal_as((Int64 ^)kvp.Value); - toPtr[i].attr = context.marshal_as((String ^)kvp.Key); - toPtr[i].datatype = HYPERDATATYPE_INT64; - toPtr[i].value_sz = sizeof(int64_t); - } - else if(kvp.Value->GetType() == Double::typeid) - { - toPtr[i].value = context.marshal_as((Double^)kvp.Value); - toPtr[i].attr = context.marshal_as((String ^)kvp.Key); - toPtr[i].datatype = HYPERDATATYPE_FLOAT; - toPtr[i].value_sz = sizeof(double); - } - else if (kvp.Value->GetType()->IsGenericType - && kvp.Value->GetType()->GetGenericTypeDefinition() == List::typeid) - { - if(kvp.Value->GetType()->GetGenericArguments()[0] == String::typeid) - { - toPtr[i].datatype = HYPERDATATYPE_LIST_STRING; - toPtr[i].attr = context.marshal_as((String^)kvp.Key); - - for each(String ^ s in (List^)kvp.Value) - { - const char* str = context.marshal_as(s); - uint32_t len = s->Length; - char * val = (char*)malloc(len + sizeof(uint32_t)); - - memcpy(val,&len,sizeof(uint32_t)); - memcpy(val + sizeof(uint32_t), str, len); - toPtr[i].value = val; - - toPtr[i].value_sz = len + sizeof(uint32_t); - } - } - else if(kvp.Value->GetType()->GetGenericArguments()[0] == Int64::typeid) - { - toPtr[i].datatype = HYPERDATATYPE_LIST_INT64; - toPtr[i].attr = context.marshal_as((String^)kvp.Key); - - uint32_t len = ((List^)kvp.Value)->Count * 8; - - char * val = (char*)malloc(len); - - for each(Int64 s in (List^)kvp.Value) - { - int64_t str = s; - memcpy(val, &str, sizeof(int64_t)); - val += sizeof(int64_t); - } - - toPtr[i].value = val - len; - toPtr[i].value_sz = len; - } - else if(kvp.Value->GetType()->GetGenericArguments()[0] == Double::typeid) - { - toPtr[i].datatype = HYPERDATATYPE_LIST_FLOAT; - toPtr[i].attr = context.marshal_as((String^)kvp.Key); - - uint32_t len = ((List^)kvp.Value)->Count * 8; - - char * val = (char*)malloc(len); - - for each(Double s in (List^)kvp.Value) - { - double str = s; - memcpy(val, &str, sizeof(double)); - val += sizeof(double); - } - - toPtr[i].value = val - len; - toPtr[i].value_sz = len; - } - } - else if (kvp.Value->GetType()->IsGenericType - && kvp.Value->GetType()->GetGenericTypeDefinition() == SortedSet::typeid) - { - if(kvp.Value->GetType()->GetGenericArguments()[0] == String::typeid) - { - toPtr[i].datatype = HYPERDATATYPE_SET_STRING; - toPtr[i].attr = context.marshal_as((String^)kvp.Key); - - uint32_t len = 0; - for each(String ^ s in (SortedSet^)kvp.Value) - { - len += sizeof(uint32_t) + s->Length; - } - - char * val = (char*)malloc(len); - - for each(String ^ s in (SortedSet^)kvp.Value) - { - const char* str = context.marshal_as(s); - uint32_t sz = s->Length; - - memcpy(val,&sz,sizeof(uint32_t)); - val += sizeof(uint32_t); - - memcpy(val, str, sz); - val += sz; - } - - toPtr[i].value = val - len; - toPtr[i].value_sz = len; - } - else if(kvp.Value->GetType()->GetGenericArguments()[0] == Int64::typeid) - { - toPtr[i].datatype = HYPERDATATYPE_SET_INT64; - toPtr[i].attr = context.marshal_as((String^)kvp.Key); - - uint32_t len = ((SortedSet^)kvp.Value)->Count * 8; - - char * val = (char*)malloc(len); - - for each(Int64 s in (SortedSet^)kvp.Value) - { - int64_t str = s; - memcpy(val, &str, sizeof(int64_t)); - val += sizeof(int64_t); - } - - toPtr[i].value = val - len; - toPtr[i].value_sz = len; - } - else if(kvp.Value->GetType()->GetGenericArguments()[0] == Double::typeid) - { - toPtr[i].datatype = HYPERDATATYPE_SET_FLOAT; - toPtr[i].attr = context.marshal_as((String^)kvp.Key); - - uint32_t len = ((SortedSet^)kvp.Value)->Count * 8; - - char * val = (char*)malloc(len); - - for each(Double s in (SortedSet^)kvp.Value) - { - double str = s; - memcpy(val, &str, sizeof(double)); - val += sizeof(double); - } - - toPtr[i].value = val - len; - toPtr[i].value_sz = len; - } - } - else - { - delete[] toPtr; - THROW_EXCEPTION(HYPERCLIENT_WRONGTYPE); - } - - ++i; - } - - toObject = toPtr; + size = fromObject->Count; + toPtr = new hyperclient_attribute[size](); + int i = 0; + for each(KeyValuePair kvp in fromObject) + { + if (kvp.Value->GetType() == String::typeid) + { + toPtr[i].value = context.marshal_as((String ^)kvp.Value); + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + toPtr[i].datatype = HYPERDATATYPE_STRING; + toPtr[i].value_sz = strlen(toPtr[i].value); + } + else if (kvp.Value->GetType() == Int64::typeid) + { + toPtr[i].value = context.marshal_as((Int64 ^)kvp.Value); + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + toPtr[i].datatype = HYPERDATATYPE_INT64; + toPtr[i].value_sz = sizeof(int64_t); + } + else if (kvp.Value->GetType() == Double::typeid) + { + toPtr[i].value = context.marshal_as((Double ^)kvp.Value); + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + toPtr[i].datatype = HYPERDATATYPE_FLOAT; + toPtr[i].value_sz = sizeof(double); + } + else if (kvp.Value->GetType()->IsGenericType + && kvp.Value->GetType()->GetGenericTypeDefinition() == List::typeid) + { + if (kvp.Value->GetType()->GetGenericArguments()[0] == String::typeid) + { + toPtr[i].datatype = HYPERDATATYPE_LIST_STRING; + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + for each(String ^ s in (List ^)kvp.Value) + { + const char *str = context.marshal_as(s); + uint32_t len = s->Length; + char *val = (char *)malloc(len + sizeof(uint32_t)); + memcpy(val, &len, sizeof(uint32_t)); + memcpy(val + sizeof(uint32_t), str, len); + toPtr[i].value = val; + toPtr[i].value_sz = len + sizeof(uint32_t); + } + } + else if (kvp.Value->GetType()->GetGenericArguments()[0] == Int64::typeid) + { + toPtr[i].datatype = HYPERDATATYPE_LIST_INT64; + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + uint32_t len = ((List ^)kvp.Value)->Count * 8; + char *val = (char *)malloc(len); + for each(Int64 s in (List ^)kvp.Value) + { + int64_t str = s; + memcpy(val, &str, sizeof(int64_t)); + val += sizeof(int64_t); + } + toPtr[i].value = val - len; + toPtr[i].value_sz = len; + } + else if (kvp.Value->GetType()->GetGenericArguments()[0] == Double::typeid) + { + toPtr[i].datatype = HYPERDATATYPE_LIST_FLOAT; + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + uint32_t len = ((List ^)kvp.Value)->Count * 8; + char *val = (char *)malloc(len); + for each(Double s in (List ^)kvp.Value) + { + double str = s; + memcpy(val, &str, sizeof(double)); + val += sizeof(double); + } + toPtr[i].value = val - len; + toPtr[i].value_sz = len; + } + } + else if (kvp.Value->GetType()->IsGenericType + && kvp.Value->GetType()->GetGenericTypeDefinition() == SortedSet::typeid) + { + if (kvp.Value->GetType()->GetGenericArguments()[0] == String::typeid) + { + toPtr[i].datatype = HYPERDATATYPE_SET_STRING; + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + uint32_t len = 0; + for each(String ^ s in (SortedSet ^)kvp.Value) + { + len += sizeof(uint32_t) + s->Length; + } + char *val = (char *)malloc(len); + for each(String ^ s in (SortedSet ^)kvp.Value) + { + const char *str = context.marshal_as(s); + uint32_t sz = s->Length; + memcpy(val, &sz, sizeof(uint32_t)); + val += sizeof(uint32_t); + memcpy(val, str, sz); + val += sz; + } + toPtr[i].value = val - len; + toPtr[i].value_sz = len; + } + else if (kvp.Value->GetType()->GetGenericArguments()[0] == Int64::typeid) + { + toPtr[i].datatype = HYPERDATATYPE_SET_INT64; + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + uint32_t len = ((SortedSet ^)kvp.Value)->Count * 8; + char *val = (char *)malloc(len); + for each(Int64 s in (SortedSet ^)kvp.Value) + { + int64_t str = s; + memcpy(val, &str, sizeof(int64_t)); + val += sizeof(int64_t); + } + toPtr[i].value = val - len; + toPtr[i].value_sz = len; + } + else if (kvp.Value->GetType()->GetGenericArguments()[0] == Double::typeid) + { + toPtr[i].datatype = HYPERDATATYPE_SET_FLOAT; + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + uint32_t len = ((SortedSet ^)kvp.Value)->Count * 8; + char *val = (char *)malloc(len); + for each(Double s in (SortedSet ^)kvp.Value) + { + double str = s; + memcpy(val, &str, sizeof(double)); + val += sizeof(double); + } + toPtr[i].value = val - len; + toPtr[i].value_sz = len; + } + } + else + { + delete[] toPtr; + THROW_EXCEPTION(HYPERCLIENT_WRONGTYPE); + } + ++i; + } + toObject = toPtr; } -msclr::interop::context_node^ >::~context_node() +msclr::interop::context_node^ >::~context_node() { - this->!context_node(); + this->!context_node(); } -msclr::interop::context_node^ >::!context_node() +msclr::interop::context_node^ >::!context_node() { - if (toPtr != NULL) { - delete toPtr; - toPtr = NULL; - } + if (toPtr != NULL) + { + delete toPtr; + toPtr = NULL; + } } -msclr::interop::context_node^>^ >::context_node(hyperclient_map_attribute*& toObject, Dictionary^>^ fromObject) +msclr::interop::context_node^>^ >::context_node(hyperclient_map_attribute *&toObject, Dictionary^> ^fromObject) { - size = 0; - for each(KeyValuePair^ > attrkvp in fromObject) - { - size += attrkvp.Value->Count; - } - - - toPtr = new hyperclient_map_attribute[size](); - - int i = 0; - for each(KeyValuePair^ > attrkvp in fromObject) - { - /* Map Attribute */ - const char* name = context.marshal_as((String ^)attrkvp.Key); - - /* Map Keys */ - for each(KeyValuePair kvp in attrkvp.Value) - { - toPtr[i].attr = name; - - if(kvp.Value->GetType() == String::typeid) - { - toPtr[i].value = context.marshal_as((String ^)kvp.Value); - toPtr[i].value_datatype = HYPERDATATYPE_STRING; - toPtr[i].value_sz = strlen(toPtr[i].value); - } - else if(kvp.Value->GetType() == Int64::typeid) - { - toPtr[i].value = context.marshal_as((Int64 ^)kvp.Value); - toPtr[i].value_datatype = HYPERDATATYPE_INT64; - toPtr[i].value_sz = sizeof(int64_t); - } - else if(kvp.Value->GetType() == Double::typeid) - { - toPtr[i].value = context.marshal_as((Double^)kvp.Value); - toPtr[i].value_datatype = HYPERDATATYPE_FLOAT; - toPtr[i].value_sz = sizeof(double); - } - else - { - delete[] toPtr; - THROW_EXCEPTION(HYPERCLIENT_WRONGTYPE); - } - - /* Map Value */ - if(kvp.Key->GetType() == String::typeid) - { - toPtr[i].map_key = context.marshal_as((String ^)kvp.Key); - toPtr[i].map_key_datatype = HYPERDATATYPE_STRING; - toPtr[i].map_key_sz = strlen(toPtr[i].map_key); - } - else if(kvp.Key->GetType() == Int64::typeid) - { - toPtr[i].map_key = context.marshal_as((Int64 ^)kvp.Key); - toPtr[i].map_key_datatype = HYPERDATATYPE_INT64; - toPtr[i].map_key_sz = sizeof(int64_t); - } - else if(kvp.Key->GetType() == Double::typeid) - { - toPtr[i].map_key = context.marshal_as((Double ^)kvp.Key); - toPtr[i].map_key_datatype = HYPERDATATYPE_FLOAT; - toPtr[i].map_key_sz = sizeof(double); - } - else - { - delete[] toPtr; - THROW_EXCEPTION(HYPERCLIENT_WRONGTYPE); - } - - ++i; - } - - ++i; - } - - toObject = toPtr; + size = 0; + for each(KeyValuePair^ > attrkvp in fromObject) + { + size += attrkvp.Value->Count; + } + toPtr = new hyperclient_map_attribute[size](); + int i = 0; + for each(KeyValuePair^ > attrkvp in fromObject) + { + /* Map Attribute */ + const char *name = context.marshal_as((String ^)attrkvp.Key); + /* Map Keys */ + for each(KeyValuePair kvp in attrkvp.Value) + { + toPtr[i].attr = name; + if (kvp.Value->GetType() == String::typeid) + { + toPtr[i].value = context.marshal_as((String ^)kvp.Value); + toPtr[i].value_datatype = HYPERDATATYPE_STRING; + toPtr[i].value_sz = strlen(toPtr[i].value); + } + else if (kvp.Value->GetType() == Int64::typeid) + { + toPtr[i].value = context.marshal_as((Int64 ^)kvp.Value); + toPtr[i].value_datatype = HYPERDATATYPE_INT64; + toPtr[i].value_sz = sizeof(int64_t); + } + else if (kvp.Value->GetType() == Double::typeid) + { + toPtr[i].value = context.marshal_as((Double ^)kvp.Value); + toPtr[i].value_datatype = HYPERDATATYPE_FLOAT; + toPtr[i].value_sz = sizeof(double); + } + else + { + delete[] toPtr; + THROW_EXCEPTION(HYPERCLIENT_WRONGTYPE); + } + /* Map Value */ + if (kvp.Key->GetType() == String::typeid) + { + toPtr[i].map_key = context.marshal_as((String ^)kvp.Key); + toPtr[i].map_key_datatype = HYPERDATATYPE_STRING; + toPtr[i].map_key_sz = strlen(toPtr[i].map_key); + } + else if (kvp.Key->GetType() == Int64::typeid) + { + toPtr[i].map_key = context.marshal_as((Int64 ^)kvp.Key); + toPtr[i].map_key_datatype = HYPERDATATYPE_INT64; + toPtr[i].map_key_sz = sizeof(int64_t); + } + else if (kvp.Key->GetType() == Double::typeid) + { + toPtr[i].map_key = context.marshal_as((Double ^)kvp.Key); + toPtr[i].map_key_datatype = HYPERDATATYPE_FLOAT; + toPtr[i].map_key_sz = sizeof(double); + } + else + { + delete[] toPtr; + THROW_EXCEPTION(HYPERCLIENT_WRONGTYPE); + } + ++i; + } + ++i; + } + toObject = toPtr; } -msclr::interop::context_node^ >^ >::~context_node() +msclr::interop::context_node^ >^ >::~context_node() { - this->!context_node(); + this->!context_node(); } -msclr::interop::context_node^ >^ >::!context_node() +msclr::interop::context_node^ >^ >::!context_node() { - if (toPtr != NULL) { - delete toPtr; - toPtr = NULL; - } + if (toPtr != NULL) + { + delete toPtr; + toPtr = NULL; + } } -msclr::interop::context_node^ >::context_node(hyperclient_attribute_check*& toObject, Dictionary^ fromObject) +msclr::interop::context_node^ >::context_node(hyperclient_attribute_check *&toObject, Dictionary ^fromObject) { - //Waste a bit of memory but we don't have to cycle the dictionary twice to find out - //how many of the checks are pairs. - size = fromObject->Count * 2; - - toPtr = new hyperclient_attribute_check[size](); - - int i = 0; - for each(KeyValuePair kvp in fromObject) - { - if(kvp.Value->GetType() == String::typeid) - { - toPtr[i].value = context.marshal_as((String ^)kvp.Value); - toPtr[i].attr = context.marshal_as((String ^)kvp.Key); - toPtr[i].datatype = HYPERDATATYPE_STRING; - toPtr[i].value_sz = strlen(toPtr[i].value); - toPtr[i].predicate = HYPERPREDICATE_EQUALS; - } - else if(kvp.Value->GetType() == Int64::typeid) - { - toPtr[i].value = context.marshal_as((Int64 ^)kvp.Value); - toPtr[i].attr = context.marshal_as((String ^)kvp.Key); - toPtr[i].datatype = HYPERDATATYPE_INT64; - toPtr[i].value_sz = sizeof(int64_t); - toPtr[i].predicate = HYPERPREDICATE_EQUALS; - } - else if(kvp.Value->GetType() == Double::typeid) - { - toPtr[i].value = context.marshal_as((Double^)kvp.Value); - toPtr[i].attr = context.marshal_as((String ^)kvp.Key); - toPtr[i].datatype = HYPERDATATYPE_FLOAT; - toPtr[i].value_sz = sizeof(double); - toPtr[i].predicate = HYPERPREDICATE_EQUALS; - } - else if (kvp.Value->GetType()->IsGenericType - && kvp.Value->GetType()->GetGenericTypeDefinition() == KeyValuePair::typeid) - { - int j = i; - do - { - if(kvp.Value->GetType() == String::typeid) - { - toPtr[i].value = context.marshal_as((String ^)kvp.Value); - toPtr[i].attr = context.marshal_as((String ^)kvp.Key); - toPtr[i].datatype = HYPERDATATYPE_STRING; - toPtr[i].value_sz = strlen(toPtr[i].value); - if(j == i) - { - /* First argument is always the lower bound. */ - toPtr[i].predicate = HYPERPREDICATE_GREATER_EQUAL; - } - else - { - /* Second argument is always the lower bound. */ - toPtr[i].predicate = HYPERPREDICATE_LESS_EQUAL; - } - } - else if(kvp.Value->GetType() == Int64::typeid) - { - toPtr[i].value = context.marshal_as((Int64 ^)kvp.Value); - toPtr[i].attr = context.marshal_as((String ^)kvp.Key); - toPtr[i].datatype = HYPERDATATYPE_INT64; - toPtr[i].value_sz = sizeof(int64_t); - if(j == i) - { - toPtr[i].predicate = HYPERPREDICATE_GREATER_EQUAL; - } - else - { - toPtr[i].predicate = HYPERPREDICATE_LESS_EQUAL; - } - } - else if(kvp.Value->GetType() == Double::typeid) - { - toPtr[i].value = context.marshal_as((Double^)kvp.Value); - toPtr[i].attr = context.marshal_as((String ^)kvp.Key); - toPtr[i].datatype = HYPERDATATYPE_FLOAT; - toPtr[i].value_sz = sizeof(double); - if(j == i) - { - toPtr[i].predicate = HYPERPREDICATE_GREATER_EQUAL; - } - else - { - toPtr[i].predicate = HYPERPREDICATE_LESS_EQUAL; - } - } - else - { - delete[] toPtr; - THROW_EXCEPTION(HYPERCLIENT_WRONGTYPE); - } - } - while(i < j + 1 && ++i); - } - - else - { - delete[] toPtr; - THROW_EXCEPTION(HYPERCLIENT_WRONGTYPE); - } - - ++i; - } - - toObject = toPtr; + //Waste a bit of memory but we don't have to cycle the dictionary twice to find out + //how many of the checks are pairs. + size = fromObject->Count * 2; + toPtr = new hyperclient_attribute_check[size](); + int i = 0; + for each(KeyValuePair kvp in fromObject) + { + if (kvp.Value->GetType() == String::typeid) + { + toPtr[i].value = context.marshal_as((String ^)kvp.Value); + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + toPtr[i].datatype = HYPERDATATYPE_STRING; + toPtr[i].value_sz = strlen(toPtr[i].value); + toPtr[i].predicate = HYPERPREDICATE_EQUALS; + } + else if (kvp.Value->GetType() == Int64::typeid) + { + toPtr[i].value = context.marshal_as((Int64 ^)kvp.Value); + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + toPtr[i].datatype = HYPERDATATYPE_INT64; + toPtr[i].value_sz = sizeof(int64_t); + toPtr[i].predicate = HYPERPREDICATE_EQUALS; + } + else if (kvp.Value->GetType() == Double::typeid) + { + toPtr[i].value = context.marshal_as((Double ^)kvp.Value); + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + toPtr[i].datatype = HYPERDATATYPE_FLOAT; + toPtr[i].value_sz = sizeof(double); + toPtr[i].predicate = HYPERPREDICATE_EQUALS; + } + else if (kvp.Value->GetType()->IsGenericType + && kvp.Value->GetType()->GetGenericTypeDefinition() == KeyValuePair::typeid) + { + int j = i; + do + { + if (kvp.Value->GetType() == String::typeid) + { + toPtr[i].value = context.marshal_as((String ^)kvp.Value); + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + toPtr[i].datatype = HYPERDATATYPE_STRING; + toPtr[i].value_sz = strlen(toPtr[i].value); + if (j == i) + { + /* First argument is always the lower bound. */ + toPtr[i].predicate = HYPERPREDICATE_GREATER_EQUAL; + } + else + { + /* Second argument is always the lower bound. */ + toPtr[i].predicate = HYPERPREDICATE_LESS_EQUAL; + } + } + else if (kvp.Value->GetType() == Int64::typeid) + { + toPtr[i].value = context.marshal_as((Int64 ^)kvp.Value); + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + toPtr[i].datatype = HYPERDATATYPE_INT64; + toPtr[i].value_sz = sizeof(int64_t); + if (j == i) + { + toPtr[i].predicate = HYPERPREDICATE_GREATER_EQUAL; + } + else + { + toPtr[i].predicate = HYPERPREDICATE_LESS_EQUAL; + } + } + else if (kvp.Value->GetType() == Double::typeid) + { + toPtr[i].value = context.marshal_as((Double ^)kvp.Value); + toPtr[i].attr = context.marshal_as((String ^)kvp.Key); + toPtr[i].datatype = HYPERDATATYPE_FLOAT; + toPtr[i].value_sz = sizeof(double); + if (j == i) + { + toPtr[i].predicate = HYPERPREDICATE_GREATER_EQUAL; + } + else + { + toPtr[i].predicate = HYPERPREDICATE_LESS_EQUAL; + } + } + else + { + delete[] toPtr; + THROW_EXCEPTION(HYPERCLIENT_WRONGTYPE); + } + } + while (i < j + 1 && ++i); + } + else + { + delete[] toPtr; + THROW_EXCEPTION(HYPERCLIENT_WRONGTYPE); + } + ++i; + } + toObject = toPtr; } -msclr::interop::context_node^ >::~context_node() +msclr::interop::context_node^ >::~context_node() { - this->!context_node(); + this->!context_node(); } -msclr::interop::context_node^ >::!context_node() +msclr::interop::context_node^ >::!context_node() { - if (toPtr != NULL) { - delete toPtr; - toPtr = NULL; - } + if (toPtr != NULL) + { + delete toPtr; + toPtr = NULL; + } } diff --git a/windows/marshal.h b/windows/marshal.h index 939b0c501..3f7c2cb39 100644 --- a/windows/marshal.h +++ b/windows/marshal.h @@ -14,85 +14,87 @@ using namespace cliext; using namespace System::Collections::Generic; #define THROW_EXCEPTION(x) \ - do{ \ - HyperClientException^ ex = gcnew HyperClientException(); \ - ex->return_code = static_cast(x); \ - throw ex; \ - } while (0) + do{ \ + HyperClientException^ ex = gcnew HyperClientException(); \ + ex->return_code = static_cast(x); \ + throw ex; \ + } while (0) -namespace msclr { - namespace interop { - template<> - ref class context_node : public context_node_base - { - private: - const char* toPtr; - marshal_context context; +namespace msclr +{ +namespace interop +{ +template<> +ref class context_node : public context_node_base +{ +private: + const char *toPtr; + marshal_context context; - public: - context_node(const char*& toObject, Double ^fromObject); - ~context_node(); +public: + context_node(const char *&toObject, Double ^fromObject); + ~context_node(); - protected: - !context_node(); - }; +protected: + !context_node(); +}; - template<> - ref class context_node : public context_node_base - { - private: - const char* toPtr; - marshal_context context; +template<> +ref class context_node : public context_node_base +{ +private: + const char *toPtr; + marshal_context context; - public: - context_node(const char*& toObject, Int64 ^fromObject); - ~context_node(); +public: + context_node(const char *&toObject, Int64 ^fromObject); + ~context_node(); - protected: - !context_node(); - }; +protected: + !context_node(); +}; - template<> - ref class context_node^ > : public context_node_base - { - private: - hyperclient_attribute* toPtr; - int size; - marshal_context context; - public: - context_node(hyperclient_attribute*& toObject, Dictionary^ fromObject); - ~context_node(); - protected: - !context_node(); - }; +template<> +ref class context_node^ > : public context_node_base +{ +private: + hyperclient_attribute *toPtr; + int size; + marshal_context context; +public: + context_node(hyperclient_attribute *&toObject, Dictionary ^fromObject); + ~context_node(); +protected: + !context_node(); +}; - template<> - ref class context_node^ >^ > : public context_node_base - { - private: - hyperclient_map_attribute* toPtr; - int size; - marshal_context context; - public: - context_node(hyperclient_map_attribute*& toObject,Dictionary^ >^ fromObject); - ~context_node(); - protected: - !context_node(); - }; +template<> +ref class context_node^ >^ > : public context_node_base +{ +private: + hyperclient_map_attribute *toPtr; + int size; + marshal_context context; +public: + context_node(hyperclient_map_attribute *&toObject, Dictionary^ > ^fromObject); + ~context_node(); +protected: + !context_node(); +}; - template<> - ref class context_node^ > : public context_node_base - { - private: - hyperclient_attribute_check* toPtr; - int size; - marshal_context context; - public: - context_node(hyperclient_attribute_check*& toObject, Dictionary^ fromObject); - ~context_node(); - protected: - !context_node(); - }; - } +template<> +ref class context_node^ > : public context_node_base +{ +private: + hyperclient_attribute_check *toPtr; + int size; + marshal_context context; +public: + context_node(hyperclient_attribute_check *&toObject, Dictionary ^fromObject); + ~context_node(); +protected: + !context_node(); +}; +} } diff --git a/windows/unistd.h b/windows/unistd.h index 651758a39..908b5f60f 100644 --- a/windows/unistd.h +++ b/windows/unistd.h @@ -1,6 +1,6 @@ -#ifdef _MSC_VER -# include -# include -#else -# include -#endif +#ifdef _MSC_VER +# include +# include +#else +# include +#endif From 0b573bbaafa7a453a008306db1e03231a9d75cf3 Mon Sep 17 00:00:00 2001 From: cnangel Date: Thu, 14 Apr 2016 13:11:05 +0800 Subject: [PATCH 6/6] add example --- client/pending_sorted_search.h | 1 - example/a.cpp | 62 +++++++++++++++ example/b.cpp | 63 +++++++++++++++ example/c.cpp | 138 +++++++++++++++++++++++++++++++++ example/d.cpp | 46 +++++++++++ example/e.cpp | 53 +++++++++++++ example/f.cpp | 94 ++++++++++++++++++++++ example/g.cpp | 96 +++++++++++++++++++++++ example/s.cpp | 110 ++++++++++++++++++++++++++ example/sum.cpp | 69 +++++++++++++++++ 10 files changed, 731 insertions(+), 1 deletion(-) create mode 100644 example/a.cpp create mode 100644 example/b.cpp create mode 100644 example/c.cpp create mode 100644 example/d.cpp create mode 100644 example/e.cpp create mode 100644 example/f.cpp create mode 100644 example/g.cpp create mode 100644 example/s.cpp create mode 100644 example/sum.cpp diff --git a/client/pending_sorted_search.h b/client/pending_sorted_search.h index 5431cda94..84c6a9140 100644 --- a/client/pending_sorted_search.h +++ b/client/pending_sorted_search.h @@ -111,7 +111,6 @@ class sorted_search_comparator uint16_t m_sort_by_idx; datatype_info *m_sort_by_di; }; - class pending_sorted_search :: item { public: diff --git a/example/a.cpp b/example/a.cpp new file mode 100644 index 000000000..5003e9c35 --- /dev/null +++ b/example/a.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace hyperdex; + +static const char rcsid[] = "$Id: " __FILE__ ",v 1.0.0-0 " __DATE__ " " __TIME__ " Cnangel Exp $"; + +int +main(int argc, const char *argv[]) +{ + //std::string description; + const char *host = "127.0.0.1"; + uint16_t port = 1982; + stringstream ss; + ss << "space phonebook1 key username attributes first, last, int phone subspace first, last, phone create 8 partitions tolerate 2 failures"; + try + { + Admin h(host, port); + hyperdex_admin_returncode rrc; + //const char *description = ss.str().c_str(); + string sa = ss.str(); + const char *description = sa.c_str(); + cout << description << endl; + int64_t rid = h.add_space(description, &rrc); + if (rid < 0) + { + std::cerr << "could not add space1: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + cout << "-------------------" << endl; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not add space2: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not add space3: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } +} diff --git a/example/b.cpp b/example/b.cpp new file mode 100644 index 000000000..5b333882a --- /dev/null +++ b/example/b.cpp @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace hyperdex; + +static const char rcsid[] = "$Id: " __FILE__ ",v 1.0.0-0 " __DATE__ " " __TIME__ " Cnangel Exp $"; + +int main(int c, char *v[]) +{ + const char *host = "127.0.0.1"; + uint16_t port = 1982; + try + { + Admin h(host, port); + hyperdex_admin_returncode rrc; + const char *spaces; + int64_t rid = h.list_spaces(&rrc, &spaces); + if (rid < 0) + { + std::cerr << "could not list spaces: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + if (lid < 0) + { + std::cerr << "could not list spaces: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + assert(rid == lid); + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not list spaces: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + if (strcmp(spaces, "") == 0) + { + std::cout << "No spaces are found." << std::endl; + } + else + { + std::cout << spaces; + return EXIT_SUCCESS; + } + } + catch (std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} diff --git a/example/c.cpp b/example/c.cpp new file mode 100644 index 000000000..0b0c5826a --- /dev/null +++ b/example/c.cpp @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +int +main(int argc, const char *argv[]) +{ + struct hyperdex_client *client = NULL; + struct hyperdex_client_attribute attr; + struct hyperdex_client_attribute_check check; + const struct hyperdex_client_attribute *attrs = NULL; + size_t attrs_sz = 0; + size_t check_len = 0; + uint64_t count; + int64_t op_id; + enum hyperdex_client_returncode op_status; + int64_t loop_id; + enum hyperdex_client_returncode loop_status; + size_t i; + const char *ns = "phonebook"; + client = hyperdex_client_create("127.0.0.1", 1982); + attr.attr = "first"; + if (argc > 1) + { + char *pointer = NULL; + int arg1 = atoi(argv[1]); + if (arg1 == 1) + { + attr.value = "Hello, World!"; + attr.value_sz = strlen(attr.value); + } + else + { + size_t p_len = 100 * 1024 * 1024; + char *p = (char *)malloc(p_len); + const char *file = "./data.txt"; + fstream fs; + fs.open(file, ios::in | ios::binary); + if (!fs) + { + cerr << "not exist file: " << file << endl; + exit(EXIT_FAILURE); + } + fs.getline(p, p_len); + fs.close(); + attr.value = p; + attr.value_sz = p_len; + pointer = p; + } + int arg2 = argv[2] == NULL ? 0 : atoi(argv[2]); + attr.datatype = HYPERDATATYPE_STRING; + if (arg2 == 0) + { + if (arg1 == 1) + printf("put \"Hello World!\"\n"); + else + printf("put \"Large Value!\"\n"); + op_id = hyperdex_client_put(client, ns, "some key", 8, &attr, 1, &op_status); + if (op_id < 0) + { + cout << hyperdex_client_error_message(client) << endl; + return EXIT_FAILURE; + } + loop_id = hyperdex_client_loop(client, -1, &loop_status); + if (loop_id < 0) + { + cout << hyperdex_client_error_message(client) << endl; + return EXIT_FAILURE; + } + assert(op_id == loop_id); + } + op_id = hyperdex_client_get(client, ns, "some key", 8, &op_status, &attrs, &attrs_sz); + if (op_id < 0) + { + cout << hyperdex_client_error_message(client) << endl; + return EXIT_FAILURE; + } + loop_id = hyperdex_client_loop(client, -1, &loop_status); + if (loop_id < 0) + { + cout << hyperdex_client_error_message(client) << endl; + return EXIT_FAILURE; + } + assert(op_id == loop_id); + printf("get done\n"); + for (i = 0; i < attrs_sz; ++i) + { + printf("got attribute \"%s\" = \"%.*s\"\n", + attrs[i].attr, attrs[i].value_sz, attrs[i].value); + } + if (pointer) + free(pointer); + hyperdex_client_destroy_attrs(attrs, attrs_sz); + } + else + { + check.attr = "first"; + check.value = "John"; + check.value_sz = strlen(check.value); + check.datatype = HYPERDATATYPE_STRING; + check.predicate = HYPERPREDICATE_EQUALS; + count = 0; + check_len += strlen(check.attr); + check_len += check.value_sz; + check_len += sizeof(size_t); + check_len += sizeof(hyperdatatype); + check_len += sizeof(hyperpredicate); + check_len = 1; + op_id = hyperdex_client_count(client, ns, &check, check_len, &op_status, &count); + if (op_id < 0) + { + cout << "count failed: " << hyperdex_client_error_message(client) << endl; + return EXIT_FAILURE; + } + loop_id = hyperdex_client_loop(client, -1, &loop_status); + if (loop_id < 0) + { + cout << hyperdex_client_error_message(client) << endl; + return EXIT_FAILURE; + } + assert(op_id == loop_id); + printf("count: %ld\n", count); + } + hyperdex_client_destroy(client); + return EXIT_SUCCESS; +} diff --git a/example/d.cpp b/example/d.cpp new file mode 100644 index 000000000..60ada7765 --- /dev/null +++ b/example/d.cpp @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +static const char rcsid[] = "$Id: " __FILE__ ",v 1.0.0-0 " __DATE__ " " __TIME__ " Cnangel Exp $"; +#define BUFFER_SIZE 1024*1024*100 + +int +main(int argc, const char *argv[]) +{ + const char *file = "./data.txt"; + if (argc == 1) + { + char *p = (char *)malloc(BUFFER_SIZE); + memset(p, 'z', BUFFER_SIZE); + fstream fs; + fs.open(file, std::ios::out | std::ios::trunc); + fs << p; + fs.close(); + free(p); + } + else if (argc == 2) + { + char *pp = (char *)malloc(BUFFER_SIZE); + fstream fs; + fs.open(file, ios::in | ios::binary); + fs.getline(pp, BUFFER_SIZE); + fs.close(); + printf("pp: %.*s", 100, pp); + free(pp); + } + else + { + unlink(file); + } +} diff --git a/example/e.cpp b/example/e.cpp new file mode 100644 index 000000000..933ae04a2 --- /dev/null +++ b/example/e.cpp @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace hyperdex; + +static const char rcsid[] = "$Id: " __FILE__ ",v 1.0.0-0 " __DATE__ " " __TIME__ " Cnangel Exp $"; + +int +main(int argc, const char *argv[]) +{ + char *p = (char *)malloc(1000); + if (p == NULL) + { + return 0; + } + memset(p, 'A', 1000); + printf("1 %p\n", p); + p = (char *)realloc(p, 200); + if (p == NULL) + { + return 0; + } + memset(p, 'B', 200); + printf("2 %p\n", p); + free(p); + p = new char[1000]; + if (p == NULL) + { + return 0; + } + memset(p, 'A', 1000); + printf("3 %p\n", p); + p = new char[200]; + if (p == NULL) + { + return 0; + } + memset(p, 'B', 200); + printf("4 %p\n", p); + free(p); + return 0; +} diff --git a/example/f.cpp b/example/f.cpp new file mode 100644 index 000000000..f06711bd7 --- /dev/null +++ b/example/f.cpp @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +int +main(int argc, const char *argv[]) +{ + struct hyperdex_client *client = NULL; + struct hyperdex_client_attribute attr; + struct hyperdex_client_attribute_check check; + const struct hyperdex_client_attribute *attrs = NULL; + size_t attrs_sz = 0; + size_t check_len = 0; + uint64_t count; + int64_t op_id; + enum hyperdex_client_returncode op_status; + int64_t loop_id; + enum hyperdex_client_returncode loop_status; + size_t i; + const char *ns = "phonebook"; + client = hyperdex_client_create("127.0.0.1", 1982); + check.attr = "first"; + check.value = "Jack"; + check.value_sz = strlen(check.value); + check.datatype = HYPERDATATYPE_STRING; + check.predicate = HYPERPREDICATE_EQUALS; + op_id = hyperdex_client_search(client, ns, &check, 1, &op_status, &attrs, &attrs_sz); + if (op_id < 0) + { + cerr << "search failed: " << hyperdex_client_error_message(client) << endl; + hyperdex_client_destroy(client); + return EXIT_FAILURE; + } + while (true) + { + loop_id = hyperdex_client_loop(client, -1, &loop_status); + if (loop_id < 0) + { + cerr << hyperdex_client_error_message(client) << endl; + break; + } + if (op_status == HYPERDEX_CLIENT_SEARCHDONE) + { + break; + } + assert(op_id == loop_id); + if (loop_status == HYPERDEX_CLIENT_SUCCESS) + { + printf("get done(%d)\n", attrs_sz); + for (i = 0; i < attrs_sz; ++i) + { + switch (attrs[i].datatype) + { + case HYPERDATATYPE_STRING: + printf("got attribute \"%s\" = \"%.*s\"\n", attrs[i].attr, attrs[i].value_sz, attrs[i].value); + break; + case HYPERDATATYPE_INT64: + { + uint64_t num = 0; + e::unpack64le(attrs[i].value, &num); + printf("got attribute \"%s\" = \"%lu\"\n", attrs[i].attr, num); + } + break; + case HYPERDATATYPE_FLOAT: + { + double num = 0; + e::unpackdoublele(attrs[i].value, &num); + printf("got attribute \"%s\" = \"%f\"\n", attrs[i].attr, num); + } + break; + default: + printf("got error attribute\n"); + } + } + } + } + hyperdex_client_destroy_attrs(attrs, attrs_sz); + hyperdex_client_destroy(client); + return EXIT_SUCCESS; +} diff --git a/example/g.cpp b/example/g.cpp new file mode 100644 index 000000000..7b06c1088 --- /dev/null +++ b/example/g.cpp @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +int +main(int argc, const char *argv[]) +{ + struct hyperdex_client *client = NULL; + struct hyperdex_client_attribute attr; + struct hyperdex_client_attribute_check check; + const struct hyperdex_client_attribute *attrs = NULL; + size_t attrs_sz = 0; + size_t check_len = 0; + uint64_t count; + int64_t op_id; + enum hyperdex_client_returncode op_status; + int64_t loop_id; + enum hyperdex_client_returncode loop_status; + size_t i; + const char *ns = "phonebook"; + client = hyperdex_client_create("127.0.0.1", 1982); + const char *key = "jsmith3"; + size_t key_len = strlen(key); + //check.attr = "first"; + //check.value = "Jack"; + //check.value_sz = strlen(check.value); + //check.datatype = HYPERDATATYPE_STRING; + //check.predicate = HYPERPREDICATE_EQUALS; + op_id = hyperdex_client_get(client, ns, key, key_len, &op_status, &attrs, &attrs_sz); + if (op_id < 0) + { + cerr << "get failed: " << hyperdex_client_error_message(client) << endl; + hyperdex_client_destroy(client); + return EXIT_FAILURE; + } + while (true) + { + loop_id = hyperdex_client_loop(client, -1, &loop_status); + if (loop_id < 0) + { + cerr << hyperdex_client_error_message(client) << endl; + break; + } + if (op_status == HYPERDEX_CLIENT_SEARCHDONE) + { + break; + } + assert(op_id == loop_id); + if (loop_status == HYPERDEX_CLIENT_SUCCESS) + { + printf("get done(%d)\n", attrs_sz); + for (i = 0; i < attrs_sz; ++i) + { + switch (attrs[i].datatype) + { + case HYPERDATATYPE_STRING: + printf("got attribute \"%s\" = \"%.*s\"\n", attrs[i].attr, attrs[i].value_sz, attrs[i].value); + break; + case HYPERDATATYPE_INT64: + { + uint64_t num = 0; + e::unpack64le(attrs[i].value, &num); + printf("got attribute \"%s\" = \"%lu\"\n", attrs[i].attr, num); + } + break; + case HYPERDATATYPE_FLOAT: + { + double num = 0; + e::unpackdoublele(attrs[i].value, &num); + printf("got attribute \"%s\" = \"%f\"\n", attrs[i].attr, num); + } + break; + default: + printf("got error attribute\n"); + } + } + } + } + hyperdex_client_destroy_attrs(attrs, attrs_sz); + hyperdex_client_destroy(client); + return EXIT_SUCCESS; +} diff --git a/example/s.cpp b/example/s.cpp new file mode 100644 index 000000000..c5457c3cb --- /dev/null +++ b/example/s.cpp @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +int +main(int argc, const char *argv[]) +{ + struct hyperdex_client *client = NULL; + struct hyperdex_client_attribute attr; + struct hyperdex_client_attribute_check check; + const struct hyperdex_client_attribute *attrs = NULL; + size_t attrs_sz = 0; + size_t check_len = 0; + uint64_t count; + int64_t op_id; + enum hyperdex_client_returncode op_status; + int64_t loop_id; + enum hyperdex_client_returncode loop_status; + size_t i; + const char *ns = "phonebook"; + client = hyperdex_client_create("127.0.0.1", 1982); + const char *sortby = "first"; + check.attr = "first"; + check.value = "Jack"; + check.value_sz = strlen(check.value); + check.datatype = HYPERDATATYPE_STRING; + check.predicate = HYPERPREDICATE_EQUALS; + int cnt = 1; + int max = 1; + if (argc == 2) + { + cnt = atoi(argv[1]); + } + else if (argc == 3) + { + cnt = atoi(argv[1]); + max = atoi(argv[2]); + } + op_id = hyperdex_client_sorted_search(client, ns, &check, 0, sortby, cnt, max, &op_status, &attrs, &attrs_sz); + if (op_id < 0) + { + cerr << "get failed: " << hyperdex_client_error_message(client) << endl; + hyperdex_client_destroy(client); + return EXIT_FAILURE; + } + while (true) + { + loop_id = hyperdex_client_loop(client, -1, &loop_status); + if (loop_id < 0) + { + cerr << hyperdex_client_error_message(client) << endl; + break; + } + if (op_status == HYPERDEX_CLIENT_SEARCHDONE) + { + break; + } + if (loop_status == HYPERDEX_CLIENT_SUCCESS) + { + printf("get done(%d)\n", attrs_sz); + for (i = 0; i < attrs_sz; ++i) + { + if (attrs[i].value_sz == 0) + { + continue; + } + switch (attrs[i].datatype) + { + case HYPERDATATYPE_STRING: + printf("got attribute \"%s\" = \"%.*s\"\n", attrs[i].attr, attrs[i].value_sz, attrs[i].value); + break; + case HYPERDATATYPE_INT64: + { + uint64_t num = 0; + e::unpack64le(attrs[i].value, &num); + printf("got attribute \"%s\" = \"%lu\"\n", attrs[i].attr, num); + } + break; + case HYPERDATATYPE_FLOAT: + { + double num = 0; + e::unpackdoublele(attrs[i].value, &num); + printf("got attribute \"%s\" = \"%f\"\n", attrs[i].attr, num); + } + break; + default: + printf("got error attribute\n"); + } + } + } + } + hyperdex_client_destroy_attrs(attrs, attrs_sz); + hyperdex_client_destroy(client); + return EXIT_SUCCESS; +} diff --git a/example/sum.cpp b/example/sum.cpp new file mode 100644 index 000000000..9382942db --- /dev/null +++ b/example/sum.cpp @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hyperdex/admin.hpp" +#include "hyperdex/client.hpp" +#include "hyperdex/client.h" +#include + +using namespace std; + +int +main(int argc, const char *argv[]) +{ + struct hyperdex_client *client = NULL; + struct hyperdex_client_attribute attr; + struct hyperdex_client_attribute_check check; + const struct hyperdex_client_attribute *attrs = NULL; + size_t attrs_sz = 0; + size_t check_len = 0; + uint64_t sum = 0; + int64_t op_id; + enum hyperdex_client_returncode op_status; + int64_t loop_id; + enum hyperdex_client_returncode loop_status; + size_t i; + const char *ns = "phonebook"; + client = hyperdex_client_create("127.0.0.1", 1982); + const char *row_key = "phone"; + check.attr = "first"; + check.value = "Jack"; + check.value_sz = strlen(check.value); + check.datatype = HYPERDATATYPE_STRING; + check.predicate = HYPERPREDICATE_EQUALS; + op_id = hyperdex_client_sum(client, ns, &check, 1, row_key, &op_status, &sum); + if (op_id < 0) + { + cerr << "search failed: " << hyperdex_client_error_message(client) << endl; + hyperdex_client_destroy(client); + return EXIT_FAILURE; + } + while (true) + { + loop_id = hyperdex_client_loop(client, -1, &loop_status); + if (loop_id < 0) + { + cerr << hyperdex_client_error_message(client) << endl; + break; + } + //if (op_status == HYPERDEX_CLIENT_SEARCHDONE) { + // break; + //} + assert(op_id == loop_id); + if (loop_status == HYPERDEX_CLIENT_SUCCESS) + { + printf("get done(%llu)\n", sum); + } + } + hyperdex_client_destroy_attrs(attrs, attrs_sz); + hyperdex_client_destroy(client); + return EXIT_SUCCESS; +}