예제 #1
0
static lcb_error_t do_unlock(lcb_t instance, const void *key, uint16_t klen,
							 lcb_cas_t cas)
{
	lcb_error_t error;
	lcb_unlock_cmd_t cmd;
	const lcb_unlock_cmd_t *const commands[] = { &cmd };
	lcb_error_t retval;

	memset(&cmd, 0, sizeof(cmd));
	cmd.v.v0.key = key;
	cmd.v.v0.nkey = klen;
	cmd.v.v0.cas = cas;

	lcb_behavior_set_syncmode(instance, LCB_SYNCHRONOUS);
	retval = lcb_unlock(instance, &error, 1, commands);
	lcb_behavior_set_syncmode(instance, LCB_ASYNCHRONOUS);

	return (retval == LCB_SUCCESS) ? error : retval;
}
예제 #2
0
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
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));
	}
}
예제 #4
0
static lcb_error_t do_remove(lcb_t instance, const void *key, uint16_t klen,
                             lcb_cas_t *cas)
{
    lcb_remove_cmd_t cmd;
    const lcb_remove_cmd_t *const commands[] = { &cmd };
    struct remove_cookie rmc;
    lcb_error_t retval;

    memset(&cmd, 0, sizeof(cmd));
    memset(&rmc, 0, sizeof(rmc));
    cmd.v.v0.key = key;
    cmd.v.v0.nkey = klen;
    cmd.v.v0.cas = *cas;

    lcb_behavior_set_syncmode(instance, LCB_SYNCHRONOUS);
    retval = lcb_remove(instance, &rmc, 1, commands);
    lcb_behavior_set_syncmode(instance, LCB_ASYNCHRONOUS);

    if (retval == LCB_SUCCESS && rmc.error == LCB_SUCCESS) {
        *cas = rmc.cas;
    }

    return (retval == LCB_SUCCESS) ? rmc.error : retval;
}
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_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
couchbase_con* couchbase_connect(struct cachedb_id* id, int is_reconnect)
{
	couchbase_con *con;
	struct lcb_create_st options;
	lcb_t instance;
	lcb_error_t rc;

	if (id == NULL) {
		LM_ERR("null cachedb_id\n");
		return 0;
	}

	con = pkg_malloc(sizeof(couchbase_con));
	if (con == NULL) {
		LM_ERR("no more pkg \n");
		return 0;
	}

	memset(con,0,sizeof(couchbase_con));
	con->id = id;
	con->ref = 1;

	/* TODO - support custom ports - couchbase expects host:port in id->host */
	memset(&options,0,sizeof(struct lcb_create_st));
	options.version = 0;
	options.v.v0.host = id->host;
	options.v.v0.user = id->username;
	options.v.v0.passwd = id->password;
	options.v.v0.bucket = id->database;
	rc=lcb_create(&instance, &options);
	if (rc!=LCB_SUCCESS) {
		LM_ERR("Failed to create libcouchbase instance: 0x%02x, %s\n",
		       rc, lcb_strerror(NULL, rc));
		return 0;
	}


	(void)lcb_set_error_callback(instance,
			couchbase_error_cb);
	(void)lcb_set_get_callback(instance,
			couchbase_get_cb);
	(void)lcb_set_store_callback(instance,
			couchbase_store_cb);
	(void)lcb_set_remove_callback(instance,
			couchbase_remove_cb);
	(void)lcb_set_arithmetic_callback(instance,couchbase_arithmetic_cb);
	(void)lcb_set_timeout(instance,couch_timeout_usec);

	//Set to synchronous mode
	lcb_behavior_set_syncmode(instance, LCB_SYNCHRONOUS);

	if (couch_lazy_connect == 0 || is_reconnect == 1) {
		rc=lcb_connect(instance);

		/*Check connection*/
		if (rc != LCB_SUCCESS) {
			/*Consider these connect failurs as fatal*/
			if(rc == LCB_AUTH_ERROR || rc == LCB_INVALID_HOST_FORMAT || rc == LCB_INVALID_CHAR) {
				LM_ERR("Fatal connection error to Couchbase. Host: %s Bucket: %s Error: %s",
					id->host, id->database, lcb_strerror(instance, rc));
				lcb_destroy(instance);
				return 0;
			} else {
			/* Non-fatal errors, we may be able to connect later */
				LM_ERR("Non-Fatal connection error to Couchbase. Host: %s Bucket: %s Error: %s",
					id->host, id->database, lcb_strerror(instance, rc));
			}
		} else {
			LM_DBG("Succesfully connected to Couchbase Server. Host: %s Bucket: %s\n", id->host, id->database);
		}
	}

	con->couchcon = instance;
	return con;
}
예제 #8
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));
	}
}
PHP_COUCHBASE_LOCAL
lcb_error_t simple_observe(lcb_t instance,
						   struct observe_entry *entries,
						   int nentries,
						   long persist_to,
						   long replicate_to)
{
	lcb_error_t err = LCB_SUCCESS;
	lcb_observe_cmd_t *cmds = ecalloc(nentries, sizeof(lcb_observe_cmd_t));
	lcb_observe_cmd_t **commands = ecalloc(nentries, sizeof(lcb_observe_cmd_t *));
	int ii;
	lcb_observe_callback org = lcb_set_observe_callback(instance,
														simple_observe_callback);
	struct observe_cookie cookie;
	int xx;
	int done = 0;
	int numtries = 0;
	int interval = INI_INT(PCBC_INIENT_OBS_INTERVAL);
	int maxretry = INI_INT(PCBC_INIENT_OBS_TIMEOUT) / interval;


	cookie.entries = entries;
	cookie.num = nentries;
	cookie.error = LCB_SUCCESS;

	lcb_behavior_set_syncmode(instance, LCB_SYNCHRONOUS);

	do {
		/* set up the commands */
		for (xx = 0, ii = 0; ii < nentries; ++ii) {
			cmds[ii].v.v0.key = entries[ii].key;
			cmds[ii].v.v0.nkey = entries[ii].nkey;
			if (should_add(&entries[ii], persist_to, replicate_to)) {
				commands[xx++] = cmds + ii;
			}
		}

		if (xx > 0) {
			if (numtries > 0) {
				usleep(interval);
			}
			++numtries;
			err = lcb_observe(instance, &cookie, xx,
							  (const lcb_observe_cmd_t * const *)commands);
		} else {
			done = 1;
		}
	} while (!done && numtries < maxretry);

	efree(cmds);
	efree(commands);

	lcb_behavior_set_syncmode(instance, LCB_ASYNCHRONOUS);
	lcb_set_observe_callback(instance, org);

	if (!done) {
		return LCB_ETIMEDOUT;
	}

	return (err == LCB_SUCCESS) ? cookie.error : err;
}
예제 #10
0
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);
	}
}
예제 #11
0
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);
}