Exemplo n.º 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));
	}
}
Exemplo n.º 2
0
static void do_memcached_flush(INTERNAL_FUNCTION_PARAMETERS,
							   int oo,
							   php_couchbase_res *res)
{
	lcb_error_t retval;
	lcb_error_t cberr = LCB_SUCCESS;
	php_couchbase_ctx *ctx;
	lcb_flush_cmd_t cmd;
	const lcb_flush_cmd_t *const commands[] = { &cmd };
	lcb_t instance;

	instance = res->handle;

	memset(&cmd, 0, sizeof(cmd));
	lcb_set_flush_callback(instance, memcached_flush_callback);
	retval = lcb_flush(instance, (const void *)&cberr, 1, commands);

	if (retval == LCB_SUCCESS) {
		retval = cberr;
	}
	res->rc = retval;

	if (retval == LCB_SUCCESS) {
		RETURN_TRUE;
	} else {
		char errmsg[256];
		sprintf(errmsg, "Failed to flush bucket: %s",
				lcb_strerror(instance, retval));
		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
							   cb_lcb_exception, errmsg);
	}
}
Exemplo n.º 3
0
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);
	}
}
Exemplo n.º 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));
	}
}
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);
}
Exemplo n.º 7
0
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);
            }
        }
    }
}
Exemplo n.º 8
0
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);
}
Exemplo n.º 9
0
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);
	}
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
0
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);
}
Exemplo n.º 12
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));
	}
}
Exemplo n.º 13
0
PHP_COUCHBASE_LOCAL
void php_couchbase_get_delayed_impl(INTERNAL_FUNCTION_PARAMETERS, int oo) /* {{{ */
{
	zval *res, *akeys;
	long with_cas = 0;
	lcb_time_t exp = {0};
	long expiry = 0;
	zend_bool lock = 0;
	int argflags = PHP_COUCHBASE_ARG_F_ASYNC;
	php_couchbase_res *couchbase_res;

#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2

	zend_fcall_info fci = {0};
	zend_fcall_info_cache fci_cache = {0};

	if (oo) {
		argflags |= PHP_COUCHBASE_ARG_F_OO;
	} else {
		argflags |= PHP_COUCHBASE_ARG_F_FUNCTIONAL;
	}

	PHP_COUCHBASE_GET_PARAMS_WITH_ZV(res, couchbase_res, argflags,
									 "a|lf!lb",
									 &akeys, &with_cas, &fci, &fci_cache, &expiry, &lock);

#else
	if (oo) {
		argflags |= PHP_COUCHBASE_ARG_F_OO;
	} else {
		argflags |= PHP_COUCHBASE_ARG_F_FUNCTIONAL;
	}

	zval *callback = NULL;
	PHP_COUCHBASE_GET_PARAMS_WITH_ZV(res, couchbase_res, argflags,
									 "a|lzlb", &akeys, &with_cas, &callback, &expiry, &lock);

	if (callback && Z_TYPE_P(callback) != IS_NULL
			&& !zend_is_callable(callback, 0, NULL)) {
		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
							   cb_exception,
							   "third argument is expected to be a valid callback");
		return;
	}
