コード例 #1
0
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));
	}
}
コード例 #2
0
ファイル: flush.c プロジェクト: copacode/php-ext-couchbase
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);
}
コード例 #3
0
ファイル: options.c プロジェクト: giabao/php-ext-couchbase
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);
	}
}
コード例 #4
0
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));
	}
}
コード例 #5
0
ファイル: store.c プロジェクト: giabao/php-ext-couchbase
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);
}
コード例 #6
0
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);
}
コード例 #7
0
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);
}
コード例 #8
0
ファイル: store.c プロジェクト: giabao/php-ext-couchbase
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);
}
コード例 #9
0
ファイル: remove.c プロジェクト: trondn/php-ext-couchbase
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);
            }
        }
    }
}
コード例 #10
0
ファイル: store.c プロジェクト: giabao/php-ext-couchbase
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);
}
コード例 #11
0
ファイル: store.c プロジェクト: giabao/php-ext-couchbase
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);
	}
}
コード例 #12
0
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);
	}
}
コード例 #13
0
ファイル: options.c プロジェクト: giabao/php-ext-couchbase
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;
}
コード例 #14
0
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));
	}
}
コード例 #15
0
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;
		}
	}
}
コード例 #16
0
ファイル: observe.c プロジェクト: gigablah/php-ext-couchbase
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);
}
コード例 #17
0
ファイル: touch.c プロジェクト: copacode/php-ext-couchbase
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);
	}
}
コード例 #18
0
ファイル: touch.c プロジェクト: copacode/php-ext-couchbase
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);
}