static void H_observe_seqno(mc_PIPELINE *pipeline, mc_PACKET *request, packet_info *response, lcb_error_t immerr) { lcb_t root = pipeline->parent->cqdata; lcb_RESPOBSEQNO resp = { 0 }; init_resp3(root, response, request, immerr, (lcb_RESPBASE*)&resp); resp.server_index = pipeline->index; if (resp.rc == LCB_SUCCESS) { const lcb_U8 *data = PACKET_BODY(response); int is_failover = *data != 0; data++; #define COPY_ADV(dstfld, n, conv_fn) \ memcpy(&resp.dstfld, data, n); \ data += n; \ resp.dstfld = conv_fn(resp.dstfld); COPY_ADV(vbid, 2, ntohs); COPY_ADV(cur_uuid, 8, lcb_ntohll); COPY_ADV(persisted_seqno, 8, lcb_ntohll); COPY_ADV(mem_seqno, 8, lcb_ntohll); if (is_failover) { COPY_ADV(old_uuid, 8, lcb_ntohll); COPY_ADV(old_seqno, 8, lcb_ntohll); } #undef COPY_ADV /* Get the server for this command. Note that since this is a successful * operation, the server is never a dummy */ } INVOKE_CALLBACK3(request, &resp, root, LCB_CALLBACK_OBSEQNO); }
/** * Handles the propagation and population of the 'synctoken' information. * @param mc_resp The response packet * @param req The request packet (used to get the vBucket) * @param tgt Pointer to synctoken which should be populated. */ static void handle_synctoken(lcb_t instance, const packet_info *mc_resp, const mc_PACKET *req, lcb_SYNCTOKEN *stok) { const char *sbuf; uint16_t vbid; if (PACKET_EXTLEN(mc_resp) == 0) { return; /* No extras */ } if (!instance->dcpinfo && LCBT_SETTING(instance, dur_synctokens)) { size_t nvb = LCBT_VBCONFIG(instance)->nvb; if (nvb) { instance->dcpinfo = calloc(nvb, sizeof(*instance->dcpinfo)); } } sbuf = PACKET_BODY(mc_resp); vbid = mcreq_get_vbucket(req); stok->vbid_ = vbid; memcpy(&stok->uuid_, sbuf, 8); memcpy(&stok->seqno_, sbuf + 8, 8); stok->uuid_ = lcb_ntohll(stok->uuid_); stok->seqno_ = lcb_ntohll(stok->seqno_); if (instance->dcpinfo) { instance->dcpinfo[vbid] = *stok; } }
static int parse_hello(mc_pSESSREQ sreq, packet_info *packet) { /* some caps */ const char *cur; const char *payload = PACKET_BODY(packet); const char *limit = payload + PACKET_NBODY(packet); for (cur = payload; cur < limit; cur += 2) { lcb_U16 tmp; memcpy(&tmp, cur, sizeof(tmp)); tmp = ntohs(tmp); lcb_log(LOGARGS(sreq, DEBUG), SESSREQ_LOGFMT "Found feature 0x%x (%s)", SESSREQ_LOGID(sreq), tmp, protocol_feature_2_text(tmp)); sreq->inner->features[tmp] = 1; } return 0; }
static void io_read_handler(lcb_connection_t conn) { packet_info pi; cccp_provider *cccp = conn->data; lcb_string jsonstr; lcb_error_t err; int rv; lcb_host_t curhost; memset(&pi, 0, sizeof(pi)); rv = lcb_packet_read_ringbuffer(&pi, conn->input); if (rv < 0) { LOG(cccp, ERR, "Couldn't parse packet!?"); mcio_error(cccp, LCB_EINTERNAL); return; } else if (rv == 0) { lcb_sockrw_set_want(conn, LCB_READ_EVENT, 1); lcb_sockrw_apply_want(conn); return; } if (PACKET_STATUS(&pi) != PROTOCOL_BINARY_RESPONSE_SUCCESS) { lcb_log(LOGARGS(cccp, ERR), "CCCP Packet responded with 0x%x; nkey=%d, nbytes=%lu, cmd=0x%x, seq=0x%x", PACKET_STATUS(&pi), PACKET_NKEY(&pi), PACKET_NBODY(&pi), PACKET_OPCODE(&pi), PACKET_OPAQUE(&pi)); switch (PACKET_STATUS(&pi)) { case PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED: case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND: mcio_error(cccp, LCB_NOT_SUPPORTED); break; default: mcio_error(cccp, LCB_PROTOCOL_ERROR); break; } return; } if (!PACKET_NBODY(&pi)) { mcio_error(cccp, LCB_PROTOCOL_ERROR); return; } if (lcb_string_init(&jsonstr)) { mcio_error(cccp, LCB_CLIENT_ENOMEM); return; } if (lcb_string_append(&jsonstr, PACKET_BODY(&pi), PACKET_NBODY(&pi))) { mcio_error(cccp, LCB_CLIENT_ENOMEM); return; } curhost = *lcb_connection_get_host(&cccp->connection); lcb_packet_release_ringbuffer(&pi, conn->input); release_socket(cccp, 1); err = lcb_cccp_update(&cccp->base, curhost.host, &jsonstr); lcb_string_release(&jsonstr); if (err == LCB_SUCCESS) { lcb_timer_disarm(cccp->timer); cccp->server_active = 0; } else { schedule_next_request(cccp, LCB_PROTOCOL_ERROR, 0); } }