8000 Allow MIGRATE to accept multiple keys · chenyongze/phpredis@9aa3dbf · GitHub
[go: up one dir, main page]

Skip to content

Commit 9aa3dbf

Browse files
Allow MIGRATE to accept multiple keys
1 parent b087223 commit 9aa3dbf

File tree

4 files changed

+93
-58
lines changed

4 files changed

+93
-58
lines changed

library.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
#define REDIS_CMD_APPEND_SSTR_STATIC(sstr, str) \
55
redis_cmd_append_sstr(sstr, str, sizeof(str)-1);
66

7+
#define REDIS_CMD_APPEND_SSTR_OPT_STATIC(sstr, opt, str) \
8+
if (opt) REDIS_CMD_APPEND_SSTR_STATIC(sstr, str);
9+
710
#define REDIS_CMD_INIT_SSTR_STATIC(sstr, argc, keyword) \
811
redis_cmd_init_sstr(sstr, argc, keyword, sizeof(keyword)-1);
912

redis.c

Lines changed: 1 addition & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3250,64 +3250,7 @@ PHP_METHOD(Redis, debug) {
32503250
/* {{{ proto Redis::migrate(host port key dest-db timeout [bool copy,
32513251
* bool replace]) */
32523252
PHP_METHOD(Redis, migrate) {
3253-
zval *object;
3254-
RedisSock *redis_sock;
3255-
char *cmd, *host, *key;
3256-
int cmd_len, key_free;
3257-
strlen_t host_len, key_len;
3258-
zend_bool copy=0, replace=0;
3259-
zend_long port, dest_db, timeout;
3260-
3261-
// Parse arguments
3262-
if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
3263-
"Oslsll|bb", &object, redis_ce, &host,
3264-
&host_len, &port, &key, &key_len, &dest_db,
3265-
&timeout, &copy, &replace) == FAILURE)
3266-
{
3267-
RETURN_FALSE;
3268-
}
3269-
3270-
/* Grabg our socket */
3271-
if ((redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL) {
3272-
RETURN_FALSE;
3273-
}
3274-
3275-
// Prefix our key if we need to, build our command
3276-
key_free = redis_key_prefix(redis_sock, &key, &key_len);
3277-
3278-
/* Construct our command */
3279-
if(copy && replace) {
3280-
cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsddss",
3281-
host, host_len, port, key, key_len,
3282-
dest_db, timeout, "COPY",
3283-
sizeof("COPY")-1, "REPLACE",
3284-
sizeof("REPLACE")-1);
3285-
} else if(copy) {
3286-
cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsdds",
3287-
host, host_len, port, key, key_len,
3288-
dest_db, timeout, "COPY",
3289-
sizeof("COPY")-1);
3290-
} else if(replace) {
3291-
cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsdds",
3292-
host, host_len, port, key, key_len,
3293-
dest_db, timeout, "REPLACE",
3294-
sizeof("REPLACE")-1);
3295-
} else {
3296-
cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsdd",
3297-
host, host_len, port, key, key_len,
3298-
dest_db, timeout);
3299-
}
3300-
3301-
/* Free our key if we prefixed it */
3302-
if(key_free) efree(key);
3303-
3304-
// Kick off our MIGRATE request
3305-
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
3306-
IF_ATOMIC() {
3307-
redis_boolean_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
3308-
NULL, NULL);
3309-
}
3310-
REDIS_PROCESS_RESPONSE(redis_boolean_response);
3253+
REDIS_PROCESS_CMD(migrate, redis_boolean_response);
33113254
}
33123255

33133256
/* {{{ proto Redis::_prefix(key) */

redis_commands.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2946,6 +2946,92 @@ int redis_georadiusbymember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
29462946
return SUCCESS;
29472947
}
29482948

