/* * cetcd_cluster_request tries to request the whole cluster. It round-robin to next server if the request failed * */ void *cetcd_cluster_request(cetcd_client *cli, cetcd_request *req) { size_t i, count; cetcd_string url; cetcd_error *err = NULL; cetcd_response *resp = NULL; cetcd_array *addrs = NULL; void *res = NULL; count = cetcd_array_size(cli->addresses); for(i = 0; i < count; ++i) { url = sdscatprintf(sdsempty(), "http://%s/%s", (cetcd_string)cetcd_array_get(cli->addresses, cli->picked), req->uri); req->url = url; req->cli = cli; res = cetcd_send_request(cli->curl, req); sdsfree(url); /*api_type == syncCluster, got address, return*/ if (req->api_type == ETCD_MEMBERS ){ if ((addrs = res)) { if ( cetcd_array_size(addrs)) { return addrs; } else { cetcd_array_destroy(addrs); } } } else { if((resp=res) && resp->err && resp->err->ecode == error_send_request_failed) { if (i != count-1) { cetcd_response_release(resp); resp = NULL; } } else { /*got response, return*/ return resp; } } /*try next*/ if (i != count-1) { cli->picked = (cli->picked + 1) % count; } } /*the whole cluster failed*/ if (req->api_type == ETCD_MEMBERS) return NULL; if (resp) { if(resp->err) { err = resp->err; /*remember last error*/ } resp->err = calloc(1, sizeof(cetcd_error)); resp->err->ecode = error_cluster_failed; resp->err->message = sdsnew("etcd_do_request: all cluster servers failed."); if (err) { resp->err->message = sdscatprintf(resp->err->message, " last error: %s", err->message); cetcd_error_release(err); } resp->err->cause = sdsdup(req->uri); } return resp; }
void cetcd_watcher_release(cetcd_watcher *watcher) { if (watcher) { if (watcher->key) { sdsfree(watcher->key); } if (watcher->curl) { curl_easy_cleanup(watcher->curl); } if (watcher->parser) { sdsfree(watcher->parser->buf); cetcd_response_release(watcher->parser->resp); free(watcher->parser); } free(watcher); } }
/* * cetcd_cluster_request tries to request the whole cluster. It round-robin to next server if the request failed * */ cetcd_response *cetcd_cluster_request(cetcd_client *cli, cetcd_request *req) { int i; size_t count; cetcd_string url; cetcd_error *err; cetcd_response *resp; err = NULL; resp = NULL; count = cetcd_array_size(cli->addresses); for(i = 0; i < count; ++i) { url = sdscatprintf(sdsempty(), "http://%s/%s", (cetcd_string)cetcd_array_get(cli->addresses, cli->picked), req->uri); req->url = url; req->cli = cli; resp = cetcd_send_request(cli->curl, req); sdsfree(url); if(resp && resp->err && resp->err->ecode == error_send_request_failed) { if (i == count-1) { break; } /*try next*/ cli->picked = (cli->picked + 1) % count; cetcd_response_release(resp); resp = NULL; } else { /*got response, return*/ return resp; } } /*the whole cluster failed*/ if (resp) { if(resp->err) { err = resp->err; /*remember last error*/ } resp->err = calloc(1, sizeof(cetcd_error)); resp->err->ecode = error_cluster_failed; resp->err->message = sdsnew("etcd_do_request: all cluster servers failed."); if (err) { resp->err->message = sdscatprintf(resp->err->message, " last error: %s", err->message); cetcd_error_release(err); } resp->err->cause = sdsdup(req->uri); } return resp; }
int main(int argc, char *argv[]) { cetcd_client cli; cetcd_response *resp; cetcd_array addrs; cetcd_array_init(&addrs, 3); cetcd_array_append(&addrs, "http://127.0.0.1:2379"); cetcd_client_init(&cli, &addrs); resp = cetcd_get(&cli, "/radar/service"); if(resp->err) { printf("error :%d, %s (%s)\n", resp->err->ecode, resp->err->message, resp->err->cause); } cetcd_response_print(resp); cetcd_response_release(resp); cetcd_array_destroy(&addrs); cetcd_client_destroy(&cli); return 0; }
static int cetcd_reap_watchers(cetcd_client *cli, CURLM *mcurl) { int added, ignore; CURLMsg *msg; CURL *curl; cetcd_string url; cetcd_watcher *watcher; cetcd_response *resp; added = 0; while ((msg = curl_multi_info_read(mcurl, &ignore)) != NULL) { if (msg->msg == CURLMSG_DONE) { curl = msg->easy_handle; curl_easy_getinfo(curl, CURLINFO_PRIVATE, &watcher); resp = watcher->parser->resp; if (msg->data.result != CURLE_OK) { /*try next in round-robin ways*/ /*FIXME There is a race condition if multiple watchers failed*/ if (watcher->attempts) { cli->picked = (cli->picked+1)%(cetcd_array_size(cli->addresses)); url = cetcd_watcher_build_url(cli, watcher); curl_easy_setopt(watcher->curl, CURLOPT_URL, url); sdsfree(url); curl_multi_remove_handle(mcurl, curl); curl_multi_add_handle(mcurl, curl); /*++added; *watcher->attempts --; */ continue; } else { resp->err = calloc(1, sizeof(cetcd_error)); resp->err->ecode = error_cluster_failed; resp->err->message = sdsnew("cetcd_reap_watchers: all cluster servers failed."); } } if (watcher->callback) { watcher->callback(watcher->userdata, resp); if (resp->err) { curl_multi_remove_handle(mcurl, curl); cetcd_watcher_release(watcher); break; } cetcd_response_release(resp); watcher->parser->resp = NULL; /*surpress it be freed again by cetcd_watcher_release*/ } if (!watcher->once) { sdsclear(watcher->parser->buf); watcher->parser->st = 0; watcher->parser->resp = calloc(1, sizeof(cetcd_response)); if (watcher->index) { watcher->index ++; url = cetcd_watcher_build_url(cli, watcher); curl_easy_setopt(watcher->curl, CURLOPT_URL, url); sdsfree(url); } curl_multi_remove_handle(mcurl, curl); curl_multi_add_handle(mcurl, curl); ++added; continue; } curl_multi_remove_handle(mcurl, curl); cetcd_watcher_release(watcher); } } return added; }