in libs/etcdlib/src/etcd.c [492:589]
int etcdlib_watch(etcdlib_t *etcdlib, const char *key, long long index, char **action, char **prevValue, char **value,
char **rkey, long long *modifiedIndex) {
json_error_t error;
json_t *js_root = NULL;
json_t *js_node = NULL;
json_t *js_prevNode = NULL;
json_t *js_action = NULL;
json_t *js_value = NULL;
json_t *js_rkey = NULL;
json_t *js_prevValue = NULL;
json_t *js_modIndex = NULL;
json_t *js_index = NULL;
int retVal = ETCDLIB_RC_ERROR;
char *url = NULL;
int res;
struct MemoryStruct reply;
reply.memory = malloc(1); /* will be grown as needed by the realloc above */
reply.memorySize = 0; /* no data at this point */
reply.header = NULL; /* will be grown as needed by the realloc above */
reply.headerSize = 0; /* no data at this point */
if (index != 0)
asprintf(&url, "http://%s:%d/v2/keys/%s?wait=true&recursive=true&waitIndex=%lld", etcdlib->host, etcdlib->port,
key, index);
else
asprintf(&url, "http://%s:%d/v2/keys/%s?wait=true&recursive=true", etcdlib->host, etcdlib->port, key);
// don't use shared curl/mutex for watch, that will lock everything.
CURL *curl = NULL;
res = performRequest(&curl, NULL, url, GET, NULL, (void *) &reply);
curl_easy_cleanup(curl);
if (url)
free(url);
if (res == CURLE_OK) {
js_root = json_loads(reply.memory, 0, &error);
if (js_root != NULL) {
js_action = json_object_get(js_root, ETCD_JSON_ACTION);
js_node = json_object_get(js_root, ETCD_JSON_NODE);
js_prevNode = json_object_get(js_root, ETCD_JSON_PREVNODE);
js_index = json_object_get(js_root, ETCD_JSON_INDEX);
retVal = ETCDLIB_RC_OK;
}
if (js_prevNode != NULL) {
js_prevValue = json_object_get(js_prevNode, ETCD_JSON_VALUE);
}
if (js_node != NULL) {
js_rkey = json_object_get(js_node, ETCD_JSON_KEY);
js_value = json_object_get(js_node, ETCD_JSON_VALUE);
js_modIndex = json_object_get(js_node, ETCD_JSON_MODIFIEDINDEX);
}
if (js_prevNode != NULL) {
js_prevValue = json_object_get(js_prevNode, ETCD_JSON_VALUE);
}
if ((prevValue != NULL) && (js_prevValue != NULL) && (json_is_string(js_prevValue))) {
*prevValue = strdup(json_string_value(js_prevValue));
}
if (modifiedIndex != NULL) {
if ((js_modIndex != NULL) && (json_is_integer(js_modIndex))) {
*modifiedIndex = json_integer_value(js_modIndex);
} else if ((js_index != NULL) && (json_is_integer(js_index))) {
*modifiedIndex = json_integer_value(js_index);
} else {
*modifiedIndex = index;
}
}
if ((rkey != NULL) && (js_rkey != NULL) && (json_is_string(js_rkey))) {
*rkey = strdup(json_string_value(js_rkey));
}
if ((action != NULL) && (js_action != NULL) && (json_is_string(js_action))) {
*action = strdup(json_string_value(js_action));
}
if ((value != NULL) && (js_value != NULL) && (json_is_string(js_value))) {
*value = strdup(json_string_value(js_value));
}
if (js_root != NULL) {
json_decref(js_root);
}
} else if (res == CURLE_OPERATION_TIMEDOUT) {
//ignore timeout
retVal = ETCDLIB_RC_TIMEOUT;
} else {
fprintf(stderr, "Got curl error: %s\n", curl_easy_strerror(res));
retVal = ETCDLIB_RC_ERROR;
}
free(reply.memory);
return retVal;
}