Example #1
0
/**
 * Optionally decompress an incoming payload.
 * @param o The instance
 * @param resp The response received
 * @param[out] bytes pointer to the final payload
 * @param[out] nbytes pointer to the size of the final payload
 * @param[out] freeptr pointer to free. This should be initialized to `NULL`.
 * If temporary dynamic storage is required this will be set to the allocated
 * pointer upon return. Otherwise it will be set to NULL. In any case it must
 */
static void
maybe_decompress(lcb_t o,
    const packet_info *respkt, lcb_RESPGET *rescmd, void **freeptr)
{
    lcb_U8 dtype = 0;
    if (!PACKET_NVALUE(respkt)) {
        return;
    }

    if (PACKET_DATATYPE(respkt) & PROTOCOL_BINARY_DATATYPE_JSON) {
        dtype = LCB_VALUE_F_JSON;
    }

    if (PACKET_DATATYPE(respkt) & PROTOCOL_BINARY_DATATYPE_COMPRESSED) {
        if (LCBT_SETTING(o, compressopts) & LCB_COMPRESS_IN) {
            /* if we inflate, we don't set the flag */
            mcreq_inflate_value(
                PACKET_VALUE(respkt), PACKET_NVALUE(respkt),
                &rescmd->value, &rescmd->nvalue, freeptr);

        } else {
            /* user doesn't want inflation. signal it's compressed */
            dtype |= LCB_VALUE_F_SNAPPYCOMP;
        }
    }
    rescmd->datatype = dtype;
}
Example #2
0
static void getq_response_handler(lcb_server_t *server, packet_info *info)
{
    lcb_t root = server->instance;
    char *packet;
    lcb_uint16_t nkey;
    const char *key = get_key(server, &nkey, &packet);
    lcb_error_t rc;
    lcb_get_resp_t resp;

    fprintf(stderr, "\n The datatype is ...%d", PACKET_DATATYPE(info));

    if (key == NULL) {
        lcb_error_handler(server->instance, LCB_EINTERNAL, NULL);
        return;

    } else if (PACKET_STATUS(info) == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
        const protocol_binary_response_getq *getq = PACKET_EPHEMERAL_START(info);
        rc = LCB_SUCCESS;
        setup_lcb_get_resp_t(&resp, key, nkey,
                             PACKET_VALUE(info), PACKET_NVALUE(info),
                             ntohl(getq->message.body.flags),
                             PACKET_CAS(info),
                             PACKET_DATATYPE(info));

    } else {
        rc = map_error(root, PACKET_STATUS(info));
        setup_lcb_get_resp_t(&resp, key, nkey, NULL, 0, 0, 0, 0);
    }

    root->callbacks.get(root, info->ct.cookie, rc, &resp);
    release_key(server, packet);
}
Example #3
0
static void
H_get(mc_PIPELINE *pipeline, mc_PACKET *request, packet_info *response,
      lcb_error_t immerr)
{
    lcb_t o;
    lcb_RESPGET resp = { 0 };
    void *freeptr = NULL;

    o = pipeline->parent->cqdata;
    init_resp3(o, response, request, immerr, (lcb_RESPBASE *)&resp);

    if (resp.rc == LCB_SUCCESS) {
        const protocol_binary_response_getq *getq =
                PACKET_EPHEMERAL_START(response);
        resp.datatype = PACKET_DATATYPE(response);
        resp.itmflags = ntohl(getq->message.body.flags);
        resp.value = PACKET_VALUE(response);
        resp.nvalue = PACKET_NVALUE(response);
        resp.bufh = response->bufh;
    }

    maybe_decompress(o, response, &resp, &freeptr);
    TRACE_GET_END(response, &resp);
    INVOKE_CALLBACK3(request, &resp, o, LCB_CALLBACK_GET);
    free(freeptr);
}
Example #4
0
static void
H_getreplica(mc_PIPELINE *pipeline, mc_PACKET *request, packet_info *response,
             lcb_error_t immerr)
{
    lcb_error_t rc;
    lcb_get_resp_t resp;
    lcb_t instance = pipeline->parent->instance;
    void *freeptr = NULL;

    MK_RESPKEY(&resp, 0, request);
    MK_ERROR(instance, rc, response, immerr);
    resp.version = 0;

    if (rc == LCB_SUCCESS) {
        const protocol_binary_response_get *get = PACKET_EPHEMERAL_START(response);
        resp.v.v0.cas = PACKET_CAS(response);
        resp.v.v0.datatype = PACKET_DATATYPE(response);
        resp.v.v0.flags = ntohl(get->message.body.flags);
        resp.v.v0.bytes = PACKET_VALUE(response);
        resp.v.v0.nbytes = PACKET_NVALUE(response);
    }
    maybe_decompress(instance, response, &resp, &freeptr);
    request->u_rdata.exdata->callback(pipeline, request, rc, &resp);
    free(freeptr);
}
Example #5
0
static void
H_getreplica(mc_PIPELINE *pipeline, mc_PACKET *request, packet_info *response,
             lcb_error_t immerr)
{
    lcb_RESPGET resp = { 0 };
    lcb_t instance = pipeline->parent->cqdata;
    void *freeptr = NULL;
    mc_REQDATAEX *rd = request->u_rdata.exdata;

    init_resp3(instance, response, request, immerr, (lcb_RESPBASE *)&resp);

    if (resp.rc == LCB_SUCCESS) {
        const protocol_binary_response_get *get = PACKET_EPHEMERAL_START(response);
        resp.itmflags = ntohl(get->message.body.flags);
        resp.datatype = PACKET_DATATYPE(response);
        resp.value = PACKET_VALUE(response);
        resp.nvalue = PACKET_NVALUE(response);
        resp.bufh = response->bufh;
    }

    maybe_decompress(instance, response, &resp, &freeptr);
    rd->procs->handler(pipeline, request, resp.rc, &resp);
    free(freeptr);
}
Example #6
0
static void
H_get(mc_PIPELINE *pipeline, mc_PACKET *request, packet_info *response,
      lcb_error_t immerr)
{
    lcb_error_t rc;
    lcb_t o;
    lcb_get_resp_t resp;
    void *freeptr = NULL;

    o = pipeline->parent->instance;
    MK_RESPKEY(&resp, 0, request);
    MK_ERROR(o, rc, response, immerr);
    resp.version = 0;

    if (rc == LCB_SUCCESS) {
        const protocol_binary_response_getq *getq =
                PACKET_EPHEMERAL_START(response);

        resp.v.v0.cas = PACKET_CAS(response);
        resp.v.v0.datatype = PACKET_DATATYPE(response);
        resp.v.v0.flags = ntohl(getq->message.body.flags);
        resp.v.v0.bytes = PACKET_VALUE(response);
        resp.v.v0.nbytes = PACKET_NVALUE(response);
        rc = LCB_SUCCESS;
    } else {
        resp.v.v0.cas = 0;
        resp.v.v0.nbytes = 0;
        resp.v.v0.bytes = NULL;
        resp.v.v0.flags = 0;
    }

    maybe_decompress(o, response, &resp, &freeptr);
    INVOKE_CALLBACK(request, o->callbacks.get,
                    (o, MCREQ_PKT_COOKIE(request), rc, &resp));
    free(freeptr);
}
Example #7
0
static void get_replica_response_handler(lcb_server_t *server,
                                         packet_info *info)
{
    lcb_t root = server->instance;
    lcb_uint16_t nkey;
    const char *key;
    char *packet;
    lcb_uint16_t status = PACKET_STATUS(info);

    lcb_error_t rc = map_error(root, status);

    /**
     * Success? always perform the callback
     */
    if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
        const protocol_binary_response_get *get = PACKET_EPHEMERAL_START(info);
        lcb_get_resp_t resp;
        setup_lcb_get_resp_t(&resp,
                             PACKET_KEY(info), PACKET_NKEY(info),
                             PACKET_VALUE(info), PACKET_NVALUE(info),
                             ntohl(get->message.body.flags),
                             PACKET_CAS(info),
                             PACKET_DATATYPE(info));
        root->callbacks.get(root, info->ct.cookie, rc, &resp);
        return;
    }

    key = get_key(server, &nkey, &packet);

    /**
     * Following code handles errors.
     */
    if (info->ct.replica == -1) {
        /* Perform the callback. Either SELECT or ALL */
        lcb_get_resp_t resp;
        setup_lcb_get_resp_t(&resp, key, nkey, NULL, 0, 0, 0, 0);
        PACKET_TRACE(TRACE_GET_END, info, rc, &resp);
        root->callbacks.get(root, info->ct.cookie, rc, &resp);
        release_key(server, packet);
        return;
    }

    /** LCB_REPLICA_FIRST */
    if (status == PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET) {
        /**
         * the config was updated, start from first replica.
         * Reset the iteration count
         */
        info->ct.replica = 0;
    } else {
        info->ct.replica++;
    }

    if (info->ct.replica < root->nreplicas) {
        /* try next replica */
        protocol_binary_request_get req;
        lcb_server_t *new_server;
        int idx = vbucket_get_replica(root->vbucket_config,
                                      info->ct.vbucket,
                                      info->ct.replica);
        if (idx < 0 || idx > (int)root->nservers) {
            lcb_error_handler(root, LCB_NETWORK_ERROR,
                              "GET_REPLICA: missing server");
            release_key(server, packet);
            return;
        }
        new_server = root->servers + idx;
        memset(&req, 0, sizeof(req));
        req.message.header.request.magic = PROTOCOL_BINARY_REQ;
        req.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
        req.message.header.request.opcode = CMD_GET_REPLICA;
        req.message.header.request.keylen = ntohs((lcb_uint16_t)nkey);
        req.message.header.request.vbucket = ntohs(info->ct.vbucket);
        req.message.header.request.bodylen = ntohl((lcb_uint32_t)nkey);
        req.message.header.request.opaque = ++root->seqno;
        TRACE_GET_BEGIN(&req, key, nkey, 0);
        lcb_server_retry_packet(new_server, &info->ct,
                                req.bytes, sizeof(req.bytes));
        lcb_server_write_packet(new_server, key, nkey);
        lcb_server_end_packet(new_server);
        lcb_server_send_packets(new_server);
    } else {
        /* give up and report the error */
        lcb_get_resp_t resp;
        setup_lcb_get_resp_t(&resp, key, nkey, NULL, 0, 0, 0, 0);
        PACKET_TRACE(TRACE_GET_END, info, rc, &resp)
        root->callbacks.get(root, info->ct.cookie, rc, &resp);
    }

    release_key(server, packet);
}