Merge pull request #2549 from hongweiwang/zookeeper

Zookeeper name resolver
pull/2941/head
David G. Quintas 10 years ago
commit bd0d1bd5d9
  1. 20
      BUILD
  2. 199
      Makefile
  3. 43
      build.json
  4. 27
      include/grpc/grpc.h
  5. 59
      include/grpc/grpc_zookeeper.h
  6. 501
      src/core/client_config/resolvers/zookeeper_resolver.c
  7. 42
      src/core/client_config/resolvers/zookeeper_resolver.h
  8. 32
      src/core/surface/init.c
  9. 214
      templates/Makefile.template
  10. 43
      test/build/zookeeper.c
  11. 223
      test/cpp/end2end/zookeeper_test.cc
  12. 8
      tools/jenkins/grpc_jenkins_slave/Dockerfile
  13. 8
      tools/jenkins/grpc_jenkins_slave_32bits/Dockerfile
  14. 1
      tools/jenkins/run_jenkins.sh
  15. 34
      tools/run_tests/sources_and_headers.json
  16. 17
      tools/run_tests/tests.json
  17. 20
      vsprojects/Grpc.mak
  18. 25
      vsprojects/grpc.sln
  19. 17
      vsprojects/grpc_csharp_ext.sln

20
BUILD

@ -649,6 +649,26 @@ cc_library(
)
cc_library(
name = "grpc_zookeeper",
srcs = [
"src/core/client_config/resolvers/zookeeper_resolver.h",
"src/core/client_config/resolvers/zookeeper_resolver.c",
],
hdrs = [
"include/grpc/grpc_zookeeper.h",
],
includes = [
"include",
".",
],
deps = [
":gpr",
":grpc",
],
)
cc_library(
name = "grpc++",
srcs = [

File diff suppressed because one or more lines are too long

@ -572,6 +572,29 @@
"secure": "no",
"vs_project_guid": "{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}"
},
{
"name": "grpc_zookeeper",
"build": "all",
"language": "c",
"public_headers": [
"include/grpc/grpc_zookeeper.h"
],
"headers": [
"src/core/client_config/resolvers/zookeeper_resolver.h"
],
"src": [
"src/core/client_config/resolvers/zookeeper_resolver.c"
],
"deps": [
"gpr",
"grpc"
],
"external_deps": [
"zookeeper"
],
"secure": "no",
"vs_project_guid": "{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}"
},
{
"name": "reconnect_server",
"build": "private",
@ -2647,6 +2670,26 @@
"gpr_test_util",
"gpr"
]
},
{
"name": "zookeeper_test",
"build": "test",
"language": "c++",
"src": [
"test/cpp/end2end/zookeeper_test.cc"
],
"deps": [
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc_zookeeper",
"grpc",
"gpr_test_util",
"gpr"
],
"external_deps": [
"zookeeper"
]
}
]
}

