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; }
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; }
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; }
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; }
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; }
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; }