Ejemplo n.º 1
0
void cetcd_client_destroy(cetcd_client *cli) {
    cetcd_addresses_release(cli->addresses);
    cetcd_array_release(cli->addresses);
    curl_easy_cleanup(cli->curl);
    curl_global_cleanup();
    cetcd_array_destroy(&cli->watchers);
}
Ejemplo n.º 2
0
/*
 * 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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
size_t cetcd_parse_response(char *ptr, size_t size, size_t nmemb, void *userdata) {
    int len, i;
    char *key, *val;
    cetcd_response_parser *parser;
    yajl_status status;
    cetcd_response *resp = NULL;
    cetcd_array *addrs = NULL;

    enum resp_parser_st {
        request_line_start_st,
        request_line_end_st,
        request_line_http_status_start_st,
        request_line_http_status_st,
        request_line_http_status_end_st,
        header_key_start_st,
        header_key_st,
        header_key_end_st,
        header_val_start_st,
        header_val_st,
        header_val_end_st,
        blank_line_st,
        json_start_st,
        json_end_st,
        response_discard_st
    };
    /* Headers we are interested in:
     * X-Etcd-Index: 14695
     * X-Raft-Index: 672930
     * X-Raft-Term: 12
     * */
    parser = userdata;
    if (parser->api_type == ETCD_MEMBERS) {
        addrs = parser->resp;
    } else {
        resp = parser->resp;
    }
    len = size * nmemb;
    for (i = 0; i < len; ++i) {
        if (parser->st == request_line_start_st) {
            if (ptr[i] == ' ') {
                parser->st = request_line_http_status_start_st;
            }
            continue;
        }
        if (parser->st == request_line_end_st) {
            if (ptr[i] == '\n') {
                parser->st = header_key_start_st;
            }
            continue;
        }
        if (parser->st == request_line_http_status_start_st) {
            parser->buf = sdscatlen(parser->buf, ptr+i, 1);
            parser->st = request_line_http_status_st;
            continue;
        }
        if (parser->st == request_line_http_status_st) {
            if (ptr[i] == ' ') {
                parser->st = request_line_http_status_end_st;
            } else {
                parser->buf = sdscatlen(parser->buf, ptr+i, 1);
                continue;
            }
        }
        if (parser->st == request_line_http_status_end_st) {
            val = parser->buf;
            parser->http_status = atoi(val);
            sdsclear(parser->buf);
            parser->st = request_line_end_st;
            if (parser->api_type == ETCD_MEMBERS && parser->http_status != 200) {
                parser->st = response_discard_st;
            }
            continue;
        }
        if (parser->st == header_key_start_st) {
            if (ptr[i] == '\r') {
                ++i;
            }
            if (ptr[i] == '\n') {
                parser->st = blank_line_st;
                if (parser->http_status >= 300 && parser->http_status < 400) {
                    /*this is a redirection, restart the state machine*/
                    parser->st = request_line_start_st;
                    break;
                }
                continue;
            }
            parser->st = header_key_st;
        }
        if (parser->st == header_key_st) {
            parser->buf = sdscatlen(parser->buf, ptr+i, 1);
            if (ptr[i] == ':') {
                parser->st = header_key_end_st;
            } else {
                continue;
            }
        }
        if (parser->st == header_key_end_st) {
            parser->st = header_val_start_st;
            continue;
        }
        if (parser->st == header_val_start_st) {
            if (ptr[i] == ' ') {
                continue;
            }
            parser->st = header_val_st;
        }
        if (parser->st == header_val_st) {
            if (ptr[i] == '\r') {
                ++i;
            }
            if (ptr[i] == '\n') {
                parser->st = header_val_end_st;
            } else {
                parser->buf = sdscatlen(parser->buf, ptr+i, 1);
                continue;
            }
        }
        if (parser->st == header_val_end_st) {
            parser->st = header_key_start_st;
            if (parser->api_type == ETCD_MEMBERS) {
                continue;
            }
            int count = 0;
            sds *kvs = sdssplitlen(parser->buf, sdslen(parser->buf), ":", 1, &count);
            sdsclear(parser->buf);
            if (count < 2) {
                sdsfreesplitres(kvs, count);
                continue;
            }
            key = kvs[0];
            val = kvs[1];
            if (strncmp(key, "X-Etcd-Index", sizeof("X-Etcd-Index")-1) == 0) {
                resp->etcd_index = atoi(val);
            } else if (strncmp(key, "X-Raft-Index", sizeof("X-Raft-Index")-1) == 0) {
                resp->raft_index = atoi(val);
            } else if (strncmp(key, "X-Raft-Term", sizeof("X-Raft-Term")-1) == 0) {
                resp->raft_term = atoi(val);
            }
            sdsfreesplitres(kvs, count);
            continue;
        }
        if (parser->st == blank_line_st) {
            if (ptr[i] != '{') {
                /*not a json response, discard*/
                parser->st = response_discard_st;
                if (resp->err == NULL && parser->api_type == ETCD_KEYS) {
                    resp->err = calloc(1, sizeof(cetcd_error));
                    resp->err->ecode = error_response_parsed_failed;
                    resp->err->message = sdsnew("not a json response");
                    resp->err->cause = sdsnewlen(ptr, len);
                }
                continue;
            }
            parser->st = json_start_st;
            cetcd_array_init(&parser->ctx.keystack, 10);
            cetcd_array_init(&parser->ctx.nodestack, 10);
            if (parser->api_type == ETCD_MEMBERS) {
                parser->ctx.userdata = addrs;
                parser->json = yajl_alloc(&sync_callbacks, 0, &parser->ctx);
            }
            else {
                if (parser->http_status != 200 && parser->http_status != 201) {
                    resp->err = calloc(1, sizeof(cetcd_error));
                    parser->ctx.userdata = resp->err;
                    parser->json = yajl_alloc(&error_callbacks, 0, &parser->ctx);
                } else {
                    parser->ctx.userdata = resp;
                    parser->json = yajl_alloc(&callbacks, 0, &parser->ctx);
                }
            }
        }
        if (parser->st == json_start_st) {
            if (yajl_status_ok != yajl_parse(parser->json, (const unsigned char *)ptr + i, len - i)) {
                parser->st = json_end_st;
            } else {
                parser->st = response_discard_st;
                yajl_free(parser->json);
                cetcd_array_destroy(&parser->ctx.keystack);
                cetcd_array_destroy(&parser->ctx.nodestack);
            }
        }
        if (parser->st == json_end_st) {
            status = yajl_complete_parse(parser->json);
            yajl_free(parser->json);
            cetcd_array_destroy(&parser->ctx.keystack);
            cetcd_array_destroy(&parser->ctx.nodestack);
            /*parse failed, TODO set error message*/
            if (status != yajl_status_ok) {
                if ( parser->api_type == ETCD_KEYS && resp->err == NULL) {
                    resp->err = calloc(1, sizeof(cetcd_error));
                    resp->err->ecode = error_response_parsed_failed;
                    resp->err->message = sdsnew("http response is invalid json format");
                    resp->err->cause = sdsnewlen(ptr, len);
                }
                return 0;
            }
            break;
        }
        if (parser->st == response_discard_st) {
            return len;
        }
    }
    return len;
}