Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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);
    }
}
Exemplo n.º 3
0
static void
cb_thr_begin(pycbc_Bucket *self)
{
    if (Py_REFCNT(self) > 1) {
        Py_DECREF(self);
        PYCBC_CONN_THR_BEGIN(self);
        return;
    }

    pycbc_assert(self->unlock_gil == 0);
    Py_DECREF(self);
}
Exemplo n.º 4
0
/**
 * 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;
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
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;
}