static void store_callback(lcb_t instance, const void *cookie, lcb_storage_t op, lcb_error_t err, const lcb_store_resp_t *resp) { pycbc_ConnectionObject *conn; pycbc_OperationResultObject *res; pycbc_MultiResultObject *mres; int rv; rv = get_common_objects((PyObject*)cookie, resp->v.v0.key, resp->v.v0.nkey, err, &conn, (pycbc_ResultBaseObject**)&res, RESTYPE_OPERATION, &mres); if (rv == -1) { CB_THR_BEGIN(conn); return; } res->rc = err; res->cas = resp->v.v0.cas; maybe_push_operr(mres, (pycbc_ResultBaseObject*)res, err, 0); CB_THR_BEGIN(conn); (void)instance; (void)op; }
static void stat_callback(lcb_t instance, const void *cookie, lcb_error_t err, const lcb_server_stat_resp_t *resp) { pycbc_MultiResultObject *mres; PyObject *value; PyObject *skey, *knodes; mres = (pycbc_MultiResultObject*)cookie; CB_THR_END(mres->parent); if (err != LCB_SUCCESS) { if (mres->errop == NULL) { pycbc_ResultBaseObject *res = (pycbc_ResultBaseObject*)pycbc_result_new(mres->parent); res->rc = err; res->key = Py_None; Py_INCREF(res->key); maybe_push_operr(mres, res, err, 0); } CB_THR_BEGIN(mres->parent); return; } if (!resp->v.v0.server_endpoint) { CB_THR_BEGIN(mres->parent); return; } skey = pycbc_SimpleStringN(resp->v.v0.key, resp->v.v0.nkey); value = pycbc_SimpleStringN(resp->v.v0.bytes, resp->v.v0.nbytes); { PyObject *intval = pycbc_maybe_convert_to_int(value); if (intval) { Py_DECREF(value); value = intval; } else { PyErr_Clear(); } } knodes = PyDict_GetItem((PyObject*)mres, skey); if (!knodes) { knodes = PyDict_New(); PyDict_SetItem((PyObject*)mres, skey, knodes); Py_DECREF(knodes); } PyDict_SetItemString(knodes, resp->v.v0.server_endpoint, value); Py_DECREF(skey); Py_DECREF(value); CB_THR_BEGIN(mres->parent); (void)instance; }
static void get_callback(lcb_t instance, const void *cookie, lcb_error_t err, const lcb_get_resp_t *resp) { int rv; pycbc_Connection *conn = NULL; pycbc_ValueResult *res = NULL; pycbc_MultiResult *mres = NULL; lcb_uint32_t eflags; rv = get_common_objects((PyObject*)cookie, resp->v.v0.key, resp->v.v0.nkey, err, &conn, (pycbc_Result**)&res, RESTYPE_VALUE, &mres); if (rv < 0) { CB_THR_BEGIN(conn); return; } res->flags = resp->v.v0.flags; res->cas = resp->v.v0.cas; maybe_push_operr(mres, (pycbc_Result*)res, err, 1); if (err != LCB_SUCCESS) { CB_THR_BEGIN(conn); return; } if (mres->mropts & PYCBC_MRES_F_FORCEBYTES) { eflags = PYCBC_FMT_BYTES; } else { eflags = resp->v.v0.flags; } rv = pycbc_tc_decode_value(mres->parent, resp->v.v0.bytes, resp->v.v0.nbytes, eflags, &res->value); if (rv < 0) { push_fatal_error(mres); } CB_THR_BEGIN(conn); (void)instance; }
static void keyop_simple_callback(lcb_t instance, int cbtype, const lcb_RESPBASE *resp) { int rv; int optflags = RESTYPE_OPERATION; pycbc_Bucket *conn = NULL; pycbc_OperationResult *res = NULL; pycbc_MultiResult *mres = NULL; if (cbtype == LCB_CALLBACK_ENDURE) { optflags |= RESTYPE_EXISTS_OK; } rv = get_common_objects(resp, &conn, (pycbc_Result**)&res, optflags, &mres); if (rv == 0) { res->rc = resp->rc; maybe_push_operr(mres, (pycbc_Result*)res, resp->rc, 0); } if (resp->cas) { res->cas = resp->cas; } operation_completed(conn, mres); CB_THR_BEGIN(conn); (void)instance; }
static void subdoc_callback(lcb_t instance, int cbtype, const lcb_RESPBASE *rb) { int rv; pycbc_Bucket *conn; pycbc__SDResult *res; pycbc_MultiResult *mres; lcb_SDENTRY cur; size_t vii = 0, oix = 0; const lcb_RESPSUBDOC *resp = (const lcb_RESPSUBDOC *)rb; rv = get_common_objects(rb, &conn, (pycbc_Result**)&res, RESTYPE_EXISTS_OK, &mres); if (rv < 0) { goto GT_ERROR; } if (rb->rc == LCB_SUCCESS || rb->rc == LCB_SUBDOC_MULTI_FAILURE) { res->cas = rb->cas; } else { maybe_push_operr(mres, (pycbc_Result*)res, rb->rc, 0); goto GT_ERROR; } while ((lcb_sdresult_next(resp, &cur, &vii))) { size_t cur_index; PyObject *cur_tuple = mk_sd_tuple(&cur); if (cbtype == LCB_CALLBACK_SDMUTATE) { cur_index = cur.index; } else { cur_index = oix++; } if (cur_tuple == NULL) { pycbc_multiresult_adderr(mres); goto GT_ERROR; } if (cur.status != LCB_SUCCESS) { if (cbtype == LCB_CALLBACK_SDMUTATE) { mk_sd_error(res, mres, cur.status, cur_index); } else if (cur.status != LCB_SUBDOC_PATH_ENOENT) { mk_sd_error(res, mres, cur.status, cur_index); } } pycbc_sdresult_addresult(res, cur_index, cur_tuple); Py_DECREF(cur_tuple); } if (rb->rc == LCB_SUCCESS) { dur_chain2(conn, mres, (pycbc_OperationResult*)res, cbtype, (const lcb_RESPBASE*)resp); return; } GT_ERROR: operation_completed(conn, mres); CB_THR_BEGIN(conn); (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_HttpResultObject *htres = (pycbc_HttpResultObject*)cookie; htres->rc = err; htres->htcode = resp->v.v0.status; CB_THR_END(htres->parent); if (resp->v.v0.nbytes) { pycbc_tc_simple_decode(&htres->http_data, resp->v.v0.bytes, resp->v.v0.nbytes, htres->format); if (!htres->http_data) { PyErr_Clear(); htres->http_data = PyBytes_FromStringAndSize(resp->v.v0.bytes, resp->v.v0.nbytes); } } else { htres->http_data = Py_None; Py_INCREF(Py_None); } CB_THR_BEGIN(htres->parent); (void)instance; (void)req; }
static void touch_callback(lcb_t instance, const void *cookie, lcb_error_t err, const lcb_touch_resp_t *resp) { int rv; pycbc_ConnectionObject *conn = NULL; pycbc_OperationResultObject *res = NULL; pycbc_MultiResultObject *mres = NULL; rv = get_common_objects((PyObject*) cookie, resp->v.v0.key, resp->v.v0.nkey, err, &conn, (pycbc_ResultBaseObject**)&res, RESTYPE_OPERATION, &mres); if (rv == 0) { res->cas = resp->v.v0.cas; res->rc = err; maybe_push_operr(mres, (pycbc_ResultBaseObject*)res, err, 1); } CB_THR_BEGIN(conn); (void)instance; }
static void arithmetic_callback(lcb_t instance, const void *cookie, lcb_error_t err, const lcb_arithmetic_resp_t *resp) { int rv; pycbc_ConnectionObject *conn = NULL; pycbc_ValueResultObject *res = NULL; pycbc_MultiResultObject *mres = NULL; rv = get_common_objects((PyObject*)cookie, resp->v.v0.key, resp->v.v0.nkey, err, &conn, (pycbc_ResultBaseObject**)&res, RESTYPE_VALUE, &mres); if (rv == 0) { res->cas = resp->v.v0.cas; res->rc = err; if (err == LCB_SUCCESS) { res->value = pycbc_IntFromULL(resp->v.v0.value); } maybe_push_operr(mres, (pycbc_ResultBaseObject*)res, err, 0); } CB_THR_BEGIN(conn); (void)instance; }
static void end_global_callback(lcb_t instance, pycbc_Bucket *self) { Py_DECREF((PyObject *)(self)); self = (pycbc_Bucket *)lcb_get_cookie(instance); if (self) { CB_THR_BEGIN(self); } }
static void observe_callback(lcb_t instance, const void *cookie, lcb_error_t err, const lcb_observe_resp_t *resp) { int rv; pycbc_ObserveInfo *oi; pycbc_Connection *conn; pycbc_ValueResult *vres; pycbc_MultiResult *mres; if (!resp->v.v0.key) { mres = (pycbc_MultiResult*)cookie;; maybe_breakout(mres->parent); return; } rv = get_common_objects((PyObject*)cookie, resp->v.v0.key, resp->v.v0.nkey, err, &conn, (pycbc_Result**)&vres, RESTYPE_VALUE|RESTYPE_EXISTS_OK|RESTYPE_VARCOUNT, &mres); if (rv < 0) { goto GT_DONE; } if (err != LCB_SUCCESS) { maybe_push_operr(mres, (pycbc_Result*)vres, err, 0); goto GT_DONE; } if (!vres->value) { vres->value = PyList_New(0); } oi = pycbc_observeinfo_new(conn); if (oi == NULL) { push_fatal_error(mres); goto GT_DONE; } oi->from_master = resp->v.v0.from_master; oi->flags = resp->v.v0.status; oi->cas = resp->v.v0.cas; PyList_Append(vres->value, (PyObject*)oi); Py_DECREF(oi); GT_DONE: CB_THR_BEGIN(conn); (void)instance; }
static void value_callback(lcb_t instance, int cbtype, const lcb_RESPBASE *resp) { int rv; pycbc_Bucket *conn = NULL; pycbc_ValueResult *res = NULL; pycbc_MultiResult *mres = NULL; rv = get_common_objects(resp, &conn, (pycbc_Result**)&res, RESTYPE_VALUE, &mres); if (rv < 0) { goto GT_DONE; } if (resp->rc == LCB_SUCCESS) { res->cas = resp->cas; } else { maybe_push_operr(mres, (pycbc_Result*)res, resp->rc, cbtype != LCB_CALLBACK_COUNTER); goto GT_DONE; } if (cbtype == LCB_CALLBACK_GET || cbtype == LCB_CALLBACK_GETREPLICA) { const lcb_RESPGET *gresp = (const lcb_RESPGET *)resp; lcb_U32 eflags; res->flags = gresp->itmflags; if (mres->mropts & PYCBC_MRES_F_FORCEBYTES) { eflags = PYCBC_FMT_BYTES; } else { eflags = gresp->itmflags; } rv = pycbc_tc_decode_value(mres->parent, gresp->value, gresp->nvalue, eflags, &res->value); if (rv < 0) { pycbc_multiresult_adderr(mres); } } else if (cbtype == LCB_CALLBACK_COUNTER) { const lcb_RESPCOUNTER *cresp = (const lcb_RESPCOUNTER *)resp; res->value = pycbc_IntFromULL(cresp->value); } GT_DONE: operation_completed(conn, mres); CB_THR_BEGIN(conn); (void)instance; }
static void observe_callback(lcb_t instance, int cbtype, const lcb_RESPBASE *resp_base) { int rv; pycbc_ObserveInfo *oi; pycbc_Bucket *conn; pycbc_ValueResult *vres; pycbc_MultiResult *mres; const lcb_RESPOBSERVE *oresp = (const lcb_RESPOBSERVE *)resp_base; if (resp_base->rflags & LCB_RESP_F_FINAL) { mres = (pycbc_MultiResult*)resp_base->cookie; operation_completed(mres->parent, mres); return; } rv = get_common_objects(resp_base, &conn, (pycbc_Result**)&vres, RESTYPE_VALUE|RESTYPE_EXISTS_OK|RESTYPE_VARCOUNT, &mres); if (rv < 0) { goto GT_DONE; } if (resp_base->rc != LCB_SUCCESS) { maybe_push_operr(mres, (pycbc_Result*)vres, resp_base->rc, 0); goto GT_DONE; } if (!vres->value) { vres->value = PyList_New(0); } oi = pycbc_observeinfo_new(conn); if (oi == NULL) { pycbc_multiresult_adderr(mres); goto GT_DONE; } oi->from_master = oresp->ismaster; oi->flags = oresp->status; oi->cas = oresp->cas; PyList_Append(vres->value, (PyObject*)oi); Py_DECREF(oi); GT_DONE: CB_THR_BEGIN(conn); (void)instance; (void)cbtype; }
static void error_callback(lcb_t instance, lcb_error_t err, const char *msg) { PyObject *errtuple; PyObject *result; pycbc_Connection *self = (pycbc_Connection*) lcb_get_cookie(instance); CB_THR_END(self); pycbc_assert(self->errors); errtuple = Py_BuildValue("(i,s)", err, msg); pycbc_assert(errtuple); result = PyObject_CallMethod(self->errors, "append", "(O)", errtuple); pycbc_assert(result); Py_DECREF(errtuple); Py_DECREF(result); CB_THR_BEGIN(self); }
/** * Common handler for durability */ static void durability_chain_common(lcb_t instance, int cbtype, const lcb_RESPBASE *resp) { pycbc_Bucket *conn; pycbc_OperationResult *res = NULL; pycbc_MultiResult *mres; int restype = RESTYPE_VARCOUNT; if (cbtype == LCB_CALLBACK_COUNTER) { restype |= RESTYPE_VALUE; } else { restype |= RESTYPE_OPERATION; } if (get_common_objects(resp, &conn, (pycbc_Result**)&res, restype, &mres) != 0) { operation_completed(conn, mres); CB_THR_BEGIN(conn); return; } dur_chain2(conn, mres, res, cbtype, resp); }
static void stats_callback(lcb_t instance, int cbtype, const lcb_RESPBASE *resp_base) { pycbc_MultiResult *mres; PyObject *value; PyObject *skey, *knodes; PyObject *mrdict; pycbc_Bucket *parent; const lcb_RESPSTATS *resp = (const lcb_RESPSTATS *)resp_base; int do_return = 0; mres = (pycbc_MultiResult*)resp->cookie; parent = mres->parent; CB_THR_END(parent); if (resp->rc != LCB_SUCCESS) { do_return = 1; if (mres->errop == NULL) { pycbc_Result *res = (pycbc_Result*)pycbc_result_new(parent); res->rc = resp->rc; res->key = Py_None; Py_INCREF(res->key); maybe_push_operr(mres, res, resp->rc, 0); } } if (resp->rflags & LCB_RESP_F_FINAL) { /* Note this can happen in both success and error cases! */ do_return = 1; operation_completed(parent, mres); } if (do_return) { CB_THR_BEGIN(parent); return; } skey = pycbc_SimpleStringN(resp->key, resp->nkey); value = pycbc_SimpleStringN(resp->value, resp->nvalue); { PyObject *intval = pycbc_maybe_convert_to_int(value); if (intval) { Py_DECREF(value); value = intval; } else { PyErr_Clear(); } } mrdict = pycbc_multiresult_dict(mres); knodes = PyDict_GetItem(mrdict, skey); if (!knodes) { knodes = PyDict_New(); PyDict_SetItem(mrdict, skey, knodes); } PyDict_SetItemString(knodes, resp->server, value); Py_DECREF(skey); Py_DECREF(value); CB_THR_BEGIN(parent); (void)instance; }
static void dur_chain2(pycbc_Bucket *conn, pycbc_MultiResult *mres, pycbc_OperationResult *res, int cbtype, const lcb_RESPBASE *resp) { lcb_error_t err; lcb_durability_opts_t dopts = { 0 }; lcb_CMDENDURE cmd = { 0 }; lcb_MULTICMD_CTX *mctx = NULL; int is_delete = cbtype == LCB_CALLBACK_REMOVE; res->rc = resp->rc; if (resp->rc == LCB_SUCCESS) { const lcb_MUTATION_TOKEN *mutinfo = lcb_resp_get_mutation_token(cbtype, resp); Py_XDECREF(res->mutinfo); if (mutinfo && LCB_MUTATION_TOKEN_ISVALID(mutinfo)) { /* Create the mutation token tuple: (vb,uuid,seqno) */ res->mutinfo = Py_BuildValue("HKKO", LCB_MUTATION_TOKEN_VB(mutinfo), LCB_MUTATION_TOKEN_ID(mutinfo), LCB_MUTATION_TOKEN_SEQ(mutinfo), conn->bucket); } else { Py_INCREF(Py_None); res->mutinfo = Py_None; } res->cas = resp->cas; } /** For remove, we check quiet */ maybe_push_operr(mres, (pycbc_Result*)res, resp->rc, is_delete ? 1 : 0); if ((mres->mropts & PYCBC_MRES_F_DURABILITY) == 0 || resp->rc != LCB_SUCCESS) { operation_completed(conn, mres); CB_THR_BEGIN(conn); return; } if (conn->dur_testhook && conn->dur_testhook != Py_None) { invoke_endure_test_notification(conn, (pycbc_Result *)res); } /** Setup global options */ dopts.v.v0.persist_to = mres->dur.persist_to; dopts.v.v0.replicate_to = mres->dur.replicate_to; dopts.v.v0.timeout = conn->dur_timeout; dopts.v.v0.check_delete = is_delete; if (mres->dur.persist_to < 0 || mres->dur.replicate_to < 0) { dopts.v.v0.cap_max = 1; } lcb_sched_enter(conn->instance); mctx = lcb_endure3_ctxnew(conn->instance, &dopts, &err); if (mctx == NULL) { goto GT_DONE; } cmd.cas = resp->cas; LCB_CMD_SET_KEY(&cmd, resp->key, resp->nkey); err = mctx->addcmd(mctx, (lcb_CMDBASE*)&cmd); if (err != LCB_SUCCESS) { goto GT_DONE; } err = mctx->done(mctx, mres); if (err == LCB_SUCCESS) { mctx = NULL; lcb_sched_leave(conn->instance); } GT_DONE: if (mctx) { mctx->fail(mctx); } if (err != LCB_SUCCESS) { res->rc = err; maybe_push_operr(mres, (pycbc_Result*)res, err, 0); operation_completed(conn, mres); } CB_THR_BEGIN(conn); }