static PyObject * Connection__thr_lockop(pycbc_Connection *self, PyObject *arg) { int rv; int is_unlock = 0; rv = PyArg_ParseTuple(arg, "i:is_unlock", &is_unlock); if (!rv) { return NULL; } if (!self->lockmode) { PYCBC_EXC_WRAP(PYCBC_EXC_THREADING, 0, "lockmode is LOCKMODE_NONE"); return NULL; } if (is_unlock) { PyThread_release_lock(self->lock); } else { if (!PyThread_acquire_lock(self->lock, WAIT_LOCK)) { PYCBC_EXC_WRAP(PYCBC_EXC_THREADING, 0, "Couldn't lock"); return NULL; } } Py_RETURN_NONE; }
PyObject * pycbc_Bucket__fts_query(pycbc_Bucket *self, PyObject *args, PyObject *kwargs) { int rv; PyObject *ret = NULL; pycbc_MultiResult *mres; pycbc_ViewResult *vres; lcb_error_t rc; lcb_CMDFTS cmd = { 0 }; const char *params; pycbc_strlen_t nparams; static char *kwlist[] = { "params", NULL }; rv = PyArg_ParseTupleAndKeywords(args, kwargs, "s#", kwlist, ¶ms, &nparams); if (!rv) { PYCBC_EXCTHROW_ARGS(); return NULL; } if (-1 == pycbc_oputil_conn_lock(self)) { return NULL; } if (self->pipeline_queue) { PYCBC_EXC_WRAP(PYCBC_EXC_PIPELINE, 0, "FTS queries cannot be executed in pipeline context"); } mres = (pycbc_MultiResult *)pycbc_multiresult_new(self); vres = (pycbc_ViewResult *)PYCBC_TYPE_CTOR(&pycbc_ViewResultType); pycbc_httpresult_init(&vres->base, mres); vres->rows = PyList_New(0); vres->base.format = PYCBC_FMT_JSON; vres->base.htype = PYCBC_HTTP_HN1QL; cmd.callback = fts_row_callback; cmd.query = params; cmd.nquery = nparams; cmd.handle = &vres->base.u.fts; rc = lcb_fts_query(self->instance, mres, &cmd); if (rc != LCB_SUCCESS) { PYCBC_EXC_WRAP(PYCBC_EXC_LCBERR, rc, "Couldn't schedule fts query"); goto GT_DONE; } ret = (PyObject *)mres; mres = NULL; GT_DONE: Py_XDECREF(mres); pycbc_oputil_conn_unlock(self); return ret; }
/** * Fetches a bunch of results from the network. Returns False when * no more results remain. */ PyObject * pycbc_HttpResult__fetch(pycbc_HttpResult *self) { lcb_error_t err; PyObject *ret = NULL; if (-1 == pycbc_oputil_conn_lock(self->parent)) { return NULL; } if (!self->htreq) { ret = Py_None; Py_INCREF(ret); goto GT_RET; } if (self->parent->flags & PYCBC_CONN_F_ASYNC) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "_fetch() should not be called with an async " "connection"); goto GT_RET; } else if (self->parent->pipeline_queue) { PYCBC_EXC_WRAP(PYCBC_EXC_PIPELINE, 0, "HTTP requests cannot be executed in pipeline context"); } if (!self->rowsbuf) { self->rowsbuf = PyList_New(0); } err = pycbc_oputil_wait_common(self->parent); if (err != LCB_SUCCESS) { PYCBC_EXCTHROW_WAIT(err); goto GT_RET; } else { if (maybe_raise(self)) { goto GT_RET; } ret = self->rowsbuf; self->rowsbuf = NULL; } if (!pycbc_assert(self->parent->nremaining == 0)) { fprintf(stderr, "Remaining count unexpected. Adjusting"); self->parent->nremaining = 0; } GT_RET: pycbc_oputil_conn_unlock(self->parent); return ret; }
static int handle_replica_options(int *optype, struct getcmd_vars_st *gv, PyObject *replica_O) { #if LCB_VERSION >= 0x020007 switch (*optype) { case PYCBC_CMD_GET: *optype = PYCBC_CMD_GETREPLICA; if (gv->u.ttl) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "TTL specified along with replica"); return -1; } gv->u.replica.strategy = LCB_REPLICA_FIRST; return 0; case PYCBC_CMD_GETREPLICA: gv->u.replica.strategy = LCB_REPLICA_FIRST; return 0; case PYCBC_CMD_GETREPLICA_INDEX: gv->u.replica.strategy = LCB_REPLICA_SELECT; if (replica_O == NULL || replica_O == Py_None) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "rgetix must have a valid replica index"); return -1; } gv->u.replica.index = pycbc_IntAsL(replica_O); if (PyErr_Occurred()) { return -1; } return 0; case PYCBC_CMD_GETREPLICA_ALL: gv->u.replica.strategy = LCB_REPLICA_ALL; return 0; default: PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Replica option not supported for this operation"); return -1; } #else PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Need libcouchbase >= 2.0.7"); (void)optype; (void)gv; (void)replica_O; #endif return -1; }
static PyObject * convert_to_string(const char *buf, size_t nbuf, int mode) { PyObject *ret = NULL; if (mode == CONVERT_MODE_BYTES_ONLY) { goto GT_BYTES; } ret = PyUnicode_DecodeUTF8(buf, nbuf, "strict"); if (ret) { return ret; } if (mode == CONVERT_MODE_UTF8_ONLY) { PYCBC_EXC_WRAP(PYCBC_EXC_ENCODING, 0, "Couldn't decode as UTF-8"); return NULL; } PyErr_Clear(); GT_BYTES: return PyBytes_FromStringAndSize(buf, nbuf); }
static PyObject * Connection_server_nodes(pycbc_Connection *self, void *unused) { const char * const *cnodes; const char **curnode; PyObject *ret_list; cnodes = lcb_get_server_list(self->instance); if (!cnodes) { PYCBC_EXC_WRAP(PYCBC_EXC_INTERNAL, 0, "Can't get server nodes"); return NULL; } ret_list = PyList_New(0); if (!ret_list) { return NULL; } for (curnode = (const char**)cnodes; *curnode; curnode++) { PyObject *tmpstr = pycbc_SimpleStringZ(*curnode); PyList_Append(ret_list, tmpstr); Py_DECREF(tmpstr); } (void)unused; return ret_list; }
static PyObject * handle_float_tmo(lcb_t instance, int cmd, int mode, PyObject *val, lcb_error_t *err) { lcb_uint32_t cval; if (val != NULL) { if (PyFloat_Check(val)) { double dv = PyFloat_AsDouble(val); if (dv < 0) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Timeout cannot be < 0"); return NULL; } cval = dv * 1000000; } else { cval = pycbc_IntAsL(val); if (cval == (lcb_uint32_t)-1 && PyErr_Occurred()) { PYCBC_EXCTHROW_ARGS(); return NULL; } } } if ( (*err = lcb_cntl(instance, mode, cmd, &cval)) != LCB_SUCCESS) { return NULL; } return pycbc_IntFromUL(cval); }
PyObject * pycbc_Connection__vbmap(pycbc_Connection *conn, PyObject *args) { pycbc_strlen_t slen = 0; const char *s = NULL; PyObject *rtuple; struct vbinfo_st info; lcb_error_t err; if (!PyArg_ParseTuple(args, "s#", &s, &slen)) { PYCBC_EXCTHROW_ARGS(); } memset(&info, 0, sizeof(info)); info.v.v0.key = s; info.v.v0.nkey = slen; err = lcb_cntl(conn->instance, CNTL_GET, CNTL_VBMAP, &info); if (err != LCB_SUCCESS) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "lcb_cntl failed"); return NULL; } rtuple = PyTuple_New(2); PyTuple_SET_ITEM(rtuple, 0, pycbc_IntFromL(info.v.v0.vbucket)); PyTuple_SET_ITEM(rtuple, 1, pycbc_IntFromL(info.v.v0.server_index)); return rtuple; }
static PyObject* Bucket__connect(pycbc_Bucket *self) { lcb_error_t err; if (self->flags & PYCBC_CONN_F_CONNECTED) { Py_RETURN_NONE; } err = lcb_connect(self->instance); if (err != LCB_SUCCESS) { PYCBC_EXC_WRAP(PYCBC_EXC_LCBERR, err, "Couldn't schedule connection. This might be a result of " "an invalid hostname."); return NULL; } pycbc_oputil_wait_common(self); if ((self->flags & PYCBC_CONN_F_ASYNC) == 0) { err = lcb_get_bootstrap_status(self->instance); if (err != LCB_SUCCESS) { PYCBC_EXCTHROW_WAIT(err); return NULL; } } Py_RETURN_NONE; }
static PyObject * Bucket__close(pycbc_Bucket *self) { lcb_error_t err; if (self->flags & PYCBC_CONN_F_CLOSED) { Py_RETURN_NONE; } self->flags |= PYCBC_CONN_F_CLOSED; lcb_destroy(self->instance); if (self->iopswrap) { Py_XDECREF(self->iopswrap); self->iopswrap = NULL; } err = lcb_create(&self->instance, NULL); pycbc_assert(err == LCB_SUCCESS); if (err != LCB_SUCCESS) { PYCBC_EXC_WRAP(PYCBC_EXC_LCBERR, err, "Internal error while closing object"); return NULL; } Py_RETURN_NONE; }
static int do_call_tc(pycbc_Bucket *conn, PyObject *obj, PyObject *flags, PyObject **result, int mode) { PyObject *meth = NULL; PyObject *args = NULL; PyObject *strlookup = NULL; int ret = -1; switch (mode) { case ENCODE_KEY: strlookup = pycbc_helpers.tcname_encode_key; args = PyTuple_Pack(1, obj); break; case DECODE_KEY: strlookup = pycbc_helpers.tcname_decode_key; args = PyTuple_Pack(1, obj); break; case ENCODE_VALUE: strlookup = pycbc_helpers.tcname_encode_value; args = PyTuple_Pack(2, obj, flags); break; case DECODE_VALUE: strlookup = pycbc_helpers.tcname_decode_value; args = PyTuple_Pack(2, obj, flags); break; } if (args == NULL) { PYCBC_EXC_WRAP(PYCBC_EXC_INTERNAL, 0, "Couldn't build arguments"); goto GT_DONE; } meth = PyObject_GetAttr(conn->tc, strlookup); if (!meth) { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ENCODING, 0, "Couldn't find transcoder method", conn->tc); goto GT_DONE; } *result = PyObject_Call(meth, args, NULL); if (*result) { ret = 0; } else { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ENCODING, 0, "User-Defined transcoder failed", obj); } GT_DONE: Py_XDECREF(meth); Py_XDECREF(args); return ret; }
PyObject * pycbc_Bucket__start_pipeline(pycbc_Bucket *self) { if (self->pipeline_queue) { PYCBC_EXC_WRAP(PYCBC_EXC_PIPELINE, 0, "A pipeline is already in progress"); return NULL; } if (self->flags & PYCBC_CONN_F_ASYNC) { PYCBC_EXC_WRAP(PYCBC_EXC_PIPELINE, 0, "Pipeline mode not valid in async handle"); return NULL; } self->pipeline_queue = PyList_New(0); Py_INCREF(self->pipeline_queue); return self->pipeline_queue; }
static int modify_event_python(pycbc_IOPSWrapper *pio, pycbc_Event *ev, pycbc_evaction_t action, lcb_socket_t newsock, void *arg) { int ret; PyObject *result; PyObject *o_arg; PyObject *meth = NULL; PyObject *argtuple; short flags = 0; unsigned long usecs = 0; argtuple = PyTuple_New(3); Py_INCREF((PyObject *)ev); PyTuple_SET_ITEM(argtuple, 0, (PyObject *)ev); PyTuple_SET_ITEM(argtuple, 1, pycbc_IntFromL(action)); if (ev->type == PYCBC_EVTYPE_IO) { flags = *(short*)arg; o_arg = pycbc_IntFromL(flags); ((pycbc_IOEvent *)ev)->fd = newsock; meth = pio->modevent; } else { usecs = *(lcb_uint32_t*)arg; o_arg = pycbc_IntFromL(usecs); meth = pio->modtimer; } PyTuple_SET_ITEM(argtuple, 2, o_arg); result = PyObject_CallObject(meth, argtuple); Py_DECREF(argtuple); Py_XDECREF(result); if (ev->type == PYCBC_EVTYPE_IO) { pycbc_IOEvent *evio = (pycbc_IOEvent*)ev; evio->flags = flags; } if (action == PYCBC_EVACTION_WATCH) { ev->state = PYCBC_EVSTATE_ACTIVE; } else { ev->state = PYCBC_EVSTATE_SUSPENDED; } if (!result) { ret = -1; PYCBC_EXC_WRAP(PYCBC_EXC_INTERNAL, 0, "Couldn't invoke IO Function"); } else { ret = 0; } return ret; }
lcb_io_opt_t pycbc_iops_new(pycbc_Connection *conn, PyObject *pyio) { lcb_io_opt_t ret = NULL; lcb_io_opt_t dfl = NULL; lcb_error_t err; struct lcb_create_io_ops_st options = { 0 }; pycbc_iops_t *pio; pio = calloc(1, sizeof(*pio)); ret = &pio->iops; pio->conn = conn; pio->pyio = pyio; Py_INCREF(pyio); /** * We create the select 'iops' handle and copy over its functionality * from there. Now that libcouchbase has the 'select' iops build in, we use * that instead. * * We discard the default iops loop data at the expense of leaking a * dlhandle. */ options.v.v0.type = LCB_IO_OPS_SELECT; err = lcb_create_io_ops(&dfl, &options); if (err != LCB_SUCCESS) { PYCBC_EXC_WRAP(PYCBC_EXC_LCBERR, err, "Couldn't create IOPS"); return NULL; } memcpy(&pio->iops, dfl, sizeof(*dfl)); /* hide the dlsym */ dfl->dlhandle = NULL; lcb_destroy_io_ops(dfl); dfl = NULL; ret->v.v0.create_event = create_event; ret->v.v0.create_timer = create_timer; ret->v.v0.destroy_event = destroy_event_common; ret->v.v0.destroy_timer = destroy_event_common; ret->v.v0.update_event = update_event; ret->v.v0.delete_event = delete_event; ret->v.v0.delete_timer = delete_timer; ret->v.v0.update_timer = update_timer; ret->v.v0.run_event_loop = run_event_loop; ret->v.v0.stop_event_loop = stop_event_loop; ret->destructor = iops_destructor; return ret; }
static int modify_event_python(pycbc_iops_t *pio, pycbc_Event *ev, pycbc_evaction_t action, lcb_socket_t newsock, void *arg) { int ret; PyObject *argtuple = NULL; PyObject *result = NULL; PyObject *meth = NULL; short flags = 0; unsigned long usecs = 0; if (ev->type == PYCBC_EVTYPE_IO) { flags = *(short*)arg; argtuple = Py_BuildValue("(O,i,i)", ev, action, flags); ((pycbc_IOEvent *)ev)->fd = newsock; meth = PyObject_GetAttr(pio->pyio, pycbc_helpers.ioname_modevent); } else { usecs = *(lcb_uint32_t*)arg; argtuple = Py_BuildValue("(O,i,k)", ev, action, usecs); meth = PyObject_GetAttr(pio->pyio, pycbc_helpers.ioname_modtimer); } assert(meth); result = PyObject_CallObject(meth, argtuple); Py_XDECREF(meth); Py_XDECREF(result); Py_XDECREF(argtuple); if (ev->type == PYCBC_EVTYPE_IO) { pycbc_IOEvent *evio = (pycbc_IOEvent*)ev; evio->flags = flags; } if (action == PYCBC_EVACTION_WATCH) { ev->state = PYCBC_EVSTATE_ACTIVE; } else { ev->state = PYCBC_EVSTATE_SUSPENDED; } if (!result) { ret = -1; PYCBC_EXC_WRAP(PYCBC_EXC_INTERNAL, 0, "Couldn't invoke IO Function"); } else { ret = 0; } return ret; }
PyObject * pycbc_Bucket__end_pipeline(pycbc_Bucket *self) { PyObject *rv; int ii; if (!self->pipeline_queue) { PYCBC_EXC_WRAP(PYCBC_EXC_PIPELINE, 0, "No pipeline in progress"); return NULL; } rv = self->pipeline_queue; if (!self->nremaining) { goto GT_DONE; } pycbc_oputil_wait_common(self); pycbc_assert(self->nremaining == 0); for (ii = 0; ii < PyList_GET_SIZE(self->pipeline_queue); ii++) { PyObject *retitem; pycbc_MultiResult *mres = (pycbc_MultiResult *)PyList_GET_ITEM(self->pipeline_queue, ii); if (pycbc_multiresult_maybe_raise(mres)) { rv = NULL; break; } /** Returns new reference to something */ retitem = pycbc_multiresult_get_result(mres); if (retitem != (PyObject *)mres) { PyList_SetItem(self->pipeline_queue, ii, retitem); } else { Py_DECREF(mres); } } GT_DONE: if (rv) { Py_INCREF(rv); pycbc_assert(rv == self->pipeline_queue); } Py_XDECREF(self->pipeline_queue); self->pipeline_queue = NULL; return rv; }
int pycbc_tc_decode_value(pycbc_Bucket *conn, const void *value, size_t nvalue, lcb_uint32_t flags, PyObject **pobj) { PyObject *result = NULL; PyObject *pint = NULL; PyObject *pbuf = NULL; int rv; if (conn->data_passthrough == 0 && conn->tc == NULL) { return decode_common(pobj, value, nvalue, flags); } if (conn->data_passthrough) { *pobj = PyBytes_FromStringAndSize(value, nvalue); if (*pobj) { return 0; } return -1; } pbuf = PyBytes_FromStringAndSize(value, nvalue); if (!pbuf) { pbuf = PyBytes_FromString(""); } pint = pycbc_IntFromUL(flags); if (!pint) { PYCBC_EXC_WRAP(PYCBC_EXC_INTERNAL, 0, "Couldn't create flags object"); rv = -1; goto GT_DONE; } rv = do_call_tc(conn, pbuf, pint, &result, DECODE_VALUE); GT_DONE: Py_XDECREF(pint); Py_XDECREF(pbuf); if (rv < 0) { return -1; } *pobj = result; return 0; }
static void maybe_invoke_async_callback(pycbc_HttpResult *htres) { PyObject *args, *ret; if (!(htres->parent->flags & PYCBC_CONN_F_ASYNC)) { return; } if ((htres->htflags & PYCBC_HTRES_F_COMPLETE) == 0 && (unsigned long)PyList_GET_SIZE(htres->rowsbuf) < (unsigned long)htres->rows_per_call) { return; } if (htres->htflags & PYCBC_HTRES_F_CHUNKED) { args = Py_BuildValue("(OO)", (PyObject *)htres, htres->rowsbuf); } else { args = Py_BuildValue("(OO)", Py_None, Py_None); } if (!htres->callback) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Missing callback for HTTP"); } else { ret = PyObject_CallObject(htres->callback, args); if (ret) { Py_XDECREF(ret); } else { PyErr_PrintEx(0); } } Py_DECREF(args); if (htres->htflags & PYCBC_HTRES_F_COMPLETE) { Py_XDECREF(htres->callback); htres->callback = NULL; Py_XDECREF(htres); } else if (htres->htflags & PYCBC_HTRES_F_CHUNKED) { Py_XDECREF(htres->rowsbuf); htres->rowsbuf = PyList_New(0); } }
static int Connection_set_format(pycbc_Connection *self, PyObject *value, void *unused) { if (value != pycbc_helpers.fmt_auto) { if (!PyNumber_Check(value)) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Format must be a number"); return -1; } if (Py_TYPE(value) == &PyBool_Type) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Format must not be a boolean"); return -1; } } Py_XDECREF(self->dfl_fmt); Py_INCREF(value); self->dfl_fmt = value; (void)unused; return 0; }
static int handle_single_observe(pycbc_Connection *self, PyObject *curkey, int ii, int master_only, struct pycbc_common_vars *cv) { int rv; char *key; size_t nkey; lcb_observe_cmd_t *ocmd = cv->cmds.obs + ii; rv = pycbc_tc_encode_key(self, &curkey, (void**)&key, &nkey); if (rv < 0) { return -1; } cv->enckeys[ii] = curkey; if (!nkey) { PYCBC_EXCTHROW_EMPTYKEY(); return -1; } if (master_only) { /** New 'MASTER_ONLY' was added in 2.3.0 */ #if LCB_VERSION < 0x020300 PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "master_only requires libcouchbase >= 2.3.0"); return -1; #else ocmd->version = 1; ocmd->v.v1.options = LCB_OBSERVE_MASTER_ONLY; #endif } ocmd->v.v0.key = key; ocmd->v.v0.nkey = nkey; cv->cmdlist.obs[ii] = ocmd; return 0; }
static PyObject * ViewResult_fetch(pycbc_ViewResult *self, PyObject *args) { PyObject *ret = NULL; pycbc_MultiResult *mres = NULL; pycbc_Bucket *bucket; int rv; rv = PyArg_ParseTuple(args, "O", &mres); if (!rv) { PYCBC_EXCTHROW_ARGS(); return NULL; } bucket = mres->parent; if (bucket->flags & PYCBC_CONN_F_ASYNC) { PYCBC_EXC_WRAP(PYCBC_EXC_INTERNAL, 0, "Cannot use fetch with async"); return NULL; } if (-1 == pycbc_oputil_conn_lock(bucket)) { return NULL; } if (!self->base.done) { pycbc_oputil_wait_common(bucket); } if (pycbc_multiresult_maybe_raise(mres)) { goto GT_DONE; } ret = self->rows ? self->rows : PyList_New(0); self->rows = PyList_New(0); GT_DONE: pycbc_oputil_conn_unlock(bucket); return ret; }
static PyObject * Bucket__mutinfo(pycbc_Bucket *self) { PyObject *ll = PyList_New(0); size_t ii, vbmax; lcbvb_CONFIG *cfg = NULL; lcb_error_t rc; rc = lcb_cntl(self->instance, LCB_CNTL_GET, LCB_CNTL_VBCONFIG, &cfg); if (rc != LCB_SUCCESS) { PYCBC_EXC_WRAP(PYCBC_EXC_LCBERR, rc, "Couldn't get vBucket config"); return NULL; } vbmax = vbucket_config_get_num_vbuckets(cfg); for (ii = 0; ii < vbmax; ++ii) { lcb_KEYBUF kb = { 0 }; const lcb_MUTATION_TOKEN *mt; lcb_error_t rc = LCB_SUCCESS; PyObject *cur; kb.type = LCB_KV_VBID; kb.contig.nbytes = (size_t)ii; mt = lcb_get_mutation_token(self->instance, &kb, &rc); if (mt == NULL) { continue; } cur = Py_BuildValue("HKK", LCB_MUTATION_TOKEN_VB(mt), LCB_MUTATION_TOKEN_ID(mt), LCB_MUTATION_TOKEN_SEQ(mt)); PyList_Append(ll, cur); Py_DECREF(cur); } return ll; }
PyObject * pycbc_Bucket__view_request(pycbc_Bucket *self, PyObject *args, PyObject *kwargs) { int rv; PyObject *ret = NULL; pycbc_MultiResult *mres = NULL; pycbc_ViewResult *vres = NULL; lcb_CMDVIEWQUERY vcmd = { 0 }; viewpath_st vp = { NULL }; lcb_error_t rc; const char *view = NULL, *design = NULL; PyObject *options = NULL; int flags; static char *kwlist[] = { "design", "view", "options", "_flags", NULL }; rv = PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi", kwlist, &design, &view, &options, &flags); if (!rv) { PYCBC_EXCTHROW_ARGS(); return NULL; } if (-1 == pycbc_oputil_conn_lock(self)) { return NULL; } if (self->pipeline_queue) { PYCBC_EXC_WRAP(PYCBC_EXC_PIPELINE, 0, "HTTP/View Requests cannot be executed in " "pipeline context"); goto GT_DONE; } mres = (pycbc_MultiResult *)pycbc_multiresult_new(self); vres = (pycbc_ViewResult *)PYCBC_TYPE_CTOR(&pycbc_ViewResultType); vres->base.htype = PYCBC_HTTP_HVIEW; pycbc_httpresult_init(&vres->base, mres); rv = get_viewpath_str(self, &vp, options); if (rv != 0) { goto GT_DONE; } vcmd.ddoc = design; vcmd.nddoc = strlen(design); vcmd.view = view; vcmd.nview = strlen(view); vcmd.optstr = vp.optstr; vcmd.noptstr = vp.noptstr; vcmd.postdata = vp.body; vcmd.npostdata = vp.nbody; vcmd.handle = &vres->base.u.vh; vcmd.callback = row_callback; vcmd.cmdflags = flags; vres->rows = PyList_New(0); vres->base.format = PYCBC_FMT_JSON; rc = lcb_view_query(self->instance, mres, &vcmd); if (rc != LCB_SUCCESS) { PYCBC_EXC_WRAP(PYCBC_EXC_LCBERR, rc, "Couldn't schedule view"); goto GT_DONE; } ret = (PyObject*)mres; mres = NULL; /* Avoid GT_DONE decref */ GT_DONE: Py_XDECREF(mres); Py_XDECREF(vp.bk); pycbc_oputil_conn_unlock(self); return ret; }
static PyObject * keyop_common(pycbc_Bucket *self, PyObject *args, PyObject *kwargs, int optype, int argopts) { int rv; Py_ssize_t ncmds = 0; pycbc_seqtype_t seqtype; PyObject *casobj = NULL; PyObject *is_quiet = NULL; PyObject *kobj = NULL; char persist_to = 0, replicate_to = 0; struct pycbc_common_vars cv = PYCBC_COMMON_VARS_STATIC_INIT; static char *kwlist[] = { "keys", "cas", "quiet", "persist_to", "replicate_to", NULL }; rv = PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOBB", kwlist, &kobj, &casobj, &is_quiet, &persist_to, &replicate_to); if (!rv) { PYCBC_EXCTHROW_ARGS(); return NULL; } if (argopts & PYCBC_ARGOPT_MULTI) { rv = pycbc_oputil_check_sequence(kobj, 1, &ncmds, &seqtype); if (rv < 0) { return NULL; } if (casobj && PyObject_IsTrue(casobj)) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Can't pass CAS for multiple keys"); } } else { ncmds = 1; } rv = pycbc_common_vars_init(&cv, self, argopts, ncmds, 0); if (rv < 0) { return NULL; } if (argopts & PYCBC_ARGOPT_MULTI) { rv = pycbc_oputil_iter_multi(self, seqtype, kobj, &cv, optype, handle_single_keyop, NULL); } else { rv = handle_single_keyop(self, &cv, optype, kobj, casobj, NULL, NULL, NULL); } if (rv < 0) { goto GT_DONE; } if (optype == PYCBC_CMD_DELETE) { rv = pycbc_handle_durability_args(self, &cv.mres->dur, persist_to, replicate_to); if (rv == 1) { cv.mres->mropts |= PYCBC_MRES_F_DURABILITY; } else if (rv == -1) { goto GT_DONE; } if (pycbc_maybe_set_quiet(cv.mres, is_quiet) == -1) { 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; }
static int Connection__init__(pycbc_Connection *self, PyObject *args, PyObject *kwargs) { int rv; int conntype = LCB_TYPE_BUCKET; lcb_error_t err; char *conncache = NULL; PyObject *unlock_gil_O = NULL; PyObject *iops_O = NULL; PyObject *timeout = NULL; PyObject *dfl_fmt = NULL; PyObject *tc = NULL; struct lcb_create_st create_opts = { 0 }; struct lcb_cached_config_st cached_config = { { 0 } }; /** * This xmacro enumerates the constructor keywords, targets, and types. * This was converted into an xmacro to ease the process of adding or * removing various parameters. */ #define XCTOR_ARGS(X) \ X("_errors", &self->errors, "O") \ X("_flags", &self->flags, "I") \ X("bucket", &create_opts.v.v1.bucket, "z") \ X("username", &create_opts.v.v1.user, "z") \ X("password", &create_opts.v.v1.passwd, "z") \ X("host", &create_opts.v.v1.host, "z") \ X("conncache", &conncache, "z") \ X("quiet", &self->quiet, "I") \ X("unlock_gil", &unlock_gil_O, "O") \ X("transcoder", &tc, "O") \ X("timeout", &timeout, "O") \ X("default_format", &dfl_fmt, "O") \ X("lockmode", &self->lockmode, "i") \ X("_conntype", &conntype, "i") \ X("_iops", &iops_O, "O") static char *kwlist[] = { #define X(s, target, type) s, XCTOR_ARGS(X) #undef X NULL }; #define X(s, target, type) type static char *argspec = "|" XCTOR_ARGS(X); #undef X if (self->init_called) { PyErr_SetString(PyExc_RuntimeError, "__init__ was already called"); return -1; } self->init_called = 1; self->flags = 0; self->unlock_gil = 1; self->lockmode = PYCBC_LOCKMODE_EXC; #define X(s, target, type) target, rv = PyArg_ParseTupleAndKeywords(args, kwargs, argspec, kwlist, XCTOR_ARGS(X) NULL); #undef X if (!rv) { PYCBC_EXCTHROW_ARGS(); return -1; } if (unlock_gil_O && PyObject_IsTrue(unlock_gil_O) == 0) { self->unlock_gil = 0; } if (create_opts.v.v1.bucket) { self->bucket = pycbc_SimpleStringZ(create_opts.v.v1.bucket); } create_opts.version = 1; create_opts.v.v1.type = conntype; if (iops_O && iops_O != Py_None) { self->iops = pycbc_iops_new(self, iops_O); create_opts.v.v1.io = self->iops; self->unlock_gil = 0; } Py_INCREF(self->errors); if (dfl_fmt == Py_None || dfl_fmt == NULL) { /** Set to 0 if None or NULL */ dfl_fmt = pycbc_IntFromL(0); } else { Py_INCREF(dfl_fmt); /* later decref */ } rv = Connection_set_format(self, dfl_fmt, NULL); Py_XDECREF(dfl_fmt); if (rv == -1) { return rv; } /** Set the transcoder */ if (tc && Connection_set_transcoder(self, tc, NULL) == -1) { return -1; } #ifdef WITH_THREAD if (!self->unlock_gil) { self->lockmode = PYCBC_LOCKMODE_NONE; } if (self->lockmode != PYCBC_LOCKMODE_NONE) { self->lock = PyThread_allocate_lock(); } #endif if (conncache) { if (conntype != LCB_TYPE_BUCKET) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Cannot use connection cache with " "management connection"); return -1; } cached_config.cachefile = conncache; memcpy(&cached_config.createopt, &create_opts, sizeof(create_opts)); err = lcb_create_compat(LCB_CACHED_CONFIG, &cached_config, &self->instance, NULL); } else { err = lcb_create(&self->instance, &create_opts); } if (err != LCB_SUCCESS) { self->instance = NULL; PYCBC_EXC_WRAP(PYCBC_EXC_LCBERR, err, "Couldn't create instance. Either bad " "credentials/hosts/bucket names were " "passed, or there was an internal error in creating the " "object"); return -1; } pycbc_callbacks_init(self->instance); lcb_set_cookie(self->instance, self); if (timeout && timeout != Py_None) { if (Connection_set_timeout(self, timeout, NULL) == -1) { return -1; } } PYCBC_CONN_THR_BEGIN(self); err = lcb_connect(self->instance); PYCBC_CONN_THR_END(self); if (err != LCB_SUCCESS) { PYCBC_EXC_WRAP(PYCBC_EXC_LCBERR, err, "Couldn't schedule connection. This might be a result of " "an invalid hostname."); return -1; } err = pycbc_oputil_wait_common(self); if (err != LCB_SUCCESS) { PYCBC_EXCTHROW_WAIT(err); 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; }
static int handle_item_kv(pycbc_Item *itm, PyObject *options, const struct storecmd_vars *scv, struct single_key_context *skc) { int rv; PyObject *ttl_O = NULL, *flagsobj_Oalt = NULL, *igncas_O = NULL; PyObject *frag_O = NULL; static char *itm_optlist[] = { "ttl", "format", "ignore_cas", "fragment", NULL }; lcb_cas_t itmcas = itm->cas; skc->value = itm->value; if (options) { rv = PyArg_ParseTupleAndKeywords(pycbc_DummyTuple, options, "|OOOO", itm_optlist, &ttl_O, &flagsobj_Oalt, &igncas_O, &frag_O); if (!rv) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Couldn't parse item options"); return -1; } if (ttl_O) { if (-1 == pycbc_get_ttl(ttl_O, &skc->ttl, 1)) { return -1; } if (!skc->ttl) { skc->ttl = scv->ttl; } } if (flagsobj_Oalt && flagsobj_Oalt != Py_None) { skc->flagsobj = flagsobj_Oalt; } if (igncas_O && PyObject_IsTrue(igncas_O)) { itmcas = 0; } if (frag_O == NULL) { if (scv->operation == LCB_APPEND || scv->operation == LCB_PREPEND) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "append/prepend must provide options with 'fragment' specifier"); return -1; } } else { if (scv->operation != LCB_APPEND && scv->operation != LCB_PREPEND) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "'fragment' only valid for append/prepend"); return -1; } skc->value = frag_O; } } else { if (scv->operation == LCB_APPEND || scv->operation == LCB_PREPEND) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "append/prepend must provide options with 'fragment' specifier"); return -1; } } if (!skc->value) { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ARGUMENTS, 0, "Value is empty", skc->value); return -1; } skc->cas = itmcas; return 0; }
static PyObject * set_common(pycbc_Bucket *self, PyObject *args, PyObject *kwargs, const lcb_storage_t operation, int argopts) { int rv; Py_ssize_t ncmds = 0; PyObject *ttl_O = NULL; PyObject *dict = NULL; PyObject *key; PyObject *value; pycbc_seqtype_t seqtype; struct pycbc_common_vars cv = PYCBC_COMMON_VARS_STATIC_INIT; struct storecmd_vars scv = { 0 }; char persist_to = 0, replicate_to = 0; static char *kwlist_multi[] = { "kv", "ttl", "format", "persist_to", "replicate_to", NULL }; static char *kwlist_single[] = { "key", "value", "cas", "ttl", "format", "persist_to", "replicate_to", NULL }; scv.operation = operation; if (argopts & PYCBC_ARGOPT_MULTI) { rv = PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOBB", kwlist_multi, &dict, &ttl_O, &scv.flagsobj, &persist_to, &replicate_to); } else { rv = PyArg_ParseTupleAndKeywords(args, kwargs, "OO|KOOBB", kwlist_single, &key, &value, &scv.single_cas, &ttl_O, &scv.flagsobj, &persist_to, &replicate_to); } if (!rv) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "couldn't parse arguments"); return NULL; } rv = pycbc_get_ttl(ttl_O, &scv.ttl, 1); if (rv < 0) { return NULL; } if (argopts & PYCBC_ARGOPT_MULTI) { rv = pycbc_oputil_check_sequence(dict, 0, &ncmds, &seqtype); if (rv < 0) { return NULL; } } else { ncmds = 1; } if (operation == LCB_APPEND || operation == LCB_PREPEND) { rv = handle_append_flags(self, &scv.flagsobj); if (rv < 0) { return NULL; } } else if (scv.flagsobj == NULL || scv.flagsobj == Py_None) { scv.flagsobj = self->dfl_fmt; } rv = pycbc_common_vars_init(&cv, self, argopts, ncmds, 1); if (rv < 0) { return NULL; } rv = pycbc_handle_durability_args(self, &cv.mres->dur, persist_to, replicate_to); if (rv == 1) { cv.mres->mropts |= PYCBC_MRES_F_DURABILITY; } else if (rv == -1) { goto GT_DONE; } if (argopts & PYCBC_ARGOPT_MULTI) { rv = pycbc_oputil_iter_multi(self, seqtype, dict, &cv, 0, handle_single_kv, &scv); } else { rv = handle_single_kv(self, &cv, 0, key, value, NULL, NULL, &scv); } if (rv < 0) { 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_Bucket__n1ql_query(pycbc_Bucket *self, PyObject *args, PyObject *kwargs) { int rv; PyObject *ret = NULL; pycbc_MultiResult *mres; pycbc_ViewResult *vres; lcb_error_t rc; lcb_CMDN1QL cmd = { 0 }; const char *params; pycbc_strlen_t nparams; int prepared = 0, cross_bucket = 0; static char *kwlist[] = { "params", "prepare", "cross_bucket", NULL }; rv = PyArg_ParseTupleAndKeywords( args, kwargs, "s#|ii", kwlist, ¶ms, &nparams, &prepared, &cross_bucket); if (!rv) { PYCBC_EXCTHROW_ARGS(); return NULL; } if (-1 == pycbc_oputil_conn_lock(self)) { return NULL; } if (self->pipeline_queue) { PYCBC_EXC_WRAP(PYCBC_EXC_PIPELINE, 0, "N1QL queries cannot be executed in " "pipeline context"); } mres = (pycbc_MultiResult *)pycbc_multiresult_new(self); vres = (pycbc_ViewResult *)PYCBC_TYPE_CTOR(&pycbc_ViewResultType); pycbc_httpresult_init(&vres->base, mres); vres->rows = PyList_New(0); vres->base.format = PYCBC_FMT_JSON; vres->base.htype = PYCBC_HTTP_HN1QL; cmd.content_type = "application/json"; cmd.callback = n1ql_row_callback; cmd.query = params; cmd.nquery = nparams; cmd.handle = &vres->base.u.nq; if (prepared) { cmd.cmdflags |= LCB_CMDN1QL_F_PREPCACHE; } if (cross_bucket) { cmd.cmdflags |= LCB_CMD_F_MULTIAUTH; } rc = lcb_n1ql_query(self->instance, mres, &cmd); if (rc != LCB_SUCCESS) { PYCBC_EXC_WRAP(PYCBC_EXC_LCBERR, rc, "Couldn't schedule n1ql query"); goto GT_DONE; } ret = (PyObject *)mres; mres = NULL; GT_DONE: Py_XDECREF(mres); pycbc_oputil_conn_unlock(self); return ret; }
/** * This is called during each iteration of delete/unlock */ static int handle_single_keyop(pycbc_Bucket *self, struct pycbc_common_vars *cv, int optype, PyObject *curkey, PyObject *curval, PyObject *options, pycbc_Item *item, void *arg) { int rv; char *key; size_t nkey; lcb_U64 cas = 0; lcb_error_t err; union { lcb_CMDBASE base; lcb_CMDREMOVE rm; lcb_CMDUNLOCK unl; lcb_CMDENDURE endure; } ucmd; (void)options; (void)arg; memset(&ucmd, 0, sizeof ucmd); if ( (optype == PYCBC_CMD_UNLOCK || optype == PYCBC_CMD_ENDURE) && PYCBC_OPRES_CHECK(curkey)) { curval = curkey; curkey = ((pycbc_OperationResult*)curkey)->key; } rv = pycbc_tc_encode_key(self, &curkey, (void**)&key, &nkey); if (rv == -1) { return -1; } if (!nkey) { PYCBC_EXCTHROW_EMPTYKEY(); rv = -1; goto GT_DONE; } if (item) { cas = item->cas; } else if (curval) { if (PyDict_Check(curval)) { PyObject *cas_o = PyDict_GetItemString(curval, "cas"); if (!cas_o) { PyErr_Clear(); } cas = pycbc_IntAsULL(cas_o); } else if (PYCBC_OPRES_CHECK(curval)) { /* If we're passed a Result object, just extract its CAS */ cas = ((pycbc_OperationResult*)curval)->cas; } else if (PyNumber_Check(curval)) { cas = pycbc_IntAsULL(curval); } if (cas == (lcb_uint64_t)-1 && PyErr_Occurred()) { PyErr_Clear(); PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Invalid CAS specified"); return -1; } } LCB_CMD_SET_KEY(&ucmd.base, key, nkey); ucmd.base.cas = cas; if (optype == PYCBC_CMD_UNLOCK) { if (!cas) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "CAS must be specified for unlock"); return -1; } err = lcb_unlock3(self->instance, cv->mres, &ucmd.unl); } else if (optype == PYCBC_CMD_ENDURE) { err = cv->mctx->addcmd(cv->mctx, &ucmd.base); } else { err = lcb_remove3(self->instance, cv->mres, &ucmd.rm); } if (err == LCB_SUCCESS) { rv = 0; } else { rv = -1; PYCBC_EXCTHROW_SCHED(err); } GT_DONE: Py_XDECREF(curkey); return rv; }