2949+
/* MIGRATE */
2950+
int redis_migrate_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
2951+
char **cmd, int *cmd_len, short *slot, void **ctx)
2952+
{
2953+
smart_string cmdstr = {0};
2954+
char *host, *key;
2955+
int argc, keyfree;
2956+
zval *z_keys, *z_key;
2957+
strlen_t hostlen, keylen;
2958+
zend_long destdb, port, timeout;
2959+
zend_bool copy = 0, replace = 0;
2960+
zend_string *zstr;
2961+
2962+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "slzll|bb", &host, &hostlen, &port,
2963+
&z_keys, &destdb, &timeout, &copy, &replace) == FAILURE)
2964+
{
2965+
return FAILURE;
2966+
}
2967+
2968+
/* Protect against being passed an array with zero elements */
2969+
if (Z_TYPE_P(z_keys) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(z_keys)) == 0) {
2970+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Keys array cannot be empty");
2971+
return FAILURE;
2972+
}
2973+
2974+
/* host, port, key|"", dest-db, timeout, [copy, replace] [KEYS key1..keyN] */
2975+
argc = 5 + copy + replace;
2976+
if (Z_TYPE_P(z_keys) == IS_ARRAY) {
2977+
/* +1 for the "KEYS" argument itself */
2978+
argc += 1 + zend_hash_num_elements(Z_ARRVAL_P(z_keys));
2979+
}
2980+
2981+
/* Initialize MIGRATE command with host and port */
2982+
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, argc, "MIGRATE");
2983+
redis_cmd_append_sstr(&cmdstr, host, hostlen);
2984+
redis_cmd_append_sstr_long(&cmdstr, port);
2985+
2986+
/* If passed a keys array the keys come later, otherwise pass the key to
2987+
* migrate here */
2988+
if (Z_TYPE_P(z_keys) == IS_ARRAY) {
2989+
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "");
2990+
} else {
2991+
/* Grab passed value as a string */
2992+
zstr = zval_get_string(z_keys);
2993+
2994+
/* We may need to prefix our string */
2995+
key = zstr->val;
2996+
keylen = zstr->len;
2997+
keyfree = redis_key_prefix(redis_sock, &key, &keylen);
2998+
2999+
/* Add key to migrate */
3000+
redis_cmd_append_sstr(&cmdstr, key, keylen);
3001+
3002+
zend_string_release(zstr);
3003+
if (keyfree) efree(key);
3004+
}
3005+
3006+
redis_cmd_append_sstr_long(&cmdstr, destdb);
3007+
redis_cmd_append_sstr_long(&cmdstr, timeout);
3008+
REDIS_CMD_APPEND_SSTR_OPT_STATIC(&cmdstr, copy, "COPY");
3009+
REDIS_CMD_APPEND_SSTR_OPT_STATIC(&cmdstr, replace, "REPLACE");
3010+
3011+
/* Append actual keys if we've got a keys array */
3012+
if (Z_TYPE_P(z_keys) == IS_ARRAY) {
3013+
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "KEYS");
3014+
3015+
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(z_keys), z_key) {
3016+
zstr = zval_get_string(z_key);
3017+
3018+
key = zstr->val;
3019+
keylen = zstr->len;
3020+
keyfree = redis_key_prefix(redis_sock, &key, &keylen);
3021+
3022+
/* Append the key */
3023+
redis_cmd_append_sstr(&cmdstr, zstr->val, zstr->len);
3024+
3025+
zend_string_release(zstr);
3026+
if (keyfree) efree(key);
3027+
} ZEND_HASH_FOREACH_END();
3028+
}
3029+
3030+
*cmd = cmdstr.c;
3031+
*cmd_len = cmdstr.len;
3032+
return SUCCESS;
3033+
}
3034+
29493035
/* DEL */
29503036
int redis_del_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
29513037
char **cmd, int *cmd_len, short *slot, void **ctx)

redis_commands.h

Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ int redis_georadius_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
251251
int redis_georadiusbymember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
252252
char **cmd, int *cmd_len, short *slot, void **ctx);
253253

254+
int redis_migrate_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
255+
char **cmd, int *cmd_len, short *slot, void **ctx);
256+
254257
/* Commands that don't communicate with Redis at all (such as getOption,
255258
* setOption, _prefix, _serialize, etc). These can be handled in one place
256259
* with the method of grabbing our RedisSock* object in different ways

0 commit comments

Comments
 (0)
0