mcs_st *lmc_create(mcs_st *ptr, const char *config) { assert(ptr); memset(ptr, 0, sizeof(*ptr)); ptr->kind = MCS_KIND_LIBMEMCACHED; memcached_st *mst = memcached_create(NULL); if (mst != NULL) { memcached_behavior_set(mst, MEMCACHED_BEHAVIOR_NO_BLOCK, 1); memcached_behavior_set(mst, MEMCACHED_BEHAVIOR_KETAMA, 1); memcached_behavior_set(mst, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1); memcached_server_st *mservers; mservers = memcached_servers_parse(config); if (mservers != NULL) { memcached_server_push(mst, mservers); ptr->data = mst; ptr->nservers = (int) memcached_server_list_count(mservers); if (ptr->nservers > 0) { ptr->servers = calloc(sizeof(mcs_server_st), ptr->nservers); if (ptr->servers != NULL) { for (int i = 0; i < ptr->nservers; i++) { ptr->servers[i].fd = -1; } int j = 0; for (; j < ptr->nservers; j++) { strncpy(ptr->servers[j].hostname, memcached_server_name(mservers + j), sizeof(ptr->servers[j].hostname) - 1); ptr->servers[j].port = (int) memcached_server_port(mservers + j); if (ptr->servers[j].port <= 0) { moxi_log_write("lmc_create failed, could not parse port: %s\n", config); break; } } if (j >= ptr->nservers) { memcached_server_list_free(mservers); return ptr; } } } memcached_server_list_free(mservers); } } mcs_free(ptr); return NULL; }
memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_server_list_st list) { uint32_t count; memcached_server_st *new_host_list; uint32_t x; if (! list) return MEMCACHED_SUCCESS; count= memcached_server_list_count(list); new_host_list= libmemcached_realloc(ptr, memcached_server_list(ptr), sizeof(memcached_server_st) * (count + memcached_server_count(ptr))); if (! new_host_list) return MEMCACHED_MEMORY_ALLOCATION_FAILURE; memcached_server_list_set(ptr, new_host_list); for (x= 0; x < count; x++) { memcached_server_write_instance_st instance; if ((ptr->flags.use_udp && list[x].type != MEMCACHED_CONNECTION_UDP) || ((list[x].type == MEMCACHED_CONNECTION_UDP) && ! (ptr->flags.use_udp)) ) return MEMCACHED_INVALID_HOST_PROTOCOL; WATCHPOINT_ASSERT(list[x].hostname[0] != 0); instance= memcached_server_instance_fetch(ptr, memcached_server_count(ptr)); /* TODO check return type */ (void)memcached_server_create_with(ptr, instance, list[x].hostname, list[x].port, list[x].weight, list[x].type); ptr->number_of_hosts++; } /* Provides backwards compatibility with server list. */ { memcached_server_write_instance_st instance; instance= memcached_server_instance_fetch(ptr, 0); instance->number_of_hosts= memcached_server_count(ptr); } return run_distribution(ptr); }
memcached_server_list_st memcached_server_list_append_with_weight(memcached_server_list_st ptr, const char *hostname, in_port_t port, uint32_t weight, memcached_return_t *error) { uint32_t count; memcached_server_list_st new_host_list; if (hostname == NULL || error == NULL) return NULL; if (! port) port= MEMCACHED_DEFAULT_PORT; /* Increment count for hosts */ count= 1; if (ptr != NULL) { count+= memcached_server_list_count(ptr); } new_host_list= (memcached_server_write_instance_st)realloc(ptr, sizeof(memcached_server_st) * count); if (!new_host_list) { *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE; return NULL; } /* TODO: Check return type */ memcached_server_create_with(NULL, &new_host_list[count-1], hostname, port, weight, MEMCACHED_CONNECTION_TCP); /* Backwards compatibility hack */ memcached_servers_set_count(new_host_list, count); *error= MEMCACHED_SUCCESS; return new_host_list; }
void server_startup(server_startup_st *construct) { unsigned int x; if ((construct->server_list= getenv("MEMCACHED_SERVERS"))) { printf("servers %s\n", construct->server_list); construct->servers= memcached_servers_parse(construct->server_list); construct->server_list= NULL; construct->count= 0; } else { { char server_string_buffer[8096]; char *end_ptr; end_ptr= server_string_buffer; for (x= 0; x < construct->count; x++) { char buffer[1024]; /* Nothing special for number */ int count; int status; sprintf(buffer, "/tmp/%umemc.pid", x); if (access(buffer, F_OK) == 0) { FILE *fp= fopen(buffer, "r"); remove(buffer); if (fp != NULL) { if (fgets(buffer, sizeof(buffer), fp) != NULL) { pid_t pid = atol(buffer); if (pid != 0) kill(pid, SIGTERM); } fclose(fp); } } if (x == 0) { sprintf(buffer, "%s -d -P /tmp/%umemc.pid -t 1 -p %u -U %u -m 128", MEMCACHED_BINARY, x, x + TEST_PORT_BASE, x + TEST_PORT_BASE); } else { sprintf(buffer, "%s -d -P /tmp/%umemc.pid -t 1 -p %u -U %u", MEMCACHED_BINARY, x, x + TEST_PORT_BASE, x + TEST_PORT_BASE); } fprintf(stderr, "STARTING SERVER: %s\n", buffer); status= system(buffer); count= sprintf(end_ptr, "localhost:%u,", x + TEST_PORT_BASE); end_ptr+= count; } *end_ptr= 0; construct->server_list= strdup(server_string_buffer); } printf("servers %s\n", construct->server_list); construct->servers= memcached_servers_parse(construct->server_list); } assert(construct->servers); srandom(time(NULL)); for (x= 0; x < memcached_server_list_count(construct->servers); x++) { printf("\t%s : %u\n", construct->servers[x].hostname, construct->servers[x].port); assert(construct->servers[x].fd == -1); assert(construct->servers[x].cursor_active == 0); } printf("\n"); }
pr_memcache_t *pr_memcache_conn_new(pool *p, module *m, unsigned long flags, uint64_t nreplicas) { pr_memcache_t *mcache; pool *sub_pool; memcached_st *mc; memcached_return res; if (p == NULL) { errno = EINVAL; return NULL; } if (configured_server_list == NULL) { pr_trace_msg(trace_channel, 9, "%s", "unable to create new memcache connection: No servers configured"); errno = EPERM; return NULL; } mc = memcached_create(NULL); if (mc == NULL) { errno = ENOMEM; return NULL; } res = memcached_server_push(mc, configured_server_list); if (res != MEMCACHED_SUCCESS) { unsigned int count; count = memcached_server_list_count(configured_server_list); pr_trace_msg(trace_channel, 2, "error adding %u memcached %s to connection: %s", count, count != 1 ? "servers" : "server", memcached_strerror(mc, res)); memcached_free(mc); errno = EPERM; return NULL; } sub_pool = make_sub_pool(p); pr_pool_tag(sub_pool, "Memcache connection pool"); mcache = pcalloc(sub_pool, sizeof(pr_memcache_t)); mcache->pool = sub_pool; mcache->owner = m; mcache->mc = mc; mcache->refcount = 1; /* The namespace table is null; it will be created if/when callers * configure namespace prefixes. */ mcache->namespace_tab = NULL; /* Set some of the desired behavior flags on the connection */ if (mcache_set_options(mcache, flags, nreplicas) < 0) { int xerrno = errno; pr_memcache_conn_close(mcache); destroy_pool(mcache->pool); errno = xerrno; return NULL; } /* Check that all of the configured servers are alive and usable. */ if (mcache_ping_servers(mcache) < 0) { int xerrno = errno; pr_memcache_conn_close(mcache); destroy_pool(mcache->pool); errno = xerrno; return NULL; } /* Make sure we are connected to the configured servers by querying * some stats/info from them. */ if (mcache_stat_servers(mcache) < 0) { int xerrno = errno; pr_memcache_conn_close(mcache); destroy_pool(mcache->pool); errno = xerrno; return NULL; } if (sess_mcache == NULL) { sess_mcache = mcache; } return mcache; }
static int mcache_ping_servers(pr_memcache_t *mcache) { memcached_server_st *alive_server_list; memcached_return res; memcached_st *clone; uint32_t server_count; register unsigned int i; /* We always start with the configured list of servers. */ clone = memcached_clone(NULL, mcache->mc); if (clone == NULL) { errno = ENOMEM; return -1; } memcached_servers_reset(clone); /* Bug#4242: Don't use memcached_server_push() if we're using * libmemcached-1.0.18 or earlier. Doing so leads to a segfault, due to * this libmemcached bug: * * https://bugs.launchpad.net/libmemcached/+bug/1154159 */ #if LIBMEMCACHED_VERSION_HEX > 0x01000018 memcached_server_push(clone, configured_server_list); #endif server_count = memcached_server_count(clone); pr_trace_msg(trace_channel, 16, "pinging %lu memcached %s", (unsigned long) server_count, server_count != 1 ? "servers" : "server"); alive_server_list = NULL; for (i = 0; i < server_count; i++) { memcached_server_instance_st server; server = memcached_server_instance_by_position(clone, i); pr_trace_msg(trace_channel, 17, "pinging server %s:%d", memcached_server_name(server), memcached_server_port(server)); if (libmemcached_util_ping(memcached_server_name(server), memcached_server_port(server), &res) == FALSE) { pr_trace_msg(trace_channel, 4, "error pinging %s:%d: %s", memcached_server_name(server), memcached_server_port(server), memcached_strerror(clone, res)); } else { pr_trace_msg(trace_channel, 17, "server %s:%d is alive", memcached_server_name(server), memcached_server_port(server)); alive_server_list = memcached_server_list_append(alive_server_list, memcached_server_name(server), memcached_server_port(server), &res); if (alive_server_list == NULL) { pr_trace_msg(trace_channel, 1, "error appending server %s:%d to list: %s", memcached_server_name(server), memcached_server_port(server), memcached_strerror(clone, res)); memcached_free(clone); errno = EPERM; return -1; } } } if (alive_server_list != NULL) { memcached_servers_reset(mcache->mc); res = memcached_server_push(mcache->mc, alive_server_list); if (res != MEMCACHED_SUCCESS) { unsigned int count; count = memcached_server_list_count(alive_server_list); pr_trace_msg(trace_channel, 2, "error adding %u alive memcached %s to connection: %s", count, count != 1 ? "servers" : "server", memcached_strerror(mcache->mc, res)); memcached_free(clone); errno = EPERM; return -1; } else { unsigned int count; count = memcached_server_list_count(alive_server_list); pr_trace_msg(trace_channel, 9, "now using %d alive memcached %s", count, count != 1 ? "servers" : "server"); memcached_server_list_free(alive_server_list); } } memcached_free(clone); return 0; }
void server_startup(server_startup_st *construct) { if ((construct->server_list= getenv("MEMCACHED_SERVERS"))) { printf("servers %s\n", construct->server_list); construct->servers= memcached_servers_parse(construct->server_list); construct->server_list= NULL; construct->count= 0; } else { { char server_string_buffer[8096]; char *end_ptr; end_ptr= server_string_buffer; for (uint32_t x= 0; x < construct->count; x++) { int count; int status; in_port_t port; { char *var; char variable_buffer[1024]; snprintf(variable_buffer, sizeof(variable_buffer), "LIBMEMCACHED_PORT_%u", x); if ((var= getenv(variable_buffer))) { port= (in_port_t)atoi(var); } else { port= (in_port_t)(x + TEST_PORT_BASE); } } char buffer[PATH_MAX]; snprintf(buffer, sizeof(buffer), PID_FILE_BASE, x); kill_file(buffer); if (x == 0) { snprintf(buffer, sizeof(buffer), "%s -d -u root -P "PID_FILE_BASE" -t 1 -p %u -U %u -m 128", MEMCACHED_BINARY, x, port, port); } else { snprintf(buffer, sizeof(buffer), "%s -d -u root -P "PID_FILE_BASE" -t 1 -p %u -U %u", MEMCACHED_BINARY, x, port, port); } if (libmemcached_util_ping("localhost", port, NULL)) { fprintf(stderr, "Server on port %u already exists\n", port); } else { status= system(buffer); fprintf(stderr, "STARTING SERVER: %s status:%d\n", buffer, status); } count= sprintf(end_ptr, "localhost:%u,", port); end_ptr+= count; } *end_ptr= 0; int *pids= calloc(construct->count, sizeof(int)); for (uint32_t x= 0; x < construct->count; x++) { char buffer[PATH_MAX]; /* Nothing special for number */ snprintf(buffer, sizeof(buffer), PID_FILE_BASE, x); uint32_t counter= 3000; // Absurd, just to catch run away process while (pids[x] <= 0 && --counter) { FILE *file= fopen(buffer, "r"); if (file) { char pid_buffer[1024]; char *found= fgets(pid_buffer, sizeof(pid_buffer), file); if (found) { pids[x]= atoi(pid_buffer); fclose(file); if (pids[x] > 0) break; } fclose(file); } global_sleep(); } bool was_started= false; if (pids[x] > 0) { counter= 30; while (--counter) { if (kill(pids[x], 0) == 0) { was_started= true; break; } global_sleep(); } } if (was_started == false) { fprintf(stderr, "Failed to open buffer %s(%d)\n", buffer, pids[x]); for (uint32_t y= 0; y < construct->count; y++) { if (pids[y] > 0) kill(pids[y], SIGTERM); } abort(); } } free(pids); construct->server_list= strdup(server_string_buffer); } printf("servers %s\n", construct->server_list); construct->servers= memcached_servers_parse(construct->server_list); } assert(construct->servers); srandom((unsigned int)time(NULL)); for (uint32_t x= 0; x < memcached_server_list_count(construct->servers); x++) { printf("\t%s : %d\n", memcached_server_name(&construct->servers[x]), memcached_server_port(&construct->servers[x])); assert(construct->servers[x].fd == -1); assert(construct->servers[x].cursor_active == 0); } printf("\n"); }
mcs_st *lmc_create(mcs_st *ptr, const char *config, const char *default_usr, const char *default_pwd, const char *opts) { assert(ptr); memset(ptr, 0, sizeof(*ptr)); ptr->kind = MCS_KIND_LIBMEMCACHED; memcached_st *mst = memcached_create(NULL); if (mst != NULL) { memcached_behavior_t b = MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED; uint64_t v = 1; if (opts != NULL) { if (strstr(opts, "distribution:ketama-weighted") != NULL) { b = MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED; v = 1; } else if (strstr(opts, "distribution:ketama") != NULL) { b = MEMCACHED_BEHAVIOR_KETAMA; v = 1; } else if (strstr(opts, "distribution:modula") != NULL) { b = MEMCACHED_BEHAVIOR_KETAMA; v = 0; } } memcached_behavior_set(mst, b, v); memcached_behavior_set(mst, MEMCACHED_BEHAVIOR_NO_BLOCK, 1); memcached_behavior_set(mst, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1); memcached_server_st *mservers; mservers = memcached_servers_parse(config); if (mservers != NULL) { memcached_server_push(mst, mservers); ptr->data = mst; ptr->nservers = (int) memcached_server_list_count(mservers); if (ptr->nservers > 0) { ptr->servers = calloc(sizeof(mcs_server_st), ptr->nservers); if (ptr->servers != NULL) { for (int i = 0; i < ptr->nservers; i++) { ptr->servers[i].fd = -1; } int j = 0; for (; j < ptr->nservers; j++) { strncpy(ptr->servers[j].hostname, memcached_server_name(mservers + j), sizeof(ptr->servers[j].hostname) - 1); ptr->servers[j].port = (int) memcached_server_port(mservers + j); if (ptr->servers[j].port <= 0) { moxi_log_write("lmc_create failed, could not parse port: %s\n", config); break; } if (default_usr != NULL) { ptr->servers[j].usr = strdup(default_usr); } if (default_pwd != NULL) { ptr->servers[j].pwd = strdup(default_pwd); } } if (j >= ptr->nservers) { memcached_server_list_free(mservers); return ptr; } } } memcached_server_list_free(mservers); } } mcs_free(ptr); return NULL; }
void server_startup(server_startup_st *construct) { unsigned int x; if ((construct->server_list= getenv("MEMCACHED_SERVERS"))) { printf("servers %s\n", construct->server_list); construct->servers= memcached_servers_parse(construct->server_list); construct->server_list= NULL; construct->count= 0; } else { { char server_string_buffer[8096]; char *end_ptr; end_ptr= server_string_buffer; for (x= 0; x < construct->count; x++) { char buffer[1024]; /* Nothing special for number */ int count; int status; if (construct->udp){ if(x == 0) { sprintf(buffer, "memcached -d -P /tmp/%umemc.pid -t 1 -U %u -m 128", x, x+ TEST_PORT_BASE); } else { sprintf(buffer, "memcached -d -P /tmp/%umemc.pid -t 1 -U %u", x, x+ TEST_PORT_BASE); } } else{ if(x == 0) { sprintf(buffer, "memcached -d -P /tmp/%umemc.pid -t 1 -p %u -m 128", x, x+ TEST_PORT_BASE); } else { sprintf(buffer, "memcached -d -P /tmp/%umemc.pid -t 1 -p %u", x, x+ TEST_PORT_BASE); } } status= system(buffer); count= sprintf(end_ptr, "localhost:%u,", x + TEST_PORT_BASE); end_ptr+= count; } *end_ptr= 0; construct->server_list= strdup(server_string_buffer); } printf("servers %s\n", construct->server_list); construct->servers= memcached_servers_parse(construct->server_list); } assert(construct->servers); srandom(time(NULL)); for (x= 0; x < memcached_server_list_count(construct->servers); x++) { printf("\t%s : %u\n", construct->servers[x].hostname, construct->servers[x].port); assert(construct->servers[x].fd == -1); assert(construct->servers[x].cursor_active == 0); } printf("\n"); }