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; }
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); }