Esempio n. 1
0
int
pycbc_tc_encode_key(pycbc_Bucket *conn,
                    PyObject **key,
                    void **buf,
                    size_t *nbuf)
{
    int rv;
    Py_ssize_t plen;

    PyObject *orig_key;
    PyObject *new_key = NULL;

    if (!conn->tc) {
        return encode_common(key, buf, nbuf, PYCBC_FMT_UTF8);
    }

    orig_key = *key;
    pycbc_assert(orig_key);

    rv = do_call_tc(conn, orig_key, NULL, &new_key, ENCODE_KEY);

    if (new_key == NULL || rv < 0) {
        return -1;
    }

    rv = PyBytes_AsStringAndSize(new_key, (char**)buf, &plen);

    if (rv == -1) {
        PYCBC_EXC_WRAP_KEY(PYCBC_EXC_ENCODING,
                           0,
                           "Couldn't convert encoded key to bytes. It is "
                           "possible that the Transcoder.encode_key method "
                           "returned an unexpected value",
                           new_key);

        Py_XDECREF(new_key);
        return -1;
    }

    if (plen == 0) {
        PYCBC_EXC_WRAP_KEY(PYCBC_EXC_ENCODING,
                           0,
                           "Transcoder.encode_key returned an empty string",
                           new_key);
        Py_XDECREF(new_key);
        return -1;
    }

    *nbuf = plen;
    *key = new_key;
    return 0;
}
Esempio n. 2
0
int
pycbc_tc_encode_key(pycbc_Bucket *conn, PyObject *src, pycbc_pybuffer *dst)
{
    int rv;
    Py_ssize_t plen;

    if (!conn->tc) {
        rv = encode_common(src, dst, PYCBC_FMT_UTF8);
        if (rv == 0 && dst->length == 0) {
            PYCBC_EXCTHROW_EMPTYKEY();
            rv = -1;
        }
        return rv;
    }

    /* Swap out key and new key. Assign back later on */

    rv = do_call_tc(conn, src, NULL, &dst->pyobj, ENCODE_KEY);

    if (dst->pyobj == NULL || rv < 0) {
        dst->pyobj = NULL;
        return -1;
    }

    rv = PyBytes_AsStringAndSize(dst->pyobj, (char**)&dst->buffer, &plen);

    if (rv == -1) {
        PYCBC_EXC_WRAP_KEY(PYCBC_EXC_ENCODING,
                           0,
                           "Couldn't convert encoded key to bytes. It is "
                           "possible that the Transcoder.encode_key method "
                           "returned an unexpected value", dst->pyobj);

        PYCBC_PYBUF_RELEASE(dst);
        return -1;
    }

    if (plen == 0) {
        PYCBC_EXC_WRAP_KEY(PYCBC_EXC_ENCODING,
                           0,
                           "Transcoder.encode_key returned an empty string",
                           dst->pyobj);
        PYCBC_PYBUF_RELEASE(dst);
        return -1;
    }
    dst->length = plen;
    return 0;
}
/**
 * This function raises exceptions from the MultiResult object, as required
 */
