Esempio n. 1
0
static lcb_error_t cccp_connect(lcb_t instance)
{
    lcb_error_t rc;
    lcb_connection_result_t connrc;
    protocol_binary_request_set_cluster_config req;
    lcb_server_t *server = &instance->bootstrap.via.cccp.server;
    lcb_connection_t conn = &server->connection;

    rc = lcb_init_next_host(instance, 11210);

    if (rc != LCB_SUCCESS) {
        return rc;
    }

    conn->on_connect_complete = lcb_server_connect_handler;
    conn->on_timeout = lcb_bootstrap_timeout_handler;
    conn->evinfo.handler = lcb_server_v0_event_handler;
    conn->completion.read = lcb_server_v1_read_handler;
    conn->completion.write = lcb_server_v1_write_handler;
    conn->completion.error = lcb_server_v1_error_handler;
    conn->timeout.usec = instance->config.bootstrap_timeout;

    if (lcb_connection_reset_buffers(conn) != LCB_SUCCESS) {
        return LCB_CLIENT_ENOMEM;
    }

    memset(&req, 0, sizeof(req));
    req.message.header.request.magic = PROTOCOL_BINARY_REQ;
    req.message.header.request.opcode = CMD_GET_CLUSTER_CONFIG;
    req.message.header.request.opaque = ++instance->seqno;
    lcb_server_complete_packet(server, NULL, req.bytes, sizeof(req.bytes));
    instance->last_error = LCB_SUCCESS;

    connrc = lcb_connection_start(conn,
                                  LCB_CONNSTART_NOCB | LCB_CONNSTART_ASYNCERR);
    if (connrc == LCB_CONN_ERROR) {
        return LCB_NETWORK_ERROR;
    }
    if (instance->config.syncmode == LCB_SYNCHRONOUS) {
        lcb_wait(instance);
    }

    return instance->last_error;
}
Esempio n. 2
0
static lcb_error_t multi_get(lcb_t instance,
                             const void *command_cookie,
                             lcb_size_t num,
                             const lcb_get_cmd_t *const *items)
{
    lcb_server_t *server = NULL;
    protocol_binary_request_noop noop;
    lcb_size_t ii, *affected_servers = NULL;
    struct server_info_st *servers = NULL;

    /* we need a vbucket config before we can start getting data.. */
    if (instance->vbucket_config == NULL) {
        switch (instance->type) {
        case LCB_TYPE_CLUSTER:
            return lcb_synchandler_return(instance, LCB_EBADHANDLE);
        case LCB_TYPE_BUCKET:
        default:
            return lcb_synchandler_return(instance, LCB_CLIENT_ETMPFAIL);
        }
    }

    affected_servers = calloc(instance->nservers, sizeof(lcb_size_t));
    if (affected_servers == NULL) {
        return lcb_synchandler_return(instance, LCB_CLIENT_ENOMEM);
    }

    servers = malloc(num * sizeof(struct server_info_st));
    if (servers == NULL) {
        free(affected_servers);
        return lcb_synchandler_return(instance, LCB_CLIENT_ENOMEM);
    }

    for (ii = 0; ii < num; ++ii) {
        const void *key = items[ii]->v.v0.key;
        lcb_size_t nkey = items[ii]->v.v0.nkey;
        const void *hashkey = items[ii]->v.v0.hashkey;
        lcb_size_t nhashkey = items[ii]->v.v0.nhashkey;

        if (nhashkey == 0) {
            hashkey = key;
            nhashkey = nkey;
        }

        (void)vbucket_map(instance->vbucket_config, hashkey, nhashkey,
                          &servers[ii].vb, &servers[ii].idx);
        if (servers[ii].idx < 0 || servers[ii].idx > (int)instance->nservers) {
            free(servers);
            free(affected_servers);
            return lcb_synchandler_return(instance, LCB_NO_MATCHING_SERVER);
        }
        affected_servers[servers[ii].idx]++;
    }

    for (ii = 0; ii < num; ++ii) {
        protocol_binary_request_gat req;
        const void *key = items[ii]->v.v0.key;
        lcb_size_t nkey = items[ii]->v.v0.nkey;
        lcb_time_t exp = items[ii]->v.v0.exptime;
        lcb_size_t nreq = sizeof(req.bytes);
        int vb;

        server = instance->servers + servers[ii].idx;
        vb = servers[ii].vb;

        memset(&req, 0, sizeof(req));
        req.message.header.request.magic = PROTOCOL_BINARY_REQ;
        req.message.header.request.keylen = ntohs((lcb_uint16_t)nkey);
        req.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
        req.message.header.request.vbucket = ntohs((lcb_uint16_t)vb);
        req.message.header.request.bodylen = ntohl((lcb_uint32_t)(nkey));
        req.message.header.request.opaque = ++instance->seqno;

        if (!exp) {
            req.message.header.request.opcode = PROTOCOL_BINARY_CMD_GETQ;
            nreq -= 4;
        } else {
            req.message.header.request.opcode = PROTOCOL_BINARY_CMD_GATQ;
            req.message.header.request.extlen = 4;
            req.message.body.expiration = ntohl((lcb_uint32_t)exp);
            req.message.header.request.bodylen = ntohl((lcb_uint32_t)(nkey) + 4);
        }
        if (items[ii]->v.v0.lock) {
            /* the expiration is optional for GETL command */
            req.message.header.request.opcode = CMD_GET_LOCKED;
        }
        lcb_server_start_packet(server, command_cookie, req.bytes, nreq);
        lcb_server_write_packet(server, key, nkey);
        lcb_server_end_packet(server);
    }
    free(servers);

    memset(&noop, 0, sizeof(noop));
    noop.message.header.request.magic = PROTOCOL_BINARY_REQ;
    noop.message.header.request.opcode = PROTOCOL_BINARY_CMD_NOOP;
    noop.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;

    /*
     ** We don't know which server we sent the data to, so examine
     ** where to send the noop
     */
    for (ii = 0; ii < instance->nservers; ++ii) {
        if (affected_servers[ii]) {
            server = instance->servers + ii;
            noop.message.header.request.opaque = ++instance->seqno;
            lcb_server_complete_packet(server, command_cookie,
                                       noop.bytes, sizeof(noop.bytes));
            lcb_server_send_packets(server);
        }
    }
    free(affected_servers);

    return lcb_synchandler_return(instance, LCB_SUCCESS);
}