#endif
	{
		zval **ppzval;
		lcb_error_t retval;
		php_couchbase_ctx *ctx;
		char **keys;
		long nkey, *klens, i;

		nkey = zend_hash_num_elements(Z_ARRVAL_P(akeys));
		keys = ecalloc(nkey, sizeof(char *));
		klens = ecalloc(nkey, sizeof(long));

		for (i = 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)), i++) {
			if (zend_hash_get_current_data(Z_ARRVAL_P(akeys), (void **)&ppzval) == FAILURE) {
				nkey--;
				continue;
			}

			if (IS_ARRAY != Z_TYPE_PP(ppzval)) {
				convert_to_string_ex(ppzval);
			}

			if (!Z_STRLEN_PP(ppzval)) {
				nkey--;
				continue;
			}

			if (couchbase_res->prefix_key_len) {
				klens[i] = spprintf(&(keys[i]), 0, "%s_%s", couchbase_res->prefix_key, Z_STRVAL_PP(ppzval));
			} else {
				keys[i] = Z_STRVAL_PP(ppzval);
				klens[i] = Z_STRLEN_PP(ppzval);
			}
		}

		if (!nkey) {
			efree(keys);
			efree(klens);
			return;
		}

		couchbase_res->seqno += nkey;
		ctx = ecalloc(1, sizeof(php_couchbase_ctx));
		ctx->res = couchbase_res;
		ctx->flags = with_cas;

		{
			lcb_get_cmd_t **commands = ecalloc(nkey, sizeof(lcb_get_cmd_t *));
			int ii;

			if (expiry) {
				exp = pcbc_check_expiry(expiry);
			}

			for (ii = 0; ii < nkey; ++ii) {
				lcb_get_cmd_t *cmd = ecalloc(1, sizeof(lcb_get_cmd_t));
				commands[ii] = cmd;
				cmd->v.v0.key = keys[ii];
				cmd->v.v0.nkey = klens[ii];
				cmd->v.v0.lock = (int)lock;
				cmd->v.v0.exptime = exp; /* NB: this assumes that sizeof(lcb_time_t) == sizeof(long) */
			}

			retval = lcb_get(couchbase_res->handle, ctx,
							 nkey, (const lcb_get_cmd_t * const *)commands);
			for (ii = 0; ii < nkey; ++ii) {
				efree(commands[ii]);
			}
			efree(commands);
		}

		if (LCB_SUCCESS != retval) {
			if (couchbase_res->prefix_key_len) {
				int i;
				for (i = 0; i < nkey; i++) {
					efree(keys[i]);
				}
			}
			efree(keys);
			efree(klens);
			efree(ctx);
			couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
								   cb_lcb_exception,
								   "Failed to schedule delayed get request: %s",
								   lcb_strerror(couchbase_res->handle, retval));
			return;
		}
		couchbase_res->async = 1;
		couchbase_res->async_ctx = ctx;
		if (couchbase_res->prefix_key_len) {
			int i;
			for (i = 0; i < nkey; i++) {
				efree(keys[i]);
			}
		}
		efree(keys);
		efree(klens);
		if (
#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2
			fci.size
#else
			callback
#endif
		) {
			zval *result, **ppzval, *retval_ptr = NULL;
			zval **params[2];

			MAKE_STD_ZVAL(result);
			array_init(result);
			ctx->rv = result;
			pcbc_start_loop(couchbase_res);
			couchbase_res->async = 0;
			for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(result));
					zend_hash_has_more_elements(Z_ARRVAL_P(result)) == SUCCESS;
					zend_hash_move_forward(Z_ARRVAL_P(result))) {
				if (zend_hash_get_current_data(Z_ARRVAL_P(result), (void **)&ppzval) == FAILURE) {
					continue;
				}

				params[0] = &res;
				params[1] = ppzval;
#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2
				fci.retval_ptr_ptr = &retval_ptr;
				fci.param_count = 2;
				fci.params = params;
				zend_call_function(&fci, &fci_cache TSRMLS_CC);
#else
				call_user_function_ex(EG(function_table), NULL, callback, &retval_ptr, 2, params, 0, NULL TSRMLS_CC);
#endif
				if (retval_ptr != NULL) {
					zval_ptr_dtor(&retval_ptr);
				}
			}
			zval_ptr_dtor(&result);
			efree(ctx);
		}
	}
	RETURN_TRUE;
}
Exemplo n.º 14
0
PHP_COUCHBASE_LOCAL
void php_couchbase_get_impl(INTERNAL_FUNCTION_PARAMETERS,
							int multi,
							int oo,
							int lock,
							int touch)
{
	char *key, **keys;
	long *klens, klen = 0;
	int	 nkey = 0;
	long flag = 0;
	lcb_time_t exp = {0};
	long expiry = 0;
	zval *res, *cas_token = NULL;
	int argflags;
	lcb_error_t retval;
	php_couchbase_res *couchbase_res;
	php_couchbase_ctx *ctx;

	argflags = oo ? PHP_COUCHBASE_ARG_F_OO : PHP_COUCHBASE_ARG_F_FUNCTIONAL;

	if (multi) {
		zval *akeys;
		zval **ppzval;
		zend_bool preserve_order;
		int i;

		if (lock) {
			PHP_COUCHBASE_GET_PARAMS_WITH_ZV(res, couchbase_res, argflags,
											 "az|ll",
											 &akeys, &cas_token,
											 &flag, &expiry);
		} else if (touch) {
			PHP_COUCHBASE_GET_PARAMS_WITH_ZV(res, couchbase_res, argflags,
											 "al|z",
											 &akeys, &expiry, &cas_token);
		} else {
			PHP_COUCHBASE_GET_PARAMS_WITH_ZV(res, couchbase_res, argflags,
											 "a|zl",
											 &akeys, &cas_token, &flag);
		}

		nkey = zend_hash_num_elements(Z_ARRVAL_P(akeys));
		keys = ecalloc(nkey, sizeof(char *));
		klens = ecalloc(nkey, sizeof(long));
		preserve_order = (flag & COUCHBASE_GET_PRESERVE_ORDER);

		array_init(return_value);

		for (i = 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)), i++) {
			if (zend_hash_get_current_data(Z_ARRVAL_P(akeys), (void **)&ppzval) == FAILURE) {
				nkey--;
				continue;
			}

			if (IS_ARRAY != Z_TYPE_PP(ppzval)) {
				convert_to_string_ex(ppzval);
			}

			if (!Z_STRLEN_PP(ppzval)) {
				nkey--;
				continue;
			}

			if (couchbase_res->prefix_key_len) {
				klens[i] = spprintf(&(keys[i]), 0, "%s_%s", couchbase_res->prefix_key, Z_STRVAL_PP(ppzval));
			} else {
				keys[i] = Z_STRVAL_PP(ppzval);
				klens[i] = Z_STRLEN_PP(ppzval);
			}

			if (preserve_order) {
				add_assoc_null_ex(return_value, keys[i], klens[i] + 1);
			}
		}

		if (!nkey) {
			efree(keys);
			efree(klens);
			return;
		}

		if (cas_token && IS_ARRAY != Z_TYPE_P(cas_token)) {
			zval_dtor(cas_token);
			array_init(cas_token);
		}
	} else {
		if (lock) {
			PHP_COUCHBASE_GET_PARAMS_WITH_ZV(res, couchbase_res, argflags,
											 "sz|l", &key, &klen,
											 &cas_token, &expiry);
		} else if (touch) {
			PHP_COUCHBASE_GET_PARAMS_WITH_ZV(res, couchbase_res, argflags,
											 "sl|z", &key, &klen, &expiry,
											 &cas_token);
		} else {
			PHP_COUCHBASE_GET_PARAMS_WITH_ZV(res, couchbase_res, argflags,
											 "s|z", &key, &klen,
											 &cas_token);
		}

		if (!klen) {
			return;
		}

		nkey = 1;
		if (couchbase_res->prefix_key_len) {
			klen = spprintf(&key, 0, "%s_%s", couchbase_res->prefix_key, key);
		}
		keys = &key;
		klens = &klen;

		if (cas_token) {
			zval_dtor(cas_token);
			ZVAL_NULL(cas_token);
		}
	}
	{
		lcb_get_cmd_t **commands = ecalloc(nkey, sizeof(lcb_get_cmd_t *));
		int ii;

		if (expiry) {
			exp = pcbc_check_expiry(expiry);
		}

		for (ii = 0; ii < nkey; ++ii) {
			lcb_get_cmd_t *cmd = ecalloc(1, sizeof(lcb_get_cmd_t));
			commands[ii] = cmd;
			cmd->v.v0.key = keys[ii];
			cmd->v.v0.nkey = klens[ii];
			cmd->v.v0.lock = (int)lock;
			cmd->v.v0.exptime = exp; /* NB: this assumes sizeof(lcb_time_t) == sizeof(long) */
		}

		ctx = ecalloc(1, sizeof(php_couchbase_ctx));
		ctx->res = couchbase_res;
		ctx->rv	 = return_value;
		ctx->cas = cas_token;

		retval = lcb_get(couchbase_res->handle, ctx,
						 nkey, (const lcb_get_cmd_t * const *)commands);
		for (ii = 0; ii < nkey; ++ii) {
			efree(commands[ii]);
		}
		efree(commands);

		if (LCB_SUCCESS != retval) {
			if (couchbase_res->prefix_key_len) {
				int i;
				for (i = 0; i < nkey; i++) {
					efree(keys[i]);
				}
			}
			if (multi) {
				efree(keys);
				efree(klens);
				zval_dtor(return_value);
			}
			efree(ctx);

			couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
								   cb_lcb_exception,
								   "Failed to schedule get request: %s",
								   lcb_strerror(couchbase_res->handle, retval));
			return;
		}

		couchbase_res->seqno += nkey;
		pcbc_start_loop(couchbase_res);
		if (LCB_SUCCESS != ctx->res->rc) {
			if (LCB_KEY_ENOENT != ctx->res->rc) {
				couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
									   cb_lcb_exception,
									   "Failed to get a value from server: %s",
									   lcb_strerror(couchbase_res->handle,
													ctx->res->rc));
			}
		}
		efree(ctx);
		if (couchbase_res->prefix_key_len) {
			int i;
			for (i = 0; i < nkey; i++) {
				efree(keys[i]);
			}
		}
		if (multi) {
			efree(keys);
			efree(klens);
		}
	}
}
Exemplo n.º 15
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);
	}
}
Exemplo n.º 16
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);
}
Exemplo n.º 17
0
static void do_rest_flush(INTERNAL_FUNCTION_PARAMETERS,
						  int oo,
						  php_couchbase_res *res)
{
	struct flush_ctx ctx;
	lcb_error_t rc;
	lcb_http_cmd_t cmd;
	lcb_t instance;
	char *path;
	lcb_http_complete_callback old;

	instance = res->handle;
	path = ecalloc(strlen(res->bucket) + 80, 1);
	sprintf(path, "/pools/default/buckets/%s/controller/doFlush",
			res->bucket);

	memset(&ctx, 0, sizeof(ctx));
	memset(&cmd, 0, sizeof(cmd));
	cmd.v.v0.path = path;
	cmd.v.v0.npath = strlen(path);
	cmd.v.v0.method = LCB_HTTP_METHOD_POST;
	cmd.v.v0.content_type = "application/x-www-form-urlencoded";

	old = lcb_set_http_complete_callback(instance, rest_flush_callback);
	rc = lcb_make_http_request(instance, &ctx, LCB_HTTP_TYPE_MANAGEMENT,
							   &cmd, NULL);
	old = lcb_set_http_complete_callback(instance, old);

	efree(path);
	if (rc == LCB_SUCCESS) {
		rc = ctx.error;
	}
	res->rc = rc;

	if (rc != LCB_SUCCESS) {
		/* An error occured occurred on libcouchbase level */
		if (ctx.payload) {
			efree(ctx.payload);
		}

		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
							   cb_lcb_exception, "Failed to flush bucket: %s",
							   lcb_strerror(instance, rc));
		return;
	}

	switch (ctx.status)  {
	case LCB_HTTP_STATUS_OK:
	case LCB_HTTP_STATUS_ACCEPTED:
		efree(ctx.payload);
		RETURN_TRUE;

	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);
		}
	}

	if (ctx.payload != NULL) {
		efree(ctx.payload);
	}
}
Exemplo n.º 18
0
PHP_COUCHBASE_LOCAL
void php_couchbase_store_impl_oo(INTERNAL_FUNCTION_PARAMETERS, lcb_storage_t op)
{
	lcb_error_t retval;
	php_couchbase_res *couchbase_res;
	php_couchbase_ctx *ctx;
	time_t exp = {0};
	unsigned int flags = 0;
	char *cas = NULL;
	char *payload;
	size_t payload_len = 0;
	unsigned long long cas_v = 0;
	long expire = 0;
	long replicate_to = 0;
	long persist_to = 0;
	long cas_len = 0;
	char *key = NULL;
	zval *value;
	long klen = 0;
	lcb_store_cmd_t cmd;
	const lcb_store_cmd_t *const commands[] = { &cmd };

	if (op == LCB_ADD) {
		PHP_COUCHBASE_GET_PARAMS(couchbase_res, PHP_COUCHBASE_ARG_F_OO,
								 "sz|lll", &key, &klen, &value, &expire,
								 &persist_to, &replicate_to);
	} else {
		PHP_COUCHBASE_GET_PARAMS(couchbase_res, PHP_COUCHBASE_ARG_F_OO,
								 "sz|lsll", &key, &klen, &value, &expire,
								 &cas, &cas_len, &persist_to, &replicate_to);
	}

	if (pcbc_check_expiry(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1,
						  expire, &exp) == -1) {
		/* Incorrect expiry time */
		return;
	}

	if (validate_simple_observe_clause(couchbase_res->handle,
									   persist_to,
									   replicate_to TSRMLS_CC) == -1) {
		/* Exception already thrown */
		return;
	}

	if (!klen) {
		zend_throw_exception(cb_illegal_key_exception,
							 "Failed to schedule set request: Empty key",
							 0 TSRMLS_CC);
		return ;
	}

	if (cas) {
		char *e;
		cas_v = (lcb_cas_t)strtoull(cas, &e, 10);
		if (*e != '\0') {
			couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1,
								   cb_illegal_key_exception,
								   "Invalid CAS specified");
			return;
		}
	}

	payload = php_couchbase_zval_to_payload(value, &payload_len, &flags,
											couchbase_res->serializer,
											couchbase_res->compressor
											TSRMLS_CC);
	if (payload == NULL) {
		/* ?? I guess we should throw an exception here? */
		RETURN_FALSE;
	}

	if (couchbase_res->prefix_key_len) {
		klen = spprintf(&key, 0, "%s_%s", couchbase_res->prefix_key, key);
	}

	ctx = ecalloc(1, sizeof(php_couchbase_ctx));
	ctx->res = couchbase_res;
	ctx->rv = return_value;
	couchbase_res->seqno += 1;

	memset(&cmd, 0, sizeof(cmd));
	cmd.v.v0.operation = op;
	cmd.v.v0.key = key;
	cmd.v.v0.nkey = klen;
	cmd.v.v0.bytes = payload;
	cmd.v.v0.nbytes = payload_len;
	cmd.v.v0.flags = flags;
	cmd.v.v0.exptime = exp;
	cmd.v.v0.cas = (uint64_t)cas_v;

	retval = lcb_store(couchbase_res->handle, ctx, 1, commands);

	efree(payload);
	if (couchbase_res->prefix_key_len) {
		efree(key);
	}

	if (retval != LCB_SUCCESS) {
		char errmsg[256];
		efree(ctx);
		sprintf(errmsg, "Failed to schedule set request: %s",
				lcb_strerror(couchbase_res->handle, retval));
		zend_throw_exception(cb_lcb_exception, errmsg, 0 TSRMLS_CC);
		return ;
	}

	pcbc_start_loop(couchbase_res);
	if (LCB_SUCCESS != ctx->res->rc) {
		RETVAL_FALSE;
		switch (op) {
		case LCB_ADD:
			if (LCB_KEY_EEXISTS == ctx->res->rc) {
				break;
			}
		case LCB_APPEND:
		case LCB_PREPEND:
			if (LCB_NOT_STORED == ctx->res->rc) {
				break;
			}
		case LCB_REPLACE:
		case LCB_SET:
			if (LCB_KEY_ENOENT == ctx->res->rc) {
				break;
			}
			if (cas && LCB_KEY_EEXISTS == ctx->res->rc) {
				break;
			}
		default: {
			char errmsg[256];
			sprintf(errmsg, "Failed to store value to server: %s",
					lcb_strerror(couchbase_res->handle, ctx->res->rc));
			zend_throw_exception(cb_lcb_exception, errmsg, 0 TSRMLS_CC);
		}

		break;
		}
	} else {
		/*
		 * The item was stored successfully. Did the user want to wait until
		 * it was persisted/replicated?
		 */
		if (persist_to != 0 || replicate_to != 0) {
			struct observe_entry entry;
			memset(&entry, 0, sizeof(entry));
			entry.key = key;
			entry.nkey = klen;
			entry.cas = strtoull(Z_STRVAL_P(return_value), 0, 10);

			retval = simple_observe(couchbase_res->handle, &entry, 1,
									persist_to, replicate_to);
			couchbase_res->rc = retval;
			if (retval != LCB_SUCCESS) {
				if (retval == LCB_ETIMEDOUT) {
					zend_throw_exception(cb_timeout_exception,
										 "Timed out waiting for the objects to persist",
										 0 TSRMLS_CC);
				} else {
					char errmsg[512];
					snprintf(errmsg, sizeof(errmsg), "observe failed for: %s",
							 klen, key, lcb_strerror(couchbase_res->handle,
													 retval));
					zend_throw_exception(cb_lcb_exception, errmsg, 0 TSRMLS_CC);
				}
			} else {
				/* @todo checkfor timeout!!! */
				if (entry.mutated) {
					zend_throw_exception(cb_key_mutated_exception,
										 "The document was mutated",
										 0 TSRMLS_CC);
				}
			}
		}
	}
	efree(ctx);
}