int
pycbc_multiresult_maybe_raise(pycbc_MultiResult *self)
{
    PyObject *type = NULL, *value = NULL, *traceback = NULL;

    if (self->errop == NULL && self->exceptions == NULL) {
        return 0;
    }

    if (self->exceptions) {
        PyObject *tuple = PyList_GetItem(self->exceptions, 0);

        assert(tuple);
        assert(PyTuple_Size(tuple) == 3);

        type = PyTuple_GetItem(tuple, 0);
        value = PyTuple_GetItem(tuple, 1);
        traceback = PyTuple_GetItem(tuple, 2);
        PyErr_NormalizeException(&type, &value, &traceback);
        Py_XINCREF(type);
        Py_XINCREF(value);
        Py_XINCREF(traceback);

        assert(PyObject_IsInstance(value, pycbc_helpers.default_exception));

    } else {
        pycbc_Result *res = (pycbc_Result*)self->errop;

        /** Craft an exception based on the operation */
        PYCBC_EXC_WRAP_KEY(PYCBC_EXC_LCBERR, res->rc, "Operational Error", res->key);

        /** Now we have an exception. Let's fetch it back */
        PyErr_Fetch(&type, &value, &traceback);
        PyObject_SetAttrString(value, "result", (PyObject*)res);
    }

    PyObject_SetAttrString(value, "all_results", (PyObject*)self);
    PyErr_Restore(type, value, traceback);

    /**
     * This is needed since the exception object will later contain
     * a reference to ourselves. If we don't free the original exception,
     * then we'll be stuck with a circular reference
     */
    Py_XDECREF(self->exceptions);
    Py_XDECREF(self->errop);
    self->exceptions = NULL;
    self->errop = NULL;


    return 1;
}
Esempio n. 4
0
int
pycbc_tc_decode_key(pycbc_Bucket *conn,
                     const void *key,
                     size_t nkey,
                     PyObject **pobj)
{
    PyObject *bobj;
    int rv = 0;
    if (conn->data_passthrough) {
        bobj = PyBytes_FromStringAndSize(key, nkey);
        *pobj = bobj;

    } else if (!conn->tc) {
        return decode_common(pobj, key, nkey, PYCBC_FMT_UTF8);

    } else {
        bobj = PyBytes_FromStringAndSize(key, nkey);
        if (bobj) {
            rv = do_call_tc(conn, bobj, NULL, pobj, DECODE_KEY);
            Py_XDECREF(bobj);

        } else {
            rv = -1;
        }

        if (rv < 0) {
            return -1;
        }
    }

    if (*pobj == NULL) {
        return -1;
    }

    if (PyObject_Hash(*pobj) == -1) {
        PYCBC_EXC_WRAP_KEY(PYCBC_EXC_ENCODING, 0,
                           "Transcoder.decode_key must return a hashable object",
                           *pobj);
        Py_XDECREF(*pobj);
        return -1;
    }

    return 0;
}
PyObject *
pycbc_Bucket__stats(pycbc_Bucket *self, PyObject *args, PyObject *kwargs)
{
    int rv;
    int ii;
    Py_ssize_t ncmds;
    lcb_error_t err = LCB_ERROR;
    PyObject *keys = NULL, *is_keystats = NULL;
    struct pycbc_common_vars cv = PYCBC_COMMON_VARS_STATIC_INIT;
    static char *kwlist[] = {  "keys", "keystats", NULL };
    lcb_CMDSTATS cmd = { 0 };

    rv = PyArg_ParseTupleAndKeywords(args, kwargs, "|OO", kwlist,
        &keys, &is_keystats);

    if (!rv) {
        PYCBC_EXCTHROW_ARGS();
        return NULL;
    }

    if (keys == NULL || PyObject_IsTrue(keys) == 0) {
        keys = NULL;
        ncmds = 1;

    } else {
        if (!PySequence_Check(keys)) {
            PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "keys argument must be sequence");
            return NULL;
        }
        ncmds = PySequence_Size(keys);
    }

    rv = pycbc_common_vars_init(&cv, self, PYCBC_ARGOPT_MULTI, ncmds, 0);
    if (rv < 0) {
        return NULL;
    }

    if (keys) {
        for (ii =0; ii < ncmds; ii++) {
            char *key;
            Py_ssize_t nkey;
            PyObject *newkey = NULL;

            PyObject *curkey = PySequence_GetItem(keys, ii);
            rv = pycbc_BufFromString(curkey, &key, &nkey, &newkey);
            if (rv < 0) {
                PYCBC_EXC_WRAP_KEY(PYCBC_EXC_ARGUMENTS, 0, "bad key type in stats", curkey);
                goto GT_DONE;
            }

            LCB_CMD_SET_KEY(&cmd, key, nkey);
            if (is_keystats && PyObject_IsTrue(is_keystats)) {
                cmd.cmdflags |= LCB_CMDSTATS_F_KV;
            }
            err = lcb_stats3(self->instance, cv.mres, &cmd);
            Py_XDECREF(newkey);
        }

    } else {
        err = lcb_stats3(self->instance, cv.mres, &cmd);
    }

    if (err != LCB_SUCCESS) {
        PYCBC_EXCTHROW_SCHED(err);
        goto GT_DONE;
    }

    if (-1 == pycbc_common_vars_wait(&cv, self)) {
        goto GT_DONE;
    }

    GT_DONE:
    pycbc_common_vars_finalize(&cv, self);
    return cv.ret;
}
Esempio n. 6
0
PyObject *
pycbc_Connection__stats(pycbc_Connection *self,
                        PyObject *args,
                        PyObject *kwargs)
{
    int rv;
    int ii;
    Py_ssize_t ncmds;
    lcb_error_t err;
    PyObject *keys = NULL;
    PyObject *ret = NULL;
    pycbc_MultiResult *mres = NULL;
    struct pycbc_common_vars cv = PYCBC_COMMON_VARS_STATIC_INIT;
    static char *kwlist[] = {  "keys", NULL };

    rv = PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &keys);

    if (!rv) {
        PYCBC_EXCTHROW_ARGS();
        return NULL;
    }

    if (keys == NULL || PyObject_IsTrue(keys) == 0) {
        keys = NULL;
        ncmds = 1;

    } else {
        if (!PySequence_Check(keys)) {
            PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "keys argument must be sequence");
            return NULL;
        }
        ncmds = PySequence_Size(keys);
    }

    rv = pycbc_common_vars_init(&cv, ncmds, sizeof(lcb_server_stats_cmd_t), 0);
    if (rv < 0) {
        return NULL;
    }

    if (keys) {
        for (ii =0; ii < ncmds; ii++) {
            char *key;
            Py_ssize_t nkey;
            PyObject *newkey = NULL;

            PyObject *curkey = PySequence_GetItem(keys, ii);
            lcb_server_stats_cmd_t *cmd = cv.cmds.stats + ii;
            rv = pycbc_BufFromString(curkey, &key, &nkey, &newkey);
            if (rv < 0) {
                PYCBC_EXC_WRAP_KEY(PYCBC_EXC_ARGUMENTS,
                                   0,
                                   "bad key type in stats",
                                   curkey);
                goto GT_DONE;
            }

            cmd->v.v0.name = key;
            cmd->v.v0.nname = nkey;
            cv.cmdlist.stats[ii] = cmd;
            cv.enckeys[ii] = newkey;
        }

    } else {
        cv.cmdlist.stats[0] = cv.cmds.stats;
    }


    mres = (pycbc_MultiResult*)pycbc_multiresult_new(self);

    err = lcb_server_stats(self->instance, mres, ncmds, cv.cmdlist.stats);
    if (err != LCB_SUCCESS) {
        PYCBC_EXCTHROW_SCHED(err);
        goto GT_DONE;
    }

    err = pycbc_oputil_wait_common(self);

    if (err != LCB_SUCCESS) {
        PYCBC_EXCTHROW_WAIT(err);
        goto GT_DONE;
    }

    ret = (PyObject*)mres;

    GT_DONE:
    pycbc_common_vars_free(&cv);

    /* Force multi, it's always a MultiResult */
    pycbc_make_retval(PYCBC_ARGOPT_MULTI, &ret, &mres);
    Py_XDECREF(mres);
    return ret;
}
Esempio n. 7
0
static int
handle_single_key(pycbc_Connection *self,
                  PyObject *curkey,
                  PyObject *curval,
                  unsigned long ttl,
                  int ii,
                  int optype,
                  struct pycbc_common_vars *cv)
{
    int rv;
    char *key;
    size_t nkey;
    unsigned int lock = 0;

