PHP_COUCHBASE_LOCAL void php_couchbase_unlock_impl(INTERNAL_FUNCTION_PARAMETERS, int oo) { char *key; char *cas = NULL; char *cas_e; long klen = 0; long cas_len = 0; lcb_cas_t cas_v = 0; php_couchbase_res *couchbase_res; lcb_error_t retval; int arg = (oo) ? PHP_COUCHBASE_ARG_F_OO : PHP_COUCHBASE_ARG_F_FUNCTIONAL; PHP_COUCHBASE_GET_PARAMS(couchbase_res, arg, "ss", &key, &klen, &cas, &cas_len); 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_illegal_key_exception, "No CAS specified: Empty cas"); return ; } cas_v = (lcb_cas_t)strtoull(cas, &cas_e, 10); if (*cas_e != '\0') { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_illegal_key_exception, "Invalid CAS specified"); return; } if (couchbase_res->prefix_key_len) { klen = spprintf(&key, 0, "%s_%s", couchbase_res->prefix_key, key); } retval = do_unlock(couchbase_res->handle, key, klen, cas_v); couchbase_res->rc = retval; if (couchbase_res->prefix_key_len) { efree(key); } if (retval == LCB_SUCCESS) { RETVAL_TRUE; } else { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_lcb_exception, "Failed to unlock the document: %s", lcb_strerror(couchbase_res->handle, retval)); } }
PHP_COUCHBASE_LOCAL void php_couchbase_flush_impl(INTERNAL_FUNCTION_PARAMETERS, int oo) { php_couchbase_res *res; lcb_t instance; int argflags = oo ? PHP_COUCHBASE_ARG_F_OO : PHP_COUCHBASE_ARG_F_FUNCTIONAL; PHP_COUCHBASE_GET_PARAMS(res, argflags, ""); instance = res->handle; lcb_behavior_set_syncmode(instance, LCB_SYNCHRONOUS); if (COUCHBASE_G(restflush)) { do_rest_flush(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, res); } else { do_memcached_flush(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, res); } lcb_behavior_set_syncmode(instance, LCB_ASYNCHRONOUS); }
PHP_COUCHBASE_LOCAL void php_couchbase_get_option_impl(INTERNAL_FUNCTION_PARAMETERS, int oo) { long option; php_couchbase_res *couchbase_res; int argflags = (oo ? PHP_COUCHBASE_ARG_F_OO : PHP_COUCHBASE_ARG_F_FUNCTIONAL) | PHP_COUCHBASE_ARG_F_ONLYVALID; PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, "l", &option); switch (option) { case COUCHBASE_OPT_SERIALIZER: RETURN_LONG(couchbase_res->serializer); break; case COUCHBASE_OPT_PREFIX_KEY: if (couchbase_res->prefix_key_len) { RETURN_STRINGL((char *)couchbase_res->prefix_key, couchbase_res->prefix_key_len, 1); } else { ZVAL_EMPTY_STRING(return_value); return; } break; case COUCHBASE_OPT_COMPRESSION: RETURN_LONG(couchbase_res->compressor); break; case COUCHBASE_OPT_IGNOREFLAGS: RETURN_LONG(couchbase_res->ignoreflags); break; case COUCHBASE_OPT_VOPTS_PASSTHROUGH: RETURN_LONG(couchbase_res->viewopts_passthrough); break; default: couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_illegal_value_exception, "unknown option type: %ld", option); } }
PHP_COUCHBASE_LOCAL void php_couchbase_stats_impl(INTERNAL_FUNCTION_PARAMETERS, int oo) { php_couchbase_res *couchbase_res; lcb_error_t retval; php_couchbase_ctx *ctx; lcb_server_stats_cmd_t cmd; const lcb_server_stats_cmd_t *const commands[] = { &cmd }; lcb_t instance; int argflags = oo ? PHP_COUCHBASE_ARG_F_OO : PHP_COUCHBASE_ARG_F_FUNCTIONAL; PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, ""); ctx = ecalloc(1, sizeof(php_couchbase_ctx)); ctx->res = couchbase_res; ctx->rv = return_value; couchbase_res->rc = LCB_SUCCESS; instance = couchbase_res->handle; memset(&cmd, 0, sizeof(cmd)); lcb_behavior_set_syncmode(instance, LCB_SYNCHRONOUS); retval = lcb_server_stats(instance, (const void *)ctx, 1, commands); lcb_behavior_set_syncmode(instance, LCB_ASYNCHRONOUS); if (retval == LCB_SUCCESS) { retval = couchbase_res->rc; } else { couchbase_res->rc = retval; } efree(ctx); if (retval != LCB_SUCCESS) { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_lcb_exception, "Failed to stat: %s", lcb_strerror(instance, retval)); } }
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); }
PHP_COUCHBASE_LOCAL void php_couchbase_list_design_docs_impl(INTERNAL_FUNCTION_PARAMETERS, int oo) { php_couchbase_res *couchbase_res; int argflags; lcb_t instance; lcb_error_t rc; struct http_ctx ctx; lcb_http_cmd_t cmd; lcb_http_complete_callback old; int len; char *path; if (oo) { argflags = PHP_COUCHBASE_ARG_F_OO; } else { argflags = PHP_COUCHBASE_ARG_F_FUNCTIONAL; } PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, ""); instance = couchbase_res->handle; memset(&ctx, 0, sizeof(ctx)); memset(&cmd, 0, sizeof(cmd)); path = ecalloc(strlen(couchbase_res->bucket) + 80, 1); len = sprintf(path, "/pools/default/buckets/%s/ddocs", couchbase_res->bucket); cmd.v.v0.path = path; cmd.v.v0.npath = len; cmd.v.v0.method = LCB_HTTP_METHOD_GET; cmd.v.v0.content_type = "application/json"; old = lcb_set_http_complete_callback(instance, http_callback); lcb_behavior_set_syncmode(instance, LCB_SYNCHRONOUS); rc = lcb_make_http_request(instance, &ctx, LCB_HTTP_TYPE_MANAGEMENT, &cmd, NULL); lcb_behavior_set_syncmode(instance, LCB_ASYNCHRONOUS); old = lcb_set_http_complete_callback(instance, old); efree(path); if (rc == LCB_SUCCESS) { rc = ctx.error; } couchbase_res->rc = rc; if (rc != LCB_SUCCESS) { /* An error occured occurred on libcouchbase level */ efree(ctx.payload); couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_lcb_exception, "Failed to retrieve design doc: %s", lcb_strerror(instance, rc)); return; } switch (ctx.status) { case LCB_HTTP_STATUS_OK: RETURN_STRING(ctx.payload, 0); case LCB_HTTP_STATUS_UNAUTHORIZED: couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_auth_exception, "Incorrect credentials"); break; default: if (ctx.payload == NULL) { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_server_exception, "{\"errors\":{\"http response\": %d }}", (int)ctx.status); } else { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_server_exception, ctx.payload); } } efree(ctx.payload); }
PHP_COUCHBASE_LOCAL void php_couchbase_delget_design_doc_impl(INTERNAL_FUNCTION_PARAMETERS, int oo, int rem) { char *path; char *name = NULL; long nname = 0; php_couchbase_res *couchbase_res; int argflags; lcb_t instance; lcb_error_t rc; struct http_ctx ctx; lcb_http_cmd_t cmd; lcb_http_complete_callback old; int len; if (oo) { argflags = PHP_COUCHBASE_ARG_F_OO; } else { argflags = PHP_COUCHBASE_ARG_F_FUNCTIONAL; } PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, "s", &name, &nname); if (!nname) { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_illegal_key_exception, "You have to specify the name of the design doc"); return; } memset(&ctx, 0, sizeof(ctx)); memset(&cmd, 0, sizeof(cmd)); instance = couchbase_res->handle; path = ecalloc(1, 80 + nname); len = sprintf(path, "/_design/%*s", (int)nname, name); cmd.v.v0.path = path; cmd.v.v0.npath = len; if (rem) { cmd.v.v0.method = LCB_HTTP_METHOD_DELETE; } else { cmd.v.v0.method = LCB_HTTP_METHOD_GET; } cmd.v.v0.content_type = "application/json"; old = lcb_set_http_complete_callback(instance, http_callback); lcb_behavior_set_syncmode(instance, LCB_SYNCHRONOUS); rc = lcb_make_http_request(instance, &ctx, LCB_HTTP_TYPE_VIEW, &cmd, NULL); lcb_behavior_set_syncmode(instance, LCB_ASYNCHRONOUS); old = lcb_set_http_complete_callback(instance, old); efree(path); if (rc == LCB_SUCCESS) { rc = ctx.error; } couchbase_res->rc = rc; if (rc != LCB_SUCCESS) { /* An error occured occurred on libcouchbase level */ efree(ctx.payload); couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_lcb_exception, "Failed to retrieve design doc: %s", lcb_strerror(instance, rc)); return; } switch (ctx.status) { case LCB_HTTP_STATUS_OK: if (rem) { efree(ctx.payload); RETURN_TRUE; } else { RETURN_STRING(ctx.payload, 0); } /* not reached */ case LCB_HTTP_STATUS_NOT_FOUND: efree(ctx.payload); RETURN_FALSE; case LCB_HTTP_STATUS_UNAUTHORIZED: couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_auth_exception, "Incorrect credentials"); break; default: if (ctx.payload == NULL) { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_server_exception, "{\"errors\":{\"http response\": %d }}", (int)ctx.status); } else { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_server_exception, ctx.payload); } } efree(ctx.payload); }
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); }
PHP_COUCHBASE_LOCAL void php_couchbase_remove_impl(INTERNAL_FUNCTION_PARAMETERS, int oo) { char *key; char *cas = NULL; long klen = 0; long cas_len = 0; long replicate_to = 0; long persist_to = 0; lcb_cas_t cas_v = 0; php_couchbase_res *couchbase_res; lcb_error_t retval; php_couchbase_ctx *ctx; char errmsg[256]; int arg = (oo) ? PHP_COUCHBASE_ARG_F_OO : PHP_COUCHBASE_ARG_F_FUNCTIONAL; PHP_COUCHBASE_GET_PARAMS(couchbase_res, arg, "s|sll", &key, &klen, &cas, &cas_len, &persist_to, &replicate_to); if (klen == 0) { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_illegal_key_exception, "No key specified: Empty key"); return ; } if (validate_simple_observe_clause(couchbase_res->handle, persist_to, replicate_to TSRMLS_CC) == -1) { /* Exception already thrown */ return; } if (cas_len > 0) { char *e; cas_v = (lcb_cas_t)strtoull(cas, &e, 10); if (*e != '\0') { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_illegal_key_exception, "Invalid CAS specified"); return; } } retval = do_remove(couchbase_res->handle, key, klen, &cas_v); couchbase_res->rc = retval; switch (retval) { case LCB_SUCCESS: Z_TYPE_P(return_value) = IS_STRING; Z_STRLEN_P(return_value) = spprintf(&(Z_STRVAL_P(return_value)), 0, "%llu", cas_v); break; case LCB_KEY_ENOENT: RETURN_FALSE; /* NOTREACHED */ case LCB_KEY_EEXISTS: if (oo) { couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_key_mutated_exception, "Failed to remove the value from the server: %s", lcb_strerror(couchbase_res->handle, retval)); return ; } else { RETURN_FALSE; } default: couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_lcb_exception, "Failed to remove the value from the server: %s", lcb_strerror(couchbase_res->handle, retval)); return ; } if (retval == LCB_SUCCESS && (persist_to > 0 || replicate_to > 0)) { /* * If we have a durability spec, after the commands have been * issued (and callbacks returned), try to fulfill that spec by * using polling observe internal (please note that this is * only possible from OO) */ struct observe_entry entry; memset(&entry, 0, sizeof(entry)); entry.key = key; entry.nkey = klen; entry.cas = cas_v; 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 { 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); } } } }
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); } }
PHP_COUCHBASE_LOCAL void php_couchbase_arithmetic_impl(INTERNAL_FUNCTION_PARAMETERS, char op, int oo) /* {{{ */ { char *key; time_t exp = {0}; long klen = 0, offset = 1, expire = 0; long create = 0, initial = 0; php_couchbase_res *couchbase_res; int argflags = oo ? PHP_COUCHBASE_ARG_F_OO : PHP_COUCHBASE_ARG_F_FUNCTIONAL; PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, "s|llll", &key, &klen, &offset, &create, &expire, &initial); { lcb_error_t retval; php_couchbase_ctx *ctx; long delta = (op == '+') ? offset : -offset; if (expire) { exp = pcbc_check_expiry(expire); } ctx = ecalloc(1, sizeof(php_couchbase_ctx)); ctx->res = couchbase_res; ctx->rv = return_value; { lcb_arithmetic_cmd_t cmd; lcb_arithmetic_cmd_t *commands[] = { &cmd }; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.key = key; cmd.v.v0.nkey = klen; cmd.v.v0.create = create; cmd.v.v0.delta = delta; cmd.v.v0.initial = initial; cmd.v.v0.exptime = exp; retval = lcb_arithmetic(couchbase_res->handle, ctx, 1, (const lcb_arithmetic_cmd_t * const *)commands); } if (LCB_SUCCESS != retval) { efree(ctx); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to schedule rithmetic request: %s", lcb_strerror(couchbase_res->handle, retval)); RETURN_FALSE; } couchbase_res->seqno += 1; pcbc_start_loop(couchbase_res); if (LCB_SUCCESS != ctx->res->rc) { // Just return false and don't print a warning when no key is present and create is false if (!(LCB_KEY_ENOENT == ctx->res->rc && create == 0)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to %s value in server: %s", (op == '+') ? "increment" : "decrement", lcb_strerror(couchbase_res->handle, ctx->res->rc)); } efree(ctx); RETURN_FALSE; } efree(ctx); } }
PHP_COUCHBASE_LOCAL void php_couchbase_set_option_impl(INTERNAL_FUNCTION_PARAMETERS, int oo) { long option; zval *value; php_couchbase_res *couchbase_res; int argflags = (oo ? PHP_COUCHBASE_ARG_F_OO : PHP_COUCHBASE_ARG_F_FUNCTIONAL) | PHP_COUCHBASE_ARG_F_NOCONN | PHP_COUCHBASE_ARG_F_ASYNC; PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, "lz", &option, &value); switch (option) { case COUCHBASE_OPT_SERIALIZER: convert_to_long_ex(&value); switch (Z_LVAL_P(value)) { case COUCHBASE_SERIALIZER_PHP: case COUCHBASE_SERIALIZER_JSON: case COUCHBASE_SERIALIZER_JSON_ARRAY: #ifdef HAVE_IGBINARY case COUCHBASE_SERIALIZER_IGBINARY: #endif couchbase_res->serializer = Z_LVAL_P(value); if (oo) { RETURN_ZVAL(getThis(), 1, 0); } RETURN_TRUE; default: couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_illegal_value_exception, "unsupported serializer: %ld", Z_LVAL_P(value)); return; } break; case COUCHBASE_OPT_PREFIX_KEY: convert_to_string_ex(&value); free(couchbase_res->prefix_key); couchbase_res->prefix_key = NULL; couchbase_res->prefix_key_len = Z_STRLEN_P(value); if (couchbase_res->prefix_key_len) { couchbase_res->prefix_key = malloc(couchbase_res->prefix_key_len + 1); memcpy(couchbase_res->prefix_key, Z_STRVAL_P(value), couchbase_res->prefix_key_len); couchbase_res->prefix_key[couchbase_res->prefix_key_len] = '\0'; } break; case COUCHBASE_OPT_COMPRESSION: convert_to_long_ex(&value); switch (Z_LVAL_P(value)) { case COUCHBASE_COMPRESSION_NONE: case COUCHBASE_COMPRESSION_FASTLZ: case COUCHBASE_COMPRESSION_ZLIB: couchbase_res->compressor = Z_LVAL_P(value); if (oo) { RETURN_ZVAL(getThis(), 1, 0); } RETURN_TRUE; break; default: couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_illegal_value_exception, "unsupported compressor: %ld", Z_LVAL_P(value)); return; } break; case COUCHBASE_OPT_IGNOREFLAGS: convert_to_long_ex(&value); couchbase_res->ignoreflags = Z_LVAL_P(value); break; case COUCHBASE_OPT_VOPTS_PASSTHROUGH: convert_to_long_ex(&value); couchbase_res->viewopts_passthrough = Z_LVAL_P(value); break; default: couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_illegal_value_exception, "unknown option type: %ld", option); return; } RETURN_TRUE; }
PHP_COUCHBASE_LOCAL void php_couchbase_arithmetic_impl(INTERNAL_FUNCTION_PARAMETERS, char op, int oo) { char *key; time_t exp; long klen = 0; long offset = 1; long expire = 0; long create = 0; long initial = 0; php_couchbase_res *couchbase_res; lcb_arithmetic_cmd_t cmd; const lcb_arithmetic_cmd_t *const commands[] = { &cmd }; lcb_error_t retval; struct arithmetic_cookie cookie; int argflags; long delta; lcb_t instance; argflags = oo ? PHP_COUCHBASE_ARG_F_OO : PHP_COUCHBASE_ARG_F_FUNCTIONAL; PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, "s|llll", &key, &klen, &offset, &create, &expire, &initial); if (pcbc_check_expiry(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, expire, &exp) == -1) { /* Incorrect expiry time */ return; } instance = couchbase_res->handle; memset(&cookie, 0, sizeof(cookie)); delta = (op == '+') ? offset : -offset; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.key = key; cmd.v.v0.nkey = klen; cmd.v.v0.create = create; cmd.v.v0.delta = delta; cmd.v.v0.initial = initial; cmd.v.v0.exptime = exp; lcb_behavior_set_syncmode(instance, LCB_SYNCHRONOUS); retval = lcb_arithmetic(instance, &cookie, 1, commands); lcb_behavior_set_syncmode(instance, LCB_ASYNCHRONOUS); if (retval == LCB_SUCCESS) { retval = cookie.error ; } couchbase_res->rc = retval; if (retval == LCB_SUCCESS) { ZVAL_LONG(return_value, cookie.value); } else { if (retval == LCB_KEY_ENOENT && create == 0) { /* The user told us to not create the key... */ RETURN_FALSE; } couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo, cb_lcb_exception, "Failed to %s value in the server: %s", (op == '+') ? "increment" : "decrement", lcb_strerror(instance, retval)); } }
PHP_COUCHBASE_LOCAL void php_couchbase_fetch_impl(INTERNAL_FUNCTION_PARAMETERS, int multi, int oo) /* {{{ */ { php_couchbase_res *couchbase_res; int argflags; if (oo) { argflags = PHP_COUCHBASE_ARG_F_OO; } else { argflags = PHP_COUCHBASE_ARG_F_FUNCTIONAL; } argflags |= PHP_COUCHBASE_ARG_F_ASYNC; PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, ""); { php_couchbase_ctx *ctx; if (!couchbase_res->async) { RETURN_FALSE; } ctx = couchbase_res->async_ctx; if (couchbase_res->async == 2) { fetch_one: { char *key; uint key_len; ulong index = 0; zval **ppzval; zval *stash = (zval *)ctx->extended_value; if (zend_hash_num_elements(Z_ARRVAL_P(stash)) == 0) { couchbase_res->async = 0; zval_ptr_dtor(&stash); efree(ctx); couchbase_res->async_ctx = NULL; RETURN_NULL(); } zend_hash_internal_pointer_reset(Z_ARRVAL_P(stash)); zend_hash_get_current_data(Z_ARRVAL_P(stash), (void **)&ppzval); RETVAL_ZVAL(*ppzval, 1, 0); zend_hash_get_current_key_ex(Z_ARRVAL_P(stash), &key, &key_len, &index, 0, NULL); zend_hash_index_del(Z_ARRVAL_P(stash), index); return; } } array_init(return_value); ctx->rv = return_value; pcbc_start_loop(couchbase_res); if (!multi) { zval *stash; MAKE_STD_ZVAL(stash); ZVAL_ZVAL(stash, return_value, 1, 0); ctx->extended_value = (void *)stash; zval_dtor(return_value); couchbase_res->async = 2; goto fetch_one; } else { efree(ctx); couchbase_res->async = 0; couchbase_res->async_ctx = NULL; } } }
PHP_COUCHBASE_LOCAL void php_couchbase_observe_impl(INTERNAL_FUNCTION_PARAMETERS, int multi, int oo, int poll) { zval *adurability = NULL, *adetails = NULL; /* zval passed by ref, will be stuffed with details if given */ php_couchbase_res *couchbase_res; struct observe_collection ocoll = { 0 }; struct observe_expectation expect = { 0 }; struct observe_pollprefs pollprefs; int argflags = oo ? PHP_COUCHBASE_ARG_F_OO : PHP_COUCHBASE_ARG_F_FUNCTIONAL; /* param handling, return value setup */ if (multi) { zval *akey_to_cas; if (poll) { PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, "aa", &akey_to_cas, &adurability); } else { PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, "a|z", &akey_to_cas, &adetails); } array_init(return_value); if (poll) { if (-1 == oks_extract_durability(couchbase_res, &expect, &pollprefs, adurability)) { RETURN_FALSE; } } if (-1 == oks_build_context(couchbase_res, &ocoll, &expect, akey_to_cas, 1)) { RETURN_FALSE; } } else { /* single */ char *key = NULL; long nkey = 0; zval *cas; zval *akc_dummy = NULL; pcbc_ht_key dummy_hk; lcb_cas_t tmpcas = 0; ZVAL_FALSE(return_value); if (poll) { PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, "sza", &key, &nkey, &cas, &adurability); } else { PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, "sz|z", &key, &nkey, &cas, &adetails); } if (adetails && IS_ARRAY != Z_TYPE_P(adetails)) { array_init(adetails); } if (key == NULL || nkey == 0) { /* empty key */ RETURN_FALSE; } make_prefixed_hk(couchbase_res, key, nkey, &dummy_hk); tmpcas = cas_from_zval(cas); if (tmpcas == -1) { pcbc_ht_key_cleanup(&dummy_hk); RETURN_FALSE; } ALLOC_INIT_ZVAL(akc_dummy); array_init(akc_dummy); if (tmpcas) { pcbc_ht_hkstores(akc_dummy, &dummy_hk, Z_STRVAL_P(cas), Z_STRLEN_P(cas)); } else { pcbc_ht_hkstoreb(akc_dummy, &dummy_hk, 0); } /* Weird block right here to sanely free the structures allocated */ { int have_failure = 0; do { if (poll) { if (-1 == oks_extract_durability(couchbase_res, &expect, &pollprefs, adurability)) { have_failure = 1; break; } } if (-1 == oks_build_context( couchbase_res, &ocoll, &expect, akc_dummy, 0)) { have_failure = 1; break; } } while (0); /** >> CLEANUP HERE */ zval_ptr_dtor(&akc_dummy); pcbc_ht_key_cleanup(&dummy_hk); if (have_failure) { RETURN_FALSE; } } } if (adetails && Z_TYPE_P(adetails) != IS_ARRAY) { array_init(adetails); } if (poll) { observe_poll(couchbase_res, &ocoll, &pollprefs); } else { observe_iterate(couchbase_res, &ocoll); } oks_populate_results(couchbase_res, &ocoll, return_value, adetails, multi); oks_cleanup_context(&ocoll); }
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); } }
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); }