int couchbase_set(cachedb_con *connection,str *attr, str *val,int expires) { lcb_t instance; lcb_error_t oprc; lcb_store_cmd_t cmd; const lcb_store_cmd_t *commands[1]; struct timeval start; start_expire_timer(start,couch_exec_threshold); instance = COUCHBASE_CON(connection); commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.operation = LCB_SET; cmd.v.v0.key = attr->s; cmd.v.v0.nkey = attr->len; cmd.v.v0.bytes = val->s; cmd.v.v0.nbytes = val->len; cmd.v.v0.exptime = expires; oprc = lcb_store(instance, NULL, 1, commands); if (oprc != LCB_SUCCESS) { LM_ERR("Set request failed - %s\n", lcb_strerror(instance, oprc)); //Attempt reconnect if(couchbase_conditional_reconnect(connection, oprc) != 1) { stop_expire_timer(start,couch_exec_threshold, "cachedb_couchbase set",attr->s,attr->len,0); return -2; } //Try again instance = COUCHBASE_CON(connection); oprc = lcb_store(instance, NULL, 1, commands); if (oprc != LCB_SUCCESS) { LM_ERR("Set command retry failed - %s\n", lcb_strerror(instance, oprc)); stop_expire_timer(start,couch_exec_threshold, "cachedb_couchbase set",attr->s,attr->len,0); return -2; } LM_ERR("Set command successfully retried\n"); } LM_DBG("Succesfully stored\n"); stop_expire_timer(start,couch_exec_threshold, "cachedb_couchbase set",attr->s,attr->len,0); return 1; }
/** Store a document by key in Couchbase * * Setup and execute a Couchbase set operation and wait for the result. * * @param instance Couchbase connection instance. * @param key Document key to store in the database. * @param document Document body to store in the database. * @param expire Expiration time for the document (0 = never) * @return Couchbase error object. */ lcb_error_t couchbase_set_key(lcb_t instance, const char *key, const char *document, int expire) { lcb_error_t error; /* couchbase command return */ lcb_store_cmd_t cmd; /* store command stuct */ const lcb_store_cmd_t *commands[1]; /* store commands array */ /* init commands */ commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); /* populate command struct */ cmd.v.v0.key = key; cmd.v.v0.nkey = strlen(cmd.v.v0.key); cmd.v.v0.bytes = document; cmd.v.v0.nbytes = strlen(cmd.v.v0.bytes); cmd.v.v0.exptime = expire; cmd.v.v0.operation = LCB_SET; /* store key/document in couchbase */ if ((error = lcb_store(instance, NULL, 1, commands)) == LCB_SUCCESS) { /* enter event loop on success */ lcb_wait(instance); } /* return error */ return error; }
static void test_get1(void) { lcb_error_t err; struct rvbuf rv; lcb_store_cmd_t storecmd; const lcb_store_cmd_t *storecmds[] = { &storecmd }; lcb_get_cmd_t getcmd; const lcb_get_cmd_t *getcmds[] = { &getcmd }; memset(&storecmd, 0, sizeof(storecmd)); storecmd.v.v0.key = "foo"; storecmd.v.v0.nkey = strlen(storecmd.v.v0.key); storecmd.v.v0.bytes = "bar"; storecmd.v.v0.nbytes = strlen(storecmd.v.v0.bytes); storecmd.v.v0.operation = LCB_SET; (void)lcb_set_store_callback(session, store_callback); (void)lcb_set_get_callback(session, get_callback); err = lcb_store(session, &rv, 1, storecmds); lcb_assert(err == LCB_SUCCESS); io->v.v0.run_event_loop(io); lcb_assert(rv.error == LCB_SUCCESS); memset(&rv, 0, sizeof(rv)); memset(&getcmd, 0, sizeof(getcmd)); getcmd.v.v0.key = "foo"; getcmd.v.v0.nkey = strlen(getcmd.v.v0.key); err = lcb_get(session, &rv, 1, getcmds); lcb_assert(err == LCB_SUCCESS); io->v.v0.run_event_loop(io); lcb_assert(rv.error == LCB_SUCCESS); lcb_assert(rv.nbytes == strlen("bar")); lcb_assert(memcmp(rv.bytes, "bar", 3) == 0); }
static void test_set2(void) { lcb_error_t err; struct rvbuf rv; lcb_size_t ii; lcb_store_cmd_t cmd; const lcb_store_cmd_t *cmds[] = { &cmd }; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.key = "foo"; cmd.v.v0.nkey = strlen(cmd.v.v0.key); cmd.v.v0.bytes = "bar"; cmd.v.v0.nbytes = strlen(cmd.v.v0.bytes); cmd.v.v0.operation = LCB_SET; (void)lcb_set_store_callback(session, mstore_callback); rv.errors = 0; rv.counter = 0; for (ii = 0; ii < 10; ++ii, ++rv.counter) { err = lcb_store(session, &rv, 1, cmds); lcb_assert(err == LCB_SUCCESS); } io->v.v0.run_event_loop(io); lcb_assert(rv.errors == 0); }
static void process_file(const char *fname) { char *ptr = NULL; size_t size; cJSON *json, *id; lcb_error_t ret; int error = 0; lcb_store_cmd_t cmd; const lcb_store_cmd_t* const cmds[1] = { &cmd }; if (fname[0] == '.') { if (strcmp(fname, ".dump_stats") == 0) { fprintf(stdout, "Dumping stats:\n"); lcb_get_timings(instance, stdout, timings_callback); fprintf(stdout, "----\n"); remove(fname); } return; } if (loadit(fname, &ptr, &size) == -1) { /* Error message already printed */ return; } if ((json = cJSON_Parse(ptr)) == NULL) { invalid_file(INVALID_JSON, fname); free(ptr); return; } id = cJSON_GetObjectItem(json, "_id"); if (id == NULL || id->type != cJSON_String) { invalid_file(UNKNOWN_JSON, fname); free(ptr); return; } memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.key = id->valuestring; cmd.v.v0.nkey = strlen(id->valuestring); cmd.v.v0.bytes = ptr; cmd.v.v0.nbytes = size; cmd.v.v0.operation = LCB_SET; ret = lcb_store(instance, &error, 1, cmds); if (ret == LCB_SUCCESS) { lcb_wait(instance); } else { error = 1; } free(ptr); if (error) { fprintf(stderr, "Failed to store %s: %s\n", fname, lcb_strerror(instance, ret)); } else { remove(fname); } }
int _tmain(int argc, _TCHAR* argv[]) { // initializing struct lcb_create_st cropts = { 0 }; cropts.version = 3; cropts.v.v3.connstr = "couchbase://localhost/default"; lcb_error_t err; lcb_t instance; err = lcb_create(&instance, &cropts); if (err != LCB_SUCCESS) { printf("Couldn't create instance!\n"); exit(1); } // connecting lcb_connect(instance); lcb_wait(instance); if ((err = lcb_get_bootstrap_status(instance)) != LCB_SUCCESS) { printf("Couldn't bootstrap!\n"); exit(1); } // installing callbacks lcb_set_store_callback(instance, storage_callback); lcb_set_get_callback(instance, get_callback); // scheduling operations lcb_store_cmd_t scmd; const lcb_store_cmd_t *scmdlist = &scmd; scmd.v.v0.key = "Hello"; scmd.v.v0.nkey = 5; scmd.v.v0.bytes = "Couchbase"; scmd.v.v0.nbytes = 9; scmd.v.v0.operation = LCB_SET; err = lcb_store(instance, NULL, 1, &scmdlist); if (err != LCB_SUCCESS) { printf("Couldn't schedule storage operation!\n"); exit(1); } lcb_wait(instance); //storage_callback is invoked here lcb_get_cmd_t gcmd = { 0 }; const lcb_get_cmd_t *gcmdlist = &gcmd; gcmd.v.v0.key = "Hello"; gcmd.v.v0.nkey = 5; err = lcb_get(instance, NULL, 1, &gcmdlist); if (err != LCB_SUCCESS) { printf("Couldn't schedule get operation!\n"); exit(1); } lcb_wait(instance); // get_callback is invoked here lcb_destroy(instance); return 0; }
lcb_error_t form_command_fset(lcb_error_t err, lcb_t instance, const char *const key) { lcb_store_cmd_t cmd; const lcb_store_cmd_t* commands[1]; commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.operation = LCB_FSET; cmd.v.v0.key = "fra"; cmd.v.v0.key = key; cmd.v.v0.nkey = 3; cmd.v.v0.bytes = "123"; cmd.v.v0.nbytes = 3; cmd.v.v0.flags = 1; // offset cmd.v.v0.exptime = (lcb_time_t)1; // length err = lcb_store(instance, NULL, 1, commands); return err; }
lcb_error_t form_command(lcb_error_t err, lcb_t instance, const char * const key, const int count) { lcb_store_cmd_t cmd; const lcb_store_cmd_t* commands[1]; commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.operation = LCB_SET; cmd.v.v0.key = "foo"; if (key) cmd.v.v0.key = key; cmd.v.v0.nkey = 3; cmd.v.v0.bytes = "bar"; cmd.v.v0.nbytes = 3; print_timestamp(); for (int i=0; i < count; i++) err = lcb_store(instance, NULL, 1, commands); return err; }
static void test_spurious_saslerr(void) { int iterations = 50; struct rvbuf rvs[50]; int i; lcb_error_t err; lcb_store_cmd_t storecmd; const lcb_store_cmd_t *storecmds[] = { &storecmd }; lcb_set_store_callback(session, mstore_callback); memset(rvs, 0, sizeof(rvs)); for (i = 0; i < iterations; i++) { rvs[i].counter = 999; /*don't trigger a stop_event_loop*/ memset(&storecmd, 0, sizeof(storecmd)); storecmd.v.v0.key = "KEY"; storecmd.v.v0.nkey = strlen(storecmd.v.v0.key); storecmd.v.v0.bytes = "KEY"; storecmd.v.v0.nbytes = strlen(storecmd.v.v0.bytes); storecmd.v.v0.operation = LCB_SET; err = lcb_store(session, rvs + i, 1, storecmds); if (err != LCB_SUCCESS) { err_exit("Store operation failed"); } } lcb_wait(session); for (i = 0; i < iterations; i++) { char *errinfo = NULL; if (rvs[i].errors != LCB_SUCCESS) { errinfo = "Did not get success response"; } else if (rvs[i].nkey != 3) { errinfo = "Did not get expected key length"; } else if (memcmp(rvs[i].key, "KEY", 3) != 0) { errinfo = "Weird key size"; } if (errinfo) { err_exit("%s", errinfo); } } }
static void test_set1(void) { lcb_error_t err; struct rvbuf rv; lcb_store_cmd_t cmd; const lcb_store_cmd_t *cmds[] = { &cmd }; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.key = "foo"; cmd.v.v0.nkey = strlen(cmd.v.v0.key); cmd.v.v0.bytes = "bar"; cmd.v.v0.nbytes = strlen(cmd.v.v0.bytes); cmd.v.v0.operation = LCB_SET; (void)lcb_set_store_callback(session, store_callback); err = lcb_store(session, &rv, 1, cmds); lcb_assert(err == LCB_SUCCESS); io->v.v0.run_event_loop(io); lcb_assert(rv.error == LCB_SUCCESS); lcb_assert(rv.operation == LCB_SET); lcb_assert(memcmp(rv.key, "foo", 3) == 0); }
int couchbase_set(cachedb_con *connection,str *attr, str *val,int expires) { lcb_t instance; lcb_error_t oprc; lcb_store_cmd_t cmd; const lcb_store_cmd_t *commands[1]; last_error = LCB_SUCCESS; instance = COUCHBASE_CON(connection); commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.operation = LCB_SET; cmd.v.v0.key = attr->s; cmd.v.v0.nkey = attr->len; cmd.v.v0.bytes = val->s; cmd.v.v0.nbytes = val->len; cmd.v.v0.exptime = expires; oprc = lcb_store(instance, NULL, 1, commands); if (oprc != LCB_SUCCESS) { LM_ERR("Failed to send the insert query - %s\n", lcb_strerror(instance, oprc)); couchbase_conditional_reconnect(connection, oprc); return -2; } lcb_wait(instance); oprc = lcb_get_last_error(instance); if (last_error != LCB_SUCCESS) { couchbase_conditional_reconnect(connection, last_error); return -1; } LM_DBG("Succesfully stored\n"); return 1; }
ERL_NIF_TERM cb_store(ErlNifEnv* env, handle_t* handle, void* obj) { store_args_t* args = (store_args_t*)obj; struct libcouchbase_callback cb; lcb_error_t ret; lcb_store_cmd_t cmd; const lcb_store_cmd_t *commands[1]; commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.operation = args->operation; cmd.v.v0.key = args->key; cmd.v.v0.nkey = args->nkey; cmd.v.v0.bytes = args->bytes; cmd.v.v0.nbytes = args->nbytes; cmd.v.v0.flags = args->flags; cmd.v.v0.exptime = args->exp; cmd.v.v0.cas = args->cas; ret = lcb_store(handle->instance, &cb, 1, commands); free(args->key); free(args->bytes); if (ret != LCB_SUCCESS) { return return_lcb_error(env, ret); } lcb_wait(handle->instance); if (cb.error != LCB_SUCCESS) { return return_lcb_error(env, cb.error); } return A_OK(env); }
PHP_COUCHBASE_LOCAL void php_couchbase_cas_impl(INTERNAL_FUNCTION_PARAMETERS, int oo) { zval *value; time_t exp = {0}; unsigned int flags = 0; size_t payload_len = 0; unsigned long long cas_v = 0; char *key, *payload, *cas = NULL; long klen = 0, expire = 0, cas_len = 0; php_couchbase_res *couchbase_res; long replicate_to = 0; long persist_to = 0; lcb_error_t retval; php_couchbase_ctx *ctx; lcb_store_cmd_t cmd; const lcb_store_cmd_t *const commands[] = { &cmd }; int argf = oo ? PHP_COUCHBASE_ARG_F_OO : PHP_COUCHBASE_ARG_F_FUNCTIONAL; PHP_COUCHBASE_GET_PARAMS(couchbase_res, argf, "ssz|lll", &cas, &cas_len, &key, &klen, &value, &expire, &persist_to, &replicate_to); if (pcbc_check_expiry(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, expire, &exp) == -1) { /* Incorrect expiry time */ return; } if (validate_simple_observe_clause(couchbase_res->handle, persist_to, replicate_to TSRMLS_CC) == -1) { /* Exception already thrown */ return; } if (klen == 0) { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_illegal_key_exception, "Failed to schedule set request: Empty key"); return; } if (cas_len == 0) { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_exception, "Illegal CAS specified"); return; } if (cas) { char *end; cas_v = strtoull(cas, &end, 10); if (*end != '\0') { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_exception, "Illegal CAS specified"); return; } } ctx = ecalloc(1, sizeof(php_couchbase_ctx)); ctx->res = couchbase_res; ctx->rv = return_value; payload = php_couchbase_zval_to_payload(value, &payload_len, &flags, couchbase_res->serializer, couchbase_res->compressor TSRMLS_CC); if (payload == NULL) { RETURN_FALSE; } if (couchbase_res->prefix_key_len) { klen = spprintf(&key, 0, "%s_%s", couchbase_res->prefix_key, key); } memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.operation = LCB_SET; cmd.v.v0.key = key; cmd.v.v0.nkey = klen; cmd.v.v0.bytes = payload; cmd.v.v0.nbytes = payload_len; cmd.v.v0.flags = flags; cmd.v.v0.exptime = exp; cmd.v.v0.cas = (uint64_t)cas_v; retval = lcb_store(couchbase_res->handle, ctx, 1, commands); efree(payload); if (couchbase_res->prefix_key_len) { efree(key); } if (retval != LCB_SUCCESS) { efree(ctx); couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_lcb_exception, "Failed to schedule cas request: %s", lcb_strerror(couchbase_res->handle, retval)); return; } ++couchbase_res->seqno; pcbc_start_loop(couchbase_res); zval_dtor(return_value); if (LCB_SUCCESS == ctx->res->rc) { ZVAL_TRUE(return_value); } else if (LCB_KEY_EEXISTS == ctx->res->rc) { ZVAL_FALSE(return_value); } else { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_lcb_exception, "Failed to store a value to server: %s", lcb_strerror(couchbase_res->handle, ctx->res->rc)); } efree(ctx); }
int main(void) { struct lcb_create_st create_options; memset(&create_options, 0, sizeof create_options); create_options.version = 3; create_options.v.v3.connstr = "couchbase://10.141.95.101/default"; // create_options.v.v3.passwd = "testbucket"; lcb_error_t err; lcb_t instance = NULL; err = lcb_create(&instance, &create_options); if (err != LCB_SUCCESS) { fprintf(stderr, "Failed to create a couchbase instance: %s\n", lcb_strerror(instance,err)); return 1; } // Default timeout values and settings: //http://developer.couchbase.com/documentation/server/current/sdks/c-2.4/options.html //Enable details error codes: lcb_cntl_string(instance,"detailed_errcodes","1"); //Connecting lcb_connect(instance); lcb_wait(instance); if ( (err = lcb_get_bootstrap_status(instance)) != LCB_SUCCESS ) { printf("Couldn't bootstrap. Exiting!\n"); exit(1); } // installing callbacks lcb_set_store_callback(instance, storage_callback); lcb_set_durability_callback(instance, durability_callback); // scheduling set operations with elements that expire lcb_store_cmd_t scmd = { 0 }; const lcb_store_cmd_t *scmdlist = &scmd; /* INSERT, Loop through x number of keys and insert them with expiry */ for( int counter=1; counter <= NUMBER_OF_DOCUMENTS; counter++){ // Setting keys and values const char *doc = "{\"json\" : \"data\" }"; char key [12]; sprintf(key, "%s%d", "test", counter); scmd.v.v0.key = key; scmd.v.v0.nkey = strlen(key); scmd.v.v0.bytes = doc; scmd.v.v0.nbytes = strlen(doc); scmd.v.v0.exptime = 300; //expiry of 5 minutes scmd.v.v0.operation = LCB_SET; err = lcb_store(instance, NULL, 1, (const lcb_store_cmd_t * const *)&scmdlist); if (err != LCB_SUCCESS) { printf("Couldn't schedule storage operation!\n"); exit(1); } lcb_wait(instance); //Durability is invoked here lcb_durability_opts_t options; lcb_durability_cmd_t cmd = { 0 }; const lcb_durability_cmd_t *cmdp = &cmd; cmd.v.v0.key = key; cmd.v.v0.nkey = strlen(key); options.v.v0.persist_to = 1; options.v.v0.replicate_to = 1; err = lcb_durability_poll(instance,NULL,&options,1,&cmdp); if (err != LCB_SUCCESS) { printf("couldn't schedule durability operation %s \n", lcb_strerror(instance, err)); } lcb_wait(instance); } //closing the connection lcb_destroy(instance); return 0; }
static inline VALUE cb_bucket_store(lcb_storage_t cmd, int argc, VALUE *argv, VALUE self) { struct cb_bucket_st *bucket = DATA_PTR(self); struct cb_context_st *ctx; VALUE rv, proc, exc, obs = Qnil; lcb_error_t err; struct cb_params_st params; if (!cb_bucket_connected_bang(bucket, storage_opcode_to_sym(cmd))) { return Qnil; } memset(¶ms, 0, sizeof(struct cb_params_st)); rb_scan_args(argc, argv, "0*&", ¶ms.args, &proc); if (!bucket->async && proc != Qnil) { rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks"); } params.type = cb_cmd_store; params.bucket = bucket; params.cmd.store.operation = cmd; cb_params_build(¶ms); obs = params.cmd.store.observe; ctx = cb_context_alloc(bucket); if (!bucket->async) { ctx->rv = rb_hash_new(); ctx->observe_options = obs; } ctx->proc = proc; ctx->nqueries = params.cmd.store.num; err = lcb_store(bucket->handle, (const void *)ctx, params.cmd.store.num, params.cmd.store.ptr); cb_params_destroy(¶ms); exc = cb_check_error(err, "failed to schedule set request", Qnil); if (exc != Qnil) { cb_context_free(ctx); rb_exc_raise(exc); } bucket->nbytes += params.npayload; if (bucket->async) { cb_maybe_do_loop(bucket); return Qnil; } else { if (ctx->nqueries > 0) { /* we have some operations pending */ lcb_wait(bucket->handle); } exc = ctx->exception; rv = ctx->rv; cb_context_free(ctx); if (exc != Qnil) { rb_exc_raise(exc); } exc = bucket->exception; if (exc != Qnil) { bucket->exception = Qnil; rb_exc_raise(exc); } if (RTEST(obs)) { rv = rb_funcall(bucket->self, cb_id_observe_and_wait, 2, rv, obs); } if (params.cmd.store.num > 1) { return rv; /* return as a hash {key => cas, ...} */ } else { VALUE vv = Qnil; rb_hash_foreach(rv, cb_first_value_i, (VALUE)&vv); return vv; } } }
static void test_touch1(void) { lcb_error_t err; struct rvbuf rv; char *key = "fooX", *val = "bar"; lcb_size_t nkey = strlen(key), nval = strlen(val); char **keys; lcb_size_t *nkeys, ii; lcb_time_t *ttls; lcb_store_cmd_t storecmd; const lcb_store_cmd_t *storecmds[] = { &storecmd }; lcb_touch_cmd_t *touchcmds[26]; (void)lcb_set_store_callback(session, store_callback); (void)lcb_set_touch_callback(session, touch_callback); keys = malloc(26 * sizeof(char *)); nkeys = malloc(26 * sizeof(lcb_size_t)); ttls = malloc(26 * sizeof(lcb_time_t)); if (keys == NULL || nkeys == NULL || ttls == NULL) { err_exit("Failed to allocate memory for keys"); } for (ii = 0; ii < 26; ii++) { nkeys[ii] = nkey; keys[ii] = strdup(key); ttls[ii] = 1; if (keys[ii] == NULL) { err_exit("Failed to allocate memory for key"); } keys[ii][3] = (char)(ii + 'a'); memset(&storecmd, 0, sizeof(storecmd)); storecmd.v.v0.key = keys[ii]; storecmd.v.v0.nkey = nkey; storecmd.v.v0.bytes = val; storecmd.v.v0.nbytes = nval; storecmd.v.v0.operation = LCB_SET; err = lcb_store(session, &rv, 1, storecmds); lcb_assert(err == LCB_SUCCESS); io->v.v0.run_event_loop(io); lcb_assert(rv.error == LCB_SUCCESS); memset(&rv, 0, sizeof(rv)); touchcmds[ii] = calloc(1, sizeof(lcb_touch_cmd_t)); if (touchcmds[ii] == NULL) { err_exit("Failed to allocate memory for touch command"); } touchcmds[ii]->v.v0.key = keys[ii]; touchcmds[ii]->v.v0.nkey = nkey; } rv.counter = 26; err = lcb_touch(session, &rv, 26, (const lcb_touch_cmd_t * const *)touchcmds); lcb_assert(err == LCB_SUCCESS); io->v.v0.run_event_loop(io); lcb_assert(rv.error == LCB_SUCCESS); for (ii = 0; ii < 26; ii++) { free(keys[ii]); free(touchcmds[ii]); } free(keys); free(ttls); free(nkeys); }
PHP_COUCHBASE_LOCAL void php_couchbase_store_multi_impl_oo(INTERNAL_FUNCTION_PARAMETERS) { lcb_error_t retval; php_couchbase_res *couchbase_res; php_couchbase_ctx *ctx; time_t exp = {0}; long expire = 0; zval *akeys; long persist_to = 0; long replicate_to = 0; struct observe_entry *entries; int numkeys; lcb_store_cmd_t *cmds; lcb_store_cmd_t **commands; int ii; PHP_COUCHBASE_GET_PARAMS(couchbase_res, PHP_COUCHBASE_ARG_F_OO, "a|lll", &akeys, &expire, &persist_to, &replicate_to); if (pcbc_check_expiry(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, expire, &exp) == -1) { /* Incorrect expiry time */ return; } if (validate_simple_observe_clause(couchbase_res->handle, persist_to, replicate_to TSRMLS_CC) == -1) { /* Exception already thrown */ return; } numkeys = zend_hash_num_elements(Z_ARRVAL_P(akeys)); if (numkeys == 0) { zend_throw_exception(cb_illegal_key_exception, "No items specified", 0 TSRMLS_CC); return ; } entries = ecalloc(numkeys, sizeof(struct observe_entry)); commands = ecalloc(numkeys, sizeof(lcb_store_cmd_t *)); cmds = ecalloc(numkeys, sizeof(lcb_store_cmd_t)); /* link the command pointers */ for (ii = 0; ii < numkeys; ++ii) { commands[ii] = cmds + ii; } ctx = ecalloc(1, sizeof(php_couchbase_ctx)); ctx->res = couchbase_res; ctx->rv = return_value; array_init(ctx->rv); for (ii = 0, zend_hash_internal_pointer_reset(Z_ARRVAL_P(akeys)); zend_hash_has_more_elements(Z_ARRVAL_P(akeys)) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_P(akeys)), ++ii) { char *key = NULL; uint klen; size_t payload_len = 0; char *payload; unsigned int flags = 0; zval **ppzval; if (zend_hash_get_current_key_type(Z_ARRVAL_P(akeys)) != HASH_KEY_IS_STRING) { int xx; for (xx = 0; xx < ii; ++xx) { efree((void *)cmds[xx].v.v0.bytes); } efree(commands); efree(cmds); efree(ctx); release_entry_array(entries, xx); zend_throw_exception(cb_illegal_key_exception, "Invalid key specified (not a string)", 0 TSRMLS_CC); return ; } zend_hash_get_current_key(Z_ARRVAL_P(akeys), &key, NULL, 0); if ((klen = strlen(key)) == 0) { int xx; for (xx = 0; xx < ii; ++xx) { efree((void *)cmds[xx].v.v0.bytes); } efree(commands); efree(cmds); efree(ctx); release_entry_array(entries, xx); zend_throw_exception(cb_illegal_key_exception, "Invalid key specified (empty string)", 0 TSRMLS_CC); return ; } if (zend_hash_get_current_data(Z_ARRVAL_P(akeys), (void **)&ppzval) == FAILURE) { int xx; for (xx = 0; xx < ii; ++xx) { efree((void *)cmds[xx].v.v0.bytes); } efree(commands); efree(cmds); efree(ctx); release_entry_array(entries, xx); zend_throw_exception(cb_exception, "Failed to get data for key", 0 TSRMLS_CC); return ; } payload = php_couchbase_zval_to_payload(*ppzval, &payload_len, &flags, couchbase_res->serializer, couchbase_res->compressor TSRMLS_CC); if (payload == NULL) { /* Shouldn't we call an exception? */ RETURN_FALSE; } if (couchbase_res->prefix_key_len) { char *new_key; klen = spprintf(&new_key, 0, "%s_%s", couchbase_res->prefix_key, key); key = new_key; } entries[ii].nkey = klen; entries[ii].key = emalloc(klen); memcpy(entries[ii].key, key, klen); cmds[ii].v.v0.operation = LCB_SET; cmds[ii].v.v0.key = entries[ii].key; cmds[ii].v.v0.nkey = klen; cmds[ii].v.v0.bytes = payload; cmds[ii].v.v0.nbytes = payload_len; cmds[ii].v.v0.flags = flags; cmds[ii].v.v0.exptime = exp; if (couchbase_res->prefix_key_len) { efree(key); } } retval = lcb_store(couchbase_res->handle, ctx, numkeys, (const lcb_store_cmd_t * const *)commands); couchbase_res->seqno += numkeys; pcbc_start_loop(couchbase_res); /* * Time to release the payloads... */ for (ii = 0; ii < numkeys; ++ii) { efree((void *)cmds[ii].v.v0.bytes); } efree(cmds); efree(commands); if (LCB_SUCCESS != retval) { efree(ctx); couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, cb_lcb_exception, "Failed to schedule set request: %s", lcb_strerror(couchbase_res->handle, retval)); release_entry_array(entries, numkeys); RETURN_FALSE; } /* * The item was stored successfully. Did the user want to wait until * it was persisted/replicated? */ if (persist_to != 0 || replicate_to != 0) { int ii = 0; for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(return_value)); zend_hash_has_more_elements(Z_ARRVAL_P(return_value)) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_P(return_value)), ++ii) { zval **curr_cas; zend_hash_get_current_data(Z_ARRVAL_P(return_value), (void **)&curr_cas); if (Z_STRLEN_PP(curr_cas)) { entries[ii].cas = strtoull(Z_STRVAL_PP(curr_cas), 0, 10); } else { /* @todo what to do here? */ fprintf(stderr, "wtf!\n"); } } retval = simple_observe(couchbase_res->handle, entries, numkeys, persist_to, replicate_to); couchbase_res->rc = retval; if (retval != LCB_SUCCESS) { if (retval == LCB_ETIMEDOUT) { zend_throw_exception(cb_timeout_exception, "Timed out waiting for the objects to persist", 0 TSRMLS_CC); } else { char errmsg[256]; snprintf(errmsg, sizeof(errmsg), "An error occured while waiting for the objects to persist: %s", lcb_strerror(couchbase_res->handle, retval)); zend_throw_exception(cb_lcb_exception, errmsg, 0 TSRMLS_CC); } } else { int currsize = 4096; char *errmsg = malloc(currsize); int offset = sprintf(errmsg, "The following documents was mutated:"); int errors = 0; for (ii = 0; ii < numkeys; ++ii) { if (entries[ii].mutated) { if ((offset + entries[ii].nkey + 3) > currsize) { char *p = realloc(errmsg, currsize * 2); if (p) { currsize *= 2; errmsg = p; } } if ((offset + entries[ii].nkey + 3) < currsize) { offset += sprintf(errmsg + offset, " \""); memcpy(errmsg + offset, entries[ii].key, entries[ii].nkey); offset += entries[ii].nkey; offset += sprintf(errmsg + offset, "\""); } errors = 1; } } if (errors) { zend_throw_exception(cb_key_mutated_exception, errmsg, 0 TSRMLS_CC); } free(errmsg); } } release_entry_array(entries, numkeys); efree(ctx); }
int main(int argc, char*argv[]) { //couchbase error type lcb_error_t err; //couchbase type lcb_t instance; // couchbase create struct? its a struct with options to create what? a cb cluster, bucket or something else? struct lcb_create_st create_options = {0}; memset(&create_options,0,sizeof(create_options)); // set command type, and creating a list of store commands? lcb_store_cmd_t scmd = {0}; const lcb_store_cmd_t *scmdlist[1]; // get command type, and list of get commands! lcb_get_cmd_t gcmd = {0}; const lcb_get_cmd_t *gcmdlist[1]; create_options.version = 3; // cb version 3? if (argc < 2) { fprintf(stderr, "Usage: %s couchbase://host/bucket [password] \n",argv[0] ); exit(EXIT_FAILURE); } create_options.v.v3.connstr = argv[1]; if (argc >=3) { create_options.v.v3.passwd = argv[2]; } //fprintf(stderr, "\n %s,%s,%s\n",create_options.v.v3.connstr,create_options.v.v3.passwd,"test" ); /* create_options.version = 3; create_options.v.v3.connstr = "couchbase://192.168.56.101/pramod"; create_options.v.v3.passwd = "couchbase"; */ err = lcb_create(&instance, &create_options); if(err != LCB_SUCCESS) { die(instance, "Couldn't create couchbase handle", err); } err = lcb_connect(instance); if(err != LCB_SUCCESS) { die(instance, "Couldn't schedule connection", err); } lcb_wait(instance); // It says this will be blocking wait and won't execute in a async fashion err = lcb_get_bootstrap_status(instance); if (err != LCB_SUCCESS) { die(instance, "Couldn't bootstrap from cluster", err); } // Assign the handlers to be called for the operations types lcb_set_get_callback(instance, get_callback); lcb_set_store_callback(instance, store_callback); //what are these callbacks for ? I thought callbacks are for getting results of asynchronous exectution of jobs? // what is happening in here? setting values? to the source command ? //let my try to wrap this up in a loop to set a 1000 values? scmd.v.v0.operation = LCB_SET; scmd.v.v0.key = "foo"; scmd.v.v0.nkey = 3 ; scmd.v.v0.bytes = "barbeque"; scmd.v.v0.nbytes = 8; scmdlist[0] = &scmd; err = lcb_store(instance, NULL, 1, scmdlist); // so here is where the data is getting written!! if (err != LCB_SUCCESS) { die (instance, "Coudn't schedule storage operations", err); } // the store_callback is involed from lcb_wait() fprintf(stderr, "Will wait for storage operation to complete\n"); lcb_wait(instance); //now fetch the items back gcmd.v.v0.key = "foo"; gcmd.v.v0.nkey = 3; gcmd.v.v0.exptime = 60; gcmdlist[0] = &gcmd; err = lcb_get(instance, NULL, 1, gcmdlist); if (err != LCB_SUCCESS) { die(instance, "Couldn't schedule retrieval operation", err); } // get callback invoked from here. fprintf(stderr, "Will wait to retrieve the set item!\n"); lcb_wait(instance); // close the connection handle after everything is done lcb_destroy(instance); return 0; }
int couchdb_update(uint64_t key, char *data, size_t len) { char *db_key = NULL; lcb_size_t key_size; lcb_error_t ret; int lock_result = -1; lcb_store_cmd_t item; const lcb_store_cmd_t *const store_items[] = { &item }; char *compressed_data = NULL; size_t compressed_len = 0; int res = 0; compressed_len = snappy_max_compressed_length(len); compressed_data = (char *)malloc(compressed_len); if (compressed_data == NULL) { syslog(LOG_ERR, "%s: Unable to allocate memory for compressed_data\n", __FUNCTION__); return (-ENOMEM); } if ((res = snappy_compress((const char *)data, len, compressed_data, &compressed_len)) != SNAPPY_OK) { free(compressed_data); return (-res); } memset(&item, 0, sizeof(lcb_store_cmd_t)); db_key = (char *) malloc(MAX_KEY_SIZE); if (NULL == db_key) { syslog(LOG_ERR, "%s: Unable to allocate memory for db_key\n", __FUNCTION__); return -ENOMEM; } sprintf(db_key,"%"PRId64"", key); USYSLOG(LOG_INFO, "%s: set1 %"PRId64" %s %s, \n", __FUNCTION__, key, (char *) data, db_key); key_size = strlen(db_key); item.v.v0.key = db_key; item.v.v0.nkey = key_size; item.v.v0.bytes = compressed_data; item.v.v0.nbytes = compressed_len; item.v.v0.operation = LCB_REPLACE; lock_result = pthread_rwlock_wrlock(&db_rwlock); if (lock_result != 0) { syslog(LOG_ERR, "%s: Failed to obtain write lock. Error = %d\n", __FUNCTION__, errno); return -errno; } ret = lcb_store(couchdb_handle, NULL, 1, store_items); if (ret != LCB_SUCCESS) { syslog(LOG_ERR, "%s: lcb_store failed with error %s\n", __FUNCTION__, lcb_strerror(couchdb_handle, ret)); return -ret; } /* Block the thread till this operation completes */ lcb_wait(couchdb_handle); pthread_rwlock_unlock(&db_rwlock); return (1); }
int main(void) { // initializing struct lcb_create_st create_options; memset(&create_options, 0, sizeof create_options); create_options.version = 3; create_options.v.v3.connstr = "couchbase://10.141.110.101,10.141.110.102,10.141.110.103/testbucket"; create_options.v.v3.passwd = "testbucket"; lcb_error_t err; lcb_t instance = NULL; err = lcb_create(&instance, &create_options); if (err != LCB_SUCCESS) { fprintf(stderr, "Failed to create a couchbase instance: %s\n", lcb_strerror(instance,err)); return 1; } // Default timeout values and settings: http://developer.couchbase.com/documentation/server/current/sdks/java-2.2/env-config.html //Enable details error codes: //http://developer.couchbase.com/documentation/server/current/sdks/c-2.4/options.html lcb_cntl_string(instance,"detailed_errcodes","1"); //connecting lcb_connect(instance); lcb_wait(instance); if ( (err = lcb_get_bootstrap_status(instance)) != LCB_SUCCESS ) { printf("Couldn't bootstrap. Exiting!\n"); exit(1); } sleep(20); // installing callbacks lcb_set_store_callback(instance, storage_callback); lcb_set_get_callback(instance, get_callback); // scheduling set operations with elements that expire lcb_store_cmd_t scmd = { 0 }; const lcb_store_cmd_t *scmdlist = &scmd; /* INSERT, Loop through x number of keys and insert them with expiry */ for( int counter=0; counter <NUMBER_OF_DOCUMENTS; counter ++){ // Setting keys and values const char *doc = "{\"json\" : \"data\" }"; char key [12]; sprintf(key, "%s%d", "test", counter); scmd.v.v0.key = key; scmd.v.v0.nkey = strlen(key); scmd.v.v0.bytes = doc; scmd.v.v0.nbytes = strlen(doc); // scmd.v.v0.exptime = 300; //expiry of 5 minutes scmd.v.v0.operation = LCB_SET; err = lcb_store(instance, NULL, 1, &scmdlist); if (err != LCB_SUCCESS) { printf("Couldn't schedule storage operation!\n"); exit(1); } lcb_wait(instance); //storage_callback is invoked here } /* GET section */ lcb_get_cmd_t gcmd = { 0 }; const lcb_get_cmd_t *gcmdlist = &gcmd; for( int counter=0; counter <NUMBER_OF_DOCUMENTS; counter ++){ char key[12]; // sleep(3); sprintf(key,"%s%d", "test", counter); gcmd.v.v0.key = key; gcmd.v.v0.nkey = strlen(key); fprintf(stderr, "GET : %s\n", key); // printf("GET %s\n", key); err = lcb_get(instance, NULL, 1, &gcmdlist); lcb_wait(instance); // get_callback is invoked here } //closing the connection lcb_destroy(instance); return 0; }
PHP_COUCHBASE_LOCAL void php_couchbase_store_impl_oo(INTERNAL_FUNCTION_PARAMETERS, lcb_storage_t op) { lcb_error_t retval; php_couchbase_res *couchbase_res; php_couchbase_ctx *ctx; time_t exp = {0}; unsigned int flags = 0; char *cas = NULL; char *payload; size_t payload_len = 0; unsigned long long cas_v = 0; long expire = 0; long replicate_to = 0; long persist_to = 0; long cas_len = 0; char *key = NULL; zval *value; long klen = 0; lcb_store_cmd_t cmd; const lcb_store_cmd_t *const commands[] = { &cmd }; if (op == LCB_ADD) { PHP_COUCHBASE_GET_PARAMS(couchbase_res, PHP_COUCHBASE_ARG_F_OO, "sz|lll", &key, &klen, &value, &expire, &persist_to, &replicate_to); } else { PHP_COUCHBASE_GET_PARAMS(couchbase_res, PHP_COUCHBASE_ARG_F_OO, "sz|lsll", &key, &klen, &value, &expire, &cas, &cas_len, &persist_to, &replicate_to); } if (pcbc_check_expiry(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, expire, &exp) == -1) { /* Incorrect expiry time */ return; } if (validate_simple_observe_clause(couchbase_res->handle, persist_to, replicate_to TSRMLS_CC) == -1) { /* Exception already thrown */ return; } if (!klen) { zend_throw_exception(cb_illegal_key_exception, "Failed to schedule set request: Empty key", 0 TSRMLS_CC); return ; } if (cas) { char *e; cas_v = (lcb_cas_t)strtoull(cas, &e, 10); if (*e != '\0') { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, cb_illegal_key_exception, "Invalid CAS specified"); return; } } payload = php_couchbase_zval_to_payload(value, &payload_len, &flags, couchbase_res->serializer, couchbase_res->compressor TSRMLS_CC); if (payload == NULL) { /* ?? I guess we should throw an exception here? */ RETURN_FALSE; } if (couchbase_res->prefix_key_len) { klen = spprintf(&key, 0, "%s_%s", couchbase_res->prefix_key, key); } ctx = ecalloc(1, sizeof(php_couchbase_ctx)); ctx->res = couchbase_res; ctx->rv = return_value; couchbase_res->seqno += 1; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.operation = op; cmd.v.v0.key = key; cmd.v.v0.nkey = klen; cmd.v.v0.bytes = payload; cmd.v.v0.nbytes = payload_len; cmd.v.v0.flags = flags; cmd.v.v0.exptime = exp; cmd.v.v0.cas = (uint64_t)cas_v; retval = lcb_store(couchbase_res->handle, ctx, 1, commands); efree(payload); if (couchbase_res->prefix_key_len) { efree(key); } if (retval != LCB_SUCCESS) { char errmsg[256]; efree(ctx); sprintf(errmsg, "Failed to schedule set request: %s", lcb_strerror(couchbase_res->handle, retval)); zend_throw_exception(cb_lcb_exception, errmsg, 0 TSRMLS_CC); return ; } pcbc_start_loop(couchbase_res); if (LCB_SUCCESS != ctx->res->rc) { RETVAL_FALSE; switch (op) { case LCB_ADD: if (LCB_KEY_EEXISTS == ctx->res->rc) { break; } case LCB_APPEND: case LCB_PREPEND: if (LCB_NOT_STORED == ctx->res->rc) { break; } case LCB_REPLACE: case LCB_SET: if (LCB_KEY_ENOENT == ctx->res->rc) { break; } if (cas && LCB_KEY_EEXISTS == ctx->res->rc) { break; } default: { char errmsg[256]; sprintf(errmsg, "Failed to store value to server: %s", lcb_strerror(couchbase_res->handle, ctx->res->rc)); zend_throw_exception(cb_lcb_exception, errmsg, 0 TSRMLS_CC); } break; } } else { /* * The item was stored successfully. Did the user want to wait until * it was persisted/replicated? */ if (persist_to != 0 || replicate_to != 0) { struct observe_entry entry; memset(&entry, 0, sizeof(entry)); entry.key = key; entry.nkey = klen; entry.cas = strtoull(Z_STRVAL_P(return_value), 0, 10); retval = simple_observe(couchbase_res->handle, &entry, 1, persist_to, replicate_to); couchbase_res->rc = retval; if (retval != LCB_SUCCESS) { if (retval == LCB_ETIMEDOUT) { zend_throw_exception(cb_timeout_exception, "Timed out waiting for the objects to persist", 0 TSRMLS_CC); } else { char errmsg[512]; snprintf(errmsg, sizeof(errmsg), "observe failed for: %s", klen, key, lcb_strerror(couchbase_res->handle, retval)); zend_throw_exception(cb_lcb_exception, errmsg, 0 TSRMLS_CC); } } else { /* @todo checkfor timeout!!! */ if (entry.mutated) { zend_throw_exception(cb_key_mutated_exception, "The document was mutated", 0 TSRMLS_CC); } } } } efree(ctx); }
PHP_COUCHBASE_LOCAL void php_couchbase_store_impl(INTERNAL_FUNCTION_PARAMETERS, lcb_storage_t op, int multi) { lcb_error_t retval; php_couchbase_res *couchbase_res; php_couchbase_ctx *ctx; time_t exp = {0}; unsigned int flags = 0; char *payload, *cas = NULL; size_t payload_len = 0; unsigned long long cas_v = 0; long expire = 0, cas_len = 0; char *key = NULL; if (!multi) { char *key = NULL; zval *value; long klen = 0; PHP_COUCHBASE_GET_PARAMS(couchbase_res, PHP_COUCHBASE_ARG_F_FUNCTIONAL, "sz|ls", &key, &klen, &value, &expire, &cas, &cas_len); if (pcbc_check_expiry(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, expire, &exp) == -1) { /* Incorrect expiry time */ return; } if (!klen) { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, cb_illegal_key_exception, "No key specified: Empty key"); return; } if (cas) { char *e; cas_v = (lcb_cas_t)strtoull(cas, &e, 10); if (*e != '\0') { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, cb_illegal_key_exception, "Invalid CAS specified"); return; } } payload = php_couchbase_zval_to_payload(value, &payload_len, &flags, couchbase_res->serializer, couchbase_res->compressor TSRMLS_CC); if (payload == NULL) { RETURN_FALSE; } if (couchbase_res->prefix_key_len) { klen = spprintf(&key, 0, "%s_%s", couchbase_res->prefix_key, key); } ctx = ecalloc(1, sizeof(php_couchbase_ctx)); ctx->res = couchbase_res; ctx->rv = return_value; couchbase_res->seqno += 1; { lcb_store_cmd_t cmd; lcb_store_cmd_t *commands[] = { &cmd }; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.operation = op; cmd.v.v0.key = key; cmd.v.v0.nkey = klen; cmd.v.v0.bytes = payload; cmd.v.v0.nbytes = payload_len; cmd.v.v0.flags = flags; cmd.v.v0.exptime = exp; cmd.v.v0.cas = (uint64_t)cas_v; retval = lcb_store(couchbase_res->handle, ctx, 1, (const lcb_store_cmd_t * const *)commands); } efree(payload); if (couchbase_res->prefix_key_len) { efree(key); } if (LCB_SUCCESS != retval) { efree(ctx); couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, cb_lcb_exception, "Failed to schedule set request: %s", lcb_strerror(couchbase_res->handle, retval)); return; } } else { /* multi */ zval *akeys, **ppzval; char *key = NULL; uint klen = 0; ulong idx; int key_type, nkey = 0; PHP_COUCHBASE_GET_PARAMS(couchbase_res, PHP_COUCHBASE_ARG_F_FUNCTIONAL, "a|l", &akeys, &expire); if (pcbc_check_expiry(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, expire, &exp) == -1) { /* Incorrect expiry time */ return; } ctx = ecalloc(1, sizeof(php_couchbase_ctx)); ctx->res = couchbase_res; ctx->rv = return_value; array_init(ctx->rv); for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(akeys)); zend_hash_has_more_elements(Z_ARRVAL_P(akeys)) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_P(akeys))) { if (zend_hash_get_current_data(Z_ARRVAL_P(akeys), (void **)&ppzval) == FAILURE) { continue; } switch ((key_type = zend_hash_get_current_key(Z_ARRVAL_P(akeys), &key, &idx, 0))) { case HASH_KEY_IS_LONG: spprintf(&key, 0, "%ld", idx); break; case HASH_KEY_IS_STRING: break; default: continue; } if (!(klen = strlen(key))) { continue; } payload = php_couchbase_zval_to_payload(*ppzval, &payload_len, &flags, couchbase_res->serializer, couchbase_res->compressor TSRMLS_CC); if (payload == NULL) { RETURN_FALSE; } if (couchbase_res->prefix_key_len) { char *new_key; klen = spprintf(&new_key, 0, "%s_%s", couchbase_res->prefix_key, key); if (key_type == HASH_KEY_IS_LONG) { efree(key); } key = new_key; } { lcb_store_cmd_t cmd; lcb_store_cmd_t *commands[] = { &cmd }; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.operation = op; cmd.v.v0.key = key; cmd.v.v0.nkey = klen; cmd.v.v0.bytes = payload; cmd.v.v0.nbytes = payload_len; cmd.v.v0.flags = flags; cmd.v.v0.exptime = exp; retval = lcb_store(couchbase_res->handle, ctx, 1, (const lcb_store_cmd_t * const *)commands); } efree(payload); if (couchbase_res->prefix_key_len || HASH_KEY_IS_LONG == key_type) { efree(key); } if (LCB_SUCCESS != retval) { efree(ctx); couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, cb_lcb_exception, "Failed to schedule set request: %s", lcb_strerror(couchbase_res->handle, retval)); return; } nkey++; } if (!nkey) { efree(ctx); return; } couchbase_res->seqno += nkey; } { pcbc_start_loop(couchbase_res); if (IS_ARRAY != Z_TYPE_P(return_value)) { if (LCB_SUCCESS != ctx->res->rc) { RETVAL_FALSE; switch (op) { case LCB_ADD: if (LCB_KEY_EEXISTS == ctx->res->rc) { break; } case LCB_APPEND: case LCB_PREPEND: if (LCB_NOT_STORED == ctx->res->rc) { break; } case LCB_REPLACE: case LCB_SET: if (LCB_KEY_ENOENT == ctx->res->rc) { break; } if (cas && LCB_KEY_EEXISTS == ctx->res->rc) { break; } default: couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, cb_lcb_exception, "Failed to store a value to server: %s", lcb_strerror(couchbase_res->handle, ctx->res->rc)); break; } } } efree(ctx); } }
ngx_int_t ngx_lcb_process(ngx_http_request_t *r) { lcb_error_t err = LCB_NOT_SUPPORTED; ngx_http_variable_value_t *vv; ngx_str_t key, val; enum ngx_lcb_cmd opcode; ngx_http_core_loc_conf_t *clcf; ngx_lcb_connection_t *conn; lcb_cas_t cas = 0; lcb_uint32_t flags = 0, exptime = 0; ngx_int_t need_free_value = 0; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); conn = ngx_http_get_couchbase_connection(clcf->name); if (conn == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "couchbase: connection not found: \"%V\"", &clcf->name); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* setup command: use variable or fallback to HTTP method */ vv = ngx_http_get_indexed_variable(r, ngx_lcb_cmd_idx); if (vv == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (vv->not_found || vv->len == 0) { if (r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD)) { opcode = ngx_lcb_cmd_get; } else if (r->method == NGX_HTTP_POST) { opcode = ngx_lcb_cmd_add; } else if (r->method == NGX_HTTP_PUT) { opcode = ngx_lcb_cmd_set; } else if (r->method == NGX_HTTP_DELETE) { opcode = ngx_lcb_cmd_delete; } else { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "ngx_memc: $memc_cmd variable requires explicit " "assignment for HTTP request method %V", &r->method_name); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_HTTP_BAD_REQUEST; } } else { if (ngx_strncmp(vv->data, "get", 3) == 0) { opcode = ngx_lcb_cmd_get; } else if (ngx_strncmp(vv->data, "add", 3) == 0) { opcode = ngx_lcb_cmd_add; } else if (ngx_strncmp(vv->data, "replace", 7) == 0) { opcode = ngx_lcb_cmd_replace; } else if (ngx_strncmp(vv->data, "set", 3) == 0) { opcode = ngx_lcb_cmd_set; } else if (ngx_strncmp(vv->data, "append", 6) == 0) { opcode = ngx_lcb_cmd_append; } else if (ngx_strncmp(vv->data, "prepend", 7) == 0) { opcode = ngx_lcb_cmd_prepend; } else if (ngx_strncmp(vv->data, "delete", 6) == 0) { opcode = ngx_lcb_cmd_delete; } else { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "ngx_memc: unknown $couchbase_cmd \"%v\"", vv); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_HTTP_BAD_REQUEST; } } /* setup key: use variable or fallback to URI */ vv = ngx_http_get_indexed_variable(r, ngx_lcb_key_idx); if (vv == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (vv->not_found || vv->len == 0) { size_t loc_len; loc_len = r->valid_location ? clcf->name.len : 0; key.data = r->uri.data + loc_len; key.len = r->uri.len - loc_len; } else { u_char *dst, *src; key.data = ngx_palloc(r->pool, vv->len); if (key.data == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } dst = key.data; src = vv->data; ngx_unescape_uri(&dst, &src, vv->len, 0); *dst = 0; key.len = dst - key.data; } /* setup value: use variable or fallback to HTTP body */ ngx_str_null(&val); if (opcode >= ngx_lcb_cmd_add && opcode <= ngx_lcb_cmd_prepend) { vv = ngx_http_get_indexed_variable(r, ngx_lcb_val_idx); if (vv == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (vv->not_found || vv->len == 0) { if (r->request_body == NULL || r->request_body->bufs == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "neither the \"$couchbase_value\" variable " "nor the request body is available"); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_HTTP_BAD_REQUEST; } else { /* copy body to the buffer */ ngx_chain_t *cl; u_char *p; val.len = 0; for (cl = r->request_body->bufs; cl; cl = cl->next) { val.len += ngx_buf_size(cl->buf); } p = val.data = ngx_palloc(r->pool, val.len); if (p == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } for (cl = r->request_body->bufs; cl; cl = cl->next) { p = ngx_copy(p, cl->buf->pos, cl->buf->last - cl->buf->pos); } vv = NULL; } } else { u_char *dst, *src; val.data = ngx_palloc(r->pool, vv->len); if (val.data == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } need_free_value = 1; dst = val.data; src = vv->data; ngx_unescape_uri(&dst, &src, vv->len, 0); *dst = 0; val.len = dst - val.data; } } /* setup CAS value */ vv = ngx_http_get_indexed_variable(r, ngx_lcb_cas_idx); if (vv == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (!vv->not_found && vv->len > 0) { if (ngx_lcb_atocas(vv->data, vv->len, &cas) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_HTTP_BAD_REQUEST; } } /* setup flags value */ vv = ngx_http_get_indexed_variable(r, ngx_lcb_flags_idx); if (vv == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (!vv->not_found && vv->len > 0) { flags = ngx_atoi(vv->data, vv->len); } /* setup expiration value */ vv = ngx_http_get_indexed_variable(r, ngx_lcb_exptime_idx); if (vv == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (!vv->not_found && vv->len > 0) { exptime = ngx_atoi(vv->data, vv->len); } switch (opcode) { case ngx_lcb_cmd_get: { lcb_get_cmd_t cmd; const lcb_get_cmd_t *commands[1]; commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.key = key.data; cmd.v.v0.nkey = key.len; cmd.v.v0.exptime = exptime; err = lcb_get(conn->lcb, r, 1, commands); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "couchbase(%p): get request \"%*s\"", (void *)conn->lcb, cmd.v.v0.nkey, cmd.v.v0.key); } break; case ngx_lcb_cmd_add: case ngx_lcb_cmd_replace: case ngx_lcb_cmd_set: case ngx_lcb_cmd_append: case ngx_lcb_cmd_prepend: { lcb_store_cmd_t cmd; const lcb_store_cmd_t *commands[1]; commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.operation = opcode; cmd.v.v0.key = key.data; cmd.v.v0.nkey = key.len; cmd.v.v0.bytes = val.data; cmd.v.v0.nbytes = val.len; cmd.v.v0.cas = cas; cmd.v.v0.flags = flags; cmd.v.v0.exptime = exptime; err = lcb_store(conn->lcb, r, 1, commands); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "couchbase(%p): store request \"%*s\", operation: 0x%02xd", (void *)conn->lcb, cmd.v.v0.nkey, cmd.v.v0.key, cmd.v.v0.operation); } break; case ngx_lcb_cmd_delete: { lcb_remove_cmd_t cmd; const lcb_remove_cmd_t *commands[1]; commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.key = key.data; cmd.v.v0.nkey = key.len; err = lcb_remove(conn->lcb, r, 1, commands); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "couchbase(%p): remove request \"%*s\"", (void *)conn->lcb, cmd.v.v0.nkey, cmd.v.v0.key); } break; } if (need_free_value) { ngx_pfree(r->pool, val.data); } if (err != LCB_SUCCESS) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "couchbase: failed to schedule couchbase request: %s", lcb_strerror(conn->lcb, err)); ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_ERROR; } return NGX_OK; }
int main(int argc, char *argv[]) { lcb_error_t err; lcb_t instance; struct lcb_create_st create_options; struct lcb_create_io_ops_st io_opts; io_opts.version = 0; io_opts.v.v0.type = LCB_IO_OPS_DEFAULT; io_opts.v.v0.cookie = NULL; memset(&create_options, 0, sizeof(create_options)); err = lcb_create_io_ops(&create_options.v.v0.io, &io_opts); if (err != LCB_SUCCESS) { fprintf(stderr, "Failed to create IO instance: %s\n", lcb_strerror(NULL, err)); return 1; } if (argc > 1) { create_options.v.v0.host = argv[1]; } if (argc > 2) { create_options.v.v0.user = argv[2]; create_options.v.v0.bucket = argv[2]; } if (argc > 3) { create_options.v.v0.passwd = argv[3]; } err = lcb_create(&instance, &create_options); if (err != LCB_SUCCESS) { fprintf(stderr, "Failed to create libcouchbase instance: %s\n", lcb_strerror(NULL, err)); return 1; } (void)lcb_set_error_callback(instance, error_callback); /* Initiate the connect sequence in libcouchbase */ if ((err = lcb_connect(instance)) != LCB_SUCCESS) { fprintf(stderr, "Failed to initiate connect: %s\n", lcb_strerror(NULL, err)); lcb_destroy(instance); return 1; } (void)lcb_set_get_callback(instance, get_callback); (void)lcb_set_store_callback(instance, store_callback); /* Run the event loop and wait until we've connected */ lcb_wait(instance); { lcb_store_cmd_t cmd; const lcb_store_cmd_t *commands[1]; commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.operation = LCB_SET; cmd.v.v0.key = "foo"; cmd.v.v0.nkey = 3; cmd.v.v0.bytes = "bar"; cmd.v.v0.nbytes = 3; err = lcb_store(instance, NULL, 1, commands); if (err != LCB_SUCCESS) { fprintf(stderr, "Failed to store: %s\n", lcb_strerror(NULL, err)); return 1; } } lcb_wait(instance); { lcb_get_cmd_t cmd; const lcb_get_cmd_t *commands[1]; commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.key = "foo"; cmd.v.v0.nkey = 3; err = lcb_get(instance, NULL, 1, commands); if (err != LCB_SUCCESS) { fprintf(stderr, "Failed to get: %s\n", lcb_strerror(NULL, err)); return 1; } } lcb_wait(instance); lcb_destroy(instance); return 0; }