mirror of
https://github.com/phpredis/phpredis.git
synced 2026-06-19 07:35:31 +00:00
Introduce new RedisCmd based command construction
* Introduce a new `RedisCmd` struct to dynamically append RESP arguments such that we don't have to precalculate the number of arguments the command will have up front. Additionally the new `RedisCmd allows both a `void *` context pointer but also can attach a `void (*ctx_dtor)(void*)` destructor so we are still able to clean up any allocated context when commands fail. This moves the context cleanup out of every individual reply handler and into the generic processing wrappers. * Create a small group of `resp_str` helper functions for lower level concatination of RESP protocol data over the wire. * Lots of small modernization of the codebase such as using `zend_string*` instead of (`char *`, `size_t`) pairs. * Greatly simplify `crosslot` handling logic
This commit is contained in:
committed by
Michael Grunder
parent
640ed13fcc
commit
2c5ef19257
@@ -26,3 +26,4 @@ doctum.phar
|
||||
run-tests.php
|
||||
vendor/
|
||||
.agents.md
|
||||
.codex
|
||||
|
||||
+266
-218
@@ -10,6 +10,8 @@
|
||||
extern zend_class_entry *redis_cluster_exception_ce;
|
||||
int le_cluster_slot_cache;
|
||||
|
||||
extern RedisCmdCtx redis_empty_ctx;
|
||||
|
||||
/* Debugging methods/
|
||||
static void cluster_dump_nodes(redisCluster *c) {
|
||||
redisClusterNode *p;
|
||||
@@ -90,17 +92,17 @@ static void dump_reply(clusterReply *reply, int indent) {
|
||||
|
||||
/* MULTI BULK processing callbacks */
|
||||
static int mbulk_resp_loop(RedisSock *redis_sock, zval *z_result,
|
||||
long long count, void *ctx);
|
||||
long long count, RedisCmdCtx ctx);
|
||||
static int mbulk_resp_loop_raw(RedisSock *redis_sock, zval *z_result,
|
||||
long long count, void *ctx);
|
||||
long long count, RedisCmdCtx ctx);
|
||||
static int mbulk_resp_loop_zipstr(RedisSock *redis_sock, zval *z_result,
|
||||
long long count, void *ctx);
|
||||
long long count, RedisCmdCtx ctx);
|
||||
static int mbulk_resp_loop_dbl(RedisSock *redis_sock, zval *z_result,
|
||||
long long count, void *ctx);
|
||||
long long count, RedisCmdCtx ctx);
|
||||
static int mbulk_resp_loop_zipdbl(RedisSock *redis_sock, zval *z_result,
|
||||
long long count, void *ctx);
|
||||
long long count, RedisCmdCtx ctx);
|
||||
static int mbulk_resp_loop_assoc(RedisSock *redis_sock, zval *z_result,
|
||||
long long count, void *ctx);
|
||||
long long count, RedisCmdCtx ctx);
|
||||
|
||||
|
||||
|
||||
@@ -457,9 +459,7 @@ int cluster_dist_add_key(redisCluster *c, HashTable *ht, char *key,
|
||||
}
|
||||
|
||||
/* Provided a clusterKeyVal, add a value */
|
||||
void cluster_dist_add_val(redisCluster *c, clusterKeyVal *kv, zval *z_val
|
||||
)
|
||||
{
|
||||
void cluster_dist_add_val(redisCluster *c, clusterKeyVal *kv, zval *z_val) {
|
||||
char *val;
|
||||
size_t val_len;
|
||||
int val_free;
|
||||
@@ -475,21 +475,24 @@ void cluster_dist_add_val(redisCluster *c, clusterKeyVal *kv, zval *z_val
|
||||
|
||||
/* Free allocated memory for a clusterMultiCmd */
|
||||
void cluster_multi_free(clusterMultiCmd *mc) {
|
||||
efree(mc->cmd.c);
|
||||
efree(mc->args.c);
|
||||
redis_cmd_free(mc->cmd);
|
||||
}
|
||||
|
||||
/* Add an argument to a clusterMultiCmd */
|
||||
void cluster_multi_add(clusterMultiCmd *mc, char *data, int data_len) {
|
||||
if (mc->cmd == NULL) {
|
||||
mc->cmd = redis_cmd_create(NULL, mc->kw, mc->kw_len);
|
||||
}
|
||||
|
||||
mc->argc++;
|
||||
redis_cmd_append_sstr(&(mc->args), data, data_len);
|
||||
redis_cmd_cat_str(mc->cmd, data, data_len);
|
||||
}
|
||||
|
||||
/* Finalize a clusterMultiCmd by constructing the whole thing */
|
||||
/* Finalize a clusterMultiCmd */
|
||||
void cluster_multi_fini(clusterMultiCmd *mc) {
|
||||
mc->cmd.len = 0;
|
||||
redis_cmd_init_sstr(&(mc->cmd), mc->argc, mc->kw, mc->kw_len);
|
||||
smart_string_appendl(&(mc->cmd), mc->args.c, mc->args.len);
|
||||
if (mc->cmd == NULL) {
|
||||
mc->cmd = redis_cmd_create(NULL, mc->kw, mc->kw_len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set our last error string encountered */
|
||||
@@ -653,7 +656,7 @@ cluster_node_create(redisCluster *c, char *host, size_t host_len,
|
||||
zend_llist_init(&node->slots, sizeof(redisSlotRange), NULL, 0);
|
||||
|
||||
// Attach socket
|
||||
node->sock = redis_sock_create(host, host_len, port,
|
||||
node->sock = redis_sock_create(REDIS_SOCK_CLUSTER, host, host_len, port,
|
||||
c->flags->timeout, c->flags->read_timeout,
|
||||
c->flags->persistent, NULL, 0);
|
||||
|
||||
@@ -876,6 +879,7 @@ PHP_REDIS_API redisCluster *cluster_create(double timeout, double read_timeout,
|
||||
|
||||
/* Initialize flags and settings */
|
||||
c->flags = ecalloc(1, sizeof(RedisSock));
|
||||
c->flags->type = REDIS_SOCK_CLUSTER;
|
||||
c->flags->timeout = timeout;
|
||||
c->flags->read_timeout = read_timeout;
|
||||
c->flags->persistent = persistent;
|
||||
@@ -1052,9 +1056,10 @@ void cluster_init_cache(redisCluster *c, redisCachedCluster *cc) {
|
||||
keylen = snprintf(key, sizeof(key), "%s:%u", ZSTR_VAL(cm->host.addr), cm->host.port);
|
||||
|
||||
/* Create socket */
|
||||
sock = redis_sock_create(ZSTR_VAL(cm->host.addr), ZSTR_LEN(cm->host.addr), cm->host.port,
|
||||
c->flags->timeout, c->flags->read_timeout, c->flags->persistent,
|
||||
NULL, 0);
|
||||
sock = redis_sock_create(REDIS_SOCK_CLUSTER, ZSTR_VAL(cm->host.addr),
|
||||
ZSTR_LEN(cm->host.addr), cm->host.port,
|
||||
c->flags->timeout, c->flags->read_timeout,
|
||||
c->flags->persistent, NULL, 0);
|
||||
|
||||
/* Stream context */
|
||||
redis_sock_set_context(sock, c->flags->context);
|
||||
@@ -1108,8 +1113,9 @@ cluster_init_seeds(redisCluster *c, zend_string **seeds, uint32_t nseeds)
|
||||
ZEND_ASSERT(sep != NULL);
|
||||
|
||||
// Allocate a structure for this seed
|
||||
sock = redis_sock_create(seed, sep - seed, atoi(sep + 1),
|
||||
c->flags->timeout, c->flags->read_timeout,
|
||||
sock = redis_sock_create(REDIS_SOCK_CLUSTER, seed, sep - seed,
|
||||
atoi(sep + 1), c->flags->timeout,
|
||||
c->flags->read_timeout,
|
||||
c->flags->persistent, NULL, 0);
|
||||
|
||||
/* Credentials and context */
|
||||
@@ -1578,8 +1584,9 @@ PHP_REDIS_API short cluster_find_slot(redisCluster *c, const char *host,
|
||||
}
|
||||
|
||||
/* Send a command to a specific slot */
|
||||
PHP_REDIS_API int cluster_send_slot(redisCluster *c, short slot, char *cmd,
|
||||
int cmd_len, REDIS_REPLY_TYPE rtype)
|
||||
PHP_REDIS_API int
|
||||
cluster_send_slot(redisCluster *c, short slot, const char *cmd, int cmd_len,
|
||||
REDIS_REPLY_TYPE rtype)
|
||||
{
|
||||
/* Point our cluster to this slot and it's socket */
|
||||
c->cmd_slot = slot;
|
||||
@@ -1729,7 +1736,7 @@ PHP_REDIS_API short cluster_send_command(redisCluster *c, short slot, const char
|
||||
|
||||
/* RAW bulk response handler */
|
||||
PHP_REDIS_API void cluster_bulk_raw_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx)
|
||||
redisCluster *c, RedisCmdCtx ctx)
|
||||
{
|
||||
char *resp;
|
||||
|
||||
@@ -1751,7 +1758,8 @@ PHP_REDIS_API void cluster_bulk_raw_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_single_line_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
cluster_single_line_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
char *p;
|
||||
|
||||
@@ -1789,7 +1797,7 @@ static int cluster_bulk_resp_to_zval(redisCluster *c, zval *zdst) {
|
||||
|
||||
/* BULK response handler */
|
||||
PHP_REDIS_API void cluster_bulk_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
zval zret;
|
||||
|
||||
@@ -1804,7 +1812,7 @@ PHP_REDIS_API void cluster_bulk_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_bulk_withmeta_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
zval zbulk, zmeta;
|
||||
|
||||
@@ -1821,7 +1829,7 @@ cluster_bulk_withmeta_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
|
||||
/* Bulk response where we expect a double */
|
||||
PHP_REDIS_API void cluster_dbl_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
char *resp;
|
||||
double dbl;
|
||||
@@ -1843,7 +1851,7 @@ PHP_REDIS_API void cluster_dbl_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *
|
||||
/* A boolean response. If we get here, we've consumed the '+' reply
|
||||
* type and will now just verify we can read the OK */
|
||||
PHP_REDIS_API void cluster_bool_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
// Check that we have +OK
|
||||
if (c->reply_type != TYPE_LINE || c->reply_len != 2 ||
|
||||
@@ -1857,7 +1865,7 @@ PHP_REDIS_API void cluster_bool_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster
|
||||
|
||||
/* Boolean response, specialized for PING */
|
||||
PHP_REDIS_API void cluster_ping_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
if (c->reply_type != TYPE_LINE || c->reply_len != 4 ||
|
||||
memcmp(c->line_reply,"PONG",sizeof("PONG")-1))
|
||||
@@ -1869,55 +1877,42 @@ PHP_REDIS_API void cluster_ping_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_hrandfield_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
cluster_hrandfield_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
cluster_bulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
} else if (ctx == PHPREDIS_CTX_PTR) {
|
||||
cluster_mbulk_raw_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
} else if (ctx == PHPREDIS_CTX_PTR + 1) {
|
||||
return cluster_mbulk_zipdbl_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
if (ctx.ptr == NULL) {
|
||||
cluster_bulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, redis_empty_ctx);
|
||||
} else if (ctx.ptr == PHPREDIS_CTX_PTR) {
|
||||
cluster_mbulk_raw_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
redis_empty_ctx);
|
||||
} else if (ctx.ptr == PHPREDIS_CTX_PTR + 1) {
|
||||
return cluster_mbulk_zipdbl_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
redis_empty_ctx);
|
||||
} else {
|
||||
ZEND_ASSERT(!"memory corruption?");
|
||||
}
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_pop_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
cluster_pop_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, RedisCmdCtx ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
cluster_bulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
} else if (ctx == PHPREDIS_CTX_PTR) {
|
||||
cluster_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
if (ctx.ptr == NULL) {
|
||||
cluster_bulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, redis_empty_ctx);
|
||||
} else if (ctx.ptr == PHPREDIS_CTX_PTR) {
|
||||
cluster_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, redis_empty_ctx);
|
||||
} else {
|
||||
ZEND_ASSERT(!"memory corruption?");
|
||||
}
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_lpos_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
cluster_lpos_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, RedisCmdCtx ctx)
|
||||
{
|
||||
zval zret = {0};
|
||||
|
||||
c->cmd_sock->null_mbulk_as_null = c->flags->null_mbulk_as_null;
|
||||
if (redis_read_lpos_response(&zret, c->cmd_sock, c->reply_type, c->reply_len, ctx) < 0) {
|
||||
ZVAL_FALSE(&zret);
|
||||
}
|
||||
|
||||
if (CLUSTER_IS_ATOMIC(c)) {
|
||||
RETVAL_ZVAL(&zret, 0, 1);
|
||||
} else {
|
||||
add_next_index_zval(&c->multi_resp, &zret);
|
||||
}
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_geosearch_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
zval zret = {0};
|
||||
|
||||
c->cmd_sock->null_mbulk_as_null = c->flags->null_mbulk_as_null;
|
||||
if (c->reply_type != TYPE_MULTIBULK ||
|
||||
redis_read_geosearch_response(&zret, c->cmd_sock, c->reply_len, ctx != NULL) < 0)
|
||||
if (redis_read_lpos_response(&zret, c->cmd_sock, c->reply_type,
|
||||
c->reply_len, ctx) < 0)
|
||||
{
|
||||
ZVAL_FALSE(&zret);
|
||||
}
|
||||
@@ -1930,76 +1925,111 @@ cluster_geosearch_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_zdiff_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
if (ctx == NULL) {
|
||||
cluster_mbulk_raw_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
} else if (ctx == PHPREDIS_CTX_PTR) {
|
||||
cluster_mbulk_zipdbl_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
cluster_geosearch_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx) {
|
||||
zval zret = {0};
|
||||
|
||||
c->cmd_sock->null_mbulk_as_null = c->flags->null_mbulk_as_null;
|
||||
if (c->reply_type != TYPE_MULTIBULK ||
|
||||
redis_read_geosearch_response(&zret, c->cmd_sock, c->reply_len,
|
||||
ctx.ptr != NULL) < 0)
|
||||
{
|
||||
ZVAL_FALSE(&zret);
|
||||
}
|
||||
|
||||
if (CLUSTER_IS_ATOMIC(c)) {
|
||||
RETVAL_ZVAL(&zret, 0, 1);
|
||||
} else {
|
||||
ZEND_ASSERT(!"memory corruption?");
|
||||
add_next_index_zval(&c->multi_resp, &zret);
|
||||
}
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_zadd_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
ZEND_ASSERT(ctx == NULL || ctx == PHPREDIS_CTX_PTR);
|
||||
|
||||
if (ctx == NULL) {
|
||||
cluster_long_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
} else {
|
||||
cluster_dbl_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_zrandmember_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
if (ctx == NULL) {
|
||||
cluster_bulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
} else if (ctx == PHPREDIS_CTX_PTR) {
|
||||
cluster_mbulk_raw_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
} else if (ctx == PHPREDIS_CTX_PTR + 1) {
|
||||
cluster_mbulk_zipdbl_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
} else {
|
||||
ZEND_ASSERT(!"memory corruption?");
|
||||
}
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_randmember_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
if (ctx == NULL) {
|
||||
cluster_bulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
} else if (ctx == PHPREDIS_CTX_PTR) {
|
||||
cluster_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
} else {
|
||||
ZEND_ASSERT(!"memory corruption?");
|
||||
}
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_object_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
ZEND_ASSERT(ctx == PHPREDIS_CTX_PTR || ctx == PHPREDIS_CTX_PTR + 1);
|
||||
|
||||
if (ctx == PHPREDIS_CTX_PTR) {
|
||||
cluster_long_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
} else {
|
||||
cluster_bulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_set_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
cluster_zdiff_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
cluster_bool_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
if (ctx.ptr == NULL) {
|
||||
cluster_mbulk_raw_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
redis_empty_ctx);
|
||||
} else if (ctx.ptr == PHPREDIS_CTX_PTR) {
|
||||
cluster_mbulk_zipdbl_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
redis_empty_ctx);
|
||||
} else {
|
||||
cluster_bulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
|
||||
ZEND_ASSERT(!"memory corruption?");
|
||||
}
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_zadd_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
ZEND_ASSERT(ctx.ptr == NULL || ctx.ptr == PHPREDIS_CTX_PTR);
|
||||
|
||||
if (ctx.ptr == NULL) {
|
||||
cluster_long_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, redis_empty_ctx);
|
||||
} else {
|
||||
cluster_dbl_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, redis_empty_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_zrandmember_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
if (ctx.ptr == NULL) {
|
||||
cluster_bulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
redis_empty_ctx);
|
||||
} else if (ctx.ptr == PHPREDIS_CTX_PTR) {
|
||||
cluster_mbulk_raw_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
redis_empty_ctx);
|
||||
} else if (ctx.ptr == PHPREDIS_CTX_PTR + 1) {
|
||||
cluster_mbulk_zipdbl_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
redis_empty_ctx);
|
||||
} else {
|
||||
ZEND_ASSERT(!"memory corruption?");
|
||||
}
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_randmember_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
if (ctx.ptr == NULL) {
|
||||
cluster_bulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, redis_empty_ctx);
|
||||
} else if (ctx.ptr == PHPREDIS_CTX_PTR) {
|
||||
cluster_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, redis_empty_ctx);
|
||||
} else {
|
||||
ZEND_ASSERT(!"memory corruption?");
|
||||
}
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_object_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
ZEND_ASSERT(ctx.ptr == PHPREDIS_CTX_PTR || ctx.ptr == PHPREDIS_CTX_PTR + 1);
|
||||
|
||||
if (ctx.ptr == PHPREDIS_CTX_PTR) {
|
||||
cluster_long_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, redis_empty_ctx);
|
||||
} else {
|
||||
cluster_bulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, redis_empty_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_set_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, RedisCmdCtx ctx)
|
||||
{
|
||||
if (ctx.ptr == NULL) {
|
||||
cluster_bool_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, redis_empty_ctx);
|
||||
} else {
|
||||
cluster_bulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, redis_empty_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* 1 or 0 response, for things like SETNX */
|
||||
PHP_REDIS_API void cluster_1_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
// Validate our reply type, and check for a zero
|
||||
if (c->reply_type != TYPE_INT || c->reply_len == 0) {
|
||||
@@ -2010,8 +2040,9 @@ PHP_REDIS_API void cluster_1_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
}
|
||||
|
||||
/* Generic integer response */
|
||||
PHP_REDIS_API void cluster_long_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
PHP_REDIS_API void
|
||||
cluster_long_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
if (c->reply_type != TYPE_INT) {
|
||||
CLUSTER_RETURN_FALSE(c);
|
||||
@@ -2020,8 +2051,9 @@ PHP_REDIS_API void cluster_long_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster
|
||||
}
|
||||
|
||||
/* TYPE response handler */
|
||||
PHP_REDIS_API void cluster_type_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
PHP_REDIS_API void
|
||||
cluster_type_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
// Make sure we got the right kind of response
|
||||
if (c->reply_type != TYPE_LINE) {
|
||||
@@ -2051,19 +2083,17 @@ PHP_REDIS_API void cluster_type_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster
|
||||
|
||||
/* SUBSCRIBE/PSCUBSCRIBE handler */
|
||||
PHP_REDIS_API void cluster_sub_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
subscribeContext *sctx = ctx;
|
||||
subscribeContext *sctx = ctx.ptr;
|
||||
zval z_tab, *z_tmp;
|
||||
int pull = 0;
|
||||
|
||||
|
||||
// Consume each MULTI BULK response (one per channel/pattern)
|
||||
while (sctx->argc--) {
|
||||
if (!cluster_zval_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
pull, mbulk_resp_loop_raw, &z_tab)
|
||||
) {
|
||||
efree(sctx);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
@@ -2071,7 +2101,6 @@ PHP_REDIS_API void cluster_sub_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *
|
||||
strcasecmp(Z_STRVAL_P(z_tmp), sctx->kw) != 0
|
||||
) {
|
||||
zval_ptr_dtor_nogc(&z_tab);
|
||||
efree(sctx);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
@@ -2153,27 +2182,27 @@ PHP_REDIS_API void cluster_sub_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *
|
||||
|
||||
// Cleanup
|
||||
zval_ptr_dtor_nogc(&z_tab);
|
||||
efree(sctx);
|
||||
|
||||
// Failure
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* UNSUBSCRIBE/PUNSUBSCRIBE */
|
||||
PHP_REDIS_API void cluster_unsub_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx)
|
||||
PHP_REDIS_API void
|
||||
cluster_unsub_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
subscribeContext *sctx = ctx;
|
||||
subscribeContext *sctx = ctx.ptr;
|
||||
zval z_tab = {0}, *z_chan, *z_flag;
|
||||
int pull = 0, argc = sctx->argc;
|
||||
|
||||
efree(sctx);
|
||||
array_init(return_value);
|
||||
|
||||
// Consume each response
|
||||
while (argc--) {
|
||||
// Fail if we didn't get an array or can't find index 1
|
||||
if (!cluster_zval_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, pull, mbulk_resp_loop_raw, &z_tab) ||
|
||||
if (!cluster_zval_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, pull,
|
||||
mbulk_resp_loop_raw, &z_tab) ||
|
||||
(z_chan = zend_hash_index_find(Z_ARRVAL(z_tab), 1)) == NULL
|
||||
) {
|
||||
zval_ptr_dtor_nogc(&z_tab);
|
||||
@@ -2247,7 +2276,7 @@ static void cluster_mbulk_variant_resp(clusterReply *r, int null_mbulk_as_null,
|
||||
* where we just map the replies from Redis type values to PHP ones directly. */
|
||||
static void
|
||||
cluster_variant_resp_generic(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
int status_strings, void *ctx)
|
||||
int status_strings, RedisCmdCtx ctx)
|
||||
{
|
||||
clusterReply *r;
|
||||
zval zv, *z_arr = &zv;
|
||||
@@ -2336,31 +2365,35 @@ cluster_variant_resp_generic(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_zrange_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
cluster_zrange_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
cluster_cb cb;
|
||||
|
||||
ZEND_ASSERT(ctx == NULL || ctx == PHPREDIS_CTX_PTR);
|
||||
ZEND_ASSERT(ctx.ptr == NULL || ctx.ptr == PHPREDIS_CTX_PTR);
|
||||
|
||||
cb = ctx ? cluster_mbulk_zipdbl_resp : cluster_mbulk_resp;
|
||||
cb = ctx.ptr ? cluster_mbulk_zipdbl_resp : cluster_mbulk_resp;
|
||||
|
||||
cb(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, ctx);
|
||||
}
|
||||
|
||||
PHP_REDIS_API void cluster_variant_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
PHP_REDIS_API void
|
||||
cluster_variant_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
cluster_variant_resp_generic(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, 0, ctx);
|
||||
}
|
||||
|
||||
PHP_REDIS_API void cluster_variant_raw_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
cluster_variant_resp_generic(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
c->flags->reply_literal, ctx);
|
||||
}
|
||||
|
||||
PHP_REDIS_API void cluster_variant_resp_strings(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
PHP_REDIS_API void
|
||||
cluster_variant_resp_strings(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
cluster_variant_resp_generic(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, 1, ctx);
|
||||
}
|
||||
@@ -2368,7 +2401,7 @@ PHP_REDIS_API void cluster_variant_resp_strings(INTERNAL_FUNCTION_PARAMETERS, re
|
||||
/* Generic MULTI BULK response processor */
|
||||
static void
|
||||
cluster_gen_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
zend_bool init_array, mbulk_cb cb, void *ctx)
|
||||
zend_bool init_array, mbulk_cb cb, RedisCmdCtx ctx)
|
||||
{
|
||||
zval z_result = {0};
|
||||
|
||||
@@ -2442,16 +2475,20 @@ cluster_scan_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
// Use the proper response callback depending on scan type
|
||||
switch(type) {
|
||||
case TYPE_SCAN:
|
||||
cluster_mbulk_raw_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU,c,NULL);
|
||||
cluster_mbulk_raw_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU,c,
|
||||
redis_empty_ctx);
|
||||
break;
|
||||
case TYPE_SSCAN:
|
||||
cluster_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU,c,NULL);
|
||||
cluster_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU,c,
|
||||
redis_empty_ctx);
|
||||
break;
|
||||
case TYPE_HSCAN:
|
||||
cluster_mbulk_zipstr_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU,c,NULL);
|
||||
cluster_mbulk_zipstr_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
redis_empty_ctx);
|
||||
break;
|
||||
case TYPE_ZSCAN:
|
||||
cluster_mbulk_zipdbl_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU,c,NULL);
|
||||
cluster_mbulk_zipdbl_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
redis_empty_ctx);
|
||||
break;
|
||||
default:
|
||||
return FAILURE;
|
||||
@@ -2463,7 +2500,7 @@ cluster_scan_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
|
||||
/* INFO response */
|
||||
PHP_REDIS_API void cluster_info_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
zval z_result;
|
||||
char *info;
|
||||
@@ -2488,7 +2525,7 @@ PHP_REDIS_API void cluster_info_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster
|
||||
|
||||
/* CLIENT LIST response */
|
||||
PHP_REDIS_API void cluster_client_list_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
char *info;
|
||||
zval z_result;
|
||||
@@ -2512,7 +2549,9 @@ PHP_REDIS_API void cluster_client_list_resp(INTERNAL_FUNCTION_PARAMETERS, redisC
|
||||
|
||||
/* XRANGE */
|
||||
PHP_REDIS_API void
|
||||
cluster_xrange_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
cluster_xrange_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
zval z_messages;
|
||||
|
||||
array_init(&z_messages);
|
||||
@@ -2534,7 +2573,9 @@ cluster_xrange_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
|
||||
/* XREAD */
|
||||
PHP_REDIS_API void
|
||||
cluster_xread_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
cluster_xread_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
zval z_streams;
|
||||
|
||||
c->cmd_sock->serializer = c->flags->serializer;
|
||||
@@ -2559,14 +2600,18 @@ cluster_xread_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
|
||||
/* XCLAIM */
|
||||
PHP_REDIS_API void
|
||||
cluster_xclaim_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
cluster_xclaim_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
zval z_msg;
|
||||
|
||||
array_init(&z_msg);
|
||||
|
||||
ZEND_ASSERT(ctx == NULL || ctx == PHPREDIS_CTX_PTR);
|
||||
ZEND_ASSERT(ctx.ptr == NULL || ctx.ptr == PHPREDIS_CTX_PTR);
|
||||
|
||||
if (redis_read_xclaim_reply(c->cmd_sock, c->reply_len, ctx == PHPREDIS_CTX_PTR, &z_msg) < 0) {
|
||||
if (redis_read_xclaim_reply(c->cmd_sock, c->reply_len,
|
||||
ctx.ptr == PHPREDIS_CTX_PTR, &z_msg) < 0)
|
||||
{
|
||||
zval_ptr_dtor_nogc(&z_msg);
|
||||
CLUSTER_RETURN_FALSE(c);
|
||||
}
|
||||
@@ -2580,7 +2625,9 @@ cluster_xclaim_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_vemb_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
cluster_vemb_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
zval z_ret;
|
||||
|
||||
ZVAL_FALSE(&z_ret);
|
||||
@@ -2607,7 +2654,9 @@ fail:
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_vinfo_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
cluster_vinfo_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
zval z_ret;
|
||||
|
||||
if (c->reply_len < 2 || c->reply_len % 2 != 0) {
|
||||
@@ -2628,7 +2677,8 @@ cluster_vinfo_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_vgetattr_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
cluster_vgetattr_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
zval z_ret;
|
||||
char *str;
|
||||
@@ -2639,7 +2689,7 @@ cluster_vgetattr_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
CLUSTER_RETURN_FALSE(c);
|
||||
}
|
||||
|
||||
if (ctx != PHPREDIS_CTX_PTR ||
|
||||
if (ctx.ptr != PHPREDIS_CTX_PTR ||
|
||||
redis_deserialize_vgetattr_reply(&z_ret, str, c->reply_len) != SUCCESS)
|
||||
{
|
||||
ZVAL_STRINGL(&z_ret, str, c->reply_len);
|
||||
@@ -2655,7 +2705,9 @@ cluster_vgetattr_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_vlinks_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
cluster_vlinks_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
zval z_ret;
|
||||
|
||||
if (c->reply_len < 0) {
|
||||
@@ -2677,7 +2729,8 @@ cluster_vlinks_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
|
||||
/* XINFO */
|
||||
PHP_REDIS_API void
|
||||
cluster_xinfo_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
cluster_xinfo_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
zval z_ret;
|
||||
|
||||
@@ -2695,7 +2748,7 @@ cluster_xinfo_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
|
||||
/* LMPOP, ZMPOP, BLMPOP, BZMPOP */
|
||||
PHP_REDIS_API void
|
||||
cluster_mpop_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
cluster_mpop_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, RedisCmdCtx ctx)
|
||||
{
|
||||
zval z_ret;
|
||||
|
||||
@@ -2711,8 +2764,8 @@ cluster_mpop_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
}
|
||||
|
||||
static void
|
||||
cluster_acl_custom_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx,
|
||||
int (*cb)(RedisSock*, zval*, long))
|
||||
cluster_acl_custom_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx, int (*cb)(RedisSock*, zval*, long))
|
||||
{
|
||||
zval z_ret;
|
||||
|
||||
@@ -2729,18 +2782,25 @@ cluster_acl_custom_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_acl_getuser_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
cluster_acl_custom_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, ctx, redis_read_acl_getuser_reply);
|
||||
cluster_acl_getuser_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
cluster_acl_custom_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, ctx,
|
||||
redis_read_acl_getuser_reply);
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_acl_log_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
cluster_acl_custom_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, ctx, redis_read_acl_log_reply);
|
||||
cluster_acl_log_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
cluster_acl_custom_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, ctx,
|
||||
redis_read_acl_log_reply);
|
||||
}
|
||||
|
||||
/* MULTI BULK response loop where we might pull the next one */
|
||||
PHP_REDIS_API zval *cluster_zval_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, int pull, mbulk_cb cb, zval *z_ret)
|
||||
redisCluster *c, int pull, mbulk_cb cb,
|
||||
zval *z_ret)
|
||||
{
|
||||
ZVAL_NULL(z_ret);
|
||||
|
||||
@@ -2760,7 +2820,7 @@ PHP_REDIS_API zval *cluster_zval_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
array_init(z_ret);
|
||||
|
||||
// Call our callback
|
||||
if (cb(c->cmd_sock, z_ret, c->reply_len, NULL) == FAILURE) {
|
||||
if (cb(c->cmd_sock, z_ret, c->reply_len, redis_empty_ctx) == FAILURE) {
|
||||
zval_ptr_dtor_nogc(z_ret);
|
||||
return NULL;
|
||||
}
|
||||
@@ -2770,7 +2830,7 @@ PHP_REDIS_API zval *cluster_zval_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
|
||||
/* MULTI MULTI BULK reply (for EXEC) */
|
||||
PHP_REDIS_API void cluster_multi_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx)
|
||||
redisCluster *c, RedisCmdCtx ctx)
|
||||
{
|
||||
zval *multi_resp = &c->multi_resp;
|
||||
uint8_t flags = c->flags->flags;
|
||||
@@ -2807,17 +2867,18 @@ PHP_REDIS_API void cluster_multi_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
}
|
||||
|
||||
/* Generic handler for MGET */
|
||||
PHP_REDIS_API void cluster_mbulk_mget_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx)
|
||||
PHP_REDIS_API void
|
||||
cluster_mbulk_mget_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
clusterMultiCtx *mctx = ctx;
|
||||
clusterMultiCtx *mctx = ctx.ptr;
|
||||
|
||||
/* Protect against an invalid response type, -1 response length, and failure
|
||||
* to consume the responses. */
|
||||
c->cmd_sock->serializer = c->flags->serializer;
|
||||
c->cmd_sock->compression = c->flags->compression;
|
||||
short fail = c->reply_type != TYPE_MULTIBULK || c->reply_len == -1 ||
|
||||
mbulk_resp_loop(c->cmd_sock, mctx->z_multi, c->reply_len, NULL) == FAILURE;
|
||||
mbulk_resp_loop(c->cmd_sock, mctx->z_multi, c->reply_len, redis_empty_ctx) == FAILURE;
|
||||
|
||||
// If we had a failure, pad results with FALSE to indicate failure. Non
|
||||
// existent keys (e.g. for MGET will come back as NULL)
|
||||
@@ -2835,18 +2896,15 @@ PHP_REDIS_API void cluster_mbulk_mget_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
add_next_index_zval(&c->multi_resp, mctx->z_multi);
|
||||
}
|
||||
|
||||
efree(mctx->z_multi);
|
||||
}
|
||||
|
||||
// Clean up this context item
|
||||
efree(mctx);
|
||||
}
|
||||
|
||||
/* Handler for MSETNX */
|
||||
PHP_REDIS_API void cluster_msetnx_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
PHP_REDIS_API void
|
||||
cluster_msetnx_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
clusterMultiCtx *mctx = ctx;
|
||||
clusterMultiCtx *mctx = ctx.ptr;
|
||||
int real_argc = mctx->count/2;
|
||||
|
||||
// Protect against an invalid response type
|
||||
@@ -2871,24 +2929,19 @@ PHP_REDIS_API void cluster_msetnx_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluste
|
||||
} else {
|
||||
add_next_index_zval(&c->multi_resp, mctx->z_multi);
|
||||
}
|
||||
efree(mctx->z_multi);
|
||||
}
|
||||
|
||||
// Free multi context
|
||||
efree(mctx);
|
||||
}
|
||||
|
||||
/* Handler for DEL */
|
||||
PHP_REDIS_API void cluster_del_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
PHP_REDIS_API void
|
||||
cluster_del_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, RedisCmdCtx ctx)
|
||||
{
|
||||
clusterMultiCtx *mctx = ctx;
|
||||
clusterMultiCtx *mctx = ctx.ptr;
|
||||
|
||||
// If we get an invalid reply, inform the client
|
||||
if (c->reply_type != TYPE_INT) {
|
||||
php_error_docref(0, E_WARNING,
|
||||
"Invalid reply type returned for DEL command");
|
||||
efree(mctx);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2901,17 +2954,14 @@ PHP_REDIS_API void cluster_del_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *
|
||||
} else {
|
||||
add_next_index_long(&c->multi_resp, Z_LVAL_P(mctx->z_multi));
|
||||
}
|
||||
efree(mctx->z_multi);
|
||||
}
|
||||
|
||||
efree(ctx);
|
||||
}
|
||||
|
||||
/* Handler for MSET */
|
||||
PHP_REDIS_API void cluster_mset_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
clusterMultiCtx *mctx = ctx;
|
||||
clusterMultiCtx *mctx = ctx.ptr;
|
||||
|
||||
// If we get an invalid reply type something very wrong has happened,
|
||||
// and we have to abort.
|
||||
@@ -2919,8 +2969,6 @@ PHP_REDIS_API void cluster_mset_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster
|
||||
php_error_docref(0, E_ERROR,
|
||||
"Invalid reply type returned for MSET command");
|
||||
zval_ptr_dtor_nogc(mctx->z_multi);
|
||||
efree(mctx->z_multi);
|
||||
efree(mctx);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
@@ -2931,50 +2979,49 @@ PHP_REDIS_API void cluster_mset_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster
|
||||
} else {
|
||||
add_next_index_bool(&c->multi_resp, zend_is_true(mctx->z_multi));
|
||||
}
|
||||
efree(mctx->z_multi);
|
||||
}
|
||||
|
||||
efree(mctx);
|
||||
}
|
||||
|
||||
/* Raw MULTI BULK reply */
|
||||
PHP_REDIS_API void
|
||||
cluster_mbulk_raw_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
cluster_mbulk_raw_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
cluster_gen_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
1, mbulk_resp_loop_raw, NULL);
|
||||
1, mbulk_resp_loop_raw, redis_empty_ctx);
|
||||
}
|
||||
|
||||
/* Unserialize all the things */
|
||||
PHP_REDIS_API void
|
||||
cluster_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
cluster_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
cluster_gen_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
1, mbulk_resp_loop, NULL);
|
||||
1, mbulk_resp_loop, redis_empty_ctx);
|
||||
}
|
||||
|
||||
/* For handling responses where we get key, value, key, value that
|
||||
* we will turn into key => value, key => value. */
|
||||
PHP_REDIS_API void
|
||||
cluster_mbulk_zipstr_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
cluster_gen_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
1, mbulk_resp_loop_zipstr, NULL);
|
||||
1, mbulk_resp_loop_zipstr, redis_empty_ctx);
|
||||
}
|
||||
|
||||
/* Handling key,value to key=>value where the values are doubles */
|
||||
PHP_REDIS_API void
|
||||
cluster_mbulk_zipdbl_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
cluster_gen_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
1, mbulk_resp_loop_zipdbl, NULL);
|
||||
1, mbulk_resp_loop_zipdbl, redis_empty_ctx);
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_mbulk_dbl_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
cluster_gen_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
1, mbulk_resp_loop_dbl, ctx);
|
||||
@@ -2983,7 +3030,7 @@ cluster_mbulk_dbl_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
/* Associate multi bulk response (for HMGET really) */
|
||||
PHP_REDIS_API void
|
||||
cluster_mbulk_assoc_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
cluster_gen_mbulk_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c,
|
||||
0, mbulk_resp_loop_assoc, ctx);
|
||||
@@ -2994,7 +3041,7 @@ cluster_mbulk_assoc_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
*/
|
||||
|
||||
static int mbulk_resp_loop_dbl(RedisSock *redis_sock, zval *z_result,
|
||||
long long count, void *ctx)
|
||||
long long count, RedisCmdCtx ctx)
|
||||
{
|
||||
char *line;
|
||||
int line_len;
|
||||
@@ -3014,7 +3061,7 @@ static int mbulk_resp_loop_dbl(RedisSock *redis_sock, zval *z_result,
|
||||
|
||||
/* MULTI BULK response where we don't touch the values (e.g. KEYS) */
|
||||
static int mbulk_resp_loop_raw(RedisSock *redis_sock, zval *z_result,
|
||||
long long count, void *ctx)
|
||||
long long count, RedisCmdCtx ctx)
|
||||
{
|
||||
char *line;
|
||||
int line_len;
|
||||
@@ -3036,7 +3083,7 @@ static int mbulk_resp_loop_raw(RedisSock *redis_sock, zval *z_result,
|
||||
|
||||
/* MULTI BULK response where we unserialize everything */
|
||||
static int mbulk_resp_loop(RedisSock *redis_sock, zval *z_result,
|
||||
long long count, void *ctx)
|
||||
long long count, RedisCmdCtx ctx)
|
||||
{
|
||||
char *line;
|
||||
int line_len;
|
||||
@@ -3061,7 +3108,7 @@ static int mbulk_resp_loop(RedisSock *redis_sock, zval *z_result,
|
||||
|
||||
/* MULTI BULK response where we turn key1,value1 into key1=>value1 */
|
||||
static int mbulk_resp_loop_zipstr(RedisSock *redis_sock, zval *z_result,
|
||||
long long count, void *ctx)
|
||||
long long count, RedisCmdCtx ctx)
|
||||
{
|
||||
char *line, *key = NULL;
|
||||
long long idx = 0;
|
||||
@@ -3097,7 +3144,7 @@ static int mbulk_resp_loop_zipstr(RedisSock *redis_sock, zval *z_result,
|
||||
|
||||
/* MULTI BULK loop processor where we expect key,score key, score */
|
||||
static int mbulk_resp_loop_zipdbl(RedisSock *redis_sock, zval *z_result,
|
||||
long long count, void *ctx)
|
||||
long long count, RedisCmdCtx ctx)
|
||||
{
|
||||
char *line, *key = NULL;
|
||||
int line_len, key_len = 0;
|
||||
@@ -3135,10 +3182,10 @@ static int mbulk_resp_loop_zipdbl(RedisSock *redis_sock, zval *z_result,
|
||||
|
||||
/* MULTI BULK where we're passed the keys, and we attach vals */
|
||||
static int mbulk_resp_loop_assoc(RedisSock *redis_sock, zval *z_result,
|
||||
long long count, void *ctx)
|
||||
long long count, RedisCmdCtx ctx)
|
||||
{
|
||||
HashTable *htctx = ctx.ptr;
|
||||
zval *zfield, z_unpacked;
|
||||
HashTable *htctx = ctx;
|
||||
int line_len;
|
||||
char *line;
|
||||
|
||||
@@ -3154,6 +3201,7 @@ static int mbulk_resp_loop_assoc(RedisSock *redis_sock, zval *z_result,
|
||||
ZVAL_COPY_VALUE(zfield, &z_unpacked);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
GC_ADDREF(htctx);
|
||||
ZVAL_ARR(z_result, htctx);
|
||||
|
||||
return SUCCESS;
|
||||
|
||||
+66
-65
@@ -2,6 +2,7 @@
|
||||
#define _PHPREDIS_CLUSTER_LIBRARY_H
|
||||
|
||||
#include "common.h"
|
||||
#include "redis_cmd.h"
|
||||
|
||||
#ifdef ZTS
|
||||
#include "TSRM.h"
|
||||
@@ -111,10 +112,10 @@
|
||||
}
|
||||
|
||||
/* Macro to clear out a clusterMultiCmd structure */
|
||||
#define CLUSTER_MULTI_CLEAR(mc) \
|
||||
mc->cmd.len = 0; \
|
||||
mc->args.len = 0; \
|
||||
mc->argc = 0; \
|
||||
#define CLUSTER_MULTI_CLEAR(mc) do { \
|
||||
if ((mc)->cmd) redis_cmd_reset((mc)->cmd, (mc)->kw, (mc)->kw_len); \
|
||||
(mc)->argc = 0; \
|
||||
} while (0)
|
||||
|
||||
/* Initialize a clusterMultiCmd with a keyword and length */
|
||||
#define CLUSTER_MULTI_INIT(mc, keyword, keyword_len) \
|
||||
@@ -131,7 +132,7 @@ typedef enum CLUSTER_REDIR_TYPE {
|
||||
} CLUSTER_REDIR_TYPE;
|
||||
|
||||
/* MULTI BULK response callback typedef */
|
||||
typedef int (*mbulk_cb)(RedisSock*,zval*,long long, void*);
|
||||
typedef int (*mbulk_cb)(RedisSock*,zval*,long long, RedisCmdCtx);
|
||||
|
||||
/* A list of covered slot ranges */
|
||||
typedef struct redisSlotRange {
|
||||
@@ -249,7 +250,7 @@ typedef struct redisCluster {
|
||||
} redisCluster;
|
||||
|
||||
/* RedisCluster response processing callback */
|
||||
typedef void (*cluster_cb)(INTERNAL_FUNCTION_PARAMETERS, redisCluster*, void*);
|
||||
typedef void (*cluster_cb)(INTERNAL_FUNCTION_PARAMETERS, redisCluster*, RedisCmdCtx);
|
||||
|
||||
/* Context for processing transactions */
|
||||
struct clusterFoldItem {
|
||||
@@ -259,8 +260,8 @@ struct clusterFoldItem {
|
||||
/* The actual socket where we send this request */
|
||||
unsigned short slot;
|
||||
|
||||
/* Any context we need to send to our callback */
|
||||
void *ctx;
|
||||
/* Context and possible context destructor */
|
||||
RedisCmdCtx ctx;
|
||||
|
||||
/* Next item in our list */
|
||||
struct clusterFoldItem *next;
|
||||
@@ -306,9 +307,8 @@ typedef struct clusterMultiCmd {
|
||||
/* Arguments in our payload */
|
||||
int argc;
|
||||
|
||||
/* The full command, built into cmd, and args as we aggregate */
|
||||
smart_string cmd;
|
||||
smart_string args;
|
||||
/* Command builder */
|
||||
RedisCmd *cmd;
|
||||
} clusterMultiCmd;
|
||||
|
||||
/* Hiredis like structure for processing any sort of reply Redis Cluster might
|
||||
@@ -334,8 +334,7 @@ HashTable *cluster_dist_create(void);
|
||||
void cluster_dist_free(HashTable *ht);
|
||||
int cluster_dist_add_key(redisCluster *c, HashTable *ht, char *key,
|
||||
size_t key_len, clusterKeyVal **kv);
|
||||
void cluster_dist_add_val(redisCluster *c, clusterKeyVal *kv, zval *val
|
||||
);
|
||||
void cluster_dist_add_val(redisCluster *c, clusterKeyVal *kv, zval *val);
|
||||
|
||||
/* Aggregation for multi commands like MGET, MSET, and MSETNX */
|
||||
void cluster_multi_init(clusterMultiCmd *mc, char *kw, int kw_len);
|
||||
@@ -371,7 +370,7 @@ PHP_REDIS_API int cluster_abort_exec(redisCluster *c);
|
||||
|
||||
PHP_REDIS_API short cluster_find_slot(redisCluster *c, const char *host,
|
||||
unsigned short port);
|
||||
PHP_REDIS_API int cluster_send_slot(redisCluster *c, short slot, char *cmd,
|
||||
PHP_REDIS_API int cluster_send_slot(redisCluster *c, short slot, const char *cmd,
|
||||
int cmd_len, REDIS_REPLY_TYPE rtype);
|
||||
|
||||
PHP_REDIS_API redisCluster *cluster_create(double timeout, double read_timeout,
|
||||
@@ -398,104 +397,104 @@ void cluster_cache_clear(redisCluster *c);
|
||||
* Redis Cluster response handlers. Our response handlers generally take the
|
||||
* following form:
|
||||
* PHP_REDIS_API void handler(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
* void *ctx)
|
||||
* RedisCmdCtx ctx)
|
||||
*
|
||||
* Reply handlers are responsible for setting the PHP return value (either to
|
||||
* something valid, or FALSE in the case of some failures).
|
||||
*/
|
||||
|
||||
PHP_REDIS_API void cluster_bool_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_ping_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_pop_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_object_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_lpos_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_hrandfield_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_zdiff_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_zadd_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_zrandmember_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_randmember_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_set_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_geosearch_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_single_line_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_bulk_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_bulk_withmeta_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_bulk_raw_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_dbl_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_1_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_long_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_type_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_sub_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_unsub_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_vemb_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_vinfo_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_vlinks_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_vgetattr_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
|
||||
PHP_REDIS_API void cluster_zrange_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
RedisCmdCtx ctx);
|
||||
|
||||
PHP_REDIS_API void cluster_variant_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
|
||||
PHP_REDIS_API void cluster_variant_raw_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
|
||||
PHP_REDIS_API void cluster_variant_resp_strings(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
|
||||
/* MULTI BULK response functions */
|
||||
PHP_REDIS_API void cluster_mbulk_raw_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_mbulk_zipstr_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_mbulk_zipdbl_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_mbulk_dbl_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_mbulk_assoc_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_multi_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API zval *cluster_zval_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, int pull, mbulk_cb cb, zval *z_ret);
|
||||
|
||||
/* Handlers for things like DEL/MGET/MSET/MSETNX */
|
||||
PHP_REDIS_API void cluster_del_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_mbulk_mget_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_mset_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_msetnx_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
|
||||
/* Response handler for ZSCAN, SSCAN, and HSCAN */
|
||||
PHP_REDIS_API int cluster_scan_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
@@ -503,28 +502,30 @@ PHP_REDIS_API int cluster_scan_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
|
||||
/* INFO response handler */
|
||||
PHP_REDIS_API void cluster_info_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
|
||||
/* CLIENT LIST response handler */
|
||||
PHP_REDIS_API void cluster_client_list_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
|
||||
/* Custom STREAM handlers */
|
||||
PHP_REDIS_API void cluster_xread_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_xrange_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_xclaim_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_xinfo_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
|
||||
PHP_REDIS_API void cluster_mpop_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, void *ctx);
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
|
||||
/* Custom ACL handlers */
|
||||
PHP_REDIS_API void cluster_acl_getuser_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx);
|
||||
PHP_REDIS_API void cluster_acl_log_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx);
|
||||
PHP_REDIS_API void cluster_acl_getuser_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void cluster_acl_log_resp(INTERNAL_FUNCTION_PARAMETERS,
|
||||
redisCluster *c, RedisCmdCtx ctx);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -200,6 +200,8 @@ typedef enum {
|
||||
Z_PARAM_ZVAL_EX(dest, 1, 0)
|
||||
#define Z_PARAM_BOOL_OR_NULL(dest, is_null) \
|
||||
Z_PARAM_BOOL_EX(dest, is_null, 1, 0)
|
||||
#define Z_PARAM_LONG_OR_NULL(dest, is_null) \
|
||||
Z_PARAM_LONG_EX(dest, is_null, 1, 0)
|
||||
#endif
|
||||
|
||||
#if PHPREDIS_DEBUG_LOGGING == 1
|
||||
@@ -262,8 +264,17 @@ typedef struct RedisHello {
|
||||
zend_string *version;
|
||||
} RedisHello;
|
||||
|
||||
typedef enum RedisSockType {
|
||||
REDIS_SOCK_STANDALONE,
|
||||
REDIS_SOCK_ARRAY,
|
||||
REDIS_SOCK_CLUSTER,
|
||||
REDIS_SOCK_SENTINEL,
|
||||
REDIS_SOCK_SESSION
|
||||
} RedisSockType;
|
||||
|
||||
/* {{{ struct RedisSock */
|
||||
typedef struct {
|
||||
RedisSockType type;
|
||||
php_stream *stream;
|
||||
zend_string *host;
|
||||
int port;
|
||||
@@ -307,16 +318,27 @@ typedef struct {
|
||||
} RedisSock;
|
||||
/* }}} */
|
||||
|
||||
typedef void (RedisCmdCtxDtor)(void *ptr);
|
||||
typedef struct RedisCmdCtx {
|
||||
void *ptr;
|
||||
RedisCmdCtxDtor *dtor;
|
||||
} RedisCmdCtx;
|
||||
|
||||
/* Redis response handler function callback prototype */
|
||||
typedef void (*ResultCallback)(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
RedisSock*, zval*, RedisCmdCtx);
|
||||
typedef int (*FailableResultCallback)(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock*, zval*, void*);
|
||||
RedisSock*, zval*, RedisCmdCtx);
|
||||
|
||||
static zend_always_inline void redis_cmd_ctx_free(RedisCmdCtx ctx) {
|
||||
if (ctx.dtor)
|
||||
ctx.dtor(ctx.ptr);
|
||||
}
|
||||
|
||||
typedef struct fold_item {
|
||||
FailableResultCallback fun;
|
||||
RedisCmdCtx ctx;
|
||||
uint8_t flags;
|
||||
void *ctx;
|
||||
} fold_item;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -325,5 +325,5 @@ if test "$PHP_REDIS" != "no"; then
|
||||
fi
|
||||
|
||||
PHP_SUBST(REDIS_SHARED_LIBADD)
|
||||
PHP_NEW_EXTENSION(redis, redis.c redis_commands.c library.c redis_session.c redis_array.c redis_array_impl.c redis_cluster.c cluster_library.c redis_sentinel.c sentinel_library.c backoff.c $lzf_sources, $ext_shared)
|
||||
PHP_NEW_EXTENSION(redis, redis.c redis_commands.c library.c redis_session.c redis_array.c redis_array_impl.c redis_cluster.c redis_cmd.c cluster_library.c redis_sentinel.c sentinel_library.c backoff.c $lzf_sources, $ext_shared)
|
||||
fi
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ ARG_ENABLE("redis-session", "whether to enable sessions", "yes");
|
||||
ARG_ENABLE("redis-igbinary", "whether to enable igbinary serializer support", "no");
|
||||
|
||||
if (PHP_REDIS != "no") {
|
||||
var sources = "redis.c redis_commands.c library.c redis_session.c redis_array.c redis_array_impl.c redis_cluster.c cluster_library.c redis_sentinel.c sentinel_library.c backoff.c";
|
||||
var sources = "redis.c redis_commands.c redis_cmd.c library.c redis_session.c redis_array.c redis_array_impl.c redis_cluster.c cluster_library.c redis_sentinel.c sentinel_library.c backoff.c";
|
||||
if (PHP_REDIS_SESSION != "no") {
|
||||
ADD_EXTENSION_DEP("redis", "session");
|
||||
ADD_FLAG("CFLAGS_REDIS", ' /D PHP_SESSION=1 ');
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
#define REDIS_LIBRARY_H
|
||||
|
||||
#include "php_redis.h"
|
||||
|
||||
/* Non cluster command helper */
|
||||
#define REDIS_SPPRINTF(ret, kw, fmt, ...) \
|
||||
redis_spprintf(redis_sock, NULL, ret, kw, fmt, ##__VA_ARGS__)
|
||||
#include "redis_cmd.h"
|
||||
|
||||
#define REDIS_CMD_APPEND_SSTR_STATIC(sstr, str) \
|
||||
redis_cmd_append_sstr(sstr, str, sizeof(str)-1);
|
||||
@@ -72,65 +69,50 @@ void redis_free_reply_callbacks(RedisSock *redis_sock);
|
||||
PHP_REDIS_API int redis_extract_auth_info(zval *ztest, zend_string **user, zend_string **pass);
|
||||
PHP_REDIS_API void redis_with_metadata(zval *zdst, zval *zsrc, zend_long length);
|
||||
|
||||
int redis_cmd_init_sstr(smart_string *str, int num_args, char *keyword, int keyword_len);
|
||||
int redis_cmd_append_sstr(smart_string *str, char *append, int append_len);
|
||||
int redis_cmd_append_sstr_int(smart_string *str, int append);
|
||||
int redis_cmd_append_sstr_long(smart_string *str, long append);
|
||||
int redis_cmd_append_sstr_zend_long(smart_string *str, zend_long append);
|
||||
int redis_cmd_append_sstr_i64(smart_string *str, int64_t append);
|
||||
int redis_cmd_append_sstr_u64(smart_string *str, uint64_t append);
|
||||
int redis_cmd_append_sstr_dbl(smart_string *str, double value);
|
||||
int redis_cmd_append_sstr_zstr(smart_string *str, zend_string *zstr);
|
||||
int redis_cmd_append_sstr_zval(smart_string *str, zval *z, RedisSock *redis_sock);
|
||||
int redis_cmd_append_sstr_key(smart_string *str, char *key, size_t len, RedisSock *redis_sock, short *slot);
|
||||
int redis_cmd_append_sstr_key_zstr(smart_string *str, zend_string *key, RedisSock *redis_sock, short *slot);
|
||||
int redis_cmd_append_sstr_key_zval(smart_string *dst, zval *zv, RedisSock *redis_sock, short *slot);
|
||||
int redis_cmd_append_sstr_key_long(smart_string *dst, zend_long lval, RedisSock *redis_sock, short *slot);
|
||||
int redis_cmd_append_sstr_arrkey(smart_string *cmd, zend_string *kstr, zend_ulong idx);
|
||||
|
||||
PHP_REDIS_API int redis_spprintf(RedisSock *redis_sock, short *slot, char **ret, char *kw, char *fmt, ...);
|
||||
PHP_REDIS_API zend_string *redis_pool_spprintf(RedisSock *redis_sock, char *fmt, ...);
|
||||
|
||||
PHP_REDIS_API char *redis_sock_read(RedisSock *redis_sock, int *buf_len);
|
||||
PHP_REDIS_API int redis_sock_gets(RedisSock *redis_sock, char *buf, int buf_size, size_t* line_len);
|
||||
PHP_REDIS_API int redis_1_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_long_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval* z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_1_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_long_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval* z_tab, RedisCmdCtx ctx);
|
||||
typedef void (*SuccessCallback)(RedisSock *redis_sock);
|
||||
PHP_REDIS_API int redis_boolean_response_impl(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx, SuccessCallback success_callback);
|
||||
PHP_REDIS_API int redis_boolean_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_bulk_double_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_string_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_bulk_withmeta_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_info_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_config_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_zrange_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_boolean_response_impl(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx, SuccessCallback success_callback);
|
||||
PHP_REDIS_API int redis_boolean_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_bulk_double_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_string_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_bulk_withmeta_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_info_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_config_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_zrange_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void redis_parse_info_response(char *response, zval *z_ret);
|
||||
PHP_REDIS_API void redis_parse_client_list_response(char *response, zval *z_ret);
|
||||
PHP_REDIS_API int redis_type_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API RedisSock* redis_sock_create(char *host, int host_len, int port, double timeout, double read_timeout, int persistent, char *persistent_id, long retry_interval);
|
||||
PHP_REDIS_API int redis_type_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API RedisSock* redis_sock_create(RedisSockType type, const char *host,
|
||||
int host_len, int port, double timeout, double read_timeout, int persistent,
|
||||
const char *persistent_id, long retry_interval);
|
||||
PHP_REDIS_API int redis_sock_configure(RedisSock *redis_sock, HashTable *opts);
|
||||
PHP_REDIS_API int redis_sock_connect(RedisSock *redis_sock);
|
||||
PHP_REDIS_API int redis_sock_server_open(RedisSock *redis_sock);
|
||||
PHP_REDIS_API int redis_sock_auth(RedisSock *redis_sock);
|
||||
PHP_REDIS_API char *redis_sock_auth_cmd(RedisSock *redis_sock, int *cmdlen);
|
||||
PHP_REDIS_API zend_string *redis_sock_auth_cmd(RedisSock *redis_sock);
|
||||
PHP_REDIS_API void redis_sock_set_auth(RedisSock *redis_sock, zend_string *user, zend_string *pass);
|
||||
PHP_REDIS_API void redis_sock_set_auth_zval(RedisSock *redis_sock, zval *zv);
|
||||
PHP_REDIS_API void redis_sock_free_auth(RedisSock *redis_sock);
|
||||
PHP_REDIS_API int redis_sock_disconnect(RedisSock *redis_sock, int force, int is_reset_mode);
|
||||
PHP_REDIS_API zval *redis_sock_read_multibulk_reply_zval(RedisSock *redis_sock, zval *z_tab);
|
||||
PHP_REDIS_API char *redis_sock_read_bulk_reply(RedisSock *redis_sock, int bytes);
|
||||
PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *_z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *_z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API void redis_mbulk_reply_loop(RedisSock *redis_sock, zval *z_tab, int count, int unserialize);
|
||||
|
||||
|
||||
PHP_REDIS_API int redis_mbulk_reply_raw(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_mbulk_reply_zipped_raw(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_mbulk_reply_zipped_vals(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_mbulk_reply_zipped_keys_int(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_mbulk_reply_zipped_keys_dbl(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_mbulk_reply_assoc(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_mbulk_reply_double(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_mbulk_reply_raw(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_mbulk_reply_zipped_raw(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_mbulk_reply_zipped_vals(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_mbulk_reply_zipped_keys_int(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_mbulk_reply_zipped_keys_dbl(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_mbulk_reply_assoc(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_mbulk_reply_double(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
|
||||
void redisSetScanCursor(zval *zv, uint64_t cursor);
|
||||
uint64_t redisGetScanCursor(zval *zv, zend_bool *was_zero);
|
||||
@@ -138,54 +120,59 @@ uint64_t redisGetScanCursor(zval *zv, zend_bool *was_zero);
|
||||
PHP_REDIS_API int redis_sock_read_scan_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, REDIS_SCAN_TYPE type, uint64_t *cursor);
|
||||
|
||||
PHP_REDIS_API int redis_xrange_reply(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_xread_reply(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
|
||||
PHP_REDIS_API int redis_xclaim_reply(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_read_xclaim_reply(
|
||||
RedisSock *redis_sock, int count, int is_xautoclaim, zval *rv);
|
||||
|
||||
PHP_REDIS_API int redis_xinfo_reply(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
|
||||
PHP_REDIS_API int redis_vinfo_reply(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_read_vinfo_response(RedisSock *redis_sock,
|
||||
zval *z_ret, long long count);
|
||||
|
||||
PHP_REDIS_API int redis_vemb_reply(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_read_vemb_response(RedisSock *redis_sock, zval *z_ret,
|
||||
long long count);
|
||||
|
||||
PHP_REDIS_API int redis_read_vlinks_response(RedisSock *redis_sock, zval *z_ret,
|
||||
long long elements, void *ctx);
|
||||
long long elements, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_vlinks_reply(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
|
||||
PHP_REDIS_API int
|
||||
redis_deserialize_vgetattr_reply(zval *z_ret, const char *reply, size_t len);
|
||||
|
||||
PHP_REDIS_API int
|
||||
redis_vgetattr_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
zval *z_tab, void *ctx);
|
||||
zval *z_tab, RedisCmdCtx ctx);
|
||||
|
||||
PHP_REDIS_API int redis_pubsub_response(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_subscribe_response(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_unsubscribe_response(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
|
||||
PHP_REDIS_API int redis_sock_write(RedisSock *redis_sock, char *cmd, size_t sz);
|
||||
PHP_REDIS_API int redis_sock_write(RedisSock *redis_sock, const char *cmd, size_t sz);
|
||||
PHP_REDIS_API int redis_check_eof(RedisSock *redis_sock, zend_bool no_retry, zend_bool no_throw);
|
||||
PHP_REDIS_API RedisSock *redis_sock_get(zval *id, int nothrow);
|
||||
PHP_REDIS_API void redis_free_socket(RedisSock *redis_sock);
|
||||
PHP_REDIS_API void redis_sock_set_err(RedisSock *redis_sock, const char *msg, int msg_len);
|
||||
PHP_REDIS_API void redis_sock_clear_err(RedisSock *redis_sock);
|
||||
|
||||
static zend_always_inline int
|
||||
redis_sock_write_cmd(RedisSock *redis_sock, RedisCmd *cmd) {
|
||||
return redis_sock_write(redis_sock, redis_cmd_str(cmd), redis_cmd_len(cmd));
|
||||
}
|
||||
|
||||
void redis_sock_set_context(RedisSock *redis_sock, HashTable *ht);
|
||||
void redis_sock_free_context(RedisSock *redis_sock);
|
||||
int redis_sock_set_context_zval(RedisSock *redis_sock, zval *zv);
|
||||
@@ -221,17 +208,17 @@ redis_read_xinfo_response(RedisSock *redis_sock, zval *z_ret, int elements);
|
||||
|
||||
PHP_REDIS_API int
|
||||
redis_mpop_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
zval *z_tab, void *ctx);
|
||||
zval *z_tab, RedisCmdCtx ctx);
|
||||
|
||||
PHP_REDIS_API int
|
||||
redis_read_mpop_response(RedisSock *redis_sock, zval *zdst, int elements, void *ctx);
|
||||
redis_read_mpop_response(RedisSock *redis_sock, zval *zdst, int elements, RedisCmdCtx ctx);
|
||||
|
||||
/* Specialized ACL reply handlers */
|
||||
PHP_REDIS_API int redis_acl_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_acl_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_read_acl_getuser_reply(RedisSock *redis_sock, zval *zret, long len);
|
||||
PHP_REDIS_API int redis_acl_getuser_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_acl_getuser_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_read_acl_log_reply(RedisSock *redis_sock, zval *zret, long count);
|
||||
PHP_REDIS_API int redis_acl_log_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_acl_log_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
|
||||
/*
|
||||
* Variant Read methods, mostly to implement eval
|
||||
@@ -240,33 +227,41 @@ PHP_REDIS_API int redis_acl_log_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *r
|
||||
PHP_REDIS_API int redis_read_reply_type(RedisSock *redis_sock, REDIS_REPLY_TYPE *reply_type, long *reply_info);
|
||||
PHP_REDIS_API int redis_read_variant_bulk(RedisSock *redis_sock, long size, zval *z_ret);
|
||||
PHP_REDIS_API int redis_read_multibulk_recursive(RedisSock *redis_sock, long long elements, int status_strings, zval *z_ret);
|
||||
PHP_REDIS_API int redis_read_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_read_raw_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_read_variant_reply_strings(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
|
||||
PHP_REDIS_API int redis_zadd_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_zrandmember_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_zdiff_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_set_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_read_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_read_raw_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_read_variant_reply_strings(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
int redis_client_trackinginfo_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
zval *z_tab, RedisCmdCtx ctx);
|
||||
int redis_client_info_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_zadd_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_zrandmember_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_zdiff_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_set_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_read_geosearch_response(zval *zdst, RedisSock *redis_sock, long long elements, int with_aux_data);
|
||||
PHP_REDIS_API int redis_geosearch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_hrandfield_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_pop_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_geosearch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_hrandfield_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_pop_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
|
||||
PHP_REDIS_API int redis_randmember_response(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_lpos_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_object_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_read_lpos_response(zval *zdst, RedisSock *redis_sock, char reply_type, long long elements, void *ctx);
|
||||
RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_lpos_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_object_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_read_lpos_response(zval *zdst, RedisSock *redis_sock, char reply_type, long long elements, RedisCmdCtx ctx);
|
||||
|
||||
PHP_REDIS_API int redis_client_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_function_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_command_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_select_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_client_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_function_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
int redis_function_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab,
|
||||
RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_command_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
zval *z_tab, RedisCmdCtx ctx);
|
||||
int redis_command_info_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_select_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
|
||||
PHP_REDIS_API int redis_hello_server_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_hello_version_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_hello_server_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
PHP_REDIS_API int redis_hello_version_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
|
||||
/* Helper methods to get configuration values from a HashTable. */
|
||||
|
||||
|
||||
@@ -178,6 +178,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<file role="src" name="redis_cluster.stub.php"/>
|
||||
<file role="src" name="redis_cluster_arginfo.h"/>
|
||||
<file role="src" name="redis_cluster_legacy_arginfo.h"/>
|
||||
<file role="src" name="redis_cmd.c"/>
|
||||
<file role="src" name="redis_cmd.h"/>
|
||||
<file role="src" name="redis_commands.c"/>
|
||||
<file role="src" name="redis_commands.h"/>
|
||||
<file role="src" name="redis_session.c"/>
|
||||
|
||||
@@ -60,6 +60,8 @@ extern ps_module ps_mod_redis_cluster;
|
||||
zend_class_entry *redis_ce;
|
||||
zend_class_entry *redis_exception_ce;
|
||||
|
||||
extern RedisCmdCtx redis_empty_ctx;
|
||||
|
||||
#if PHP_VERSION_ID < 80000
|
||||
#include "redis_legacy_arginfo.h"
|
||||
#else
|
||||
@@ -484,7 +486,8 @@ PHP_METHOD(Redis, __construct)
|
||||
ZEND_PARSE_PARAMETERS_END_EX(RETURN_THROWS());
|
||||
|
||||
redis = PHPREDIS_ZVAL_GET_OBJECT(redis_object, getThis());
|
||||
redis->sock = redis_sock_create(ZEND_STRL("127.0.0.1"), 6379, 0, 0, 0, NULL, 0);
|
||||
redis->sock = redis_sock_create(REDIS_SOCK_STANDALONE, ZEND_STRL("127.0.0.1"),
|
||||
6379, 0, 0, 0, NULL, 0);
|
||||
if (opts != NULL && redis_sock_configure(redis->sock, opts) != SUCCESS) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
@@ -494,7 +497,7 @@ PHP_METHOD(Redis, __construct)
|
||||
/* {{{ proto Redis Redis::__destruct()
|
||||
Public Destructor
|
||||
*/
|
||||
PHP_METHOD(Redis,__destruct) {
|
||||
PHP_METHOD(Redis, __destruct) {
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
@@ -508,8 +511,6 @@ PHP_METHOD(Redis,__destruct) {
|
||||
// If we think we're in MULTI mode, send a discard
|
||||
if (IS_MULTI(redis_sock)) {
|
||||
if (!IS_PIPELINE(redis_sock) && redis_sock->stream) {
|
||||
// Discard any multi commands, and free any callbacks that have been
|
||||
// queued
|
||||
redis_send_discard(redis_sock);
|
||||
}
|
||||
redis_free_reply_callbacks(redis_sock);
|
||||
@@ -604,8 +605,9 @@ redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
|
||||
redis_free_socket(redis->sock);
|
||||
}
|
||||
|
||||
redis->sock = redis_sock_create(host, host_len, port, timeout, read_timeout,
|
||||
persistent, persistent_id, retry_interval);
|
||||
redis->sock = redis_sock_create(REDIS_SOCK_STANDALONE, host, host_len, port,
|
||||
timeout, read_timeout, persistent,
|
||||
persistent_id, retry_interval);
|
||||
|
||||
if (context) {
|
||||
/* Stream context (e.g. TLS) */
|
||||
@@ -631,13 +633,20 @@ redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static inline void
|
||||
pipeline_enqueue_command(RedisSock *redis_sock, const char *cmd, int cmd_len) {
|
||||
smart_string_appendl(&redis_sock->pipeline_cmd, cmd, cmd_len);
|
||||
static zend_always_inline void
|
||||
pipeline_enqueue_cmd_strl(RedisSock *redis_sock, const char *cmd, int len) {
|
||||
smart_string_appendl(&redis_sock->pipeline_cmd, cmd, len);
|
||||
}
|
||||
|
||||
static zend_always_inline void
|
||||
pipeline_enqueue_cmd(RedisSock *redis_sock, RedisCmd *cmd) {
|
||||
pipeline_enqueue_cmd_strl(redis_sock, redis_cmd_str(cmd),
|
||||
redis_cmd_len(cmd));
|
||||
}
|
||||
|
||||
static void
|
||||
redis_save_callback(RedisSock *redis_sock, FailableResultCallback cb, void *ctx)
|
||||
redis_save_callback(RedisSock *redis_sock, FailableResultCallback cb,
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
fold_item *fi;
|
||||
|
||||
@@ -647,57 +656,73 @@ redis_save_callback(RedisSock *redis_sock, FailableResultCallback cb, void *ctx)
|
||||
fi->ctx = ctx;
|
||||
}
|
||||
|
||||
#define REDIS_PROCESS_RESPONSE_CLOSURE(function, closure_context) \
|
||||
if (!IS_PIPELINE(redis_sock)) { \
|
||||
if (redis_response_enqueued(redis_sock) != SUCCESS) { \
|
||||
RETURN_FALSE; \
|
||||
} \
|
||||
} \
|
||||
redis_save_callback(redis_sock, function, closure_context); \
|
||||
RETURN_ZVAL(getThis(), 1, 0); \
|
||||
|
||||
|
||||
static int redis_process_request(RedisSock *redis_sock, char *cmd, int cmdlen) {
|
||||
static int
|
||||
redis_process_request_strl(RedisSock *redis_sock, const char *cmd, int len) {
|
||||
int res = SUCCESS;
|
||||
|
||||
if (IS_PIPELINE(redis_sock)) {
|
||||
pipeline_enqueue_command(redis_sock, cmd, cmdlen);
|
||||
} else if (UNEXPECTED(redis_sock_write(redis_sock, cmd, cmdlen) < 0)) {
|
||||
pipeline_enqueue_cmd_strl(redis_sock, cmd, len);
|
||||
} else if (UNEXPECTED(redis_sock_write(redis_sock, cmd, len) < 0)) {
|
||||
res = FAILURE;
|
||||
}
|
||||
|
||||
efree(cmd);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
redis_process_request(RedisSock *redis_sock, RedisCmd *cmd) {
|
||||
return redis_process_request_strl(redis_sock, redis_cmd_str(cmd),
|
||||
redis_cmd_len(cmd));
|
||||
}
|
||||
|
||||
static void
|
||||
redis_process_cmd(INTERNAL_FUNCTION_PARAMETERS, redis_cmd_cb cmd_cb,
|
||||
redis_process_cmd(INTERNAL_FUNCTION_PARAMETERS, redis_cmd_cb *cmd_cb,
|
||||
FailableResultCallback resp_cb)
|
||||
{
|
||||
RedisSock *redis_sock;
|
||||
void *ctx = NULL;
|
||||
int cmd_len;
|
||||
char *cmd;
|
||||
RedisCmdCtx ctx;
|
||||
RedisCmd *cmd;
|
||||
int res;
|
||||
|
||||
redis_sock = redis_sock_get(getThis(), 0);
|
||||
if (UNEXPECTED(redis_sock == NULL)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (UNEXPECTED(cmd_cb(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, &cmd,
|
||||
&cmd_len, NULL, &ctx) == FAILURE))
|
||||
{
|
||||
cmd = cmd_cb(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock);
|
||||
if (UNEXPECTED(cmd == NULL)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (redis_process_request(redis_sock, cmd, cmd_len) != SUCCESS) {
|
||||
ctx = redis_cmd_pop_ctx(cmd);
|
||||
|
||||
if (IS_PIPELINE(redis_sock)) {
|
||||
pipeline_enqueue_cmd(redis_sock, cmd);
|
||||
res = SUCCESS;
|
||||
} else {
|
||||
res = redis_sock_write_cmd(redis_sock, cmd) < 0 ? FAILURE : SUCCESS;
|
||||
}
|
||||
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
if (UNEXPECTED(res != SUCCESS)) {
|
||||
redis_cmd_ctx_free(ctx);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (IS_ATOMIC(redis_sock)) {
|
||||
resp_cb(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, ctx);
|
||||
redis_cmd_ctx_free(ctx);
|
||||
} else {
|
||||
REDIS_PROCESS_RESPONSE_CLOSURE(resp_cb, ctx);
|
||||
if (!IS_PIPELINE(redis_sock)) {
|
||||
if (redis_response_enqueued(redis_sock) != SUCCESS) {
|
||||
redis_cmd_ctx_free(ctx);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
redis_save_callback(redis_sock, resp_cb, ctx);
|
||||
RETURN_ZVAL(getThis(), 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,32 +732,52 @@ redis_process_cmd(INTERNAL_FUNCTION_PARAMETERS, redis_cmd_cb cmd_cb,
|
||||
|
||||
void
|
||||
redis_process_kw_cmd(INTERNAL_FUNCTION_PARAMETERS, const char *kw,
|
||||
redis_kw_cmd_cb cmd_cb, FailableResultCallback resp_cb,
|
||||
void *ctx)
|
||||
redis_kw_cmd_cb *cmd_cb, FailableResultCallback resp_cb)
|
||||
{
|
||||
RedisSock *redis_sock;
|
||||
int cmd_len;
|
||||
char *cmd;
|
||||
RedisCmdCtx ctx;
|
||||
RedisCmd *cmd;
|
||||
int res;
|
||||
|
||||
redis_sock = redis_sock_get(getThis(), 0);
|
||||
if (UNEXPECTED(redis_sock == NULL)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (UNEXPECTED(cmd_cb(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, (char*)kw, &cmd,
|
||||
&cmd_len, NULL, &ctx) == FAILURE))
|
||||
{
|
||||
cmd = cmd_cb(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, (char*)kw);
|
||||
if (UNEXPECTED(cmd == NULL)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (redis_process_request(redis_sock, cmd, cmd_len) != SUCCESS) {
|
||||
ctx = redis_cmd_pop_ctx(cmd);
|
||||
|
||||
if (IS_PIPELINE(redis_sock)) {
|
||||
pipeline_enqueue_cmd(redis_sock, cmd);
|
||||
res = SUCCESS;
|
||||
} else {
|
||||
res = redis_sock_write_cmd(redis_sock, cmd) < 0 ? FAILURE : SUCCESS;
|
||||
}
|
||||
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
if (UNEXPECTED(res != SUCCESS)) {
|
||||
redis_cmd_ctx_free(ctx);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (IS_ATOMIC(redis_sock)) {
|
||||
resp_cb(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, ctx);
|
||||
redis_cmd_ctx_free(ctx);
|
||||
} else {
|
||||
REDIS_PROCESS_RESPONSE_CLOSURE(resp_cb, ctx);
|
||||
if (!IS_PIPELINE(redis_sock)) {
|
||||
if (redis_response_enqueued(redis_sock) != SUCCESS) {
|
||||
redis_cmd_ctx_free(ctx);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
redis_save_callback(redis_sock, resp_cb, ctx);
|
||||
RETURN_ZVAL(getThis(), 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -847,7 +892,7 @@ PHP_METHOD(Redis, reset)
|
||||
char *response;
|
||||
int response_len;
|
||||
RedisSock *redis_sock;
|
||||
smart_string cmd = {0};
|
||||
RedisCmd *cmd;
|
||||
zend_bool ret = 0;
|
||||
|
||||
if ((redis_sock = redis_sock_get(getThis(), 0)) == NULL) {
|
||||
@@ -855,15 +900,18 @@ PHP_METHOD(Redis, reset)
|
||||
}
|
||||
|
||||
if (IS_PIPELINE(redis_sock)) {
|
||||
php_error_docref(NULL, E_ERROR, "Reset isn't allowed in pipeline mode!");
|
||||
php_error_docref(NULL, E_ERROR,
|
||||
"Reset isn't allowed in pipeline mode!");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
redis_cmd_init_sstr(&cmd, 0, ZEND_STRL("RESET"));
|
||||
cmd = redis_cmd_create_literal(NULL, "RESET");
|
||||
|
||||
if (redis_process_request(redis_sock, cmd.c, cmd.len) != SUCCESS) {
|
||||
if (redis_process_request(redis_sock, cmd) != SUCCESS) {
|
||||
redis_cmd_free(cmd);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
if ((response = redis_sock_read(redis_sock, &response_len)) != NULL) {
|
||||
ret = REDIS_STRCMP_STATIC(response, response_len, "+RESET");
|
||||
@@ -1010,11 +1058,12 @@ PHP_REDIS_API void redis_set_watch(RedisSock *redis_sock)
|
||||
redis_sock->watching = 1;
|
||||
}
|
||||
|
||||
PHP_REDIS_API int redis_watch_response(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx)
|
||||
PHP_REDIS_API int
|
||||
redis_watch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
zval *z_tab, RedisCmdCtx ctx)
|
||||
{
|
||||
return redis_boolean_response_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
|
||||
z_tab, ctx, redis_set_watch);
|
||||
return redis_boolean_response_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU,
|
||||
redis_sock, z_tab, ctx, redis_set_watch);
|
||||
}
|
||||
|
||||
/* {{{ proto boolean Redis::watch(string key1, string key2...)
|
||||
@@ -1031,7 +1080,7 @@ PHP_REDIS_API void redis_clear_watch(RedisSock *redis_sock)
|
||||
|
||||
PHP_REDIS_API int redis_unwatch_response(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab,
|
||||
void *ctx)
|
||||
RedisCmdCtx ctx)
|
||||
{
|
||||
return redis_boolean_response_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
|
||||
z_tab, ctx, redis_clear_watch);
|
||||
@@ -1360,63 +1409,46 @@ PHP_METHOD(Redis, sort_ro) {
|
||||
REDIS_PROCESS_KW_CMD("SORT_RO", redis_sort_cmd, redis_read_variant_reply);
|
||||
}
|
||||
|
||||
static void
|
||||
generic_sort_cmd(INTERNAL_FUNCTION_PARAMETERS, int desc, int alpha)
|
||||
static RedisCmd *
|
||||
generic_sort_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, int desc,
|
||||
int alpha)
|
||||
{
|
||||
zend_string *key = NULL, *pattern = NULL, *store = NULL, *zpattern;
|
||||
zval *object, *zele, *zget = NULL;
|
||||
RedisSock *redis_sock;
|
||||
zend_string *zpattern;
|
||||
char *key = NULL, *pattern = NULL, *store = NULL;
|
||||
size_t keylen, patternlen, storelen;
|
||||
zend_long offset = -1, count = -1;
|
||||
int argc = 1; /* SORT key is the simplest SORT command */
|
||||
smart_string cmd = {0};
|
||||
RedisCmd *cmd;
|
||||
|
||||
/* Parse myriad of sort arguments */
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
|
||||
"Os|s!z!lls", &object, redis_ce, &key,
|
||||
&keylen, &pattern, &patternlen, &zget,
|
||||
&offset, &count, &store, &storelen)
|
||||
"OS|S!z!llS", &object, redis_ce, &key,
|
||||
&pattern, &zget, &offset, &count, &store)
|
||||
== FAILURE)
|
||||
{
|
||||
RETURN_FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Ensure we're sorting something, and we can get context */
|
||||
if (keylen == 0 || !(redis_sock = redis_sock_get(object, 0)))
|
||||
RETURN_FALSE;
|
||||
|
||||
/* Start calculating argc depending on input arguments */
|
||||
if (pattern && patternlen) argc += 2; /* BY pattern */
|
||||
if (offset >= 0 && count >= 0) argc += 3; /* LIMIT offset count */
|
||||
if (alpha) argc += 1; /* ALPHA */
|
||||
if (store) argc += 2; /* STORE destination */
|
||||
if (desc) argc += 1; /* DESC (ASC is the default) */
|
||||
|
||||
/* GET is special. It can be 0 .. N arguments depending what we have */
|
||||
if (zget) {
|
||||
if (Z_TYPE_P(zget) == IS_ARRAY)
|
||||
argc += zend_hash_num_elements(Z_ARRVAL_P(zget));
|
||||
else if (Z_STRLEN_P(zget) > 0) {
|
||||
argc += 2; /* GET pattern */
|
||||
}
|
||||
}
|
||||
if (ZSTR_LEN(key) == 0)
|
||||
return NULL;
|
||||
|
||||
/* Start constructing final command and append key */
|
||||
redis_cmd_init_sstr(&cmd, argc, ZEND_STRL("SORT"));
|
||||
redis_cmd_append_sstr_key(&cmd, key, keylen, redis_sock, NULL);
|
||||
cmd = redis_cmd_create_literal(redis_sock, "SORT");
|
||||
if (!redis_cmd_cat_key_zstr(cmd, key)) {
|
||||
redis_cmd_free(cmd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* BY pattern */
|
||||
if (pattern && patternlen) {
|
||||
redis_cmd_append_sstr(&cmd, ZEND_STRL("BY"));
|
||||
redis_cmd_append_sstr(&cmd, pattern, patternlen);
|
||||
if (pattern && ZSTR_LEN(pattern)) {
|
||||
redis_cmd_cat_literal(cmd, "BY");
|
||||
redis_cmd_cat_zstr(cmd, pattern);
|
||||
}
|
||||
|
||||
/* LIMIT offset count */
|
||||
if (offset >= 0 && count >= 0) {
|
||||
redis_cmd_append_sstr(&cmd, ZEND_STRL("LIMIT"));
|
||||
redis_cmd_append_sstr_long(&cmd, offset);
|
||||
redis_cmd_append_sstr_long(&cmd, count);
|
||||
redis_cmd_cat_literal(cmd, "LIMIT");
|
||||
redis_cmd_cat_long(cmd, offset);
|
||||
redis_cmd_cat_long(cmd, count);
|
||||
}
|
||||
|
||||
/* Handle any number of GET pattern arguments we've been passed */
|
||||
@@ -1424,74 +1456,61 @@ generic_sort_cmd(INTERNAL_FUNCTION_PARAMETERS, int desc, int alpha)
|
||||
if (Z_TYPE_P(zget) == IS_ARRAY) {
|
||||
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zget), zele) {
|
||||
zpattern = zval_get_string(zele);
|
||||
redis_cmd_append_sstr(&cmd, ZEND_STRL("GET"));
|
||||
redis_cmd_append_sstr(&cmd, ZSTR_VAL(zpattern), ZSTR_LEN(zpattern));
|
||||
redis_cmd_cat_literal(cmd, "GET");
|
||||
redis_cmd_cat_zstr(cmd, zpattern);
|
||||
zend_string_release(zpattern);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} else {
|
||||
zpattern = zval_get_string(zget);
|
||||
redis_cmd_append_sstr(&cmd, ZEND_STRL("GET"));
|
||||
redis_cmd_append_sstr(&cmd, ZSTR_VAL(zpattern), ZSTR_LEN(zpattern));
|
||||
redis_cmd_cat_literal(cmd, "GET");
|
||||
redis_cmd_cat_zstr(cmd, zpattern);
|
||||
zend_string_release(zpattern);
|
||||
}
|
||||
}
|
||||
|
||||
/* Append optional DESC and ALPHA modifiers */
|
||||
if (desc) redis_cmd_append_sstr(&cmd, ZEND_STRL("DESC"));
|
||||
if (alpha) redis_cmd_append_sstr(&cmd, ZEND_STRL("ALPHA"));
|
||||
if (desc) redis_cmd_cat_literal(cmd, "DESC");
|
||||
if (alpha) redis_cmd_cat_literal(cmd, "ALPHA");
|
||||
|
||||
/* Finally append STORE if we've got it */
|
||||
if (store && storelen) {
|
||||
redis_cmd_append_sstr(&cmd, ZEND_STRL("STORE"));
|
||||
redis_cmd_append_sstr_key(&cmd, store, storelen, redis_sock, NULL);
|
||||
}
|
||||
|
||||
if (redis_process_request(redis_sock, cmd.c, cmd.len) != SUCCESS) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (IS_ATOMIC(redis_sock)) {
|
||||
if (redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
|
||||
redis_sock, NULL, NULL) < 0)
|
||||
{
|
||||
RETURN_FALSE;
|
||||
if (store && ZSTR_LEN(store)) {
|
||||
redis_cmd_cat_literal(cmd, "STORE");
|
||||
if (!redis_cmd_cat_key_zstr(cmd, store)) {
|
||||
redis_cmd_free(cmd);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
REDIS_PROCESS_RESPONSE_CLOSURE(redis_read_variant_reply, NULL);
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/* {{{ proto array Redis::sortAsc(string key, string pattern, string get,
|
||||
* int start, int end, bool getList]) */
|
||||
PHP_METHOD(Redis, sortAsc)
|
||||
{
|
||||
generic_sort_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
|
||||
}
|
||||
/* }}} */
|
||||
#define REDIS_SORT_CMD_FUNC(name, desc, alpha) \
|
||||
RedisCmd * \
|
||||
redis_##name##_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock) { \
|
||||
return generic_sort_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, \
|
||||
desc, alpha); \
|
||||
}
|
||||
|
||||
/* {{{ proto array Redis::sortAscAlpha(string key, string pattern, string get,
|
||||
* int start, int end, bool getList]) */
|
||||
PHP_METHOD(Redis, sortAscAlpha)
|
||||
{
|
||||
generic_sort_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
|
||||
}
|
||||
/* }}} */
|
||||
REDIS_SORT_CMD_FUNC(sort_asc_numeric, 0, 0)
|
||||
REDIS_SORT_CMD_FUNC(sort_asc_alpha, 0, 1)
|
||||
REDIS_SORT_CMD_FUNC(sort_desc_numeric, 1, 0)
|
||||
REDIS_SORT_CMD_FUNC(sort_desc_alpha, 1, 1)
|
||||
|
||||
/* {{{ proto array Redis::sortDesc(string key, string pattern, string get,
|
||||
* int start, int end, bool getList]) */
|
||||
PHP_METHOD(Redis, sortDesc)
|
||||
{
|
||||
generic_sort_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
|
||||
PHP_METHOD(Redis, sortAsc) {
|
||||
REDIS_PROCESS_CMD(sort_asc_numeric, redis_read_variant_reply);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto array Redis::sortDescAlpha(string key, string pattern, string get,
|
||||
* int start, int end, bool getList]) */
|
||||
PHP_METHOD(Redis, sortDescAlpha)
|
||||
{
|
||||
generic_sort_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1);
|
||||
PHP_METHOD(Redis, sortAscAlpha){
|
||||
REDIS_PROCESS_CMD(sort_asc_alpha, redis_read_variant_reply);
|
||||
}
|
||||
|
||||
PHP_METHOD(Redis, sortDesc) {
|
||||
REDIS_PROCESS_CMD(sort_desc_numeric, redis_read_variant_reply);
|
||||
}
|
||||
|
||||
PHP_METHOD(Redis, sortDescAlpha) {
|
||||
REDIS_PROCESS_CMD(sort_desc_alpha, redis_read_variant_reply);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto array Redis::expire(string key, int timeout) */
|
||||
PHP_METHOD(Redis, expire) {
|
||||
@@ -2122,8 +2141,8 @@ PHP_METHOD(Redis, multi)
|
||||
/* Don't want to do anything if we're already in MULTI mode */
|
||||
if (!IS_MULTI(redis_sock)) {
|
||||
if (IS_PIPELINE(redis_sock)) {
|
||||
pipeline_enqueue_command(redis_sock, ZEND_STRL(RESP_MULTI_CMD));
|
||||
redis_save_callback(redis_sock, NULL, NULL);
|
||||
pipeline_enqueue_cmd_strl(redis_sock, ZEND_STRL(RESP_MULTI_CMD));
|
||||
redis_save_callback(redis_sock, NULL, redis_empty_ctx);
|
||||
redis_sock->mode |= MULTI;
|
||||
} else {
|
||||
if (redis_sock_write(redis_sock, ZEND_STRL(RESP_MULTI_CMD)) < 0) {
|
||||
@@ -2222,8 +2241,8 @@ PHP_METHOD(Redis, exec)
|
||||
|
||||
if (IS_MULTI(redis_sock)) {
|
||||
if (IS_PIPELINE(redis_sock)) {
|
||||
pipeline_enqueue_command(redis_sock, ZEND_STRL(RESP_EXEC_CMD));
|
||||
redis_save_callback(redis_sock, NULL, NULL);
|
||||
pipeline_enqueue_cmd_strl(redis_sock, ZEND_STRL(RESP_EXEC_CMD));
|
||||
redis_save_callback(redis_sock, NULL, redis_empty_ctx);
|
||||
redis_sock->mode &= ~MULTI;
|
||||
RETURN_ZVAL(getThis(), 1, 0);
|
||||
}
|
||||
@@ -2910,36 +2929,21 @@ PHP_METHOD(Redis, client) {
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto mixed Redis::rawcommand(string $command, [ $arg1 ... $argN]) */
|
||||
PHP_METHOD(Redis, rawcommand) {
|
||||
int argc, cmd_len;
|
||||
char *cmd = NULL;
|
||||
RedisSock *redis_sock;
|
||||
zval *z_args;
|
||||
static RedisCmd *
|
||||
redis_rawcommand_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock) {
|
||||
zval *argv;
|
||||
int argc;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, -1)
|
||||
Z_PARAM_VARIADIC('+', z_args, argc)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
Z_PARAM_VARIADIC('+', argv, argc)
|
||||
ZEND_PARSE_PARAMETERS_END_EX(return NULL);
|
||||
|
||||
if (redis_build_raw_cmd(z_args, argc, &cmd, &cmd_len) < 0 ||
|
||||
(redis_sock = redis_sock_get(getThis(), 0)) == NULL
|
||||
) {
|
||||
if (cmd) efree(cmd);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (redis_process_request(redis_sock, cmd, cmd_len) != SUCCESS) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (IS_ATOMIC(redis_sock)) {
|
||||
redis_read_raw_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
|
||||
redis_sock,NULL,NULL);
|
||||
} else {
|
||||
REDIS_PROCESS_RESPONSE_CLOSURE(redis_read_variant_reply, NULL);
|
||||
}
|
||||
return redis_build_raw_cmd(argv, argc);
|
||||
}
|
||||
|
||||
PHP_METHOD(Redis, rawcommand) {
|
||||
REDIS_PROCESS_CMD(rawcommand, redis_read_raw_variant_reply);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto array Redis::command()
|
||||
* proto array Redis::command('info', string cmd)
|
||||
@@ -2956,18 +2960,12 @@ PHP_METHOD(Redis, copy) {
|
||||
/* }}} */
|
||||
|
||||
/* Helper to format any combination of SCAN arguments */
|
||||
static int
|
||||
redis_build_scan_cmd(char **cmd, REDIS_SCAN_TYPE type, char *key, int key_len,
|
||||
uint64_t cursor, char *pattern, int pattern_len, int count,
|
||||
zend_string *match_type)
|
||||
static RedisCmd *
|
||||
redis_build_scan_cmd(REDIS_SCAN_TYPE type, zend_string *key, uint64_t cursor,
|
||||
zend_string *pattern, int count, zend_string *match_type)
|
||||
{
|
||||
smart_string cmdstr = {0};
|
||||
RedisCmd *cmd;
|
||||
char *keyword;
|
||||
int argc;
|
||||
|
||||
/* Count our arguments +1 for key if it's got one, and + 2 for pattern */
|
||||
/* or count given that they each carry keywords with them. */
|
||||
argc = 1 + (key_len > 0) + (pattern_len > 0 ? 2 : 0) + (count > 0 ? 2 : 0) + (match_type ? 2 : 0);
|
||||
|
||||
/* Turn our type into a keyword */
|
||||
switch(type) {
|
||||
@@ -2986,63 +2984,61 @@ redis_build_scan_cmd(char **cmd, REDIS_SCAN_TYPE type, char *key, int key_len,
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Start the command */
|
||||
redis_cmd_init_sstr(&cmdstr, argc, keyword, strlen(keyword));
|
||||
if (key_len) redis_cmd_append_sstr(&cmdstr, key, key_len);
|
||||
redis_cmd_append_sstr_u64(&cmdstr, cursor);
|
||||
cmd = redis_cmd_create(NULL, keyword, strlen(keyword));
|
||||
if (key && ZSTR_LEN(key) > 0) redis_cmd_cat_zstr(cmd, key);
|
||||
redis_cmd_cat_u64(cmd, cursor);
|
||||
|
||||
/* Append COUNT if we've got it */
|
||||
if(count) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "COUNT");
|
||||
redis_cmd_append_sstr_int(&cmdstr, count);
|
||||
redis_cmd_cat_literal(cmd, "COUNT");
|
||||
redis_cmd_cat_long(cmd, count);
|
||||
}
|
||||
|
||||
/* Append MATCH if we've got it */
|
||||
if(pattern_len) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "MATCH");
|
||||
redis_cmd_append_sstr(&cmdstr, pattern, pattern_len);
|
||||
if(pattern && ZSTR_LEN(pattern) > 0) {
|
||||
redis_cmd_cat_literal(cmd, "MATCH");
|
||||
redis_cmd_cat_zstr(cmd, pattern);
|
||||
}
|
||||
|
||||
if (match_type) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "TYPE");
|
||||
redis_cmd_append_sstr(&cmdstr, ZSTR_VAL(match_type), ZSTR_LEN(match_type));
|
||||
redis_cmd_cat_literal(cmd, "TYPE");
|
||||
redis_cmd_cat_zstr(cmd, match_type);
|
||||
}
|
||||
|
||||
/* Return our command length */
|
||||
*cmd = cmdstr.c;
|
||||
return cmdstr.len;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/* {{{ proto redis::scan(&$cursor, [pattern, [count, [type]]]) */
|
||||
PHP_REDIS_API void
|
||||
generic_scan_cmd(INTERNAL_FUNCTION_PARAMETERS, REDIS_SCAN_TYPE type) {
|
||||
zend_string *key = NULL, *pattern = NULL;
|
||||
zend_string *match_type = NULL;
|
||||
zval *object, *z_cursor;
|
||||
RedisSock *redis_sock;
|
||||
HashTable *hash;
|
||||
char *pattern = NULL, *cmd, *key = NULL;
|
||||
int cmd_len, num_elements, key_free = 0, pattern_free = 0;
|
||||
size_t key_len = 0, pattern_len = 0;
|
||||
zend_string *match_type = NULL;
|
||||
zend_bool pattern_free = 0;
|
||||
zend_long count = 0;
|
||||
zend_bool completed;
|
||||
HashTable *hash;
|
||||
int num_elements;
|
||||
uint64_t cursor;
|
||||
RedisCmd *cmd;
|
||||
|
||||
/* Different prototype depending on if this is a key based scan */
|
||||
if(type != TYPE_SCAN) {
|
||||
// Requires a key
|
||||
if(zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
|
||||
"Os!z/|s!l", &object, redis_ce, &key,
|
||||
&key_len, &z_cursor, &pattern,
|
||||
&pattern_len, &count)==FAILURE)
|
||||
"OS!z/|S!l", &object, redis_ce, &key,
|
||||
&z_cursor, &pattern, &count)==FAILURE)
|
||||
{
|
||||
RETURN_FALSE;
|
||||
}
|
||||
} else {
|
||||
// Doesn't require a key
|
||||
if(zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
|
||||
"Oz/|s!lS!", &object, redis_ce, &z_cursor,
|
||||
&pattern, &pattern_len, &count, &match_type)
|
||||
== FAILURE)
|
||||
"Oz/|S!lS!", &object, redis_ce, &z_cursor,
|
||||
&pattern, &count, &match_type) == FAILURE)
|
||||
{
|
||||
RETURN_FALSE;
|
||||
}
|
||||
@@ -3065,13 +3061,12 @@ generic_scan_cmd(INTERNAL_FUNCTION_PARAMETERS, REDIS_SCAN_TYPE type) {
|
||||
if (completed)
|
||||
RETURN_FALSE;
|
||||
|
||||
/* Prefix our key if we've got one and we have a prefix set */
|
||||
if(key_len) {
|
||||
key_free = redis_key_prefix(redis_sock, &key, &key_len);
|
||||
}
|
||||
if(key)
|
||||
key = redis_key_prefix_zstr(redis_sock, key);
|
||||
|
||||
if (redis_sock->scan & REDIS_SCAN_PREFIX) {
|
||||
pattern_free = redis_key_prefix(redis_sock, &pattern, &pattern_len);
|
||||
if (pattern && redis_sock->scan & REDIS_SCAN_PREFIX) {
|
||||
pattern = redis_key_prefix_zstr(redis_sock, pattern);
|
||||
pattern_free = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3091,31 +3086,32 @@ generic_scan_cmd(INTERNAL_FUNCTION_PARAMETERS, REDIS_SCAN_TYPE type) {
|
||||
}
|
||||
|
||||
// Format our SCAN command
|
||||
cmd_len = redis_build_scan_cmd(&cmd, type, key, key_len, cursor,
|
||||
pattern, pattern_len, count, match_type);
|
||||
cmd = redis_build_scan_cmd(type, key, cursor, pattern, count, match_type);
|
||||
|
||||
if (redis_process_request(redis_sock, cmd, cmd_len) != SUCCESS) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if(redis_sock_read_scan_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
|
||||
redis_sock,type, &cursor) < 0)
|
||||
if (redis_process_request(redis_sock, cmd) != SUCCESS ||
|
||||
redis_sock_read_scan_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
|
||||
redis_sock, type, &cursor) < 0)
|
||||
{
|
||||
if(key_free) efree(key);
|
||||
if (key)
|
||||
zend_string_release(key);
|
||||
if (pattern_free)
|
||||
zend_string_release(pattern);
|
||||
redis_cmd_free(cmd);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* Get the number of elements */
|
||||
hash = Z_ARRVAL_P(return_value);
|
||||
num_elements = zend_hash_num_elements(hash);
|
||||
|
||||
redis_cmd_free(cmd);
|
||||
} while (redis_sock->scan & REDIS_SCAN_RETRY && cursor != 0 &&
|
||||
num_elements == 0);
|
||||
num_elements == 0);
|
||||
|
||||
/* Free our pattern if it was prefixed */
|
||||
if (pattern_free) efree(pattern);
|
||||
|
||||
/* Free our key if it was prefixed */
|
||||
if(key_free) efree(key);
|
||||
if (pattern_free)
|
||||
zend_string_release(pattern);
|
||||
if(key)
|
||||
zend_string_release(key);
|
||||
|
||||
/* Update our cursor reference */
|
||||
redisSetScanCursor(z_cursor, cursor);
|
||||
|
||||
+3
-3
@@ -64,9 +64,9 @@ ra_load_hosts(RedisArray *ra, HashTable *hosts, zend_string *user,
|
||||
redis = PHPREDIS_ZVAL_GET_OBJECT(redis_object, &ra->redis[i]);
|
||||
|
||||
/* create socket */
|
||||
redis->sock = redis_sock_create(host, host_len, port, ra->connect_timeout,
|
||||
ra->read_timeout, ra->pconnect, NULL,
|
||||
retry_interval);
|
||||
redis->sock = redis_sock_create(REDIS_SOCK_ARRAY, host, host_len, port,
|
||||
ra->connect_timeout, ra->read_timeout,
|
||||
ra->pconnect, NULL, retry_interval);
|
||||
|
||||
redis_sock_set_auth(redis->sock, user, pass);
|
||||
|
||||
|
||||
+317
-337
File diff suppressed because it is too large
Load Diff
+490
@@ -0,0 +1,490 @@
|
||||
#include "php.h"
|
||||
#include "common.h"
|
||||
#include "redis_cmd.h"
|
||||
#include "library.h"
|
||||
#include "cluster_library.h"
|
||||
#include "Zend/zend_smart_str.h"
|
||||
|
||||
// Max possible: "*4294967295\r\n"
|
||||
#define REDIS_MB_HDR "PHPREDISPHP\r\n"
|
||||
|
||||
#define REDIS_MB_HDR_LEN (sizeof(REDIS_MB_HDR) - 1)
|
||||
|
||||
typedef struct RespHeader {
|
||||
char *str;
|
||||
size_t len;
|
||||
} RespHeader;
|
||||
|
||||
static const RespHeader bulk_header[] = {
|
||||
{ZEND_STRL("$0\r\n")}, {ZEND_STRL("$1\r\n")}, {ZEND_STRL("$2\r\n")},
|
||||
{ZEND_STRL("$3\r\n")}, {ZEND_STRL("$4\r\n")}, {ZEND_STRL("$5\r\n")},
|
||||
{ZEND_STRL("$6\r\n")}, {ZEND_STRL("$7\r\n")}, {ZEND_STRL("$8\r\n")},
|
||||
{ZEND_STRL("$9\r\n")}, {ZEND_STRL("$10\r\n")}, {ZEND_STRL("$11\r\n")},
|
||||
{ZEND_STRL("$12\r\n")}, {ZEND_STRL("$13\r\n")}, {ZEND_STRL("$14\r\n")},
|
||||
{ZEND_STRL("$15\r\n")}, {ZEND_STRL("$16\r\n")}, {ZEND_STRL("$17\r\n")},
|
||||
{ZEND_STRL("$18\r\n")}, {ZEND_STRL("$19\r\n")}, {ZEND_STRL("$20\r\n")},
|
||||
{ZEND_STRL("$21\r\n")}, {ZEND_STRL("$22\r\n")}, {ZEND_STRL("$23\r\n")},
|
||||
{ZEND_STRL("$24\r\n")}, {ZEND_STRL("$25\r\n")}, {ZEND_STRL("$26\r\n")},
|
||||
{ZEND_STRL("$27\r\n")}, {ZEND_STRL("$28\r\n")}, {ZEND_STRL("$29\r\n")},
|
||||
{ZEND_STRL("$30\r\n")}, {ZEND_STRL("$31\r\n")}, {ZEND_STRL("$32\r\n")},
|
||||
};
|
||||
|
||||
#define BULK_HDR_STRL(n) bulk_header[n].str, bulk_header[n].len
|
||||
|
||||
/* zend_print_ulong_to_buf will null terminate the string which we do not want */
|
||||
static inline char *print_u64_to_buf(char *buf, uint64_t n) {
|
||||
do {
|
||||
*--buf = (char)(n % 10) + '0';
|
||||
n /= 10;
|
||||
} while (n > 0);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* zend_print_ulong_to_buf will null terminate the string which we do not want */
|
||||
static inline char *print_u32_to_buf(char *buf, uint32_t n) {
|
||||
return print_u64_to_buf(buf, n);
|
||||
}
|
||||
|
||||
static RedisCmd *redis_cmd_alloc(RedisSock *redis_sock) {
|
||||
RedisCmd *cmd;
|
||||
|
||||
cmd = ecalloc(1, sizeof(*cmd));
|
||||
cmd->redis_sock = redis_sock;
|
||||
cmd->slot = -1;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
RedisCmd *
|
||||
redis_cmd_create(RedisSock *redis_sock, const char *kw, size_t kwlen) {
|
||||
RedisCmd *cmd;
|
||||
|
||||
cmd = redis_cmd_alloc(redis_sock);
|
||||
|
||||
smart_string_appendl_ex(&cmd->s, ZEND_STRL(REDIS_MB_HDR), 0);
|
||||
|
||||
redis_cmd_cat_str(cmd, kw, kwlen);
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void redis_cmd_reset(RedisCmd *cmd, const char *kw, size_t kwlen) {
|
||||
redis_cmd_free_ctx(cmd);
|
||||
smart_string_reset(&cmd->s);
|
||||
|
||||
cmd->argc = 0;
|
||||
cmd->head = NULL;
|
||||
cmd->slot = -1;
|
||||
|
||||
smart_string_appendl_ex(&cmd->s, ZEND_STRL(REDIS_MB_HDR), 0);
|
||||
redis_cmd_cat_str(cmd, kw, kwlen);
|
||||
}
|
||||
|
||||
void redis_cmd_free_ctx(RedisCmd *cmd) {
|
||||
redis_cmd_ctx_free(cmd->ctx);
|
||||
memset(&cmd->ctx, 0, sizeof(RedisCmdCtx));
|
||||
}
|
||||
|
||||
void redis_cmd_free_ex(RedisCmd *cmd, int free_ctx) {
|
||||
if (cmd == NULL)
|
||||
return;
|
||||
|
||||
smart_string_free(&cmd->s);
|
||||
|
||||
if (free_ctx) {
|
||||
redis_cmd_free_ctx(cmd);
|
||||
}
|
||||
|
||||
efree(cmd);
|
||||
}
|
||||
|
||||
static void redis_cmd_finalize(RedisCmd *cmd) {
|
||||
char *eptr;
|
||||
|
||||
if (cmd->head != NULL)
|
||||
return;
|
||||
|
||||
if (cmd->redis_sock != NULL && cmd->redis_sock->type == REDIS_SOCK_CLUSTER) {
|
||||
ZEND_ASSERT(cmd->slot >= 0 && cmd->slot < REDIS_CLUSTER_SLOTS);
|
||||
|
||||
if (UNEXPECTED(cmd->slot < 0 || cmd->slot >= REDIS_CLUSTER_SLOTS)) {
|
||||
zend_error_noreturn(E_ERROR, "Invalid Redis Cluster slot %d", cmd->slot);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the end pointer right before the trailing \r\n and print argc */
|
||||
eptr = cmd->s.c + REDIS_MB_HDR_LEN - 2;
|
||||
cmd->head = print_u32_to_buf(eptr, cmd->argc);
|
||||
|
||||
/* Prepend the multibulk reply-type */
|
||||
*--cmd->head = '*';
|
||||
|
||||
/* Null-terminate the string */
|
||||
smart_string_0(&cmd->s);
|
||||
}
|
||||
|
||||
void redis_cmd_cat_str(RedisCmd *cmd, const char *str, size_t len) {
|
||||
if (cmd->argc == UINT32_MAX) {
|
||||
zend_error_noreturn(E_ERROR, "Too many arguments");
|
||||
}
|
||||
|
||||
if (EXPECTED(len < sizeof(bulk_header) / sizeof(RespHeader))) {
|
||||
smart_string_appendl_ex(&cmd->s, BULK_HDR_STRL(len), 0);
|
||||
} else {
|
||||
smart_string_appendc(&cmd->s, '$');
|
||||
smart_string_append_unsigned(&cmd->s, len);
|
||||
smart_string_appendl_ex(&cmd->s, ZEND_STRL("\r\n"), 0);
|
||||
}
|
||||
|
||||
smart_string_appendl(&cmd->s, str, len);
|
||||
smart_string_appendl_ex(&cmd->s, ZEND_STRL("\r\n"), 0);
|
||||
|
||||
cmd->argc++;
|
||||
}
|
||||
|
||||
void redis_cmd_cat_arrkey(RedisCmd *cmd, zend_string *str, zend_ulong idx) {
|
||||
if (str) {
|
||||
redis_cmd_cat_zstr(cmd, str);
|
||||
} else {
|
||||
redis_cmd_cat_ulong(cmd, idx);
|
||||
}
|
||||
}
|
||||
|
||||
static inline zend_bool
|
||||
update_slot(RedisCmd *cmd, const char *key, size_t keylen) {
|
||||
short slot;
|
||||
|
||||
if (cmd->redis_sock == NULL || cmd->redis_sock->type != REDIS_SOCK_CLUSTER)
|
||||
return 1;
|
||||
|
||||
slot = cluster_hash_key(key, keylen);
|
||||
|
||||
if (cmd->slot == -1) {
|
||||
cmd->slot = slot;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return cmd->slot == slot ? 1 : 0;
|
||||
}
|
||||
|
||||
zend_bool redis_cmd_cat_key_str(RedisCmd *cmd, const char *key, size_t len) {
|
||||
char *aux = (char*)key;
|
||||
int keyfree;
|
||||
|
||||
if (UNEXPECTED(cmd->redis_sock == NULL)) {
|
||||
redis_cmd_cat_str(cmd, key, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
keyfree = redis_key_prefix(cmd->redis_sock, &aux, &len);
|
||||
|
||||
if (!update_slot(cmd, aux, len)) {
|
||||
if (keyfree) efree(aux);
|
||||
return 0;
|
||||
}
|
||||
|
||||
redis_cmd_cat_str(cmd, aux, len);
|
||||
if (keyfree) efree(aux);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
zend_bool redis_cmd_cat_key_zval(RedisCmd *cmd, zval *zv) {
|
||||
zend_string *zstr, *tmp;
|
||||
int ret;
|
||||
|
||||
zstr = zval_get_tmp_string(zv, &tmp);
|
||||
ret = redis_cmd_cat_key_zstr(cmd, zstr);
|
||||
zend_tmp_string_release(tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
zend_bool redis_cmd_cat_key_zstr(RedisCmd *cmd, zend_string *key) {
|
||||
if (UNEXPECTED(cmd->redis_sock == NULL)) {
|
||||
redis_cmd_cat_zstr(cmd, key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
key = redis_key_prefix_zstr(cmd->redis_sock, key);
|
||||
|
||||
if (!update_slot(cmd, ZSTR_VAL(key), ZSTR_LEN(key))) {
|
||||
zend_string_release(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
redis_cmd_cat_zstr(cmd, key);
|
||||
zend_string_release(key);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
zend_bool redis_cmd_cat_key_long(RedisCmd *cmd, zend_long lval) {
|
||||
char buf[21], *key;
|
||||
int keyfree;
|
||||
size_t len;
|
||||
|
||||
key = zend_print_long_to_buf(buf + sizeof(buf) - 1, lval);
|
||||
len = buf + sizeof(buf) - 1 - key;
|
||||
|
||||
if (UNEXPECTED(cmd->redis_sock == NULL)) {
|
||||
redis_cmd_cat_str(cmd, key, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
keyfree = redis_key_prefix(cmd->redis_sock, &key, &len);
|
||||
|
||||
if (!update_slot(cmd, key, len)) {
|
||||
if (keyfree) efree(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
redis_cmd_cat_str(cmd, key, len);
|
||||
if (keyfree) efree(key);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
zend_bool redis_cmd_cat_key_arrkey(RedisCmd *cmd, zend_string *str, zend_ulong idx) {
|
||||
char buf[21], *key;
|
||||
int keyfree;
|
||||
size_t len;
|
||||
|
||||
if (str == NULL) {
|
||||
key = zend_print_ulong_to_buf(buf + sizeof(buf) - 1, idx);
|
||||
len = buf + sizeof(buf) - 1 - key;
|
||||
} else {
|
||||
key = ZSTR_VAL(str);
|
||||
len = ZSTR_LEN(str);
|
||||
}
|
||||
|
||||
if (UNEXPECTED(cmd->redis_sock == NULL)) {
|
||||
redis_cmd_cat_str(cmd, key, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
keyfree = redis_key_prefix(cmd->redis_sock, &key, &len);
|
||||
if (!update_slot(cmd, key, len)) {
|
||||
if (keyfree) efree(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
redis_cmd_cat_str(cmd, key, len);
|
||||
if (keyfree) efree(key);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void redis_cmd_cat_zstr(RedisCmd *cmd, zend_string *str) {
|
||||
redis_cmd_cat_str(cmd, ZSTR_VAL(str), ZSTR_LEN(str));
|
||||
}
|
||||
|
||||
void redis_cmd_cat_long(RedisCmd *cmd, zend_long lval) {
|
||||
char buf[21], *res;
|
||||
int len;
|
||||
|
||||
res = zend_print_long_to_buf(buf + sizeof(buf) - 1, lval);
|
||||
len = buf + sizeof(buf) - 1 - res;
|
||||
|
||||
redis_cmd_cat_str(cmd, res, len);
|
||||
}
|
||||
|
||||
void redis_cmd_cat_ulong(RedisCmd *cmd, zend_ulong lval) {
|
||||
char buf[21], *res;
|
||||
int len;
|
||||
|
||||
res = zend_print_ulong_to_buf(buf + sizeof(buf) - 1, lval);
|
||||
len = buf + sizeof(buf) - 1 - res;
|
||||
|
||||
redis_cmd_cat_str(cmd, res, len);
|
||||
}
|
||||
|
||||
void redis_cmd_cat_u64(RedisCmd *cmd, uint64_t u64) {
|
||||
char buf[21], *res;
|
||||
int len;
|
||||
|
||||
res = print_u64_to_buf(buf + sizeof(buf) - 1, u64);
|
||||
len = buf + sizeof(buf) - 1 - res;
|
||||
|
||||
redis_cmd_cat_str(cmd, res, len);
|
||||
}
|
||||
|
||||
void redis_cmd_cat_u32(RedisCmd *cmd, uint32_t u32) {
|
||||
return redis_cmd_cat_u64(cmd, u32);
|
||||
}
|
||||
|
||||
void redis_cmd_cat_double(RedisCmd *cmd, double dval) {
|
||||
#if PHP_VERSION_ID >= 80200
|
||||
char buf[ZEND_DOUBLE_MAX_LENGTH], *nul;
|
||||
|
||||
zend_gcvt(dval, 17, '.', 'e', buf);
|
||||
|
||||
nul = memchr(buf, 0, sizeof(buf));
|
||||
ZEND_ASSERT(nul != NULL);
|
||||
|
||||
redis_cmd_cat_str(cmd, buf, nul - buf);
|
||||
|
||||
#else
|
||||
char buf[64], *p;
|
||||
int len;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "%.17g", dval);
|
||||
|
||||
/* Legacy behavior locale fixup */
|
||||
if ((p = strchr(buf, ',')) != NULL)
|
||||
*p = '.';
|
||||
|
||||
redis_cmd_cat_str(cmd, buf, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
void redis_cmd_cat_zval_zstr(RedisCmd *cmd, zval *zv) {
|
||||
zend_string *zstr, *tmp;
|
||||
|
||||
switch (Z_TYPE_P(zv)) {
|
||||
case IS_FALSE:
|
||||
redis_cmd_cat_str(cmd, ZEND_STRL("0"));
|
||||
return;
|
||||
case IS_TRUE:
|
||||
redis_cmd_cat_str(cmd, ZEND_STRL("1"));
|
||||
return;
|
||||
case IS_LONG:
|
||||
redis_cmd_cat_long(cmd, Z_LVAL_P(zv));
|
||||
return;
|
||||
case IS_DOUBLE:
|
||||
redis_cmd_cat_double(cmd, Z_DVAL_P(zv));
|
||||
return;
|
||||
default:
|
||||
zstr = zval_get_tmp_string(zv, &tmp);
|
||||
redis_cmd_cat_zstr(cmd, zstr);
|
||||
zend_tmp_string_release(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void redis_cmd_cat_zval(RedisCmd *cmd, zval *zv) {
|
||||
int valfree;
|
||||
size_t len;
|
||||
char *str;
|
||||
|
||||
if (UNEXPECTED(cmd->redis_sock == NULL)) {
|
||||
redis_cmd_cat_zval_zstr(cmd, zv);
|
||||
return;
|
||||
}
|
||||
|
||||
valfree = redis_pack(cmd->redis_sock, zv, &str, &len);
|
||||
redis_cmd_cat_str(cmd, str, len);
|
||||
|
||||
if (valfree)
|
||||
efree(str);
|
||||
}
|
||||
|
||||
/* A printf like method to construct a Redis RESP command. It has been extended
|
||||
* to take a few different format specifiers that are convenient to phpredis.
|
||||
*
|
||||
* s - C string followed by length as a
|
||||
* S - Pointer to a zend_string
|
||||
* k - Same as 's' but the value will be prefixed if phpredis is set up do do
|
||||
* that and the working slot will be set if it has been passed.
|
||||
* K - Same as 'S' but the value will be prefixed if phpredis is set up do do
|
||||
* v - A z_val which will be serialized if phpredis is configured to serialize.
|
||||
* f - A double value
|
||||
* F - Alias to 'f'
|
||||
* i - An integer
|
||||
* d - Alias to 'i'
|
||||
* l - A long
|
||||
* L - Alias to 'l'
|
||||
*/
|
||||
RedisCmd *redis_cmd_fmt(RedisSock *redis_sock, char *kw, char *fmt, ...) {
|
||||
RedisCmd *ret;
|
||||
va_list ap;
|
||||
size_t len;
|
||||
char *str;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
ret = redis_cmd_create(redis_sock, kw, strlen(kw));
|
||||
|
||||
while (*fmt) {
|
||||
switch (*fmt) {
|
||||
case 's':
|
||||
str = va_arg(ap, char*);
|
||||
len = va_arg(ap, size_t);
|
||||
redis_cmd_cat_str(ret, str, len);
|
||||
break;
|
||||
case 'S':
|
||||
redis_cmd_cat_zstr(ret, va_arg(ap, zend_string*));
|
||||
break;
|
||||
case 'k':
|
||||
str = va_arg(ap, char*);
|
||||
len = va_arg(ap, size_t);
|
||||
redis_cmd_cat_key_str(ret, str, len);
|
||||
break;
|
||||
case 'K':
|
||||
redis_cmd_cat_key_zstr(ret, va_arg(ap, zend_string*));
|
||||
break;
|
||||
case 'v':
|
||||
redis_cmd_cat_zval(ret, va_arg(ap, zval*));
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
redis_cmd_cat_double(ret, va_arg(ap, double));
|
||||
break;
|
||||
case 'i':
|
||||
case 'd':
|
||||
redis_cmd_cat_long(ret, va_arg(ap, int));
|
||||
break;
|
||||
case 'l':
|
||||
case 'L':
|
||||
redis_cmd_cat_long(ret, va_arg(ap, zend_long));
|
||||
break;
|
||||
}
|
||||
|
||||
fmt++;
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void redis_cmd_set_ctx_ex(RedisCmd *cmd, void *ctx, RedisCmdCtxDtor *dtor) {
|
||||
cmd->ctx.ptr = ctx;
|
||||
cmd->ctx.dtor = dtor;
|
||||
}
|
||||
|
||||
const char *redis_cmd_str(RedisCmd *cmd) {
|
||||
redis_cmd_finalize(cmd);
|
||||
|
||||
return cmd->head;
|
||||
}
|
||||
|
||||
size_t redis_cmd_len(RedisCmd *cmd) {
|
||||
redis_cmd_finalize(cmd);
|
||||
|
||||
return cmd->s.len - (cmd->head - cmd->s.c);
|
||||
}
|
||||
|
||||
void redis_cmd_randslot(RedisCmd *cmd) {
|
||||
if (cmd->redis_sock && cmd->redis_sock->type == REDIS_SOCK_CLUSTER)
|
||||
cmd->slot = rand() % REDIS_CLUSTER_MOD;
|
||||
}
|
||||
|
||||
void resp_str_cat_str(smart_str *s, const char *str, zend_ulong len) {
|
||||
smart_str_appendc(s, '$');
|
||||
smart_str_append_unsigned(s, len);
|
||||
smart_str_appendl_ex(s, ZEND_STRL("\r\n"), 0);
|
||||
smart_str_appendl(s, str, len);
|
||||
smart_str_appendl_ex(s, ZEND_STRL("\r\n"), 0);
|
||||
}
|
||||
|
||||
void resp_str_cat_cmd(smart_str *s, zend_ulong argc, const char *kw, size_t len) {
|
||||
smart_str_appendc(s, '*');
|
||||
smart_str_append_unsigned(s, 1 + argc);
|
||||
smart_str_appendl_ex(s, ZEND_STRL("\r\n"), 0);
|
||||
resp_str_cat_str(s, kw, len);
|
||||
}
|
||||
|
||||
void resp_str_cat_zstr(smart_str *s, zend_string *str) {
|
||||
resp_str_cat_str(s, ZSTR_VAL(str), ZSTR_LEN(str));
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
#ifndef REDIS_CMD_H
|
||||
#define REDIS_CMD_H
|
||||
|
||||
#include "php.h"
|
||||
#include <zend_smart_string.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
typedef struct RedisCmd {
|
||||
RedisSock *redis_sock;
|
||||
short slot;
|
||||
smart_string s;
|
||||
RedisCmdCtx ctx;
|
||||
uint32_t argc;
|
||||
char *head;
|
||||
} RedisCmd;
|
||||
|
||||
#define redis_cmd_create_literal(redis_sock, kw) \
|
||||
redis_cmd_create(redis_sock, kw, sizeof(kw) - 1)
|
||||
|
||||
#define redis_cmd_cat_literal(cmd, lit) \
|
||||
redis_cmd_cat_str(cmd, lit, sizeof(lit) - 1)
|
||||
|
||||
#define redis_cmd_cat_literal_if(cmd, opt, lit) do { \
|
||||
if (opt) \
|
||||
redis_cmd_cat_str(cmd, lit, sizeof(lit) - 1); \
|
||||
} while (0)
|
||||
|
||||
#define redis_cmd_cat_zstr_if(cmd, opt, zstr) do { \
|
||||
if (opt) \
|
||||
redis_cmd_cat_zstr(cmd, zstr); \
|
||||
} while (0)
|
||||
|
||||
RedisCmd *redis_cmd_create(RedisSock *redis_sock, const char *kw, size_t kwlen);
|
||||
void redis_cmd_reset(RedisCmd *cmd, const char *kw, size_t kwlen);
|
||||
void redis_cmd_free_ex(RedisCmd *cmd, int free_ctx);
|
||||
void redis_cmd_free_ctx(RedisCmd *cmd);
|
||||
|
||||
static inline RedisCmdCtx redis_cmd_pop_ctx(RedisCmd *cmd) {
|
||||
RedisCmdCtx ctx = cmd->ctx;
|
||||
|
||||
memset(&cmd->ctx, 0, sizeof(RedisCmdCtx));
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static inline void redis_cmd_free(RedisCmd *cmd) {
|
||||
redis_cmd_free_ex(cmd, 0);
|
||||
}
|
||||
|
||||
static inline RedisCmd *
|
||||
redis_cmd_create_zstr(RedisSock *redis_sock, zend_string *kw) {
|
||||
return redis_cmd_create(redis_sock, ZSTR_VAL(kw), ZSTR_LEN(kw));
|
||||
}
|
||||
|
||||
void redis_cmd_cat_zstr(RedisCmd *cmd, zend_string *str);
|
||||
void redis_cmd_cat_str(RedisCmd *cmd, const char *str, size_t len);
|
||||
void redis_cmd_cat_long(RedisCmd *cmd, zend_long lval);
|
||||
void redis_cmd_cat_ulong(RedisCmd *cmd, zend_ulong ulval);
|
||||
void redis_cmd_cat_u32(RedisCmd *cmd, uint32_t u32);
|
||||
void redis_cmd_cat_u64(RedisCmd *cmd, uint64_t u64);
|
||||
void redis_cmd_cat_double(RedisCmd *cmd, double dval);
|
||||
|
||||
zend_bool redis_cmd_cat_key_zval(RedisCmd *cmd, zval *zv);
|
||||
zend_bool redis_cmd_cat_key_zstr(RedisCmd *cmd, zend_string *key);
|
||||
zend_bool redis_cmd_cat_key_long(RedisCmd *cmd, zend_long key);
|
||||
zend_bool redis_cmd_cat_key_str(RedisCmd *cmd, const char *key, size_t len);
|
||||
zend_bool redis_cmd_cat_key_arrkey(RedisCmd *cmd, zend_string *str, zend_ulong idx);
|
||||
|
||||
void redis_cmd_cat_zval(RedisCmd *cmd, zval *zv);
|
||||
void redis_cmd_cat_zval_zstr(RedisCmd *cmd, zval *zv);
|
||||
|
||||
void redis_cmd_cat_arrkey(RedisCmd *cmd, zend_string *str, zend_ulong idx);
|
||||
|
||||
void redis_cmd_set_ctx_ex(RedisCmd *cmd, void *ptr, RedisCmdCtxDtor *dtor);
|
||||
|
||||
static zend_always_inline void redis_cmd_set_ctx(RedisCmd *cmd, void *ptr) {
|
||||
redis_cmd_set_ctx_ex(cmd, ptr, NULL);
|
||||
}
|
||||
|
||||
static zend_always_inline void
|
||||
redis_cmd_set_ctx_u64(RedisCmd *cmd, uint64_t u64) {
|
||||
redis_cmd_set_ctx(cmd, (void*)(uintptr_t)u64);
|
||||
}
|
||||
|
||||
void redis_cmd_randslot(RedisCmd *cmd);
|
||||
|
||||
static inline void redis_cmd_ctx_efree(void *ptr) {
|
||||
if (ptr) efree(ptr);
|
||||
}
|
||||
|
||||
RedisCmd *redis_cmd_fmt(RedisSock *redis_sock, char *kw, char *fmt, ...);
|
||||
|
||||
#define redis_cmd_fmt_literal(redis_sock, kw, fmt, ...) \
|
||||
redis_cmd_fmt(redis_sock, kw, fmt, ##__VA_ARGS__)
|
||||
|
||||
const char *redis_cmd_str(RedisCmd *cmd);
|
||||
size_t redis_cmd_len(RedisCmd *cmd);
|
||||
|
||||
/* Specialized thin wrapper around smart_str for the times we want to construct
|
||||
* one buffer with 1-N commands */
|
||||
void resp_str_cat_str(smart_str *s, const char *str, zend_ulong len);
|
||||
void resp_str_cat_cmd(smart_str *s, zend_ulong argc, const char *kw, size_t len);
|
||||
void resp_str_cat_zstr(smart_str *s, zend_string *str);
|
||||
|
||||
#define resp_str_cat_cmd_literal(s_, kw_, argc_) \
|
||||
resp_str_cat_cmd(s_, argc_, kw_, sizeof(kw_) - 1)
|
||||
#define resp_str_cat_literal(s_, lit_) \
|
||||
resp_str_cat_str(s_, lit_, sizeof(lit_) - 1)
|
||||
|
||||
#endif // REDIS_CMD_H
|
||||
+2287
-3124
File diff suppressed because it is too large
Load Diff
+137
-406
@@ -4,6 +4,7 @@
|
||||
#include "common.h"
|
||||
#include "library.h"
|
||||
#include "cluster_library.h"
|
||||
#include "redis_cmd.h"
|
||||
|
||||
/* Pick a random slot, any slot (for stuff like publish/subscribe) */
|
||||
#define CMD_RAND_SLOT(slot) \
|
||||
@@ -26,424 +27,154 @@ typedef struct subscribeContext {
|
||||
} subscribeContext;
|
||||
|
||||
/* Construct a raw command */
|
||||
int redis_build_raw_cmd(zval *z_args, int argc, char **cmd, int *cmd_len);
|
||||
RedisCmd *redis_build_raw_cmd(zval *z_args, int argc);
|
||||
|
||||
/* Construct a script command */
|
||||
smart_string *redis_build_script_cmd(smart_string *cmd, int argc, zval *z_args);
|
||||
RedisCmd *redis_build_script_cmd(int argc, zval *z_args);
|
||||
|
||||
typedef int (*redis_cmd_cb)(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
typedef RedisCmd * redis_cmd_cb(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
|
||||
typedef int (*redis_kw_cmd_cb)(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot,
|
||||
void **ctx);
|
||||
typedef RedisCmd * redis_kw_cmd_cb(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw);
|
||||
|
||||
/* Process a command but with a specific command building function
|
||||
* and keyword which is passed to us*/
|
||||
void redis_process_kw_cmd(INTERNAL_FUNCTION_PARAMETERS, const char *kw,
|
||||
redis_kw_cmd_cb cmd_cb, FailableResultCallback resp_cb,
|
||||
void *ctx);
|
||||
redis_kw_cmd_cb cmd_cb, FailableResultCallback resp_cb);
|
||||
|
||||
#define REDIS_PROCESS_KW_CMD(kw, cmdfunc, resp_func) \
|
||||
redis_process_kw_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, kw, \
|
||||
cmdfunc, resp_func, NULL)
|
||||
|
||||
/* Redis command generics. Many commands share common prototypes meaning that
|
||||
* we can write one function to handle all of them. For example, there are
|
||||
* many COMMAND key value commands, or COMMAND key commands. */
|
||||
|
||||
int redis_replicaof_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot,
|
||||
void **ctx);
|
||||
|
||||
int redis_empty_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_opt_str_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_str_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_key_long_val_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_key_long_str_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_kv_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_key_str_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_key_key_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_key_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_key_long_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_long_long_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_key_long_long_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_key_str_str_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_key_dbl_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_key_varval_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_key_val_arr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_key_str_arr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_pop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_blocking_pop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
/* Construct SCAN and similar commands, as well as check iterator */
|
||||
int redis_scan_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
REDIS_SCAN_TYPE type, char **cmd, int *cmd_len);
|
||||
|
||||
/* ZRANGE, ZREVRANGE, ZRANGEBYSCORE, and ZREVRANGEBYSCORE callback type */
|
||||
typedef int (*zrange_cb)(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *,char**,int*,int*,short*,void**);
|
||||
|
||||
int redis_zrange_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_config_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_function_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_zrandmember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_zdiff_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_zinterunion_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_zdiffstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_zinterunionstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_intercard_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot,
|
||||
void **ctx);
|
||||
|
||||
int redis_slowlog_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_lcs_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_mpop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_restore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_pubsub_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_unsubscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_zrangebylex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_gen_zlex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_eval_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_fcall_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_failover_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_flush_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_xrange_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_vrange_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_georadius_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_georadiusbymember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_geosearch_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_geosearchstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
/* Commands which need a unique construction mechanism. This is either because
|
||||
* they don't share a signature with any other command, or because there is
|
||||
* specific processing we do (e.g. verifying subarguments) that make them
|
||||
* unique */
|
||||
|
||||
int redis_waitaof_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_info_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_script_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_acl_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_getex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_brpoplpush_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_incr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_decr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_delex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_hincrby_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_hincrbyfloat_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_hmget_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_hgetex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_hsetex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_hgetdel_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_mget_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_hmset_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_hstrlen_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_bitop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_bitcount_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_bitpos_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_pfcount_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_pfadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_pfmerge_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_auth_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_setbit_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_linsert_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_lrem_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_lpos_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_smove_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_hrandfield_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_hset_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_hsetnx_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_select_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_zincrby_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_hdel_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_zadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_object_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_client_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_command_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_copy_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_fmt_scan_cmd(char **cmd, REDIS_SCAN_TYPE type, char *key, int key_len,
|
||||
cmdfunc, resp_func)
|
||||
|
||||
/* Redis command builders */
|
||||
|
||||
RedisCmd *redis_replicaof_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_empty_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_opt_str_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_str_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_key_long_val_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_key_long_str_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_kv_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_key_str_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_key_key_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_key_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_key_long_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_long_long_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_key_long_long_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_key_str_str_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_key_dbl_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_key_varval_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_key_val_arr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_key_str_arr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_pop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_blocking_pop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_zrange_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_config_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_function_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_zrandmember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_zdiff_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_zinterunion_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_zdiffstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_zinterunionstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_intercard_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_slowlog_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_lcs_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_mpop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_restore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_pubsub_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_unsubscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_zrangebylex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_gen_zlex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_eval_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_fcall_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_failover_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_flush_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_xrange_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_vrange_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_georadius_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_georadiusbymember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_geosearch_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_geosearchstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_waitaof_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_info_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_script_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_acl_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_getex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_brpoplpush_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_incr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_decr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_delex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_hincrby_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_hincrbyfloat_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_hmget_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_hgetex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_hsetex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_hgetdel_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_mget_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_hmset_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_hstrlen_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_bitop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_bitcount_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_bitpos_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_pfcount_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_pfadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_pfmerge_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_auth_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_setbit_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_linsert_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_lrem_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_lpos_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_smove_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_hrandfield_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_hset_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_hsetnx_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_select_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_zincrby_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_hdel_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_zadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_object_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_client_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_command_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_copy_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_fmt_scan_cmd(REDIS_SCAN_TYPE type, char *key, int key_len,
|
||||
uint64_t it, char *pat, int pat_len, long count);
|
||||
|
||||
int redis_geoadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_geodist_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_migrate_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_vadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_vsim_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_vemb_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_vgetattr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_vsetattr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_gcra_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_vlinks_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_xadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_xdelex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_xautoclaim_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_xclaim_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_xpending_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_xack_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_xgroup_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_xinfo_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_xread_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_xreadgroup_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_xtrim_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_expiremember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_expirememberat_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_randmember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_hexpire_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_httl_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_lmove_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_expire_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_varkey_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_vararg_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_mset_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_msetex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_sentinel_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_sentinel_str_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_sort_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
RedisCmd *redis_geoadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_geodist_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_migrate_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_vadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_vsim_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_vemb_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_vgetattr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_vsetattr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_gcra_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_vlinks_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_xadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_xdelex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_xackdel_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_xautoclaim_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_xclaim_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_xpending_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_xack_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_xgroup_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_xinfo_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_xread_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_xreadgroup_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_xtrim_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_expiremember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_expirememberat_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_randmember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_hexpire_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_httl_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_lmove_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_expire_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_varkey_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_mset_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_msetex_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
RedisCmd *redis_sentinel_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_sentinel_str_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
RedisCmd *redis_sort_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw);
|
||||
|
||||
/* Commands that don't communicate with Redis at all (such as getOption,
|
||||
* setOption, _prefix, _serialize, etc). These can be handled in one place
|
||||
|
||||
+2
-1
@@ -50,7 +50,8 @@ PHP_METHOD(RedisSentinel, __construct)
|
||||
ZEND_PARSE_PARAMETERS_END_EX(RETURN_THROWS());
|
||||
|
||||
sentinel = PHPREDIS_ZVAL_GET_OBJECT(redis_sentinel_object, getThis());
|
||||
sentinel->sock = redis_sock_create(ZEND_STRL("127.0.0.1"), 26379, 0, 0, 0, NULL, 0);
|
||||
sentinel->sock = redis_sock_create(REDIS_SOCK_SENTINEL, ZEND_STRL("127.0.0.1"),
|
||||
26379, 0, 0, 0, NULL, 0);
|
||||
if (opts != NULL && redis_sock_configure(sentinel->sock, opts) != SUCCESS) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
+177
-141
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "redis_cmd.h"
|
||||
|
||||
#if PHP_VERSION_ID < 80400
|
||||
#include <ext/standard/php_random.h>
|
||||
@@ -246,7 +247,7 @@ session_uncompress_data(RedisSock *redis_sock, char *data, size_t len,
|
||||
}
|
||||
|
||||
/* Send a command to Redis. Returns byte count written to socket (-1 on failure) */
|
||||
static int redis_simple_cmd(RedisSock *redis_sock, char *cmd, int cmdlen,
|
||||
static int redis_simple_cmd(RedisSock *redis_sock, const char *cmd, int cmdlen,
|
||||
char **reply, int *replylen)
|
||||
{
|
||||
*reply = NULL;
|
||||
@@ -259,13 +260,6 @@ static int redis_simple_cmd(RedisSock *redis_sock, char *cmd, int cmdlen,
|
||||
return len_written;
|
||||
}
|
||||
|
||||
static int
|
||||
redis_simple_cmd_sstr(RedisSock *redis_sock, smart_string *cmd,
|
||||
char **reply, int *replylen)
|
||||
{
|
||||
return redis_simple_cmd(redis_sock, cmd->c, cmd->len, reply, replylen);
|
||||
}
|
||||
|
||||
static inline int weighted_seed(zend_string *key) {
|
||||
/* In GCC the fast-path is one 32-bit load with a union */
|
||||
union { int pos; } u;
|
||||
@@ -306,8 +300,8 @@ redis_pool_get_sock(redis_pool *pool, zend_string *key) {
|
||||
}
|
||||
|
||||
/* Helper to set our session lock key */
|
||||
static int set_session_lock_key(RedisSock *redis_sock, char *cmd, int cmd_len
|
||||
)
|
||||
static int
|
||||
set_session_lock_key(RedisSock *redis_sock, const char *cmd, int cmd_len)
|
||||
{
|
||||
char *reply;
|
||||
int sent_len, reply_len;
|
||||
@@ -359,8 +353,8 @@ static void generate_lock_secret(redis_session_lock_status *status) {
|
||||
static int
|
||||
lock_acquire(RedisSock *redis_sock, redis_session_lock_status *lock_status) {
|
||||
zend_long wait_time, expiry, retries, attempt = 0;
|
||||
int cmd_len, result;
|
||||
char *cmd;
|
||||
RedisCmd *cmd;
|
||||
int result;
|
||||
|
||||
/* Short circuit if we are already locked or not using session locks */
|
||||
if (lock_status->is_locked || !INI_INT("redis.session.locking_enabled"))
|
||||
@@ -388,17 +382,18 @@ lock_acquire(RedisSock *redis_sock, redis_session_lock_status *lock_status) {
|
||||
generate_lock_secret(lock_status);
|
||||
|
||||
if (expiry > 0) {
|
||||
cmd_len = REDIS_SPPRINTF(&cmd, "SET", "SSssd", lock_status->lock_key,
|
||||
lock_status->lock_secret, "NX", 2, "PX", 2,
|
||||
expiry * 1000);
|
||||
cmd = redis_cmd_fmt(redis_sock, "SET", "SSssd", lock_status->lock_key,
|
||||
lock_status->lock_secret, "NX", 2, "PX", 2,
|
||||
expiry * 1000);
|
||||
} else {
|
||||
cmd_len = REDIS_SPPRINTF(&cmd, "SET", "SSs", lock_status->lock_key,
|
||||
lock_status->lock_secret, "NX", 2);
|
||||
cmd = redis_cmd_fmt(redis_sock, "SET", "SSs", lock_status->lock_key,
|
||||
lock_status->lock_secret, "NX", 2);
|
||||
}
|
||||
|
||||
/* Attempt to get our lock */
|
||||
for (;;) {
|
||||
result = set_session_lock_key(redis_sock, cmd, cmd_len);
|
||||
result = set_session_lock_key(redis_sock, redis_cmd_str(cmd),
|
||||
redis_cmd_len(cmd));
|
||||
|
||||
if (result == SUCCESS) {
|
||||
lock_status->is_locked = 1;
|
||||
@@ -417,16 +412,21 @@ lock_acquire(RedisSock *redis_sock, redis_session_lock_status *lock_status) {
|
||||
usleep(wait_time);
|
||||
}
|
||||
|
||||
/* Cleanup SET command */
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
/* Success if we're locked */
|
||||
return lock_status->is_locked ? SUCCESS : FAILURE;
|
||||
}
|
||||
|
||||
#define IS_LOCK_SECRET(reply, len, secret) (len == ZSTR_LEN(secret) && !redis_strncmp(reply, ZSTR_VAL(secret), len))
|
||||
static int write_allowed(RedisSock *redis_sock, redis_session_lock_status *lock_status)
|
||||
{
|
||||
static zend_always_inline
|
||||
zend_bool is_lock_secret(const char *str, size_t len, zend_string *secret) {
|
||||
return len == ZSTR_LEN(secret) && !redis_strncmp(str, ZSTR_VAL(secret), len);
|
||||
}
|
||||
|
||||
static int
|
||||
write_allowed(RedisSock *redis_sock, redis_session_lock_status *lock_status) {
|
||||
RedisCmd *cmd;
|
||||
|
||||
if (!INI_INT("redis.session.locking_enabled")) {
|
||||
return 1;
|
||||
}
|
||||
@@ -434,20 +434,23 @@ static int write_allowed(RedisSock *redis_sock, redis_session_lock_status *lock_
|
||||
Therefore it is guaranteed that the current process is still holding the lock */
|
||||
|
||||
if (lock_status->is_locked && INI_INT("redis.session.lock_expire") != 0) {
|
||||
char *cmd, *reply = NULL;
|
||||
int replylen, cmdlen;
|
||||
char *reply = NULL;
|
||||
int replylen;
|
||||
|
||||
/* Command to get our lock key value and compare secrets */
|
||||
cmdlen = REDIS_SPPRINTF(&cmd, "GET", "S", lock_status->lock_key);
|
||||
cmd = redis_cmd_fmt(redis_sock, "GET", "S", lock_status->lock_key);
|
||||
|
||||
/* Attempt to refresh the lock */
|
||||
redis_simple_cmd(redis_sock, cmd, cmdlen, &reply, &replylen);
|
||||
/* Cleanup */
|
||||
efree(cmd);
|
||||
redis_simple_cmd(redis_sock, redis_cmd_str(cmd), redis_cmd_len(cmd),
|
||||
&reply, &replylen);
|
||||
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
if (reply == NULL) {
|
||||
lock_status->is_locked = 0;
|
||||
} else {
|
||||
lock_status->is_locked = IS_LOCK_SECRET(reply, replylen, lock_status->lock_secret);
|
||||
lock_status->is_locked = is_lock_secret(reply, replylen,
|
||||
lock_status->lock_secret);
|
||||
efree(reply);
|
||||
}
|
||||
|
||||
@@ -488,44 +491,47 @@ get_del_result(RedisSock *redis_sock, const char *reply, int len)
|
||||
|
||||
static delResult
|
||||
lock_release_delex(RedisSock *redis_sock, redis_session_lock_status *status) {
|
||||
smart_string cmd = {0};
|
||||
delResult result;
|
||||
RedisCmd *cmd;
|
||||
char *reply;
|
||||
int len;
|
||||
|
||||
REDIS_CMD_INIT_SSTR_STATIC(&cmd, 3, "DELEX");
|
||||
redis_cmd_append_sstr_zstr(&cmd, status->lock_key);
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmd, "IFEQ");
|
||||
redis_cmd_append_sstr_zstr(&cmd, status->lock_secret);
|
||||
cmd = redis_cmd_create_literal(redis_sock, "DELEX");
|
||||
|
||||
redis_simple_cmd_sstr(redis_sock, &cmd, &reply, &len);
|
||||
redis_cmd_cat_zstr(cmd, status->lock_key);
|
||||
redis_cmd_cat_literal(cmd, "IFEQ");
|
||||
redis_cmd_cat_zstr(cmd, status->lock_secret);
|
||||
|
||||
redis_simple_cmd(redis_sock, redis_cmd_str(cmd), redis_cmd_len(cmd), &reply,
|
||||
&len);
|
||||
|
||||
result = get_del_result(redis_sock, reply, len);
|
||||
|
||||
if (reply) efree(reply);
|
||||
smart_string_free(&cmd);
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static delResult
|
||||
lock_release_delifeq(RedisSock *redis_sock, redis_session_lock_status *status) {
|
||||
smart_string cmd = {0};
|
||||
delResult result;
|
||||
RedisCmd *cmd;
|
||||
char *reply;
|
||||
int len;
|
||||
|
||||
REDIS_CMD_INIT_SSTR_STATIC(&cmd, 2, "DELIFEQ");
|
||||
cmd = redis_cmd_create_literal(redis_sock, "DELIFEQ");
|
||||
|
||||
redis_cmd_append_sstr_zstr(&cmd, status->lock_key);
|
||||
redis_cmd_append_sstr_zstr(&cmd, status->lock_secret);
|
||||
redis_cmd_cat_zstr(cmd, status->lock_key);
|
||||
redis_cmd_cat_zstr(cmd, status->lock_secret);
|
||||
|
||||
redis_simple_cmd_sstr(redis_sock, &cmd, &reply, &len);
|
||||
redis_simple_cmd(redis_sock, redis_cmd_str(cmd), redis_cmd_len(cmd), &reply,
|
||||
&len);
|
||||
|
||||
result = get_del_result(redis_sock, reply, len);
|
||||
|
||||
if (reply) efree(reply);
|
||||
smart_string_free(&cmd);
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -536,18 +542,20 @@ lock_release_delifeq(RedisSock *redis_sock, redis_session_lock_status *status) {
|
||||
* calls should then succeed using EVALSHA. */
|
||||
static void
|
||||
lock_release_lua(RedisSock *redis_sock, redis_session_lock_status *status) {
|
||||
int i, cmdlen, replylen;
|
||||
char *cmd, *reply;
|
||||
int i, replylen;
|
||||
RedisCmd *cmd;
|
||||
char *reply;
|
||||
|
||||
/* We first want to try EVALSHA and then fall back to EVAL */
|
||||
for (i = 0; status->is_locked && i < sizeof(lua_cmd)/sizeof(*lua_cmd); i++)
|
||||
{
|
||||
cmdlen = REDIS_SPPRINTF(&cmd, lua_cmd[i].kw, "sdSS", lua_cmd[i].str,
|
||||
lua_cmd[i].len, 1, status->lock_key,
|
||||
status->lock_secret);
|
||||
cmd = redis_cmd_fmt(redis_sock, lua_cmd[i].kw, "sdSS", lua_cmd[i].str,
|
||||
lua_cmd[i].len, 1, status->lock_key,
|
||||
status->lock_secret);
|
||||
|
||||
/* Send it off */
|
||||
redis_simple_cmd(redis_sock, cmd, cmdlen, &reply, &replylen);
|
||||
redis_simple_cmd(redis_sock, redis_cmd_str(cmd), redis_cmd_len(cmd),
|
||||
&reply, &replylen);
|
||||
|
||||
/* Release lock and cleanup reply if we got one */
|
||||
if (reply != NULL) {
|
||||
@@ -556,7 +564,7 @@ lock_release_lua(RedisSock *redis_sock, redis_session_lock_status *status) {
|
||||
}
|
||||
|
||||
/* Cleanup command */
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
}
|
||||
|
||||
/* Something has failed if we are still locked */
|
||||
@@ -708,6 +716,7 @@ PS_OPEN_FUNC(redis)
|
||||
}
|
||||
|
||||
RedisSock *redis_sock;
|
||||
const char *persistent_id_str;
|
||||
char *addr, *scheme;
|
||||
size_t addrlen;
|
||||
int port, addr_free = 0;
|
||||
@@ -723,8 +732,10 @@ PS_OPEN_FUNC(redis)
|
||||
addrlen = strlen(addr);
|
||||
}
|
||||
|
||||
redis_sock = redis_sock_create(addr, addrlen, port, timeout, read_timeout,
|
||||
persistent, persistent_id ? ZSTR_VAL(persistent_id) : NULL,
|
||||
persistent_id_str = persistent_id ? ZSTR_VAL(persistent_id) : NULL;
|
||||
redis_sock = redis_sock_create(REDIS_SOCK_SESSION, addr, addrlen,
|
||||
port, timeout, read_timeout,
|
||||
persistent, persistent_id_str,
|
||||
retry_interval);
|
||||
|
||||
if (db >= 0) { /* default is -1 which leaves the choice to redis. */
|
||||
@@ -799,6 +810,11 @@ redis_session_key(RedisSock *redis_sock, const char *key, int key_len)
|
||||
ZSTR_LEN(redis_sock->prefix), key, key_len);
|
||||
}
|
||||
|
||||
static zend_always_inline zend_string *
|
||||
redis_session_key_zstr(RedisSock *redis_sock, zend_string *key) {
|
||||
return redis_session_key(redis_sock, ZSTR_VAL(key), ZSTR_LEN(key));
|
||||
}
|
||||
|
||||
/* {{{ PS_CREATE_SID_FUNC
|
||||
*/
|
||||
PS_CREATE_SID_FUNC(redis)
|
||||
@@ -847,13 +863,12 @@ PS_CREATE_SID_FUNC(redis)
|
||||
*/
|
||||
PS_VALIDATE_SID_FUNC(redis)
|
||||
{
|
||||
char *cmd, *response;
|
||||
int cmd_len, response_len;
|
||||
int response_len;
|
||||
char *response;
|
||||
RedisCmd *cmd;
|
||||
|
||||
const char *skey = ZSTR_VAL(key);
|
||||
size_t skeylen = ZSTR_LEN(key);
|
||||
|
||||
if (!skeylen) return FAILURE;
|
||||
if (ZSTR_LEN(key) < 1)
|
||||
return FAILURE;
|
||||
|
||||
redis_pool *pool = PS_GET_MOD_DATA();
|
||||
redis_pool_member *rpm = redis_pool_get_sock(pool, key);
|
||||
@@ -864,16 +879,19 @@ PS_VALIDATE_SID_FUNC(redis)
|
||||
}
|
||||
|
||||
/* send EXISTS command */
|
||||
zend_string *session = redis_session_key(redis_sock, skey, skeylen);
|
||||
cmd_len = REDIS_SPPRINTF(&cmd, "EXISTS", "S", session);
|
||||
zend_string *session = redis_session_key_zstr(redis_sock, key);
|
||||
cmd = redis_cmd_fmt(redis_sock, "EXISTS", "S", session);
|
||||
zend_string_release(session);
|
||||
if (redis_sock_write(redis_sock, cmd, cmd_len) < 0 || (response = redis_sock_read(redis_sock, &response_len)) == NULL) {
|
||||
|
||||
if (redis_sock_write_cmd(redis_sock, cmd) < 0 ||
|
||||
(response = redis_sock_read(redis_sock, &response_len)) == NULL)
|
||||
{
|
||||
php_error_docref(NULL, E_WARNING, "Error communicating with Redis server");
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
if (response_len == 2 && response[0] == ':' && response[1] == '1') {
|
||||
efree(response);
|
||||
@@ -889,13 +907,12 @@ PS_VALIDATE_SID_FUNC(redis)
|
||||
*/
|
||||
PS_UPDATE_TIMESTAMP_FUNC(redis)
|
||||
{
|
||||
char *cmd, *response;
|
||||
int cmd_len, response_len;
|
||||
int response_len;
|
||||
char *response;
|
||||
RedisCmd *cmd;
|
||||
|
||||
const char *skey = ZSTR_VAL(key);
|
||||
size_t skeylen = ZSTR_LEN(key);
|
||||
|
||||
if (!skeylen) return FAILURE;
|
||||
if (ZSTR_LEN(key) < 1)
|
||||
return FAILURE;
|
||||
|
||||
/* No need to update the session timestamp if we've already done so */
|
||||
if (INI_INT("redis.session.early_refresh")) {
|
||||
@@ -911,17 +928,19 @@ PS_UPDATE_TIMESTAMP_FUNC(redis)
|
||||
}
|
||||
|
||||
/* send EXPIRE command */
|
||||
zend_string *session = redis_session_key(redis_sock, skey, skeylen);
|
||||
cmd_len = REDIS_SPPRINTF(&cmd, "EXPIRE", "Sd", session, session_gc_maxlifetime());
|
||||
zend_string *session = redis_session_key_zstr(redis_sock, key);
|
||||
cmd = redis_cmd_fmt(redis_sock, "EXPIRE", "Sd", session, session_gc_maxlifetime());
|
||||
zend_string_release(session);
|
||||
|
||||
if (redis_sock_write(redis_sock, cmd, cmd_len) < 0 || (response = redis_sock_read(redis_sock, &response_len)) == NULL) {
|
||||
if (redis_sock_write(redis_sock, redis_cmd_str(cmd), redis_cmd_len(cmd)) < 0 ||
|
||||
(response = redis_sock_read(redis_sock, &response_len)) == NULL)
|
||||
{
|
||||
php_error_docref(NULL, E_WARNING, "Error communicating with Redis server");
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
if (response_len == 2 && response[0] == ':') {
|
||||
efree(response);
|
||||
@@ -937,10 +956,11 @@ PS_UPDATE_TIMESTAMP_FUNC(redis)
|
||||
*/
|
||||
PS_READ_FUNC(redis)
|
||||
{
|
||||
char *resp, *cmd, *compressed_buf;
|
||||
int resp_len, cmd_len, compressed_free;
|
||||
char *resp, *compressed_buf;
|
||||
int resp_len, compressed_free;
|
||||
const char *skey = ZSTR_VAL(key);
|
||||
size_t skeylen = ZSTR_LEN(key), compressed_len;
|
||||
RedisCmd *cmd;
|
||||
|
||||
if (!skeylen) return FAILURE;
|
||||
|
||||
@@ -958,10 +978,13 @@ PS_READ_FUNC(redis)
|
||||
|
||||
/* Update the session ttl if early refresh is enabled */
|
||||
if (INI_INT("redis.session.early_refresh")) {
|
||||
cmd_len = REDIS_SPPRINTF(&cmd, "GETEX", "Ssd", pool->lock_status.session_key,
|
||||
"EX", 2, session_gc_maxlifetime());
|
||||
cmd = redis_cmd_create_literal(redis_sock, "GETEX");
|
||||
redis_cmd_cat_zstr(cmd, pool->lock_status.session_key);
|
||||
redis_cmd_cat_literal(cmd, "EX");
|
||||
redis_cmd_cat_long(cmd, session_gc_maxlifetime());
|
||||
} else {
|
||||
cmd_len = REDIS_SPPRINTF(&cmd, "GET", "S", pool->lock_status.session_key);
|
||||
cmd = redis_cmd_create_literal(redis_sock, "GET");
|
||||
redis_cmd_cat_zstr(cmd, pool->lock_status.session_key);
|
||||
}
|
||||
|
||||
if (lock_acquire(redis_sock, &pool->lock_status) != SUCCESS) {
|
||||
@@ -970,18 +993,18 @@ PS_READ_FUNC(redis)
|
||||
php_error_docref(NULL, E_WARNING, "Failed to acquire session lock, session will be read only");
|
||||
} else {
|
||||
php_error_docref(NULL, E_WARNING, "Failed to acquire session lock");
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (redis_sock_write(redis_sock, cmd, cmd_len) < 0) {
|
||||
if (redis_sock_write_cmd(redis_sock, cmd) < 0) {
|
||||
php_error_docref(NULL, E_WARNING, "Error communicating with Redis server");
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
/* Read response from Redis. If we get a NULL response from redis_sock_read
|
||||
* this can indicate an error, OR a "NULL bulk" reply (empty session data)
|
||||
@@ -1011,13 +1034,14 @@ PS_READ_FUNC(redis)
|
||||
*/
|
||||
PS_WRITE_FUNC(redis)
|
||||
{
|
||||
char *cmd, *response;
|
||||
int cmd_len, response_len, compressed_free;
|
||||
const char *skey = ZSTR_VAL(key);
|
||||
size_t skeylen = ZSTR_LEN(key), svallen = ZSTR_LEN(val);
|
||||
char *response;
|
||||
int response_len, compressed_free;
|
||||
size_t svallen;
|
||||
RedisCmd *cmd;
|
||||
char *sval;
|
||||
|
||||
if (!skeylen) return FAILURE;
|
||||
if (ZSTR_LEN(key) < 1)
|
||||
return FAILURE;
|
||||
|
||||
redis_pool *pool = PS_GET_MOD_DATA();
|
||||
redis_pool_member *rpm = redis_pool_get_sock(pool, key);
|
||||
@@ -1028,12 +1052,13 @@ PS_WRITE_FUNC(redis)
|
||||
}
|
||||
|
||||
/* send SET command */
|
||||
zend_string *session = redis_session_key(redis_sock, skey, skeylen);
|
||||
zend_string *session = redis_session_key_zstr(redis_sock, key);
|
||||
|
||||
compressed_free = session_compress_data(redis_sock, ZSTR_VAL(val), ZSTR_LEN(val),
|
||||
&sval, &svallen);
|
||||
|
||||
cmd_len = REDIS_SPPRINTF(&cmd, "SETEX", "Sds", session, session_gc_maxlifetime(), sval, svallen);
|
||||
cmd = redis_cmd_fmt(redis_sock, "SETEX", "Sds", session,
|
||||
session_gc_maxlifetime(), sval, svallen);
|
||||
zend_string_release(session);
|
||||
if (compressed_free) {
|
||||
efree(sval);
|
||||
@@ -1041,17 +1066,19 @@ PS_WRITE_FUNC(redis)
|
||||
|
||||
if (!write_allowed(redis_sock, &pool->lock_status)) {
|
||||
php_error_docref(NULL, E_WARNING, "Unable to write session: session lock not held");
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (redis_sock_write(redis_sock, cmd, cmd_len ) < 0 || (response = redis_sock_read(redis_sock, &response_len)) == NULL) {
|
||||
if (redis_sock_write_cmd(redis_sock, cmd) < 0 ||
|
||||
(response = redis_sock_read(redis_sock, &response_len)) == NULL)
|
||||
{
|
||||
php_error_docref(NULL, E_WARNING, "Error communicating with Redis server");
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
if (is_redis_ok(response, response_len)) {
|
||||
efree(response);
|
||||
@@ -1068,10 +1095,9 @@ PS_WRITE_FUNC(redis)
|
||||
*/
|
||||
PS_DESTROY_FUNC(redis)
|
||||
{
|
||||
char *cmd, *response;
|
||||
int cmd_len, response_len;
|
||||
const char *skey = ZSTR_VAL(key);
|
||||
size_t skeylen = ZSTR_LEN(key);
|
||||
char *response;
|
||||
int response_len;
|
||||
RedisCmd *cmd;
|
||||
|
||||
redis_pool *pool = PS_GET_MOD_DATA();
|
||||
redis_pool_member *rpm = redis_pool_get_sock(pool, key);
|
||||
@@ -1085,18 +1111,22 @@ PS_DESTROY_FUNC(redis)
|
||||
lock_release(redis_sock, &pool->lock_status);
|
||||
|
||||
/* send DEL command */
|
||||
zend_string *session = redis_session_key(redis_sock, skey, skeylen);
|
||||
cmd_len = REDIS_SPPRINTF(&cmd, "DEL", "S", session);
|
||||
zend_string *session = redis_session_key_zstr(redis_sock, key);
|
||||
cmd = redis_cmd_fmt(redis_sock, "DEL", "S", session);
|
||||
zend_string_release(session);
|
||||
if (redis_sock_write(redis_sock, cmd, cmd_len) < 0 || (response = redis_sock_read(redis_sock, &response_len)) == NULL) {
|
||||
if (redis_sock_write_cmd(redis_sock, cmd) < 0 ||
|
||||
(response = redis_sock_read(redis_sock, &response_len)) == NULL)
|
||||
{
|
||||
php_error_docref(NULL, E_WARNING, "Error communicating with Redis server");
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
if (response_len == 2 && response[0] == ':' && (response[1] == '0' || response[1] == '1')) {
|
||||
if (response_len == 2 && response[0] == ':' &&
|
||||
(response[1] == '0' || response[1] == '1'))
|
||||
{
|
||||
efree(response);
|
||||
return SUCCESS;
|
||||
} else {
|
||||
@@ -1261,9 +1291,10 @@ PS_CREATE_SID_FUNC(rediscluster)
|
||||
{
|
||||
redisCluster *c = PS_GET_MOD_DATA();
|
||||
clusterReply *reply;
|
||||
char *cmd, *skey;
|
||||
char *skey;
|
||||
RedisCmd *cmd;
|
||||
zend_string *sid;
|
||||
int cmdlen, skeylen;
|
||||
int skeylen;
|
||||
int retries = 3;
|
||||
short slot;
|
||||
|
||||
@@ -1280,21 +1311,21 @@ PS_CREATE_SID_FUNC(rediscluster)
|
||||
|
||||
/* Create session key if it doesn't already exist */
|
||||
skey = cluster_session_key(c, ZSTR_VAL(sid), ZSTR_LEN(sid), &skeylen, &slot);
|
||||
cmdlen = redis_spprintf(NULL, NULL, &cmd, "SET", "ssssd", skey,
|
||||
cmd = redis_cmd_fmt(NULL, "SET", "ssssd", skey,
|
||||
skeylen, "", 0, "NX", 2, "EX", 2, session_gc_maxlifetime());
|
||||
|
||||
efree(skey);
|
||||
|
||||
/* Attempt to kick off our command */
|
||||
c->readonly = 0;
|
||||
if (cluster_send_command(c,slot,cmd,cmdlen) < 0 || c->err) {
|
||||
if (cluster_send_command(c,slot,redis_cmd_str(cmd),redis_cmd_len(cmd)) < 0 || c->err) {
|
||||
php_error_docref(NULL, E_NOTICE, "Redis connection not available");
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
zend_string_release(sid);
|
||||
return php_session_create_id(NULL);;
|
||||
}
|
||||
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
/* Attempt to read reply */
|
||||
reply = cluster_read_resp(c, 1);
|
||||
@@ -1326,8 +1357,9 @@ PS_VALIDATE_SID_FUNC(rediscluster)
|
||||
{
|
||||
redisCluster *c = PS_GET_MOD_DATA();
|
||||
clusterReply *reply;
|
||||
char *cmd, *skey;
|
||||
int cmdlen, skeylen;
|
||||
char *skey;
|
||||
RedisCmd *cmd;
|
||||
int skeylen;
|
||||
int res = FAILURE;
|
||||
short slot;
|
||||
|
||||
@@ -1338,18 +1370,18 @@ PS_VALIDATE_SID_FUNC(rediscluster)
|
||||
}
|
||||
|
||||
skey = cluster_session_key(c, ZSTR_VAL(key), ZSTR_LEN(key), &skeylen, &slot);
|
||||
cmdlen = redis_spprintf(NULL, NULL, &cmd, "EXISTS", "s", skey, skeylen);
|
||||
cmd = redis_cmd_fmt(NULL, "EXISTS", "s", skey, skeylen);
|
||||
efree(skey);
|
||||
|
||||
/* We send to master, to ensure consistency */
|
||||
c->readonly = 0;
|
||||
if (cluster_send_command(c,slot,cmd,cmdlen) < 0 || c->err) {
|
||||
if (cluster_send_command(c,slot,redis_cmd_str(cmd),redis_cmd_len(cmd)) < 0 || c->err) {
|
||||
php_error_docref(NULL, E_NOTICE, "Redis connection not available");
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
/* Attempt to read reply */
|
||||
reply = cluster_read_resp(c, 0);
|
||||
@@ -1375,8 +1407,9 @@ PS_VALIDATE_SID_FUNC(rediscluster)
|
||||
PS_UPDATE_TIMESTAMP_FUNC(rediscluster) {
|
||||
redisCluster *c = PS_GET_MOD_DATA();
|
||||
clusterReply *reply;
|
||||
char *cmd, *skey;
|
||||
int cmdlen, skeylen;
|
||||
char *skey;
|
||||
RedisCmd *cmd;
|
||||
int skeylen;
|
||||
short slot;
|
||||
|
||||
/* No need to update the session timestamp if we've already done so */
|
||||
@@ -1386,20 +1419,20 @@ PS_UPDATE_TIMESTAMP_FUNC(rediscluster) {
|
||||
|
||||
/* Set up command and slot info */
|
||||
skey = cluster_session_key(c, ZSTR_VAL(key), ZSTR_LEN(key), &skeylen, &slot);
|
||||
cmdlen = redis_spprintf(NULL, NULL, &cmd, "EXPIRE", "sd", skey,
|
||||
cmd = redis_cmd_fmt(NULL, "EXPIRE", "sd", skey,
|
||||
skeylen, session_gc_maxlifetime());
|
||||
efree(skey);
|
||||
|
||||
/* Attempt to send EXPIRE command */
|
||||
c->readonly = 0;
|
||||
if (cluster_send_command(c,slot,cmd,cmdlen) < 0 || c->err) {
|
||||
if (cluster_send_command(c,slot,redis_cmd_str(cmd),redis_cmd_len(cmd)) < 0 || c->err) {
|
||||
php_error_docref(NULL, E_NOTICE, "Redis unable to update session expiry");
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Clean up our command */
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
/* Attempt to read reply */
|
||||
reply = cluster_read_resp(c, 0);
|
||||
@@ -1420,8 +1453,9 @@ PS_UPDATE_TIMESTAMP_FUNC(rediscluster) {
|
||||
PS_READ_FUNC(rediscluster) {
|
||||
redisCluster *c = PS_GET_MOD_DATA();
|
||||
clusterReply *reply;
|
||||
char *cmd, *skey, *compressed_buf;
|
||||
int cmdlen, skeylen, free_flag, compressed_free;
|
||||
char *skey, *compressed_buf;
|
||||
RedisCmd *cmd;
|
||||
int skeylen, free_flag, compressed_free;
|
||||
size_t compressed_len;
|
||||
short slot;
|
||||
|
||||
@@ -1430,24 +1464,24 @@ PS_READ_FUNC(rediscluster) {
|
||||
|
||||
/* Update the session ttl if early refresh is enabled */
|
||||
if (INI_INT("redis.session.early_refresh")) {
|
||||
cmdlen = redis_spprintf(NULL, NULL, &cmd, "GETEX", "ssd", skey,
|
||||
cmd = redis_cmd_fmt(NULL, "GETEX", "ssd", skey,
|
||||
skeylen, "EX", 2, session_gc_maxlifetime());
|
||||
c->readonly = 0;
|
||||
} else {
|
||||
cmdlen = redis_spprintf(NULL, NULL, &cmd, "GET", "s", skey, skeylen);
|
||||
cmd = redis_cmd_fmt(NULL, "GET", "s", skey, skeylen);
|
||||
c->readonly = 1;
|
||||
}
|
||||
|
||||
efree(skey);
|
||||
|
||||
/* Attempt to kick off our command */
|
||||
if (cluster_send_command(c,slot,cmd,cmdlen) < 0 || c->err) {
|
||||
efree(cmd);
|
||||
if (cluster_send_command(c,slot,redis_cmd_str(cmd),redis_cmd_len(cmd)) < 0 || c->err) {
|
||||
redis_cmd_free(cmd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Clean up command */
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
/* Attempt to read reply */
|
||||
reply = cluster_read_resp(c, 0);
|
||||
@@ -1481,8 +1515,9 @@ PS_READ_FUNC(rediscluster) {
|
||||
PS_WRITE_FUNC(rediscluster) {
|
||||
redisCluster *c = PS_GET_MOD_DATA();
|
||||
clusterReply *reply;
|
||||
char *cmd, *skey, *sval;
|
||||
int cmdlen, skeylen, compressed_free;
|
||||
char *skey, *sval;
|
||||
RedisCmd *cmd;
|
||||
int skeylen, compressed_free;
|
||||
size_t svallen;
|
||||
short slot;
|
||||
|
||||
@@ -1491,7 +1526,7 @@ PS_WRITE_FUNC(rediscluster) {
|
||||
|
||||
/* Set up command and slot info */
|
||||
skey = cluster_session_key(c, ZSTR_VAL(key), ZSTR_LEN(key), &skeylen, &slot);
|
||||
cmdlen = redis_spprintf(NULL, NULL, &cmd, "SETEX", "sds", skey,
|
||||
cmd = redis_cmd_fmt(NULL, "SETEX", "sds", skey,
|
||||
skeylen, session_gc_maxlifetime(),
|
||||
sval, svallen);
|
||||
efree(skey);
|
||||
@@ -1501,13 +1536,13 @@ PS_WRITE_FUNC(rediscluster) {
|
||||
|
||||
/* Attempt to send command */
|
||||
c->readonly = 0;
|
||||
if (cluster_send_command(c,slot,cmd,cmdlen) < 0 || c->err) {
|
||||
efree(cmd);
|
||||
if (cluster_send_command(c,slot,redis_cmd_str(cmd),redis_cmd_len(cmd)) < 0 || c->err) {
|
||||
redis_cmd_free(cmd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Clean up our command */
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
/* Attempt to read reply */
|
||||
reply = cluster_read_resp(c, 0);
|
||||
@@ -1527,24 +1562,25 @@ PS_WRITE_FUNC(rediscluster) {
|
||||
PS_DESTROY_FUNC(rediscluster) {
|
||||
redisCluster *c = PS_GET_MOD_DATA();
|
||||
clusterReply *reply;
|
||||
char *cmd, *skey;
|
||||
int cmdlen, skeylen;
|
||||
char *skey;
|
||||
RedisCmd *cmd;
|
||||
int skeylen;
|
||||
short slot;
|
||||
|
||||
/* Set up command and slot info */
|
||||
skey = cluster_session_key(c, ZSTR_VAL(key), ZSTR_LEN(key), &skeylen, &slot);
|
||||
|
||||
cmdlen = redis_spprintf(NULL, NULL, &cmd, "DEL", "s", skey, skeylen);
|
||||
cmd = redis_cmd_fmt(NULL, "DEL", "s", skey, skeylen);
|
||||
efree(skey);
|
||||
|
||||
/* Attempt to send command */
|
||||
if (cluster_send_command(c,slot,cmd,cmdlen) < 0 || c->err) {
|
||||
efree(cmd);
|
||||
if (cluster_send_command(c,slot,redis_cmd_str(cmd),redis_cmd_len(cmd)) < 0 || c->err) {
|
||||
redis_cmd_free(cmd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Clean up our command */
|
||||
efree(cmd);
|
||||
redis_cmd_free(cmd);
|
||||
|
||||
/* Attempt to read reply */
|
||||
reply = cluster_read_resp(c, 0);
|
||||
|
||||
+2
-1
@@ -31,7 +31,8 @@ create_sentinel_object(zend_class_entry *ce)
|
||||
}
|
||||
|
||||
PHP_REDIS_API int
|
||||
sentinel_mbulk_reply_zipped_assoc(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx)
|
||||
sentinel_mbulk_reply_zipped_assoc(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
zval *z_tab, RedisCmdCtx ctx)
|
||||
{
|
||||
char inbuf[4096];
|
||||
int i, nelem;
|
||||
|
||||
+1
-1
@@ -8,6 +8,6 @@ typedef redis_object redis_sentinel_object;
|
||||
|
||||
zend_object *create_sentinel_object(zend_class_entry *ce);
|
||||
|
||||
PHP_REDIS_API int sentinel_mbulk_reply_zipped_assoc(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int sentinel_mbulk_reply_zipped_assoc(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, RedisCmdCtx ctx);
|
||||
|
||||
#endif /* REDIS_SENTINEL_LIBRARY_H */
|
||||
|
||||
+16
-7
@@ -31,11 +31,11 @@ class Redis_Test extends TestSuite {
|
||||
$result = [Redis::SERIALIZER_NONE, Redis::SERIALIZER_PHP];
|
||||
|
||||
if (defined('Redis::SERIALIZER_IGBINARY'))
|
||||
$result[] = Redis::SERIALIZER_IGBINARY;
|
||||
$result['igbinary'] = Redis::SERIALIZER_IGBINARY;
|
||||
if (defined('Redis::SERIALIZER_JSON'))
|
||||
$result[] = Redis::SERIALIZER_JSON;
|
||||
$result['json'] = Redis::SERIALIZER_JSON;
|
||||
if (defined('Redis::SERIALIZER_MSGPACK'))
|
||||
$result[] = Redis::SERIALIZER_MSGPACK;
|
||||
$result['msgpack'] = Redis::SERIALIZER_MSGPACK;
|
||||
|
||||
return $result;
|
||||
}
|
||||
@@ -6032,9 +6032,9 @@ class Redis_Test extends TestSuite {
|
||||
$this->redis->getOption(Redis::OPT_COMPRESSION)
|
||||
];
|
||||
|
||||
foreach ($this->getSerializers() as $ser) {
|
||||
foreach ($this->getSerializers() as $ser_name => $ser) {
|
||||
$compressors = $this->getCompressors();
|
||||
foreach ($compressors as $cmp) {
|
||||
foreach ($compressors as $cmp_name => $cmp) {
|
||||
$this->redis->setOption(Redis::OPT_SERIALIZER, $ser);
|
||||
$this->redis->setOption(Redis::OPT_COMPRESSION, $cmp);
|
||||
|
||||
@@ -6052,10 +6052,12 @@ class Redis_Test extends TestSuite {
|
||||
$this->redis->setOption(Redis::OPT_SERIALIZER, $ser);
|
||||
$this->redis->setOption(Redis::OPT_COMPRESSION, $cmp);
|
||||
|
||||
$this->assertEquals($raw, $this->redis->_pack($v));
|
||||
$this->assertEquals($raw, $this->redis->_pack($v),
|
||||
"$ser_name + $cmp_name");
|
||||
|
||||
$unpacked = $this->redis->get('packkey');
|
||||
$this->assertEquals($unpacked, $this->redis->_unpack($raw));
|
||||
$this->assertEquals($unpacked, $this->redis->_unpack($raw),
|
||||
"$ser_name + $cmp_name");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8763,6 +8765,13 @@ class Redis_Test extends TestSuite {
|
||||
$list = $this->redis->command('list', 'filterby', 'pattern', 'lol*');
|
||||
$this->assertIsArray($list);
|
||||
$this->assertEquals(['lolwut'], $list);
|
||||
|
||||
$keys_and_flags = $this->redis->command(
|
||||
'getkeysandflags', 'MSET', 'key1', 'value1',
|
||||
);
|
||||
$this->assertEquals(
|
||||
[['key1', ['OW', 'update']]], $keys_and_flags,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -464,12 +464,14 @@ class TestSuite
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function assertEquals($expected, $actual): bool {
|
||||
protected function assertEquals($expected, $actual, ?string $context = NULL): bool {
|
||||
if ($expected === $actual)
|
||||
return true;
|
||||
|
||||
self::$errors[] = $this->assertionTrace("%s !== %s", $this->printArg($actual),
|
||||
$this->printArg($expected));
|
||||
$context = $context === NULL ? '' : " ($context)";
|
||||
|
||||
self::$errors[] = $this->assertionTrace("%s !== %s%s", $this->printArg($actual),
|
||||
$this->printArg($expected), $context);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user