@ -376,6 +376,23 @@ typedef struct grpc_op {
} data;
} grpc_op;
/** Registers a plugin to be initialized and destroyed with the library.
The \a init and \a destroy functions will be invoked as part of
\a grpc_init() and \a grpc_shutdown(), respectively.
Note that these functions can be invoked an arbitrary number of times
(and hence so will \a init and \a destroy).
It is safe to pass NULL to either argument. Plugins are destroyed in
the reverse order they were initialized. */
void grpc_register_plugin(void (*init)(void), void (*destroy)(void));
/** Frees the memory used by all the plugin information.
While grpc_init and grpc_shutdown can be called multiple times, the plugins
won't be unregistered and their memory cleaned up unless you call that
function. Using atexit(grpc_unregister_all_plugins) is a valid method. */
void grpc_unregister_all_plugins();
/* Propagation bits: this can be bitwise or-ed to form propagation_mask for
* grpc_call */
/** Propagate deadline */
@ -388,8 +405,8 @@ typedef struct grpc_op {
/* Default propagation mask: clients of the core API are encouraged to encode
deltas from this in their implementations... ie write:
GRPC_PROPAGATE_DEFAULTS & ~GRPC_PROPAGATE_DEADLINE to disable deadline
propagation. Doing so gives flexibility in the future to define new
GRPC_PROPAGATE_DEFAULTS & ~GRPC_PROPAGATE_DEADLINE to disable deadline
propagation. Doing so gives flexibility in the future to define new
propagation types that are default inherited or not. */
#define GRPC_PROPAGATE_DEFAULTS \
((gpr_uint32)(( \
@ -436,8 +453,8 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cq,
otherwise a grpc_event describing the event that occurred.
Callers must not call grpc_completion_queue_next and
grpc_completion_queue_pluck simultaneously on the same completion queue.
grpc_completion_queue_pluck simultaneously on the same completion queue.
Completion queues support a maximum of GRPC_MAX_COMPLETION_QUEUE_PLUCKERS
concurrently executing plucks at any time. */
grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cq, void *tag,
@ -477,7 +494,7 @@ void grpc_channel_watch_connectivity_state(
completions are sent to 'completion_queue'. 'method' and 'host' need only
live through the invocation of this function.
If parent_call is non-NULL, it must be a server-side call. It will be used
to propagate properties from the server call to this new client call.
to propagate properties from the server call to this new client call.
*/
grpc_call *grpc_channel_create_call(grpc_channel *channel,
grpc_call *parent_call,

@ -0,0 +1,59 @@
/*
*
* Copyright 2015, Google Inc.
* 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 Google Inc. 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.
*
*/
/** Support zookeeper as alternative name system in addition to DNS
* Zookeeper name in gRPC is represented as a URI:
* zookeeper://host:port/path/service/instance
*
* Where zookeeper is the name system scheme
* host:port is the address of a zookeeper server
* /path/service/instance is the zookeeper name to be resolved
*
* Refer doc/naming.md for more details
*/
#ifndef GRPC_GRPC_ZOOKEEPER_H
#define GRPC_GRPC_ZOOKEEPER_H
#ifdef __cplusplus
extern "C" {
#endif
/** Register zookeeper name resolver in grpc */
void grpc_zookeeper_register();
#ifdef __cplusplus
}
#endif
#endif /* GRPC_GRPC_ZOOKEEPER_H */

@ -0,0 +1,501 @@
/*
*
* Copyright 2015, Google Inc.
* 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 Google Inc. 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.
*
*/
#include "src/core/client_config/resolvers/zookeeper_resolver.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include <grpc/grpc_zookeeper.h>
#include <zookeeper/zookeeper.h>
#include "src/core/client_config/lb_policies/pick_first.h"
#include "src/core/client_config/resolver_registry.h"
#include "src/core/iomgr/resolve_address.h"
#include "src/core/support/string.h"
#include "src/core/json/json.h"
/** Zookeeper session expiration time in milliseconds */
#define GRPC_ZOOKEEPER_SESSION_TIMEOUT 15000
typedef struct {
/** base class: must be first */
grpc_resolver base;
/** refcount */
gpr_refcount refs;
/** name to resolve */
char *name;
/** subchannel factory */
grpc_subchannel_factory *subchannel_factory;
/** load balancing policy factory */
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
size_t num_subchannels);
/** mutex guarding the rest of the state */
gpr_mu mu;
/** are we currently resolving? */
int resolving;
/** which version of resolved_config have we published? */
int published_version;
/** which version of resolved_config is current? */
int resolved_version;
/** pending next completion, or NULL */
grpc_iomgr_closure *next_completion;
/** target config address for next completion */
grpc_client_config **target_config;
/** current (fully resolved) config */
grpc_client_config *resolved_config;
/** zookeeper handle */
zhandle_t *zookeeper_handle;
/** zookeeper resolved addresses */
grpc_resolved_addresses *resolved_addrs;
/** total number of addresses to be resolved */
int resolved_total;
/** number of addresses resolved */
int resolved_num;
} zookeeper_resolver;
static void zookeeper_destroy(grpc_resolver *r);
static void zookeeper_start_resolving_locked(zookeeper_resolver *r);
static void zookeeper_maybe_finish_next_locked(zookeeper_resolver *r);
static void zookeeper_shutdown(grpc_resolver *r);
static void zookeeper_channel_saw_error(grpc_resolver *r,
struct sockaddr *failing_address,
int failing_address_len);
static void zookeeper_next(grpc_resolver *r, grpc_client_config **target_config,
grpc_iomgr_closure *on_complete);
static const grpc_resolver_vtable zookeeper_resolver_vtable = {
zookeeper_destroy, zookeeper_shutdown, zookeeper_channel_saw_error,
zookeeper_next};
static void zookeeper_shutdown(grpc_resolver *resolver) {
zookeeper_resolver *r = (zookeeper_resolver *)resolver;
gpr_mu_lock(&r->mu);
if (r->next_completion != NULL) {
*r->target_config = NULL;
grpc_iomgr_add_callback(r->next_completion);
r->next_completion = NULL;
}
zookeeper_close(r->zookeeper_handle);
gpr_mu_unlock(&r->mu);
}
static void zookeeper_channel_saw_error(grpc_resolver *resolver,
struct sockaddr *sa, int len) {
zookeeper_resolver *r = (zookeeper_resolver *)resolver;
gpr_mu_lock(&r->mu);
if (r->resolving == 0) {
zookeeper_start_resolving_locked(r);
}
gpr_mu_unlock(&r->mu);
}
static void zookeeper_next(grpc_resolver *resolver,
grpc_client_config **target_config,
grpc_iomgr_closure *on_complete) {
zookeeper_resolver *r = (zookeeper_resolver *)resolver;
gpr_mu_lock(&r->mu);
GPR_ASSERT(r->next_completion == NULL);
r->next_completion = on_complete;
r->target_config = target_config;
if (r->resolved_version == 0 && r->resolving == 0) {
zookeeper_start_resolving_locked(r);
} else {
zookeeper_maybe_finish_next_locked(r);
}
gpr_mu_unlock(&r->mu);
}
/** Zookeeper global watcher for connection management
TODO: better connection management besides logs */
static void zookeeper_global_watcher(zhandle_t *zookeeper_handle, int type,
int state, const char *path,
void *watcher_ctx) {
if (type == ZOO_SESSION_EVENT) {
if (state == ZOO_EXPIRED_SESSION_STATE) {
gpr_log(GPR_ERROR, "Zookeeper session expired");
} else if (state == ZOO_AUTH_FAILED_STATE) {
gpr_log(GPR_ERROR, "Zookeeper authentication failed");
}
}
}
/** Zookeeper watcher triggered by changes to watched nodes
Once triggered, it tries to resolve again to get updated addresses */
static void zookeeper_watcher(zhandle_t *zookeeper_handle, int type, int state,
const char *path, void *watcher_ctx) {
if (watcher_ctx != NULL) {
zookeeper_resolver *r = (zookeeper_resolver *)watcher_ctx;
if (state == ZOO_CONNECTED_STATE) {
gpr_mu_lock(&r->mu);
if (r->resolving == 0) {
zookeeper_start_resolving_locked(r);
}
gpr_mu_unlock(&r->mu);
}
}
}
/** Callback function after getting all resolved addresses
Creates a subchannel for each address */
static void zookeeper_on_resolved(void *arg,
grpc_resolved_addresses *addresses) {
zookeeper_resolver *r = arg;
grpc_client_config *config = NULL;
grpc_subchannel **subchannels;
grpc_subchannel_args args;
grpc_lb_policy *lb_policy;
size_t i;
if (addresses != NULL) {
config = grpc_client_config_create();
subchannels = gpr_malloc(sizeof(grpc_subchannel *) * addresses->naddrs);
for (i = 0; i < addresses->naddrs; i++) {
memset(&args, 0, sizeof(args));
args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
args.addr_len = addresses->addrs[i].len;
subchannels[i] = grpc_subchannel_factory_create_subchannel(
r->subchannel_factory, &args);
}
lb_policy = r->lb_policy_factory(subchannels, addresses->naddrs);
grpc_client_config_set_lb_policy(config, lb_policy);
GRPC_LB_POLICY_UNREF(lb_policy, "construction");
grpc_resolved_addresses_destroy(addresses);
gpr_free(subchannels);
}
gpr_mu_lock(&r->mu);
GPR_ASSERT(r->resolving == 1);
r->resolving = 0;
if (r->resolved_config != NULL) {
grpc_client_config_unref(r->resolved_config);
}
r->resolved_config = config;
r->resolved_version++;
zookeeper_maybe_finish_next_locked(r);
gpr_mu_unlock(&r->mu);
GRPC_RESOLVER_UNREF(&r->base, "zookeeper-resolving");
}
/** Callback function for each DNS resolved address */
static void zookeeper_dns_resolved(void *arg,
grpc_resolved_addresses *addresses) {
size_t i;
zookeeper_resolver *r = arg;
int resolve_done = 0;
gpr_mu_lock(&r->mu);
r->resolved_num++;
r->resolved_addrs->addrs =
gpr_realloc(r->resolved_addrs->addrs,
sizeof(grpc_resolved_address) *
(r->resolved_addrs->naddrs + addresses->naddrs));
for (i = 0; i < addresses->naddrs; i++) {
memcpy(r->resolved_addrs->addrs[i + r->resolved_addrs->naddrs].addr,
addresses->addrs[i].addr, addresses->addrs[i].len);
r->resolved_addrs->addrs[i + r->resolved_addrs->naddrs].len =
addresses->addrs[i].len;
}
r->resolved_addrs->naddrs += addresses->naddrs;
grpc_resolved_addresses_destroy(addresses);
/** Wait for all addresses to be resolved */
resolve_done = (r->resolved_num == r->resolved_total);
gpr_mu_unlock(&r->mu);
if (resolve_done) {
zookeeper_on_resolved(r, r->resolved_addrs);
}
}
/** Parses JSON format address of a zookeeper node */
static char *zookeeper_parse_address(const char *value, int value_len) {
grpc_json *json;
grpc_json *cur;
const char *host;
const char *port;
char* buffer;
char *address = NULL;
buffer = gpr_malloc(value_len);
memcpy(buffer, value, value_len);
json = grpc_json_parse_string_with_len(buffer, value_len);
if (json != NULL) {
host = NULL;
port = NULL;
for (cur = json->child; cur != NULL; cur = cur->next) {
if (!strcmp(cur->key, "host")) {
host = cur->value;
if (port != NULL) {
break;
}
} else if (!strcmp(cur->key, "port")) {
port = cur->value;
if (host != NULL) {
break;
}
}
}
if (host != NULL && port != NULL) {
gpr_asprintf(&address, "%s:%s", host, port);
}
grpc_json_destroy(json);
}
gpr_free(buffer);
return address;
}
static void zookeeper_get_children_node_completion(int rc, const char *value,
int value_len,
const struct Stat *stat,
const void *arg) {
char *address = NULL;
zookeeper_resolver *r = (zookeeper_resolver *)arg;
int resolve_done = 0;
if (rc != 0) {
gpr_log(GPR_ERROR, "Error in getting a child node of %s", r->name);
return;
}
address = zookeeper_parse_address(value, value_len);
if (address != NULL) {
/** Further resolves address by DNS */
grpc_resolve_address(address, NULL, zookeeper_dns_resolved, r);
gpr_free(address);
} else {
gpr_log(GPR_ERROR, "Error in resolving a child node of %s", r->name);
gpr_mu_lock(&r->mu);
r->resolved_total--;
resolve_done = (r->resolved_num == r->resolved_total);
gpr_mu_unlock(&r->mu);
if (resolve_done) {
zookeeper_on_resolved(r, r->resolved_addrs);
}
}
}
static void zookeeper_get_children_completion(
int rc, const struct String_vector *children, const void *arg) {
char *path;
int status;
int i;
zookeeper_resolver *r = (zookeeper_resolver *)arg;
if (rc != 0) {
gpr_log(GPR_ERROR, "Error in getting zookeeper children of %s", r->name);
return;
}
if (children->count == 0) {
gpr_log(GPR_ERROR, "Error in resolving zookeeper address %s", r->name);
return;
}
r->resolved_addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
r->resolved_addrs->addrs = NULL;
r->resolved_addrs->naddrs = 0;
r->resolved_total = children->count;
/** TODO: Replace expensive heap allocation with stack
if we can get maximum length of zookeeper path */
for (i = 0; i < children->count; i++) {
gpr_asprintf(&path, "%s/%s", r->name, children->data[i]);
status = zoo_awget(r->zookeeper_handle, path, zookeeper_watcher, r,
zookeeper_get_children_node_completion, r);
gpr_free(path);
if (status != 0) {
gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", path);
}
}
}
static void zookeeper_get_node_completion(int rc, const char *value,
int value_len,
const struct Stat *stat,
const void *arg) {
int status;
char *address = NULL;
zookeeper_resolver *r = (zookeeper_resolver *)arg;
r->resolved_addrs = NULL;
r->resolved_total = 0;
r->resolved_num = 0;
if (rc != 0) {
gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", r->name);
return;
}
/** If zookeeper node of path r->name does not have address
(i.e. service node), get its children */
address = zookeeper_parse_address(value, value_len);
if (address != NULL) {
r->resolved_addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
r->resolved_addrs->addrs = NULL;
r->resolved_addrs->naddrs = 0;
r->resolved_total = 1;
/** Further resolves address by DNS */
grpc_resolve_address(address, NULL, zookeeper_dns_resolved, r);
gpr_free(address);
return;
}
status = zoo_awget_children(r->zookeeper_handle, r->name, zookeeper_watcher,
r, zookeeper_get_children_completion, r);
if (status != 0) {
gpr_log(GPR_ERROR, "Error in getting zookeeper children of %s", r->name);
}
}
static void zookeeper_resolve_address(zookeeper_resolver *r) {
int status;
status = zoo_awget(r->zookeeper_handle, r->name, zookeeper_watcher, r,
zookeeper_get_node_completion, r);
if (status != 0) {
gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", r->name);
}
}
static void zookeeper_start_resolving_locked(zookeeper_resolver *r) {
GRPC_RESOLVER_REF(&r->base, "zookeeper-resolving");
GPR_ASSERT(r->resolving == 0);
r->resolving = 1;
zookeeper_resolve_address(r);
}
static void zookeeper_maybe_finish_next_locked(zookeeper_resolver *r) {
if (r->next_completion != NULL &&
r->resolved_version != r->published_version) {
*r->target_config = r->resolved_config;
if (r->resolved_config != NULL) {
grpc_client_config_ref(r->resolved_config);
}
grpc_iomgr_add_callback(r->next_completion);
r->next_completion = NULL;
r->published_version = r->resolved_version;
}
}
static void zookeeper_destroy(grpc_resolver *gr) {
zookeeper_resolver *r = (zookeeper_resolver *)gr;
gpr_mu_destroy(&r->mu);
if (r->resolved_config != NULL) {
grpc_client_config_unref(r->resolved_config);
}
grpc_subchannel_factory_unref(r->subchannel_factory);
gpr_free(r->name);
gpr_free(r);
}
static grpc_resolver *zookeeper_create(
grpc_uri *uri,
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
size_t num_subchannels),
grpc_subchannel_factory *subchannel_factory) {
zookeeper_resolver *r;
size_t length;
char *path = uri->path;
if (0 == strcmp(uri->authority, "")) {
gpr_log(GPR_ERROR, "No authority specified in zookeeper uri");
return NULL;
}
/** Removes the trailing slash if exists */
length = strlen(path);
if (length > 1 && path[length - 1] == '/') {
path[length - 1] = 0;
}
r = gpr_malloc(sizeof(zookeeper_resolver));
memset(r, 0, sizeof(*r));
gpr_ref_init(&r->refs, 1);
gpr_mu_init(&r->mu);
grpc_resolver_init(&r->base, &zookeeper_resolver_vtable);
r->name = gpr_strdup(path);
r->subchannel_factory = subchannel_factory;
r->lb_policy_factory = lb_policy_factory;
grpc_subchannel_factory_ref(subchannel_factory);
/** Initializes zookeeper client */
zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
r->zookeeper_handle = zookeeper_init(uri->authority, zookeeper_global_watcher,
GRPC_ZOOKEEPER_SESSION_TIMEOUT, 0, 0, 0);
if (r->zookeeper_handle == NULL) {
gpr_log(GPR_ERROR, "Unable to connect to zookeeper server");
return NULL;
}
return &r->base;
}
static void zookeeper_plugin_init() {
grpc_register_resolver_type("zookeeper",
grpc_zookeeper_resolver_factory_create());
}
void grpc_zookeeper_register() {
grpc_register_plugin(zookeeper_plugin_init, NULL);
}
/*
* FACTORY
*/
static void zookeeper_factory_ref(grpc_resolver_factory *factory) {}
static void zookeeper_factory_unref(grpc_resolver_factory *factory) {}
static grpc_resolver *zookeeper_factory_create_resolver(
grpc_resolver_factory *factory, grpc_uri *uri,
grpc_subchannel_factory *subchannel_factory) {
return zookeeper_create(uri, grpc_create_pick_first_lb_policy,
subchannel_factory);
}
static const grpc_resolver_factory_vtable zookeeper_factory_vtable = {
zookeeper_factory_ref, zookeeper_factory_unref,
zookeeper_factory_create_resolver};
static grpc_resolver_factory zookeeper_resolver_factory = {
&zookeeper_factory_vtable};
grpc_resolver_factory *grpc_zookeeper_resolver_factory_create() {
return &zookeeper_resolver_factory;
}

@ -0,0 +1,42 @@
/*
*
* Copyright 2015, Google Inc.
* 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 Google Inc. 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 GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVERS_ZOOKEEPER_RESOLVER_H
#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVERS_ZOOKEEPER_RESOLVER_H
#include "src/core/client_config/resolver_factory.h"
/** Create a zookeeper resolver factory */
grpc_resolver_factory *grpc_zookeeper_resolver_factory_create(void);
#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVERS_ZOOKEEPER_RESOLVER_H */

@ -33,8 +33,11 @@
#include <grpc/support/port_platform.h>
#include <memory.h>
#include <grpc/census.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/time.h>
#include "src/core/channel/channel_stack.h"
#include "src/core/client_config/resolver_registry.h"
@ -49,6 +52,8 @@
#include "src/core/transport/chttp2_transport.h"
#include "src/core/transport/connectivity_state.h"
#define MAX_PLUGINS 128
static gpr_once g_basic_init = GPR_ONCE_INIT;
static gpr_mu g_init_mu;
static int g_initializations;
@ -58,7 +63,23 @@ static void do_basic_init(void) {
g_initializations = 0;
}
typedef struct grpc_plugin {
void (*init)();
void (*destroy)();
} grpc_plugin;
static grpc_plugin g_all_of_the_plugins[MAX_PLUGINS];
static int g_number_of_plugins = 0;
void grpc_register_plugin(void (*init)(void), void (*destroy)(void)) {
GPR_ASSERT(g_number_of_plugins != MAX_PLUGINS);
g_all_of_the_plugins[g_number_of_plugins].init = init;
g_all_of_the_plugins[g_number_of_plugins].destroy = destroy;
g_number_of_plugins++;
}
void grpc_init(void) {
int i;
gpr_once_init(&g_basic_init, do_basic_init);
gpr_mu_lock(&g_init_mu);
@ -87,11 +108,17 @@ void grpc_init(void) {
}
}
grpc_timers_global_init();
for (i = 0; i < g_number_of_plugins; i++) {
if (g_all_of_the_plugins[i].init != NULL) {
g_all_of_the_plugins[i].init();
}
}
}
gpr_mu_unlock(&g_init_mu);
}
void grpc_shutdown(void) {
int i;
gpr_mu_lock(&g_init_mu);
if (--g_initializations == 0) {
grpc_iomgr_shutdown();
@ -99,6 +126,11 @@ void grpc_shutdown(void) {
grpc_timers_global_destroy();
grpc_tracer_shutdown();
grpc_resolver_registry_shutdown();
for (i = 0; i < g_number_of_plugins; i++) {
if (g_all_of_the_plugins[i].destroy != NULL) {
g_all_of_the_plugins[i].destroy();
}
}
}
gpr_mu_unlock(&g_init_mu);
}

@ -436,6 +436,7 @@ PROTOC_CHECK_CMD = which protoc > /dev/null
PROTOC_CHECK_VERSION_CMD = protoc --version | grep -q libprotoc.3
DTRACE_CHECK_CMD = which dtrace > /dev/null
SYSTEMTAP_HEADERS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/systemtap.c $(LDFLAGS)
ZOOKEEPER_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/zookeeper.c $(LDFLAGS) -lzookeeper_mt
ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG)
HAS_SYSTEM_PERFTOOLS ?= $(shell $(PERFTOOLS_CHECK_CMD) 2> /dev/null && echo true || echo false)
@ -503,6 +504,8 @@ ifeq ($(HAS_SYSTEMTAP),true)
CACHE_MK += HAS_SYSTEMTAP = true,
endif
HAS_ZOOKEEPER = $(shell $(ZOOKEEPER_CHECK_CMD) 2> /dev/null && echo true || echo false)
# Note that for testing purposes, one can do:
# make HAS_EMBEDDED_OPENSSL_ALPN=false
# to emulate the fact we do not have OpenSSL in the third_party folder.
@ -621,6 +624,14 @@ PC_LIBS_PRIVATE = $(PC_LIBS_GRPC)
PC_LIB = -lgrpc
GRPC_UNSECURE_PC_FILE := $(PC_TEMPLATE)
# gprc_zookeeper .pc file
PC_NAME = gRPC zookeeper
PC_DESCRIPTION = gRPC's zookeeper plugin
PC_CFLAGS =
PC_REQUIRES_PRIVATE =
PC_LIBS_PRIVATE = -lzookeeper_mt
GRPC_ZOOKEEPER_PC_FILE := $(PC_TEMPLATE)
PROTOBUF_PKG_CONFIG = false
PC_REQUIRES_GRPCXX =
@ -813,6 +824,7 @@ run_dep_checks:
$(PERFTOOLS_CHECK_CMD) || true
$(PROTOBUF_CHECK_CMD) || true
$(PROTOC_CHECK_VERSION_CMD) || true
$(ZOOKEEPER_CHECK_CMD) || true
$(LIBDIR)/$(CONFIG)/zlib/libz.a:
$(E) "[MAKE] Building zlib"
@ -871,12 +883,13 @@ $(LIBDIR)/$(CONFIG)/protobuf/libprotobuf.a: third_party/protobuf/configure
static: static_c static_cxx
static_c: pc_c pc_c_unsecure cache.mk \
static_c: pc_c pc_c_unsecure cache.mk pc_gpr pc_c_zookeeper\
% for lib in libs:
% if lib.build == 'all' and lib.language == 'c':
% if lib.build == 'all' and lib.language == 'c' and not lib.get('external_deps', None):
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a\
% endif
% endfor
static_zookeeper_libs
static_cxx: pc_cxx pc_cxx_unsecure pc_gpr cache.mk \
@ -889,13 +902,13 @@ static_cxx: pc_cxx pc_cxx_unsecure pc_gpr cache.mk \
shared: shared_c shared_cxx
shared_c: pc_c pc_c_unsecure pc_gpr cache.mk\
shared_c: pc_c pc_c_unsecure pc_gpr cache.mk pc_c_zookeeper\
% for lib in libs:
% if lib.build == 'all' and lib.language == 'c':
% if lib.build == 'all' and lib.language == 'c' and not lib.get('external_deps', None):
$(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)\
% endif
% endfor
shared_zookeeper_libs
shared_cxx: pc_cxx pc_cxx_unsecure cache.mk\
% for lib in libs:
@ -912,6 +925,29 @@ shared_csharp: shared_c \
% endif
% endfor
ifeq ($(HAS_ZOOKEEPER),true)
static_zookeeper_libs:\
% for lib in libs:
% if lib.build == 'all' and lib.language == 'c' and 'zookeeper' in lib.get('external_deps', []):
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a\
% endif
% endfor
shared_zookeeper_libs:\
% for lib in libs:
% if lib.build == 'all' and lib.language == 'c' and 'zookeeper' in lib.get('external_deps', []):
$(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)\
% endif
% endfor
else
static_zookeeper_libs:
shared_zookeeper_libs:
endif
grpc_csharp_ext: shared_csharp
plugins: $(PROTOC_PLUGINS)
@ -920,7 +956,7 @@ privatelibs: privatelibs_c privatelibs_cxx
privatelibs_c: \
% for lib in libs:
% if lib.build == 'private' and lib.language == 'c':
% if lib.build == 'private' and lib.language == 'c' and not lib.get('external_deps', None):
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a\
% endif
% endfor
@ -931,43 +967,75 @@ pc_c: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc.pc
pc_c_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_unsecure.pc
ifeq ($(HAS_ZOOKEEPER),true)
pc_c_zookeeper: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_zookeeper.pc
else
pc_c_zookeeper:
endif
pc_cxx: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc
pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc
privatelibs_cxx: \
% for lib in libs:
% if lib.build == 'private' and lib.language == 'c++':
% if lib.build == 'private' and lib.language == 'c++' and not lib.get('external_deps', None):
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a\
% endif
% endfor
buildtests: buildtests_c buildtests_cxx
ifeq ($(HAS_ZOOKEEPER),true)
privatelibs_zookeeper: \
% for lib in libs:
% if lib.build == 'private' and lib.language == 'c++' and zookeeper in lib.get('external_deps', []):
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a\
% endif
% endfor
else
privatelibs_zookeeper:
endif
buildtests: buildtests_c buildtests_cxx buildtests_zookeeper
buildtests_c: privatelibs_c\
% for tgt in targets:
% if tgt.build == 'test' and not tgt.language == 'c++':
% if tgt.build == 'test' and not tgt.language == 'c++' and not tgt.get('external_deps', None):
$(BINDIR)/$(CONFIG)/${tgt.name}\
% endif
% endfor
buildtests_cxx: privatelibs_cxx\
buildtests_cxx: buildtests_zookeeper privatelibs_cxx\
% for tgt in targets:
% if tgt.build == 'test' and tgt.language == 'c++':
% if tgt.build == 'test' and tgt.language == 'c++' and not tgt.get('external_deps', None):
$(BINDIR)/$(CONFIG)/${tgt.name}\
% endif
% endfor
test: test_c test_cxx
ifeq ($(HAS_ZOOKEEPER),true)
buildtests_zookeeper: privatelibs_zookeeper\
% for tgt in targets:
% if tgt.build == 'test' and tgt.language == 'c++' and 'zookeeper' in tgt.get('external_deps', []):
$(BINDIR)/$(CONFIG)/${tgt.name}\
% endif
% endfor
flaky_test: flaky_test_c flaky_test_cxx
else
buildtests_zookeeper:
endif
test: test_c test_cxx test_zookeeper
flaky_test: flaky_test_c flaky_test_cxx flaky_test_zookeeper
test_c: buildtests_c
% for tgt in targets:
% if tgt.build == 'test' and tgt.get('run', True) and not tgt.language == 'c++' and not tgt.get('flaky', False):
% if tgt.build == 'test' and tgt.get('run', True) and not tgt.language == 'c++' and not tgt.get('flaky', False) and not tgt.get('external_deps', None):
$(E) "[RUN] Testing ${tgt.name}"
$(Q) $(BINDIR)/$(CONFIG)/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 )
% endif
@ -976,16 +1044,16 @@ test_c: buildtests_c
flaky_test_c: buildtests_c
% for tgt in targets:
% if tgt.build == 'test' and tgt.get('run', True) and not tgt.language == 'c++' and tgt.get('flaky', False):
% if tgt.build == 'test' and tgt.get('run', True) and not tgt.language == 'c++' and tgt.get('flaky', False) and not tgt.get('external_deps', None):
$(E) "[RUN] Testing ${tgt.name}"
$(Q) $(BINDIR)/$(CONFIG)/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 )
% endif
% endfor
test_cxx: buildtests_cxx
test_cxx: test_zookeeper buildtests_cxx
% for tgt in targets:
% if tgt.build == 'test' and tgt.get('run', True) and tgt.language == 'c++' and not tgt.get('flaky', False):
% if tgt.build == 'test' and tgt.get('run', True) and tgt.language == 'c++' and not tgt.get('flaky', False) and not tgt.get('external_deps', None):
$(E) "[RUN] Testing ${tgt.name}"
$(Q) $(BINDIR)/$(CONFIG)/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 )
% endif
@ -994,13 +1062,37 @@ test_cxx: buildtests_cxx
flaky_test_cxx: buildtests_cxx
% for tgt in targets:
% if tgt.build == 'test' and tgt.get('run', True) and tgt.language == 'c++' and tgt.get('flaky', False):
% if tgt.build == 'test' and tgt.get('run', True) and tgt.language == 'c++' and tgt.get('flaky', False) and not tgt.get('external_deps', None):
$(E) "[RUN] Testing ${tgt.name}"
$(Q) $(BINDIR)/$(CONFIG)/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 )
% endif
% endfor
ifeq ($(HAS_ZOOKEEPER),true)
test_zookeeper: buildtests_zookeeper
% for tgt in targets:
% if tgt.build == 'test' and tgt.get('run', True) and tgt.language == 'c++' and not tgt.get('flaky', False) and 'zookeeper' in tgt.get('external_deps', []):
$(E) "[RUN] Testing ${tgt.name}"
$(Q) $(BINDIR)/$(CONFIG)/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 )
% endif
% endfor
flaky_test_zookeeper: buildtests_zookeeper
% for tgt in targets:
% if tgt.build == 'test' and tgt.get('run', True) and tgt.language == 'c++' and tgt.get('flaky', False) and 'zookeeper' in tgt.get('external_deps', []):
$(E) "[RUN] Testing ${tgt.name}"
$(Q) $(BINDIR)/$(CONFIG)/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 )
% endif
% endfor
else
test_zookeeper:
flaky_test_zookeeper:
endif
test_python: static_c
$(E) "[RUN] Testing python code"
$(Q) tools/run_tests/run_tests.py -lpython -c$(CONFIG)
@ -1063,11 +1155,26 @@ ifeq ($(CONFIG),opt)
% for lib in libs:
% if lib.language == "c++":
% if lib.build == "all":
% if not lib.get('external_deps', None):
$(E) "[STRIP] Stripping lib${lib.name}.a"
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/lib${lib.name}.a
% endif
% endif
% endif
% endfor
ifeq ($(HAS_ZOOKEEPER),true)
% for lib in libs:
% if lib.language == "c++":
% if lib.build == "all":
% if 'zookeeper' in lib.get('external_deps', []):
$(E) "[STRIP] Stripping lib${lib.name}.a"
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/lib${lib.name}.a
% endif
% endif
% endif
% endfor
endif
endif
strip-shared_c: shared_c
@ -1075,12 +1182,26 @@ ifeq ($(CONFIG),opt)
% for lib in libs:
% if lib.language == "c":
% if lib.build == "all":
% if not lib.get('external_deps', None):
$(E) "[STRIP] Stripping lib${lib.name}.so"
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)
% endif
% endif
% endif
% endfor
ifeq ($(HAS_ZOOKEEPER),true)
% for lib in libs:
% if lib.language == "c":
% if lib.build == "all":
% if 'zookeeper' in lib.get('external_deps', []):
$(E) "[STRIP] Stripping lib${lib.name}.so"
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)
% endif
% endif
% endif
% endfor
endif
endif
strip-shared_cxx: shared_cxx
ifeq ($(CONFIG),opt)
@ -1125,6 +1246,11 @@ $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_unsecure.pc:
$(Q) mkdir -p $(@D)
$(Q) echo "$(GRPC_UNSECURE_PC_FILE)" | tr , '\n' >$@
$(LIBDIR)/$(CONFIG)/pkgconfig/grpc_zookeeper.pc:
$(E) "[MAKE] Generating $@"
$(Q) mkdir -p $(@D)
$(Q) echo -e "$(GRPC_ZOOKEEPER_PC_FILE)" >$@
$(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc:
$(E) "[MAKE] Generating $@"
$(Q) mkdir -p $(@D)
@ -1213,12 +1339,27 @@ install-static_c: static_c strip-static_c install-pkg-config_c
% for lib in libs:
% if lib.language == "c":
% if lib.build == "all":
% if not lib.get('external_deps', None):
$(E) "[INSTALL] Installing lib${lib.name}.a"
$(Q) $(INSTALL) -d $(prefix)/lib
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}.a $(prefix)/lib/lib${lib.name}.a
% endif
% endif
% endif
% endfor
ifeq ($(HAS_ZOOKEEPER),true)
% for lib in libs:
% if lib.language == "c":
% if lib.build == "all":
% if 'zookeeper' in lib.get('external_deps', []):
$(E) "[INSTALL] Installing lib${lib.name}.a"
$(Q) $(INSTALL) -d $(prefix)/lib
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}.a $(prefix)/lib/lib${lib.name}.a
% endif
% endif
% endif
% endfor
endif
install-static_cxx: static_cxx strip-static_cxx install-pkg-config_cxx
% for lib in libs:
@ -1235,6 +1376,30 @@ install-static_cxx: static_cxx strip-static_cxx install-pkg-config_cxx
% for lib in libs:
% if lib.language == lang_filter:
% if lib.build == "all":
% if not lib.get('external_deps', None):
ifeq ($(SYSTEM),MINGW32)
$(E) "[INSTALL] Installing ${lib.name}.$(SHARED_EXT)"
$(Q) $(INSTALL) -d $(prefix)/lib
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/${lib.name}.$(SHARED_EXT) $(prefix)/lib/${lib.name}.$(SHARED_EXT)
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}-imp.a $(prefix)/lib/lib${lib.name}-imp.a
else
$(E) "[INSTALL] Installing lib${lib.name}.$(SHARED_EXT)"
$(Q) $(INSTALL) -d $(prefix)/lib
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.$(SHARED_EXT)
ifneq ($(SYSTEM),Darwin)
$(Q) ln -sf lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so.${settings.version.major}
$(Q) ln -sf lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so
endif
endif
% endif
% endif
% endif
% endfor
ifeq ($(HAS_ZOOKEEPER),true)
% for lib in libs:
% if lib.language == lang_filter:
% if lib.build == "all":
% if 'zookeeper' in lib.get('external_deps', []):
ifeq ($(SYSTEM),MINGW32)
$(E) "[INSTALL] Installing ${lib.name}.$(SHARED_EXT)"
$(Q) $(INSTALL) -d $(prefix)/lib
@ -1251,7 +1416,9 @@ endif
endif
% endif
% endif
% endif
% endfor
endif
ifneq ($(SYSTEM),MINGW32)
ifneq ($(SYSTEM),Darwin)
$(Q) ldconfig || true
@ -1281,12 +1448,15 @@ else
% endfor
endif
install-pkg-config_c: pc_gpr pc_c pc_c_unsecure
install-pkg-config_c: pc_gpr pc_c pc_c_unsecure pc_c_zookeeper
$(E) "[INSTALL] Installing C pkg-config files"
$(Q) $(INSTALL) -d $(prefix)/lib/pkgconfig
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/pkgconfig/gpr.pc $(prefix)/lib/pkgconfig/gpr.pc
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/pkgconfig/grpc.pc $(prefix)/lib/pkgconfig/grpc.pc
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_unsecure.pc $(prefix)/lib/pkgconfig/grpc_unsecure.pc
ifeq ($(HAS_ZOOKEEPER),true)
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_zookeeper.pc $(prefix)/lib/pkgconfig/grpc_zookeeper.pc
endif
install-pkg-config_cxx: pc_cxx pc_cxx_unsecure
$(E) "[INSTALL] Installing C++ pkg-config files"
@ -1480,6 +1650,9 @@ endif
for src in lib.src:
sources_that_don_t_need_openssl.add(src)
if 'zookeeper' in lib.get('external_deps', []):
libs = libs + ' -lzookeeper_mt'
if lib.get('secure', 'check') == 'yes' or lib.get('secure', 'check') == 'check':
lib_deps = lib_deps + ' $(OPENSSL_DEP)'
mingw_lib_deps = mingw_lib_deps + ' $(OPENSSL_DEP)'
@ -1619,6 +1792,9 @@ $(${tgt.name.upper()}_OBJS)\
% for dep in tgt.deps:
$(LIBDIR)/$(CONFIG)/lib${dep}.a\
% endfor
% if 'zookeeper' in tgt.get('external_deps', []):
-lzookeeper_mt\
% endif
% if tgt.language == "c++":
% if tgt.build == 'protoc':
$(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC)\