    rv = pycbc_tc_encode_key(self, &curkey, (void**)&key, &nkey);
    if (rv == -1) {
        return -1;
    }

    cv->enckeys[ii] = curkey;

    if (curval) {
        static char *kwlist[] = { "ttl", NULL };
        PyObject *ttl_O = NULL;
        if (ttl) {
            PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS,
                           0,
                           "Both global and single TTL specified");
            return -1;
        }

        if (PyDict_Check(curval)) {
            rv = PyArg_ParseTupleAndKeywords(pycbc_DummyTuple, curval,
                                             "|O", kwlist, &ttl_O);
            if (!rv) {
                PYCBC_EXC_WRAP_KEY(PYCBC_EXC_ARGUMENTS, 0,
                                   "Couldn't get sub-parmeters for key",
                                   curkey);
                return -1;
            }
        } else {
            ttl_O = curval;
        }

        rv = pycbc_get_ttl(ttl_O, &ttl, 1);
        if (rv < 0) {
            return -1;
        }
    }
    switch (optype) {
    case PYCBC_CMD_GAT:
        if (!ttl) {
            PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "GAT must have positive TTL");
            return -1;
        }
        goto GT_GET;

    case PYCBC_CMD_LOCK:
        if (!ttl) {
            PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Lock must have an expiry");
        }
        lock = 1;
        goto GT_GET;

    case PYCBC_CMD_GET:
        GT_GET: {
            lcb_get_cmd_t *gcmd = cv->cmds.get + ii;
            gcmd->v.v0.lock = lock;
            gcmd->v.v0.key = key;
            gcmd->v.v0.nkey = nkey;
            gcmd->v.v0.exptime = ttl;
            cv->cmdlist.get[ii] = gcmd;
        }
        break;

    case PYCBC_CMD_TOUCH: {
        lcb_touch_cmd_t *tcmd = cv->cmds.touch + ii;
        tcmd->v.v0.key = key;
        tcmd->v.v0.nkey = nkey;
        tcmd->v.v0.exptime = ttl;
        cv->cmdlist.touch[ii] = tcmd;
        break;
    }
    }

    return 0;
}
static int
handle_single_key(pycbc_Connection *self,
                  struct pycbc_common_vars *cv,
                  int optype,
                  PyObject *curkey,
                  PyObject *curval,
                  PyObject *options,
                  pycbc_Item *itm,
                  int ii,
                  void *arg)
{
    int rv;
    char *key;
    size_t nkey;
    unsigned int lock = 0;
    struct getcmd_vars_st *gv = (struct getcmd_vars_st *)arg;
    unsigned long ttl = gv->u.ttl;

    (void)itm;

    rv = pycbc_tc_encode_key(self, &curkey, (void**)&key, &nkey);
    if (rv == -1) {
        return -1;
    }

    cv->enckeys[ii] = curkey;

    if (!nkey) {
        PYCBC_EXCTHROW_EMPTYKEY();
        return -1;
    }

    if (curval && gv->allow_dval && options == NULL) {
        options = curval;
    }
    if (options) {
        static char *kwlist[] = { "ttl", NULL };
        PyObject *ttl_O = NULL;
        if (gv->u.ttl) {
            PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS,
                           0,
                           "Both global and single TTL specified");
            return -1;
        }

        if (PyDict_Check(curval)) {
            rv = PyArg_ParseTupleAndKeywords(pycbc_DummyTuple, curval,
                                             "|O", kwlist, &ttl_O);
            if (!rv) {
                PYCBC_EXC_WRAP_KEY(PYCBC_EXC_ARGUMENTS, 0,
                                   "Couldn't get sub-parmeters for key",
                                   curkey);
                return -1;
            }
        } else {
            ttl_O = curval;
        }

        rv = pycbc_get_ttl(ttl_O, &ttl, 1);
        if (rv < 0) {
            return -1;
        }
    }
    switch (optype) {
    case PYCBC_CMD_GAT:
        if (!ttl) {
            PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "GAT must have positive TTL");
            return -1;
        }
        goto GT_GET;

    case PYCBC_CMD_LOCK:
        if (!ttl) {
            PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Lock must have an expiry");
            return -1;
        }
        lock = 1;
        goto GT_GET;

    case PYCBC_CMD_GET:
        GT_GET: {
            lcb_get_cmd_t *gcmd = cv->cmds.get + ii;
            gcmd->v.v0.lock = lock;
            gcmd->v.v0.key = key;
            gcmd->v.v0.nkey = nkey;
            gcmd->v.v0.exptime = ttl;
            cv->cmdlist.get[ii] = gcmd;
        }
        break;

    case PYCBC_CMD_TOUCH: {
        lcb_touch_cmd_t *tcmd = cv->cmds.touch + ii;
        tcmd->v.v0.key = key;
        tcmd->v.v0.nkey = nkey;
        tcmd->v.v0.exptime = ttl;
        cv->cmdlist.touch[ii] = tcmd;
        break;
    }

    case PYCBC_CMD_GETREPLICA:
    case PYCBC_CMD_GETREPLICA_INDEX:
    case PYCBC_CMD_GETREPLICA_ALL: {
        lcb_get_replica_cmd_t *rcmd = cv->cmds.replica + ii;
        rcmd->version = 1;
        rcmd->v.v1.key = key;
        rcmd->v.v1.nkey = nkey;
        rcmd->v.v1.nkey = nkey;
        rcmd->v.v1.strategy = gv->u.replica.strategy;
        rcmd->v.v1.index = gv->u.replica.index;

        cv->cmdlist.replica[ii] = rcmd;
        break;
    }

    }

    return 0;
}
Esempio n. 9
0
static int
handle_single_arith(pycbc_Bucket *self,
                    struct pycbc_common_vars *cv,
                    int optype,
                    PyObject *curkey,
                    PyObject *curvalue,
                    PyObject *options,
                    pycbc_Item *item,
                    int ii,
                    void *arg)
{
    void *key;
    size_t nkey;
    int rv;
    lcb_arithmetic_cmd_t *acmd;
    struct arithmetic_common_vars my_params;
    static char *kwlist[] = { "delta", "initial", "ttl", NULL };
    my_params = *(struct arithmetic_common_vars *)arg;

    (void)item;

    acmd = cv->cmds.arith + ii;

    rv = pycbc_tc_encode_key(self, &curkey, &key, &nkey);
    if (rv < 0) {
        return -1;
    }

    cv->enckeys[ii] = curkey;

    if (!nkey) {
        PYCBC_EXCTHROW_EMPTYKEY();
        return -1;
    }

    if (options) {
        curvalue = options;
    }

    if (curvalue) {
        if (PyDict_Check(curvalue)) {
            PyObject *initial_O = NULL;
            rv = PyArg_ParseTupleAndKeywords(pycbc_DummyTuple,
                                             curvalue,
                                             "L|Ok",
                                             kwlist,
                                             &my_params.delta,
                                             &initial_O,
                                             &my_params.ttl);
            if (!rv) {
                PYCBC_EXC_WRAP_KEY(PYCBC_EXC_ARGUMENTS, 0,
                                   "Couldn't parse parameter for key",
                                   curkey);
                return -1;
            }

            if (initial_O) {
                if (PyNumber_Check(initial_O)) {
                    my_params.create = 1;
                    my_params.initial = pycbc_IntAsULL(initial_O);

                } else {
                    my_params.create = 0;
                }
            }

        } else if (PyNumber_Check(curvalue)) {
            my_params.delta = pycbc_IntAsLL(curvalue);
        } else {
            PYCBC_EXC_WRAP_KEY(PYCBC_EXC_ARGUMENTS,
                               0,
                               "value for key must be an integer amount "
                               "or a dict of parameters",
                               curkey);
            return -1;
        }
    }

    acmd->v.v0.key = key;
    acmd->v.v0.nkey = nkey;
    acmd->v.v0.delta = my_params.delta;
    acmd->v.v0.create = my_params.create;
    acmd->v.v0.exptime = my_params.ttl;
    acmd->v.v0.initial = my_params.initial;
    cv->cmdlist.arith[ii] = acmd;

    return 0;
}