Esempio n. 1
0
static void
Bucket_dtor(pycbc_Bucket *self)
{
    if (self->flags & PYCBC_CONN_F_CLOSED) {
        lcb_destroy(self->instance);
        self->instance = NULL;
    }

    if (self->instance) {
        lcb_set_cookie(self->instance, NULL);
        pycbc_schedule_dtor_event(self);
    }

    Py_XDECREF(self->dtorcb);
    Py_XDECREF(self->dfl_fmt);
    Py_XDECREF(self->tc);
    Py_XDECREF(self->bucket);
    Py_XDECREF(self->conncb);
    Py_XDECREF(self->dur_testhook);
    Py_XDECREF(self->iopswrap);

    if (self->instance) {
        lcb_destroy(self->instance);
    }

#ifdef WITH_THREAD
    if (self->lock) {
        PyThread_free_lock(self->lock);
        self->lock = NULL;
    }
#endif

    Py_TYPE(self)->tp_free((PyObject*)self);
}
static ngx_int_t
ngx_lcb_init_process(ngx_cycle_t *cycle)
{
    ngx_lcb_main_conf_t *cmcf;
    struct lcb_create_io_ops_st options;
    lcb_error_t err;
    ngx_int_t rc;
    ngx_uint_t i;
    ngx_lcb_connection_t *conn;
    ngx_lcb_loc_conf_t **ccfp;

    /* initialize libcouchbase IO plugin */
    memset(&options, 0, sizeof(options));
    options.version = 2;
    options.v.v2.create = ngx_lcb_create_io_opts;
    options.v.v2.cookie = &lcb_cookie;
    err = lcb_create_io_ops(&lcb_cookie.io, &options);
    if (err != LCB_SUCCESS) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                      "couchbase: failed to create IO object for libcouchbase: 0x%02xd \"%s\"",
                      err, lcb_strerror(NULL, err));
        return NGX_ERROR;
    }

    lcb_cookie.log = cycle->log;
    lcb_cookie.pool = cycle->pool;

    /* materialize upstream connections */
    rc = ngx_array_init(&lcb_connections, cycle->pool, 4, sizeof(ngx_lcb_connection_t));
    if (rc != NGX_OK) {
        return NGX_ERROR;
    }
    cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_couchbase_module);
    ccfp = cmcf->connection_confs.elts;
    for (i = 0; i < cmcf->connection_confs.nelts; i++) {
        struct lcb_create_st opts = ccfp[i]->options;

        conn = ngx_array_push(&lcb_connections);
        if (conn == NULL) {
            return NGX_ERROR;
        }
        conn->log = cycle->log;
        conn->name = ccfp[i]->name;
        rc = ngx_array_init(&conn->backlog, cycle->pool, 4, sizeof(ngx_http_request_t *));
        if (rc != NGX_OK) {
            return NGX_ERROR;
        }
        opts.v.v0.io = lcb_cookie.io;
        err = lcb_create(&conn->lcb, &opts);
        if (err != LCB_SUCCESS) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
                          "couchbase: failed to create libcouchbase instance: 0x%02xd \"%s\"",
                          err, lcb_strerror(NULL, err));
            return NGX_ERROR;
        }
        (void)lcb_set_error_callback(conn->lcb, ngx_lcb_error_callback);
        (void)lcb_set_timeout(conn->lcb, ccfp[i]->connect_timeout * 1000); /* in usec */
        (void)lcb_set_get_callback(conn->lcb, ngx_lcb_get_callback);
        (void)lcb_set_store_callback(conn->lcb, ngx_lcb_store_callback);
        (void)lcb_set_remove_callback(conn->lcb, ngx_lcb_remove_callback);
        (void)lcb_set_configuration_callback(conn->lcb, ngx_lcb_configuration_callback);
        (void)lcb_set_cookie(conn->lcb, conn);
        ngx_log_debug7(NGX_LOG_DEBUG_HTTP, cycle->log, 0,
                       "couchbase(%p): configured connection \"%V\": connect_timeout:%Mms "
                       "address:%s bucket:%s user:%s password:%s",
                       conn->lcb, &conn->name, ccfp[i]->connect_timeout,
                       opts.v.v0.host ? opts.v.v0.host : "(null)",
                       opts.v.v0.bucket ? opts.v.v0.bucket : "(null)",
                       opts.v.v0.user ? opts.v.v0.user : "******",
                       opts.v.v0.passwd ? opts.v.v0.passwd : "(null)");
    }
    return NGX_OK;
}
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;
}
Esempio n. 4
0
static int
Bucket__init__(pycbc_Bucket *self,
                       PyObject *args, PyObject *kwargs)
{
    int rv;
    int conntype = LCB_TYPE_BUCKET;

    lcb_error_t err;
    PyObject *unlock_gil_O = NULL;
    PyObject *iops_O = NULL;
    PyObject *dfl_fmt = NULL;
    PyObject *tc = NULL;

    struct lcb_create_st create_opts = { 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("connection_string", &create_opts.v.v3.connstr, "z") \
    X("connstr", &create_opts.v.v3.connstr, "z") \
    X("username", &create_opts.v.v3.username, "z") \
    X("password", &create_opts.v.v3.passwd, "z") \
    X("quiet", &self->quiet, "I") \
    X("unlock_gil", &unlock_gil_O, "O") \
    X("transcoder", &tc, "O") \
    X("default_format", &dfl_fmt, "O") \
    X("lockmode", &self->lockmode, "i") \
    X("_flags", &self->flags, "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;
    }

    create_opts.version = 3;
    create_opts.v.v3.type = conntype;

    if (iops_O && iops_O != Py_None) {
        self->iopswrap = pycbc_iowrap_new(self, iops_O);
        create_opts.v.v3.io = pycbc_iowrap_getiops(self->iopswrap);
        self->unlock_gil = 0;
    }

    if (dfl_fmt == Py_None || dfl_fmt == NULL) {
        /** Set to 0 if None or NULL */
        dfl_fmt = pycbc_IntFromL(PYCBC_FMT_JSON);

    } else {
        Py_INCREF(dfl_fmt); /* later decref */
    }

    rv = Bucket_set_format(self, dfl_fmt, NULL);
    Py_XDECREF(dfl_fmt);
    if (rv == -1) {
        return rv;
    }

    /** Set the transcoder */
    if (tc && Bucket_set_transcoder(self, tc, NULL) == -1) {
        return -1;
    }

#if defined(WITH_THREAD)
    if (!self->unlock_gil) {
        self->lockmode = PYCBC_LOCKMODE_NONE;
    }

    if (self->lockmode != PYCBC_LOCKMODE_NONE) {
        self->lock = PyThread_allocate_lock();
    }
#else
    self->unlock_gil = 0;
    self->lockmode = PYCBC_LOCKMODE_NONE;
#endif

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

    if (pycbc_log_handler) {
        err = lcb_cntl(self->instance, LCB_CNTL_SET, LCB_CNTL_LOGGER,
                       &pycbc_lcb_logprocs);
        if (err != LCB_SUCCESS) {
            self->instance = NULL;
            PYCBC_EXC_WRAP(PYCBC_EXC_LCBERR, err, "Couldn't create log handler");
            return -1;
        }
    }

    pycbc_callbacks_init(self->instance);
    lcb_set_cookie(self->instance, self);
    {
        const char *bucketstr;
        err = lcb_cntl(self->instance, LCB_CNTL_GET, LCB_CNTL_BUCKETNAME, &bucketstr);
        if (err == LCB_SUCCESS && bucketstr != NULL) {
            self->bucket = pycbc_SimpleStringZ(bucketstr);
        }
    }
    return 0;
}