/** Update the configuration from a server. */ lcb_error_t lcb_cccp_update(clconfig_provider *provider, const char *host, lcb_string *data) { VBUCKET_CONFIG_HANDLE vbc; clconfig_info *new_config; cccp_provider *cccp = (cccp_provider *)provider; vbc = vbucket_config_create(); if (!vbc) { return LCB_CLIENT_ENOMEM; } if (vbucket_config_parse2(vbc, LIBVBUCKET_SOURCE_MEMORY, data->base, host)) { vbucket_config_destroy(vbc); return LCB_PROTOCOL_ERROR; } new_config = lcb_clconfig_create(vbc, data, LCB_CLCONFIG_CCCP); if (!new_config) { vbucket_config_destroy(vbc); return LCB_CLIENT_ENOMEM; } if (cccp->config) { lcb_clconfig_decref(cccp->config); } /** TODO: Figure out the comparison vector */ new_config->cmpclock = gethrtime(); cccp->config = new_config; lcb_confmon_set_next(provider->parent, new_config, 0); return LCB_SUCCESS; }
static VBUCKET_CONFIG_HANDLE parse_cjson(cJSON *config) { cJSON *json; struct vbucket_config_st *vb; vb = calloc(1, sizeof(struct vbucket_config_st)); if (vb == NULL) { errstr = "Failed to allocate vbucket config struct"; return NULL; } /* set optional credentials */ json = cJSON_GetObjectItem(config, "name"); if (json != NULL && json->type == cJSON_String && strcmp(json->valuestring, "default") != 0) { vb->user = strdup(json->valuestring); } json = cJSON_GetObjectItem(config, "saslPassword"); if (json != NULL && json->type == cJSON_String) { vb->password = strdup(json->valuestring); } /* by default it uses vbucket distribution to map keys to servers */ vb->distribution = VBUCKET_DISTRIBUTION_VBUCKET; json = cJSON_GetObjectItem(config, "nodeLocator"); if (json == NULL) { /* special case: it migth be config without envelope */ if (parse_vbucket_config(vb, config) == NULL) { vbucket_config_destroy(vb); return NULL; } } else if (json->type == cJSON_String) { if (strcmp(json->valuestring, "vbucket") == 0) { vb->distribution = VBUCKET_DISTRIBUTION_VBUCKET; if (parse_vbucket_config(vb, config) == NULL) { vbucket_config_destroy(vb); return NULL; } } else if (strcmp(json->valuestring, "ketama") == 0) { vb->distribution = VBUCKET_DISTRIBUTION_KETAMA; if (parse_ketama_config(vb, config) == NULL) { vbucket_config_destroy(vb); return NULL; } } } else { errstr = "Expected string for nodeLocator"; vbucket_config_destroy(vb); return NULL; } return vb; }
/* Returns true if curr_version could be updated with next_version in * a low-impact stable manner (server-list is the same), allowing the * same connections to be reused. Or returns false if the delta was * too large for an in-place updating of curr_version with information * from next_version. * * The next_version may be destroyed in this call, and the caller * should afterwards only call mcs_free() on the next_version. */ bool lvb_stable_update(mcs_st *curr_version, mcs_st *next_version) { assert(curr_version->kind == MCS_KIND_LIBVBUCKET); assert(curr_version->data != NULL); assert(next_version->kind == MCS_KIND_LIBVBUCKET); assert(next_version->data != NULL); bool rv = false; VBUCKET_CONFIG_DIFF *diff = vbucket_compare((VBUCKET_CONFIG_HANDLE) curr_version->data, (VBUCKET_CONFIG_HANDLE) next_version->data); if (diff != NULL) { if (!diff->sequence_changed) { vbucket_config_destroy((VBUCKET_CONFIG_HANDLE) curr_version->data); curr_version->data = next_version->data; next_version->data = 0; rv = true; } vbucket_free_diff(diff); } return rv; }
static void testConfigDiff(void) { VBUCKET_CONFIG_HANDLE vb1 = vbucket_config_parse_file(configPath("config-diff1")); VBUCKET_CONFIG_HANDLE vb2 = vbucket_config_parse_file(configPath("config-diff2")); VBUCKET_CONFIG_DIFF *diff; assert(vb2); diff = vbucket_compare(vb1, vb2); assert(vb1); assert(diff); assert(diff->sequence_changed); assert(diff->n_vb_changes == 1); assert(strcmp(diff->servers_added[0], "server4:11211") == 0); assert(diff->servers_added[1] == NULL); assert(strcmp(diff->servers_removed[0], "server3:11211") == 0); assert(diff->servers_removed[1] == NULL); vbucket_free_diff(diff); vbucket_config_destroy(vb2); vb2 = vbucket_config_parse_file(configPath("config-diff3")); assert(vb2); diff = vbucket_compare(vb1, vb2); assert(diff); assert(diff->sequence_changed); assert(diff->n_vb_changes == -1); assert(diff->servers_added[0] == NULL); assert(strcmp(diff->servers_removed[0], "server3:11211") == 0); assert(diff->servers_removed[1] == NULL); }
static void testWrongNumVbuckets(const char *fname) { VBUCKET_CONFIG_HANDLE vb = vbucket_config_create(); assert(vb != NULL); assert(vbucket_config_parse(vb, LIBVBUCKET_SOURCE_FILE, configPath(fname)) != 0); assert(strcmp(vbucket_get_error_message(vb), "Number of vBuckets must be a power of two > 0 and <= 65536") == 0); vbucket_config_destroy(vb); }
static void testWrongServer(const char *fname) { VBUCKET_CONFIG_HANDLE vb = vbucket_config_parse_file(configPath(fname)); if (vb == NULL) { fprintf(stderr, "vbucket_config_parse_file error: %s\n", vbucket_get_error()); abort(); } /* Starts at 0 */ assert(vbucket_get_master(vb, 0) == 0); /* Does not change when I told it I found the wrong thing */ assert(vbucket_found_incorrect_master(vb, 0, 1) == 0); assert(vbucket_get_master(vb, 0) == 0); /* Does change if I tell it I got the right thing and it was wrong. */ assert(vbucket_found_incorrect_master(vb, 0, 0) == 1); assert(vbucket_get_master(vb, 0) == 1); /* ...and again */ assert(vbucket_found_incorrect_master(vb, 0, 1) == 2); assert(vbucket_get_master(vb, 0) == 2); /* ...and then wraps */ assert(vbucket_found_incorrect_master(vb, 0, 2) == 0); assert(vbucket_get_master(vb, 0) == 0); vbucket_config_destroy(vb); }
static void config_callback(lcb_server_t *server, lcb_error_t error, const char *json) { VBUCKET_CONFIG_HANDLE config; lcb_t instance = server->instance; server->connection.timeout.usec = 0; lcb_connection_cancel_timer(&server->connection); if (error != LCB_SUCCESS) { lcb_error_handler(instance, error, "Failed to receive configration"); return; } config = vbucket_config_create(); if (config == NULL) { lcb_error_handler(instance, LCB_CLIENT_ENOMEM, "Failed to allocate memory for configuration"); return; } if (vbucket_config_parse2(config, LIBVBUCKET_SOURCE_MEMORY, json, server->connection.host)) { vbucket_config_destroy(config); lcb_error_handler(instance, LCB_PROTOCOL_ERROR, vbucket_get_error_message(config)); return; } lcb_update_vbconfig(instance, config); }
LIBCOUCHBASE_API libcouchbase_error_t libcouchbase_create_compat(libcouchbase_cluster_t type, const void *specific, libcouchbase_t *instance, struct libcouchbase_io_opt_st *io) { libcouchbase_error_t ret = LIBCOUCHBASE_NOT_SUPPORTED; VBUCKET_CONFIG_HANDLE config; *instance = libcouchbase_create(NULL, NULL, NULL, NULL, io); if (*instance == NULL) { return LIBCOUCHBASE_CLIENT_ENOMEM; } config = vbucket_config_create(); if (config == NULL) { libcouchbase_destroy(*instance); *instance = NULL; return LIBCOUCHBASE_CLIENT_ENOMEM; } if (type == LIBCOUCHBASE_MEMCACHED_CLUSTER) { ret = create_memcached(specific, config); } if (ret == LIBCOUCHBASE_SUCCESS) { libcouchbase_apply_vbucket_config(*instance, config); } else { vbucket_config_destroy(config); libcouchbase_destroy(*instance); *instance = NULL; } return ret; }
static int populate_servers(struct vbucket_config_st *vb, cJSON *c) { int i; vb->servers = calloc(vb->num_servers, sizeof(struct server_st)); if (vb->servers == NULL) { vbucket_config_destroy(vb); errstr = "Failed to allocate servers array"; return -1; } for (i = 0; i < vb->num_servers; ++i) { char *server; cJSON *jServer = cJSON_GetArrayItem(c, i); if (jServer == NULL || jServer->type != cJSON_String) { errstr = "Expected array of strings for serverList"; return -1; } server = strdup(jServer->valuestring); if (server == NULL) { errstr = "Failed to allocate storage for server string"; return -1; } vb->servers[i].authority = server; } return 0; }
static void testConfigDiffKetamaSame(void) { VBUCKET_CONFIG_HANDLE vb1 = vbucket_config_parse_file(configPath("ketama-eight-nodes")); VBUCKET_CONFIG_HANDLE vb2 = vbucket_config_parse_file(configPath("ketama-ordered-eight-nodes")); VBUCKET_CONFIG_DIFF *diff; assert(vb1); assert(vb2); diff = vbucket_compare(vb1, vb2); assert(diff); assert(diff->sequence_changed == 0); assert(diff->n_vb_changes == 0); assert(diff->servers_added[0] == NULL); assert(diff->servers_removed[0] == NULL); vbucket_free_diff(diff); vbucket_config_destroy(vb1); vbucket_config_destroy(vb2); }
void lvb_free_data(mcs_st *ptr) { assert(ptr->kind == MCS_KIND_LIBVBUCKET); if (ptr->data != NULL) { vbucket_config_destroy((VBUCKET_CONFIG_HANDLE) ptr->data); } ptr->data = NULL; }
/** Update the configuration from a server. */ lcb_error_t lcb_cccp_update(clconfig_provider *provider, const char *host, lcb_string *data) { VBUCKET_CONFIG_HANDLE vbc; lcb_string sanitized; int rv; clconfig_info *new_config; cccp_provider *cccp = (cccp_provider *)provider; vbc = vbucket_config_create(); if (!vbc) { return LCB_CLIENT_ENOMEM; } lcb_string_init(&sanitized); sanitize_config(data, host, &sanitized); rv = vbucket_config_parse(vbc, LIBVBUCKET_SOURCE_MEMORY, sanitized.base); if (rv) { lcb_string_release(&sanitized); vbucket_config_destroy(vbc); lcb_string_release(&sanitized); return LCB_PROTOCOL_ERROR; } new_config = lcb_clconfig_create(vbc, &sanitized, LCB_CLCONFIG_CCCP); lcb_string_release(&sanitized); if (!new_config) { vbucket_config_destroy(vbc); return LCB_CLIENT_ENOMEM; } if (cccp->config) { lcb_clconfig_decref(cccp->config); } /** TODO: Figure out the comparison vector */ new_config->cmpclock = gethrtime(); cccp->config = new_config; lcb_confmon_provider_success(provider, new_config); return LCB_SUCCESS; }
int main(void) { char *root = getenv("srcdir"); DIR *dp; const char *host; char buffer[PATH_MAX]; char key[NKEY]; int idx, i, len; struct dirent *de; VBUCKET_CONFIG_HANDLE vb; unsigned char checksum[16]; unsigned char expected[16]; void *ctx; if (root != NULL) { sprintf(buffer, "%s/tests/config", root); dp = opendir(buffer); if (dp == NULL) { fprintf(stderr, "Skipping ketama check\nFailed to open %s: %s\n", buffer, strerror(errno)); return 0; } while ((de = readdir(dp)) != NULL) { if (strncmp(de->d_name, "ketama", 6) == 0 && strchr(de->d_name, '.') == NULL) { sprintf(buffer, "%s/tests/config/%s", root, de->d_name); fprintf(stderr, "Running ketama test for: %s\n", de->d_name); vb = vbucket_config_parse_file(buffer); assert(vb != NULL); /* check if it conforms to libketama results */ sprintf(buffer, "%s/tests/config/%s.md5sum", root, de->d_name); read_checksum(buffer, expected); memset(checksum, 0, 16); ctx = NULL; for (i = 0; i < 1000000; i++) { len = sprintf(key, "%d", i); vbucket_map(vb, key, len, NULL, &idx); host = vbucket_config_get_server(vb, idx); ctx = hash_md5_update(ctx, host, strlen(host)); } hash_md5_final(ctx, checksum); for (i = 0; i < 16; i++) { assert(checksum[i] == expected[i]); } vbucket_config_destroy(vb); } } closedir(dp); } return 0; }
static lcb_error_t set_next_config(struct htvb_st *vbs) { VBUCKET_CONFIG_HANDLE new_config = NULL; new_config = vbucket_config_create(); if (!new_config) { return LCB_CLIENT_ENOMEM; } if (vbucket_config_parse(new_config, LIBVBUCKET_SOURCE_MEMORY, vbs->input.base)) { vbucket_config_destroy(new_config); return LCB_PROTOCOL_ERROR; } if (vbs->config) { /** We have a previous configuration... */ VBUCKET_CHANGE_STATUS chstatus = VBUCKET_NO_CHANGES; VBUCKET_CONFIG_DIFF *diff = NULL; VBUCKET_CONFIG_HANDLE old_config = vbs->config->vbc; diff = vbucket_compare(old_config, new_config); if (diff) { chstatus = vbucket_what_changed(diff); vbucket_free_diff(diff); } if (chstatus == VBUCKET_NO_CHANGES) { vbs->config->cmpclock = gethrtime(); vbucket_config_destroy(new_config); return LCB_SUCCESS; } } if (vbs->config) { lcb_clconfig_decref(vbs->config); } vbs->config = lcb_clconfig_create(new_config, &vbs->input, LCB_CLCONFIG_HTTP); vbs->config->cmpclock = gethrtime(); vbs->generation++; return LCB_SUCCESS; }
static void testConfigUserPassword(void) { VBUCKET_CONFIG_HANDLE vb1; VBUCKET_CONFIG_HANDLE vb2; VBUCKET_CONFIG_DIFF *diff; vb1 = vbucket_config_parse_file(configPath("config-user-password1")); assert(vb1); assert(strcmp(vbucket_config_get_user(vb1), "theUser") == 0); assert(strcmp(vbucket_config_get_password(vb1), "thePassword") == 0); vb2 = vbucket_config_parse_file(configPath("config-user-password2")); assert(vb2); assert(strcmp(vbucket_config_get_user(vb2), "theUserIsDifferent") == 0); assert(strcmp(vbucket_config_get_password(vb2), "thePasswordIsDifferent") == 0); diff = vbucket_compare(vb1, vb2); assert(diff); assert(diff->sequence_changed); assert(diff->n_vb_changes == 0); assert(diff->servers_added[0] == NULL); assert(diff->servers_removed[0] == NULL); vbucket_free_diff(diff); diff = vbucket_compare(vb1, vb1); assert(diff); assert(diff->sequence_changed == 0); assert(diff->n_vb_changes == 0); assert(diff->servers_added[0] == NULL); assert(diff->servers_removed[0] == NULL); vbucket_free_diff(diff); vbucket_config_destroy(vb1); vbucket_config_destroy(vb2); }
static VBUCKET_CONFIG_HANDLE backwards_compat(vbucket_source_t source, const char *data) { VBUCKET_CONFIG_HANDLE ret = vbucket_config_create(); if (ret == NULL) { return NULL; } if (vbucket_config_parse(ret, source, data) != 0) { errstr = strdup(ret->errmsg); vbucket_config_destroy(ret); ret = NULL; } return ret; }
LIBCOUCHBASE_API void libcouchbase_destroy(libcouchbase_t instance) { libcouchbase_size_t ii; free(instance->http_uri); if (instance->sock != INVALID_SOCKET) { instance->io->delete_event(instance->io, instance->sock, instance->event); instance->io->destroy_event(instance->io, instance->event); instance->io->close(instance->io, instance->sock); } if (instance->timeout.event != NULL) { instance->io->delete_timer(instance->io, instance->timeout.event); instance->io->destroy_timer(instance->io, instance->timeout.event); instance->timeout.event = NULL; } if (instance->ai != NULL) { freeaddrinfo(instance->ai); } if (instance->vbucket_config != NULL) { vbucket_config_destroy(instance->vbucket_config); } for (ii = 0; ii < instance->nservers; ++ii) { libcouchbase_server_destroy(instance->servers + ii); } free(instance->servers); free(instance->backup_nodes); if (instance->io && instance->io->destructor) { instance->io->destructor(instance->io); } free(instance->vbucket_stream.input.data); free(instance->vbucket_stream.chunk.data); free(instance->vbucket_stream.header); free(instance->vb_server_map); free(instance->histogram); memset(instance, 0xff, sizeof(*instance)); free(instance); }
static void testConfig(const char *fname) { int whoops = 0; const struct key_st *k; int i = 0; VBUCKET_CONFIG_HANDLE vb = vbucket_config_parse_file(configPath(fname)); if (vb == NULL) { fprintf(stderr, "vbucket_config_parse_file error: %s\n", vbucket_get_error()); abort(); } while ((k = &keys[i++])->key != NULL) { int id = vbucket_get_vbucket_by_key(vb, k->key, strlen(k->key)); if (id != k->vbucket) { fprintf(stderr, "Expected vbucket %d for key '%s' but got %d\n", k->vbucket, k->key, id); whoops = 1; } } if (whoops) { abort(); } assert(vbucket_config_get_num_servers(vb) == 3 || vbucket_config_get_num_servers(vb) == 4); assert(vbucket_config_get_num_replicas(vb) == 2); for (i = 0; i < 3; ++i) { assert(strcmp(vbucket_config_get_server(vb, i), servers[i]) == 0); } for (i = 0; i < 4; ++i) { assert(vbucket_get_master(vb, i) == vbuckets[i].master); assert(vbucket_get_replica(vb, i, 0) == vbuckets[i].replicas[0]); assert(vbucket_get_replica(vb, i, 1) == vbuckets[i].replicas[1]); } assert(vbucket_config_get_user(vb) == NULL); assert(vbucket_config_get_password(vb) == NULL); vbucket_config_destroy(vb); }
int main(void) { char *root = getenv("srcdir"); const char *host; char buffer[FILENAME_MAX]; char key[NKEY]; int idx, i, len, ff; VBUCKET_CONFIG_HANDLE vb; unsigned char checksum[16]; unsigned char expected[16]; void *ctx; if (root != NULL) { for (ff = 0; test_cases[ff] != NULL; ++ff) { snprintf(buffer, FILENAME_MAX, "%s/tests/config/%s", root, test_cases[ff]); fprintf(stderr, "Running ketama test for: %s\n", test_cases[ff]); vb = vbucket_config_create(); assert(vbucket_config_parse(vb, LIBVBUCKET_SOURCE_FILE, buffer) == 0); /* check if it conforms to libketama results */ snprintf(buffer, FILENAME_MAX,"%s/tests/config/%s.md5sum", root, test_cases[ff]); read_checksum(buffer, expected); memset(checksum, 0, 16); ctx = NULL; for (i = 0; i < 1000000; i++) { len = snprintf(key, NKEY, "%d", i); vbucket_map(vb, key, len, NULL, &idx); host = vbucket_config_get_server(vb, idx); ctx = hash_md5_update(ctx, host, strlen(host)); } hash_md5_final(ctx, checksum); for (i = 0; i < 16; i++) { assert(checksum[i] == expected[i]); } vbucket_config_destroy(vb); } } exit(EXIT_SUCCESS); }
static void testWrongServerFFT(const char *fname) { VBUCKET_CONFIG_HANDLE vb = vbucket_config_parse_file(configPath(fname)); int rv = 0; int nvb = 0; int i = 0; if (vb == NULL) { fprintf(stderr, "vbucket_config_parse_file error: %s\n", vbucket_get_error()); abort(); } /* found incorrect master should not be the same as get master now */ nvb = vbucket_config_get_num_vbuckets(vb); for (i = 0; i < nvb; i++) { rv = vbucket_get_master(vb, i); assert(rv != vbucket_found_incorrect_master(vb, i, rv)); } /* the ideal test case should be that we check that the vbucket */ /* and the fvbucket map are identical at this point. TODO untill */ /* we have a vbucketlib function that diffs vbuckets and fvbuckets */ vbucket_config_destroy(vb); }
static lcb_error_t set_next_config(struct htvb_st *vbs) { VBUCKET_CONFIG_HANDLE new_config = NULL; new_config = vbucket_config_create(); if (!new_config) { return LCB_CLIENT_ENOMEM; } if (vbucket_config_parse(new_config, LIBVBUCKET_SOURCE_MEMORY, vbs->input.base)) { vbucket_config_destroy(new_config); return LCB_PROTOCOL_ERROR; } if (vbs->config) { lcb_clconfig_decref(vbs->config); } vbs->config = lcb_clconfig_create(new_config, &vbs->input, LCB_CLCONFIG_HTTP); vbs->config->cmpclock = gethrtime(); vbs->generation++; return LCB_SUCCESS; }
int main(int argc, char **argv) { VBUCKET_CONFIG_HANDLE vb = NULL; int rval; int num_keys_per_vbucket; int num_keys_to_generate; int num_vbuckets; char *** keys; int i, j, v, k, total; char *key; if (argc < 4) { printf("vbucketkeygen mapfile <keys per vbucket> <keys to generate>\n\n"); printf(" vbucketkeygen will output a list of keys that equally\n"); printf(" distribute amongst every vbucket.\n\n"); printf(" vbucketkeygen expects a vBucketServerMap JSON mapfile, and\n"); printf(" will print the keyname and vBucketId.\n"); printf(" You may use '-' instead for the filename to specify stdin.\n\n"); printf(" Examples:\n"); printf(" ./vbucketkeygen file.json 10 10000\n\n"); printf(" curl http://HOST:8091/pools/default/buckets/default | \\\n"); printf(" ./vbucketkeygen - 5 10000\n"); exit(1); } if (strcmp("-", argv[1]) == 0) { char buf[50000]; if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) { fprintf(stderr, "ERROR: vbucketkeygen found no input on stdin\n"); exit(1); } buf[sizeof(buf) - 1] = '\0'; vb = vbucket_config_parse_string(buf); } else { vb = vbucket_config_parse_file(argv[1]); } if (vb == NULL) { fprintf(stderr, "ERROR: vbucket_config_parse_string error: %s\n", vbucket_get_error()); exit(1); } rval = 0; num_keys_per_vbucket = atoi(argv[2]); num_keys_to_generate = atoi(argv[3]); num_vbuckets = vbucket_config_get_num_vbuckets(vb); /* allocate memory and set each key to null since strdup will allocate that */ keys = malloc(sizeof(char***) * num_vbuckets); for (i = 0; i < num_vbuckets; i++) { keys[i] = malloc(sizeof(char**) * num_keys_per_vbucket); } for (i = 0; i < num_vbuckets; i++) { for (j = 0 ; j < num_keys_per_vbucket ; j++) { keys[i][j] = 0; } } /* generate keys and copy them to the keys structure */ key = malloc(sizeof(char) * (MAX_KEY_SIZE+1)); for (i = 0; i < num_keys_to_generate; i++) { snprintf(key, MAX_KEY_SIZE + 1, "key_%010d", i); v = vbucket_get_vbucket_by_key(vb, key, strlen(key)); for (k = 0; k < num_keys_per_vbucket; k++) { if (keys[v][k] == 0) { keys[v][k] = strdup(key); break; } } } /* print out <key> <vbucket> and count up total keys so we can check that every vbucket has the correct number of keys */ total = 0; for (i = 0; i < num_vbuckets; i++) { for (j = 0 ; j < num_keys_per_vbucket ; j++) { if (keys[i][j] != 0) { printf("%s %d\n", keys[i][j], i); total++; } } } if (total < (num_vbuckets * num_keys_per_vbucket)) { fprintf(stderr, "some vbuckets don't have enough keys\n"); rval = 1; } vbucket_config_destroy(vb); return rval; }
static int load_cache(file_provider *provider) { lcb_string str; char line[1024]; lcb_ssize_t nr; int fail; FILE *fp = NULL; VBUCKET_CONFIG_HANDLE config = NULL; char *end; struct stat st; int status = -1; lcb_string_init(&str); if (provider->filename == NULL) { return -1; } fp = fopen(provider->filename, "r"); if (fp == NULL) { LOG(provider, ERROR, "Couldn't open filename"); return -1; } if (fstat(fileno(fp), &st)) { provider->last_errno = errno; goto GT_DONE; } if (provider->last_mtime == st.st_mtime) { LOG(provider, INFO, "Rejecting file. Modification time too old"); goto GT_DONE; } config = vbucket_config_create(); if (config == NULL) { goto GT_DONE; } lcb_string_init(&str); while ((nr = fread(line, 1, sizeof(line), fp)) > 0) { if (lcb_string_append(&str, line, nr)) { goto GT_DONE; } } if (ferror(fp)) { goto GT_DONE; } fclose(fp); fp = NULL; if (!str.nused) { status = -1; goto GT_DONE; } end = strstr(str.base, CONFIG_CACHE_MAGIC); if (end == NULL) { LOG(provider, ERROR, "Couldn't find magic in file"); remove(provider->filename); status = -1; goto GT_DONE; } fail = vbucket_config_parse(config, LIBVBUCKET_SOURCE_MEMORY, str.base); if (fail) { status = -1; LOG(provider, ERROR, "Couldn't parse configuration"); remove(provider->filename); goto GT_DONE; } if (vbucket_config_get_distribution_type(config) != VBUCKET_DISTRIBUTION_VBUCKET) { status = -1; LOG(provider, ERROR, "Not applying cached memcached config"); goto GT_DONE; } if (provider->config) { lcb_clconfig_decref(provider->config); } provider->config = lcb_clconfig_create(config, &str, LCB_CLCONFIG_FILE); provider->config->cmpclock = gethrtime(); provider->config->origin = provider->base.type; provider->last_mtime = st.st_mtime; status = 0; config = NULL; GT_DONE: if (fp != NULL) { fclose(fp); } if (config != NULL) { vbucket_config_destroy(config); } lcb_string_release(&str); return status; }