@ -0,0 +1,43 @@
/*
*
* Copyright 2015, Google Inc.
* 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 Google Inc. 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.
*
*/
/* This is just a compilation test, to see if we have Zookeeper C client
library installed. */
#include <stdlib.h>
#include <zookeeper/zookeeper.h>
int main() {
zookeeper_init(NULL, NULL, 0, 0, 0, 0);
return 0;
}

@ -0,0 +1,223 @@
/*
*
* Copyright 2015, Google Inc.
* 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 Google Inc. 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.
*
*/
#include "test/core/util/test_config.h"
#include "test/core/util/port.h"
#include "test/cpp/util/echo.grpc.pb.h"
#include "src/core/support/env.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/server_credentials.h>
#include <grpc++/status.h>
#include <gtest/gtest.h>
#include <grpc/grpc.h>
#include <grpc/grpc_zookeeper.h>
#include <zookeeper/zookeeper.h>
using grpc::cpp::test::util::EchoRequest;
using grpc::cpp::test::util::EchoResponse;
namespace grpc {
namespace testing {
class ZookeeperTestServiceImpl
: public ::grpc::cpp::test::util::TestService::Service {
public:
Status Echo(ServerContext* context, const EchoRequest* request,
EchoResponse* response) GRPC_OVERRIDE {
response->set_message(request->message());
return Status::OK;
}
};
class ZookeeperTest : public ::testing::Test {
protected:
ZookeeperTest() {}
void SetUp() GRPC_OVERRIDE {
SetUpZookeeper();
// Sets up two servers
int port1 = grpc_pick_unused_port_or_die();
server1_ = SetUpServer(port1);
int port2 = grpc_pick_unused_port_or_die();
server2_ = SetUpServer(port2);
// Registers service /test in zookeeper
RegisterService("/test", "test");
// Registers service instance /test/1 in zookeeper
string value =
"{\"host\":\"localhost\",\"port\":\"" + to_string(port1) + "\"}";
RegisterService("/test/1", value);
// Registers service instance /test/2 in zookeeper
value =
"{\"host\":\"localhost\",\"port\":\"" + to_string(port2) + "\"}";
RegisterService("/test/2", value);
}
// Requires zookeeper server running
void SetUpZookeeper() {
// Finds zookeeper server address in environment
// Default is localhost:2181
zookeeper_address_ = "localhost:2181";
char* addr = gpr_getenv("GRPC_ZOOKEEPER_SERVER_TEST");
if (addr != NULL) {
string addr_str(addr);
zookeeper_address_ = addr_str;
gpr_free(addr);
}
gpr_log(GPR_DEBUG, zookeeper_address_.c_str());
// Connects to zookeeper server
zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
zookeeper_handle_ =
zookeeper_init(zookeeper_address_.c_str(), NULL, 15000, 0, 0, 0);
GPR_ASSERT(zookeeper_handle_ != NULL);
// Registers zookeeper name resolver in grpc
grpc_zookeeper_register();
}
std::unique_ptr<Server> SetUpServer(const int port) {
string server_address = "localhost:" + to_string(port);
ServerBuilder builder;
builder.AddListeningPort(server_address, InsecureServerCredentials());
builder.RegisterService(&service_);
std::unique_ptr<Server> server = builder.BuildAndStart();
return server;
}
void RegisterService(const string& name, const string& value) {
char* path = (char*)gpr_malloc(name.size());
int status = zoo_exists(zookeeper_handle_, name.c_str(), 0, NULL);
if (status == ZNONODE) {
status =
zoo_create(zookeeper_handle_, name.c_str(), value.c_str(),
value.size(), &ZOO_OPEN_ACL_UNSAFE, 0, path, name.size());
} else {
status = zoo_set(zookeeper_handle_, name.c_str(), value.c_str(),
value.size(), -1);
}
gpr_free(path);
GPR_ASSERT(status == 0);
}
void DeleteService(const string& name) {
int status = zoo_delete(zookeeper_handle_, name.c_str(), -1);
GPR_ASSERT(status == 0);
}
void ChangeZookeeperState() {
server1_->Shutdown();
DeleteService("/test/1");
}
void TearDown() GRPC_OVERRIDE {
server1_->Shutdown();
server2_->Shutdown();
zookeeper_close(zookeeper_handle_);
}
void ResetStub() {
string target = "zookeeper://" + zookeeper_address_ + "/test";
channel_ = CreateChannel(target, InsecureCredentials(), ChannelArguments());
stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel_));
}
string to_string(const int number) {
std::stringstream strs;
strs << number;
return strs.str();
}
std::shared_ptr<ChannelInterface> channel_;
std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub_;
std::unique_ptr<Server> server1_;
std::unique_ptr<Server> server2_;
ZookeeperTestServiceImpl service_;
zhandle_t* zookeeper_handle_;
string zookeeper_address_;
};
// Tests zookeeper state change between two RPCs
// TODO(ctiller): leaked objects in this test
TEST_F(ZookeeperTest, ZookeeperStateChangeTwoRpc) {
ResetStub();
// First RPC
EchoRequest request1;
EchoResponse response1;
ClientContext context1;
context1.set_authority("test");
request1.set_message("Hello");
Status s1 = stub_->Echo(&context1, request1, &response1);
EXPECT_EQ(response1.message(), request1.message());
EXPECT_TRUE(s1.ok());
// Zookeeper state changes
gpr_log(GPR_DEBUG, "Zookeeper state change");
ChangeZookeeperState();
// Waits for re-resolving addresses
// TODO(ctiller): RPC will probably fail if not waiting
sleep(1);
// Second RPC
EchoRequest request2;
EchoResponse response2;
ClientContext context2;
context2.set_authority("test");
request2.set_message("World");
Status s2 = stub_->Echo(&context2, request2, &response2);
EXPECT_EQ(response2.message(), request2.message());
EXPECT_TRUE(s2.ok());
}
} // namespace testing
} // namespace grpc
int main(int argc, char** argv) {
grpc_test_init(argc, argv);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -146,6 +146,14 @@ RUN wget http://www.dotdeb.org/dotdeb.gpg -O- | apt-key add -
RUN apt-get update && apt-get install -y \
git php5 php5-dev phpunit unzip
##################
# Zookeeper dependencies
# Install dependencies
RUN apt-get install -y libzookeeper-mt-dev
RUN mkdir /var/local/jenkins
# Define the default command.

@ -146,6 +146,14 @@ RUN wget http://www.dotdeb.org/dotdeb.gpg -O- | apt-key add -
RUN apt-get update && apt-get install -y \
git php5 php5-dev phpunit unzip
##################
# Zookeeper dependencies
# Install dependencies
RUN apt-get install -y libzookeeper-mt-dev
RUN mkdir /var/local/jenkins
# Define the default command.

@ -79,6 +79,7 @@ then
-e "config=$config" \
-e "language=$language" \
-e "arch=$arch" \
-e "GRPC_ZOOKEEPER_SERVER_TEST=grpc-jenkins-master:2181" \
-e CCACHE_DIR=/tmp/ccache \
-i \
-v "$git_root:/var/local/jenkins/grpc" \

@ -1671,6 +1671,23 @@
"test/cpp/end2end/thread_stress_test.cc"
]
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc++",
"grpc++_test_util",
"grpc_test_util",
"grpc_zookeeper"
],
"headers": [],
"language": "c++",
"name": "zookeeper_test",
"src": [
"test/cpp/end2end/zookeeper_test.cc"
]
},
{
"deps": [
"end2end_certs",
@ -13030,6 +13047,23 @@
"src/core/transport/transport_op_string.c"
]
},
{
"deps": [
"gpr",
"grpc"
],
"headers": [
"include/grpc/grpc_zookeeper.h",
"src/core/client_config/resolvers/zookeeper_resolver.h"
],
"language": "c",
"name": "grpc_zookeeper",
"src": [
"include/grpc/grpc_zookeeper.h",
"src/core/client_config/resolvers/zookeeper_resolver.c",
"src/core/client_config/resolvers/zookeeper_resolver.h"
]
},
{
"deps": [
"gpr",

@ -1472,6 +1472,23 @@
"windows"
]
},
{
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"flaky": false,
"language": "c++",
"name": "zookeeper_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
]
},
{
"ci_platforms": [
"linux",

File diff suppressed because one or more lines are too long

@ -52,6 +52,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_unsecure", "grpc_unsec
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_zookeeper", "grpc_zookeeper\grpc_zookeeper.vcxproj", "{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}"
ProjectSection(myProperties) = preProject
lib = "True"
EndProjectSection
ProjectSection(ProjectDependencies) = postProject
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc++", "grpc++\grpc++.vcxproj", "{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}"
ProjectSection(myProperties) = preProject
lib = "True"
@ -178,6 +187,22 @@ Global
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}.Release-DLL|Win32.Build.0 = Release-DLL|Win32
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}.Release-DLL|x64.ActiveCfg = Release-DLL|x64
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}.Release-DLL|x64.Build.0 = Release-DLL|x64
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Debug|Win32.ActiveCfg = Debug|Win32
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Debug|x64.ActiveCfg = Debug|x64
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Release|Win32.ActiveCfg = Release|Win32
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Release|x64.ActiveCfg = Release|x64
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Debug|Win32.Build.0 = Debug|Win32
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Debug|x64.Build.0 = Debug|x64
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Release|Win32.Build.0 = Release|Win32
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Release|x64.Build.0 = Release|x64
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Debug-DLL|Win32.Build.0 = Debug|Win32
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Debug-DLL|x64.ActiveCfg = Debug|x64
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Debug-DLL|x64.Build.0 = Debug|x64
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Release-DLL|Win32.ActiveCfg = Release|Win32
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Release-DLL|Win32.Build.0 = Release|Win32
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Release-DLL|x64.ActiveCfg = Release|x64
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Release-DLL|x64.Build.0 = Release|x64
{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Debug|Win32.ActiveCfg = Debug|Win32
{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Debug|x64.ActiveCfg = Debug|x64
{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Release|Win32.ActiveCfg = Release|Win32

@ -24,6 +24,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_unsecure", "grpc_unsec
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_zookeeper", "grpc_zookeeper\grpc_zookeeper.vcxproj", "{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}"
ProjectSection(myProperties) = preProject
lib = "True"
EndProjectSection
ProjectSection(ProjectDependencies) = postProject
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_csharp_ext", "grpc_csharp_ext\grpc_csharp_ext.vcxproj", "{D64C6D63-4458-4A88-AB38-35678384A7E4}"
ProjectSection(myProperties) = preProject
lib = "True"
@ -65,6 +74,14 @@ Global
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}.Release|Win32.Build.0 = Release-DLL|Win32
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}.Release|x64.ActiveCfg = Release-DLL|x64
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}.Release|x64.Build.0 = Release-DLL|x64
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Debug|Win32.ActiveCfg = Debug|Win32
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Debug|Win32.Build.0 = Debug|Win32
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Debug|x64.ActiveCfg = Debug|x64
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Debug|x64.Build.0 = Debug|x64
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Release|Win32.ActiveCfg = Release|Win32
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Release|Win32.Build.0 = Release|Win32
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Release|x64.ActiveCfg = Release|x64
{F14EBEC1-DC43-45D3-8A7D-1A47072EFE50}.Release|x64.Build.0 = Release|x64
{D64C6D63-4458-4A88-AB38-35678384A7E4}.Debug|Win32.ActiveCfg = Debug|Win32
{D64C6D63-4458-4A88-AB38-35678384A7E4}.Debug|Win32.Build.0 = Debug|Win32
{D64C6D63-4458-4A88-AB38-35678384A7E4}.Debug|x64.ActiveCfg = Debug|x64

Loading…
Cancel
Save