// Doing a touch will set the expiration time of the item // http://docs.couchbase.com/sdk-api/couchbase-c-client-2.4.6/group__lcb-touch.html void blockingTouch(lcb_t instance, int expTimeSeconds, char *keyName) { int keyLength = strlen(keyName); lcb_error_t touchErrorCode = 0; lcb_touch_cmd_t *touchCommand = calloc(1, sizeof(*touchCommand)); touchCommand->v.v0.key = keyName; touchCommand->v.v0.nkey = keyLength; touchCommand->v.v0.exptime = expTimeSeconds; touchCommand->v.v0.lock = 0; const lcb_touch_cmd_t *touchCommandList[] = { touchCommand }; touchErrorCode = lcb_touch(instance, NULL, 1, touchCommandList); if (touchErrorCode != LCB_SUCCESS) { printf("Couldn't schedule touch operation!\n"); printf("lcb_touch errorCode is 0x%.8X \n", touchErrorCode); exit(1); } printf("TOUCH: About to do lcb_wait()...\n"); lcb_wait(instance); printf("TOUCH: Back from lcb_wait()...\n"); } // end of blockingTouch()
ERL_NIF_TERM cb_mtouch(ErlNifEnv* env, handle_t* handle, void* obj) { mtouch_args_t* args = (mtouch_args_t*)obj; struct libcouchbase_callback_m cb; int i = 0; lcb_error_t ret; ERL_NIF_TERM* results; ERL_NIF_TERM returnValue; ErlNifBinary key_binary; cb.currKey = 0; cb.ret = malloc(sizeof(struct libcouchbase_callback*) * args->numkeys); const lcb_touch_cmd_t* commands[args->numkeys]; i = 0; for (; i < args->numkeys; i++) { lcb_touch_cmd_t* touch = calloc(1, sizeof(*touch)); touch->version = 0; touch->v.v0.key = args->keys[i]; touch->v.v0.nkey = args->nkeys[i]; touch->v.v0.exptime = args->exp[i]; commands[i] = touch; } ret = lcb_touch(handle->instance, &cb, args->numkeys, commands); if (ret != LCB_SUCCESS) { return return_lcb_error(env, ret); } lcb_wait(handle->instance); results = malloc(sizeof(ERL_NIF_TERM) * args->numkeys); i = 0; for(; i < args->numkeys; i++) { enif_alloc_binary(cb.ret[i]->nkey, &key_binary); memcpy(key_binary.data, cb.ret[i]->key, cb.ret[i]->nkey); ERL_NIF_TERM key = enif_make_binary(env, &key_binary); if (cb.ret[i]->error == LCB_SUCCESS) { results[i] = enif_make_tuple2(env, key, A_OK(env)); } else { results[i] = enif_make_tuple2(env, key, return_lcb_error(env, cb.ret[i]->error)); } free(cb.ret[i]->key); free(cb.ret[i]); free(args->keys[i]); free((lcb_touch_cmd_t*) commands[i]); } returnValue = enif_make_list_from_array(env, results, args->numkeys); free(results); free(cb.ret); free(args->keys); free(args->exp); free(args->nkeys); return enif_make_tuple2(env, A_OK(env), returnValue); }
PHP_COUCHBASE_LOCAL void php_couchbase_touch_multi_impl(INTERNAL_FUNCTION_PARAMETERS, int oo) { int argflags; int idx = 0; int ii; lcb_error_t retval; lcb_t instance; lcb_time_t exp = 0; lcb_touch_cmd_t **commands; lcb_touch_cmd_t *cmd; long expiry; php_couchbase_res *couchbase_res; struct multi_touch_cookie cookie; zval **ppzval; zval *arr_keys; /* parameter handling and return_value setup: */ if (oo) { argflags = PHP_COUCHBASE_ARG_F_OO; } else { argflags = PHP_COUCHBASE_ARG_F_FUNCTIONAL; } PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, "al", &arr_keys, &expiry); instance = couchbase_res->handle; memset(&cookie, 0, sizeof(cookie)); cookie.nkeys = zend_hash_num_elements(Z_ARRVAL_P(arr_keys)); cookie.keys = ecalloc(cookie.nkeys, sizeof(struct touch_cookie)); for (ii = 0, zend_hash_internal_pointer_reset(Z_ARRVAL_P(arr_keys)); zend_hash_has_more_elements(Z_ARRVAL_P(arr_keys)) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_P(arr_keys)), ii++) { if (zend_hash_get_current_data(Z_ARRVAL_P(arr_keys), (void **)&ppzval) == FAILURE) { continue; } if (IS_ARRAY != Z_TYPE_PP(ppzval)) { convert_to_string_ex(ppzval); } if (!Z_STRLEN_PP(ppzval)) { continue; } if (couchbase_res->prefix_key_len) { cookie.keys[idx].nkey = spprintf(&(cookie.keys[idx].key), 0, "%s_%s", couchbase_res->prefix_key, Z_STRVAL_PP(ppzval)); } else { cookie.keys[idx].key = Z_STRVAL_PP(ppzval); cookie.keys[idx].nkey = Z_STRLEN_PP(ppzval); } ++idx; } if (idx == 0) { efree(cookie.keys); couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_illegal_key_exception, "No keys specified"); return; } if (expiry) { exp = pcbc_check_expiry(expiry); } cmd = ecalloc(idx, sizeof(lcb_touch_cmd_t)); commands = ecalloc(idx, sizeof(lcb_touch_cmd_t *)); for (ii = 0; ii < idx; ++ii) { cmd[ii].v.v0.key = cookie.keys[ii].key; cmd[ii].v.v0.nkey = cookie.keys[ii].nkey; cmd[ii].v.v0.exptime = exp; commands[ii] = cmd + ii; } lcb_set_touch_callback(instance, multi_touch_callback); lcb_behavior_set_syncmode(instance, LCB_SYNCHRONOUS); retval = lcb_touch(instance, &cookie, idx, (const lcb_touch_cmd_t * const *)commands); lcb_behavior_set_syncmode(instance, LCB_ASYNCHRONOUS); if (retval == LCB_SUCCESS) { retval = cookie.error; } couchbase_res->rc = retval; if (retval == LCB_SUCCESS) { /* Time to build up the array with the keys we found etc */ array_init(return_value); for (ii = 0; ii < idx; ++ii) { char *k = cookie.keys[ii].key; if (cookie.keys[ii].error == LCB_SUCCESS) { char cas[80]; snprintf(cas, sizeof(cas), "%llu", (unsigned long long)cookie.keys[ii].cas); add_assoc_string(return_value, k, cas, 1); } else { add_assoc_bool(return_value, k, (zend_bool)0); } } } else { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_lcb_exception, "Failed to touch key: %s", lcb_strerror(instance, retval)); } /* Release allocated memory */ efree(cmd); efree(commands); if (couchbase_res->prefix_key_len) { for (ii = 0; ii < idx; ++ii) { efree(cookie.keys[ii].key); } } efree(cookie.keys); }
PHP_COUCHBASE_LOCAL void php_couchbase_touch_impl(INTERNAL_FUNCTION_PARAMETERS, int oo) { struct touch_cookie cookie; char *key = NULL; long nkey = 0; lcb_time_t exp = 0; long expiry; php_couchbase_res *couchbase_res; int argflags; lcb_t instance; lcb_error_t retval; lcb_touch_cmd_t cmd; const lcb_touch_cmd_t *const commands[] = { &cmd }; /* parameter handling and return_value setup: */ if (oo) { argflags = PHP_COUCHBASE_ARG_F_OO; } else { argflags = PHP_COUCHBASE_ARG_F_FUNCTIONAL; } PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, "sl", &key, &nkey, &expiry); if (!nkey) { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_illegal_key_exception, "No key specified: Empty key"); return; } if (couchbase_res->prefix_key_len) { nkey = spprintf(&key, 0, "%s_%s", couchbase_res->prefix_key, key); } if (expiry) { exp = pcbc_check_expiry(expiry); } memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.key = key; cmd.v.v0.nkey = nkey; cmd.v.v0.exptime = exp; instance = couchbase_res->handle; cookie.error = LCB_ERROR; lcb_set_touch_callback(instance, single_touch_callback); lcb_behavior_set_syncmode(instance, LCB_SYNCHRONOUS); retval = lcb_touch(instance, &cookie, 1, commands); lcb_behavior_set_syncmode(instance, LCB_ASYNCHRONOUS); if (retval == LCB_SUCCESS) { retval = cookie.error; } couchbase_res->rc = retval; if (couchbase_res->prefix_key_len) { efree(key); } if (retval != LCB_SUCCESS) { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_lcb_exception, "Failed to touch key: %s", lcb_strerror(instance, retval)); return; } else { Z_TYPE_P(return_value) = IS_STRING; Z_STRLEN_P(return_value) = spprintf(&(Z_STRVAL_P(return_value)), 0, "%llu", cookie.cas); } }
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); }