Пример #1
0
void lcb_failout_observe_request(lcb_server_t *server,
                                 struct lcb_command_data_st *command_data,
                                 const char *packet,
                                 lcb_size_t npacket,
                                 lcb_error_t err)
{
    lcb_t instance = server->instance;
    protocol_binary_request_header *req = (void *)packet;
    const char *ptr = packet + sizeof(req->bytes);
    const char *end = packet + npacket;
    lcb_observe_resp_t resp;

    memset(&resp, 0, sizeof(resp));
    resp.v.v0.status = LCB_OBSERVE_MAX;
    while (ptr < end) {
        lcb_uint16_t nkey;

        /* ignore vbucket */
        ptr += sizeof(lcb_uint16_t);
        memcpy(&nkey, ptr, sizeof(nkey));
        nkey = ntohs(nkey);

        ptr += sizeof(lcb_uint16_t);
        resp.v.v0.key = ptr;
        resp.v.v0.nkey = nkey;

        TRACE_OBSERVE_PROGRESS(req->request.opaque, ntohs(req->request.vbucket),
                               req->request.opcode, err, &resp);
        lcb_observe_invoke_callback(instance, command_data, err, &resp);
        ptr += nkey;
    }
    if ((command_data->flags & LCB_CMD_F_OBS_BCAST) &&
            lcb_lookup_server_with_command(instance, CMD_OBSERVE,
                                           req->request.opaque, server) < 0) {
        TRACE_OBSERVE_END(req->request.opaque, ntohs(req->request.vbucket),
                          req->request.opcode, err);
        resp.v.v0.key = NULL;
        resp.v.v0.nkey = 0;
        lcb_observe_invoke_callback(instance, command_data, err, &resp);
    }
}
Пример #2
0
static void
H_observe(mc_PIPELINE *pipeline, mc_PACKET *request, packet_info *response,
          lcb_error_t immerr)
{
    lcb_t root = pipeline->parent->cqdata;
    uint32_t ttp;
    uint32_t ttr;
    lcb_size_t pos;
    lcbvb_CONFIG* config;
    const char *end, *ptr;
    mc_REQDATAEX *rd = request->u_rdata.exdata;
    lcb_RESPOBSERVE resp = { 0 };
    MK_ERROR(root, &resp, response, immerr);

    if (resp.rc != LCB_SUCCESS) {
        if (! (request->flags & MCREQ_F_INVOKED)) {
            rd->procs->handler(pipeline, request, resp.rc, NULL);
        }
        return;
    }

    /** The CAS field is split into TTP/TTR values */
    ptr = (char *)&response->res.response.cas;
    memcpy(&ttp, ptr, sizeof(ttp));
    memcpy(&ttr, ptr + sizeof(ttp), sizeof(ttp));

    ttp = ntohl(ttp);
    ttr = ntohl(ttr);

    /** Actual payload sequence of (vb, nkey, key). Repeats multiple times */
    ptr = response->payload;
    end = (char *)ptr + PACKET_NBODY(response);
    config = pipeline->parent->config;

    for (pos = 0; ptr < end; pos++) {
        lcb_cas_t cas;
        lcb_uint8_t obs;
        lcb_uint16_t nkey, vb;
        const char *key;

        memcpy(&vb, ptr, sizeof(vb));
        vb = ntohs(vb);
        ptr += sizeof(vb);
        memcpy(&nkey, ptr, sizeof(nkey));
        nkey = ntohs(nkey);
        ptr += sizeof(nkey);
        key = (const char *)ptr;
        ptr += nkey;
        obs = *((lcb_uint8_t *)ptr);
        ptr += sizeof(obs);
        memcpy(&cas, ptr, sizeof(cas));
        ptr += sizeof(cas);

        resp.key = key;
        resp.nkey = nkey;
        resp.cas = cas;
        resp.status = obs;
        resp.ismaster = pipeline->index == lcbvb_vbmaster(config, vb);
        resp.ttp = 0;
        resp.ttr = 0;
        TRACE_OBSERVE_PROGRESS(response, &resp);
        if (! (request->flags & MCREQ_F_INVOKED)) {
            rd->procs->handler(pipeline, request, resp.rc, &resp);
        }
    }
    TRACE_OBSERVE_END(response);
}
Пример #3
0
static void observe_response_handler(lcb_server_t *server,
                                     struct lcb_command_data_st *command_data,
                                     protocol_binary_response_header *res)
{
    lcb_t root = server->instance;
    lcb_uint16_t status = ntohs(res->response.status);
    lcb_error_t rc = map_error(root, status);
    lcb_uint32_t ttp;
    lcb_uint32_t ttr;
    lcb_size_t pos;

    VBUCKET_CONFIG_HANDLE config;
    const char *end, *ptr = (const char *)&res->response.cas;

    /**
     * If we have an error we must decode the request instead
     */
    if (rc != LCB_SUCCESS) {
        protocol_binary_request_header req;
        lcb_size_t nr;

        nr = ringbuffer_peek(&server->cmd_log, req.bytes, sizeof(req.bytes));
        if (nr != sizeof(req.bytes)) {
            lcb_error_handler(server->instance, LCB_EINTERNAL, NULL);
            abort();
        }
        if (req.request.bodylen) {
            lcb_size_t npacket = sizeof(req.bytes) + ntohl(req.request.bodylen);
            char *packet = server->cmd_log.read_head;
            int allocated = 0;

            if (!ringbuffer_is_continous(&server->cmd_log, RINGBUFFER_READ, npacket)) {
                packet = malloc(npacket);
                if (packet == NULL) {
                    lcb_error_handler(root, LCB_CLIENT_ENOMEM, NULL);
                    abort();
                }
                nr = ringbuffer_peek(&server->cmd_log, packet, npacket);
                if (nr != npacket) {
                    lcb_error_handler(root, LCB_EINTERNAL, NULL);
                    free(packet);
                    abort();
                }
                allocated = 1;
            }
            lcb_failout_observe_request(server, command_data, packet, npacket, rc);
            if (allocated) {
                free(packet);
            }
        }
        return;
    }


    memcpy(&ttp, ptr, sizeof(ttp));
    ttp = ntohl(ttp);
    memcpy(&ttr, ptr + sizeof(ttp), sizeof(ttr));
    ttr = ntohl(ttr);


    ptr = (const char *)res + sizeof(res->bytes);
    end = ptr + ntohl(res->response.bodylen);
    config = root->vbucket_config;
    for (pos = 0; ptr < end; pos++) {
        lcb_cas_t cas;
        lcb_uint8_t obs;
        lcb_uint16_t nkey, vb;
        const char *key;
        lcb_observe_resp_t resp;

        memcpy(&vb, ptr, sizeof(vb));
        vb = ntohs(vb);
        ptr += sizeof(vb);
        memcpy(&nkey, ptr, sizeof(nkey));
        nkey = ntohs(nkey);
        ptr += sizeof(nkey);
        key = (const char *)ptr;
        ptr += nkey;
        obs = *((lcb_uint8_t *)ptr);
        ptr += sizeof(obs);
        memcpy(&cas, ptr, sizeof(cas));
        ptr += sizeof(cas);

        setup_lcb_observe_resp_t(&resp, key, nkey, cas, obs,
                                 server->index == vbucket_get_master(config, vb),
                                 ttp, ttr);
        TRACE_OBSERVE_PROGRESS(res->response.opaque, command_data->vbucket,
                               res->response.opcode, rc, &resp);
        lcb_observe_invoke_callback(root, command_data, rc, &resp);
    }

    /* run callback with null-null-null to signal the end of transfer */
    if ((command_data->flags & LCB_CMD_F_OBS_BCAST) &&
            lcb_lookup_server_with_command(root, CMD_OBSERVE,
                                           res->response.opaque, server) < 0) {

        lcb_observe_resp_t resp;
        memset(&resp, 0, sizeof(resp));
        TRACE_OBSERVE_END(res->response.opaque, command_data->vbucket,
                          res->response.opcode, rc);
        lcb_observe_invoke_callback(root, command_data, LCB_SUCCESS, &resp);
    }
}