static void row_callback(lcb_t instance, int cbtype, const lcb_RESPVIEWQUERY *resp) { pycbc_MultiResult *mres = (pycbc_MultiResult*)resp->cookie; pycbc_Bucket *bucket = mres->parent; const char * const * hdrs = NULL; short htcode = 0; pycbc_ViewResult *vres; if (resp->htresp != NULL) { hdrs = resp->htresp->headers; htcode = resp->htresp->htstatus; } PYCBC_CONN_THR_END(bucket); vres = (pycbc_ViewResult*)PyDict_GetItem((PyObject*)mres, Py_None); if (resp->rflags & LCB_RESP_F_FINAL) { pycbc_httpresult_add_data(mres, &vres->base, resp->value, resp->nvalue); } else if (resp->rc == LCB_SUCCESS) { if (parse_row_json(bucket, vres, mres, resp) != 0) { pycbc_multiresult_adderr(mres); } } pycbc_viewresult_step(vres, mres, bucket, resp->rflags & LCB_RESP_F_FINAL); if (resp->rflags & LCB_RESP_F_FINAL) { pycbc_httpresult_complete(&vres->base, mres, resp->rc, htcode, hdrs); } else { PYCBC_CONN_THR_BEGIN(bucket); } (void)instance; (void)cbtype; }
static void fts_row_callback(lcb_t instance, int ign, const lcb_RESPFTS *resp) { pycbc_MultiResult *mres = (pycbc_MultiResult *)resp->cookie; pycbc_Bucket *bucket = mres->parent; pycbc_ViewResult *vres; const char * const * hdrs = NULL; short htcode = 0; PYCBC_CONN_THR_END(bucket); vres = (pycbc_ViewResult *)PyDict_GetItem((PyObject*)mres, Py_None); if (resp->htresp) { hdrs = resp->htresp->headers; htcode = resp->htresp->htstatus; } if (resp->rflags & LCB_RESP_F_FINAL) { pycbc_httpresult_add_data(mres, &vres->base, resp->row, resp->nrow); } else { /* Like views, try to decode the row and invoke the callback; if we can */ /* Assume success! */ pycbc_viewresult_addrow(vres, mres, resp->row, resp->nrow); } pycbc_viewresult_step(vres, mres, bucket, resp->rflags & LCB_RESP_F_FINAL); if (resp->rflags & LCB_RESP_F_FINAL) { pycbc_httpresult_complete(&vres->base, mres, resp->rc, htcode, hdrs); } else { PYCBC_CONN_THR_BEGIN(bucket); } }
/** * This callback does things a bit differently. * Instead of using a MultiResult, we use a single HttpResult object. * We won't ever have "multiple" http objects. */ static void http_complete_callback(lcb_http_request_t req, lcb_t instance, const void *cookie, lcb_error_t err, const lcb_http_resp_t *resp) { pycbc_HttpResult *htres = (pycbc_HttpResult*)cookie; htres->htreq = NULL; htres->rc = err; htres->htcode = resp->v.v0.status; htres->htflags |= PYCBC_HTRES_F_COMPLETE; if (!htres->parent) { return; } PYCBC_CONN_THR_END(htres->parent); add_data(htres, resp->v.v0.bytes, resp->v.v0.nbytes); get_headers(htres, resp); finalize_data(htres); PYCBC_CONN_THR_BEGIN(htres->parent); if (htres->htflags & PYCBC_HTRES_F_CHUNKED) { /** No data here */ if (!htres->parent->nremaining) { lcb_breakout(instance); } maybe_invoke_async_callback(htres); return; } if (htres->parent->flags & PYCBC_CONN_F_ASYNC) { maybe_invoke_async_callback(htres); return; } if (!--htres->parent->nremaining) { lcb_breakout(instance); } (void)instance; (void)req; }
static void http_data_callback(lcb_http_request_t req, lcb_t instance, const void *cookie, lcb_error_t err, const lcb_http_resp_t *resp) { pycbc_HttpResult *htres = (pycbc_HttpResult*)cookie; htres->htcode = resp->v.v0.status; htres->rc = err; PYCBC_CONN_THR_END(htres->parent); get_headers(htres, resp); if (err != LCB_SUCCESS || resp->v.v0.status < 200 || resp->v.v0.status > 299) { PyObject *old_data = htres->http_data; lcbex_vrow_free(htres->rctx); htres->rctx = NULL; htres->http_data = PyList_New(0); if (old_data) { if (old_data != Py_None) { PyList_Append(htres->http_data, old_data); } Py_DECREF(old_data); } } if (htres->rctx) { lcbex_vrow_feed(htres->rctx, resp->v.v0.bytes, resp->v.v0.nbytes); } else if (resp->v.v0.bytes) { get_data(htres, resp->v.v0.bytes, resp->v.v0.nbytes); } if (!htres->parent->nremaining) { lcb_breakout(instance); } PYCBC_CONN_THR_BEGIN(htres->parent); (void)req; (void)instance; }
/** * This callback does things a bit differently. * Instead of using a MultiResult, we use a single HttpResult object. * We won't ever have "multiple" http objects. */ static void http_complete_callback(lcb_http_request_t req, lcb_t instance, const void *cookie, lcb_error_t err, const lcb_http_resp_t *resp) { pycbc_HttpResult *htres = (pycbc_HttpResult*)cookie; htres->htreq = NULL; if (!htres->parent) { return; } htres->rc = err; htres->htcode = resp->v.v0.status; if (htres->htflags & PYCBC_HTRES_F_CHUNKED) { /** No data here */ if (!pycbc_assert(resp->v.v0.nbytes == 0)) { fprintf(stderr, "Unexpected payload in HTTP response callback\n"); } if (!htres->parent->nremaining) { lcb_breakout(instance); } return; } PYCBC_CONN_THR_END(htres->parent); if (!--htres->parent->nremaining) { lcb_breakout(instance); } get_data(htres, resp->v.v0.bytes, resp->v.v0.nbytes); get_headers(htres, resp); PYCBC_CONN_THR_BEGIN(htres->parent); (void)instance; (void)req; }
static void http_data_callback(lcb_http_request_t req, lcb_t instance, const void *cookie, lcb_error_t err, const lcb_http_resp_t *resp) { pycbc_HttpResult *htres = (pycbc_HttpResult*)cookie; htres->htcode = resp->v.v0.status; htres->rc = err; PYCBC_CONN_THR_END(htres->parent); get_headers(htres, resp); if (err != LCB_SUCCESS || resp->v.v0.status < 200 || resp->v.v0.status > 299) { lcbex_vrow_free(htres->rctx); htres->rctx = NULL; } if (htres->rctx) { lcbex_vrow_feed(htres->rctx, resp->v.v0.bytes, resp->v.v0.nbytes); maybe_invoke_async_callback(htres); } else if (resp->v.v0.bytes) { add_data(htres, resp->v.v0.bytes, resp->v.v0.nbytes); } if (!htres->parent->nremaining) { lcb_breakout(instance); } PYCBC_CONN_THR_BEGIN(htres->parent); (void)req; (void)instance; }
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; }
static void cb_thr_end(pycbc_Bucket *self) { PYCBC_CONN_THR_END(self); Py_INCREF((PyObject *)self); }