Couchbase-Client

 view release on metacpan or  search on metacpan

xs/Client_multi.xs  view on Meta::CPAN

    
    void **keys;
    size_t *sizes;
    time_t *exps;
    SV **tmpsv;
    PLCB_sync_t *syncp;
    
    void *keys_stacked[MULTI_STACK_ELEM];
    size_t sizes_stacked[MULTI_STACK_ELEM];
    time_t exps_stacked[MULTI_STACK_ELEM];
    
    mk_instance_vars(self, instance, object);
    _MULTI_INIT_COMMON(object, ret, nreq, args, now);
    
    syncp = &object->sync;
    syncp->parent = object;
    syncp->ret = (AV*)ret;
    
    if(nreq <= MULTI_STACK_ELEM) {
        keys = keys_stacked;
        sizes = sizes_stacked;
        exps = (cmd == MULTI_CMD_GET) ? NULL : exps_stacked;
    } else {
        Newx(keys, nreq, void*); SAVEFREEPV(keys);
        Newx(sizes, nreq, size_t); SAVEFREEPV(sizes);
        if(cmd == MULTI_CMD_GET) {
            exps = NULL;
        } else {
            Newx(exps, nreq, time_t); SAVEFREEPV(exps);
        } 
    }
    
    for(i = 0; i < nreq; i++) {
        _fetch_assert(tmpsv, args, i, "arguments");
        
        if(SvTYPE(*tmpsv) <= SVt_PV) {
            if(exps) {
                die("This command requires a valid expiry");
            }
            plcb_get_str_or_die(*tmpsv, keys[i], sizes[i], "key");            
        } else {
            AV *argav;
            
            if(SvROK(*tmpsv) == 0 || ( (argav = (AV*)SvRV(*tmpsv))
                                      && SvTYPE(argav) != SVt_PVAV)) {
                die("Expected an array reference");
            }
            _fetch_assert(tmpsv, argav, 0, "missing key");
            
            plcb_get_str_or_die(*tmpsv, keys[i], sizes[i], "key");
            
            if(exps) {
                _fetch_assert(tmpsv, argav, 1, "expiry");
                if(! (exps[i] = SvUV(*tmpsv)) ) {
                    die("expiry of 0 passed. This is not what you want");
                }
            }
        }
    }
    
    plcb_callbacks_set_multi(object);
    
    if(cmd == MULTI_CMD_TOUCH) {
        err = libcouchbase_mtouch(instance, syncp, nreq,
                                  (const void* const*)keys, sizes, exps);
    } else {
        err = libcouchbase_mget(instance, syncp, nreq,
                                (const void* const*)keys, sizes, NULL);
    }
    
    if(err == LIBCOUCHBASE_SUCCESS) {
        object->io_ops->run_event_loop(object->io_ops);
    } else {
        for(i = 0; i < nreq; i++) {
            AV *errav = newAV();
            plcb_ret_set_err(object, errav, err);
            hv_store(ret, keys[i], sizes[i],
                     plcb_ret_blessed_rv(object, errav), 0);
        }
    }
    
    plcb_callbacks_set_single(object);
    
    return newRV_inc( (SV*)ret);
}

static SV*
PLCB_multi_set_common(SV *self, AV *args, int cmd)
{
    _dMULTI_VARS
    PLCB_sync_t *syncs = NULL;
    PLCB_sync_t syncs_stacked[MULTI_STACK_ELEM];
    libcouchbase_storage_t storop;
    int nwait;
    
    mk_instance_vars(self, instance, object);
    
    _MULTI_INIT_COMMON(object, ret, nreq, args, now);
    
    if(nreq <= MULTI_STACK_ELEM) {
        syncs = syncs_stacked;
    } else {
        Newx(syncs, nreq, PLCB_sync_t);
        SAVEFREEPV(syncs);
    }
    
    nwait = 0;
    storop = _cmd2storop(cmd);
    
    for(i = 0; i < nreq; i++) {
        AV *argav;
        SV **tmpsv;
        char *value;
        STRLEN nvalue;
        SV *value_sv = NULL;
        uint32_t store_flags = 0;
        uint64_t cas = 0;
        time_t exp = 0;
        
        _fetch_assert(tmpsv, args, i, "empty argument in spec");
        
        if (SvROK(*tmpsv) == 0 || ( ((argav = (AV*)SvRV(*tmpsv)) &&
                                    SvTYPE(argav) != SVt_PVAV))) {
            die("Expected array reference");
        }
        
        _fetch_assert(tmpsv, argav, 0, "expected key");
        plcb_get_str_or_die(*tmpsv, syncs[i].key, syncs[i].nkey, "key");
        _fetch_assert(tmpsv, argav, 1, "expected_value");
        plcb_get_str_or_die(*tmpsv, value, nvalue, "value");
        value_sv = *tmpsv;
        
        switch(cmd) {
        case MULTI_CMD_SET:
        case MULTI_CMD_ADD:
        case MULTI_CMD_REPLACE:
        case MULTI_CMD_APPEND:
        case MULTI_CMD_PREPEND:
            _exp_from_av(argav, 2, now, exp, tmpsv);
            _cas_from_av(argav, 3, cas, tmpsv);
            break;
        case MULTI_CMD_CAS:



( run in 0.895 second using v1.01-cache-2.11-cpan-140bd7fdf52 )