mirror of
https://github.com/phpredis/phpredis.git
synced 2026-06-19 07:35:31 +00:00
Implement new RESTORE options
Add the new RESTORE options REPLACE, ABSTTL, FREQ <freq> and IDLETIME <idletime> Fixes #1410
This commit is contained in:
committed by
Michael Grunder
parent
6ea978eb72
commit
9a3fe401dc
@@ -3025,8 +3025,7 @@ PHP_METHOD(Redis, dump) {
|
||||
|
||||
/* {{{ proto Redis::restore(ttl, key, value) */
|
||||
PHP_METHOD(Redis, restore) {
|
||||
REDIS_PROCESS_KW_CMD("RESTORE", redis_key_long_str_cmd,
|
||||
redis_boolean_response);
|
||||
REDIS_PROCESS_CMD(restore, redis_boolean_response);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
+1
-1
@@ -364,7 +364,7 @@ public function persist(string $key): bool;
|
||||
|
||||
public function reset(): bool;
|
||||
|
||||
public function restore(string $key, int $timeout, string $value): bool;
|
||||
public function restore(string $key, int $timeout, string $value, ?array $options = NULL): bool;
|
||||
|
||||
public function role(): mixed;
|
||||
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: f547b5f24c4d373043c89dab57d450d27f959b08 */
|
||||
* Stub hash: 2c4ee6dc4a5aa66b1700df8859233c349aa00519 */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "null")
|
||||
@@ -642,6 +642,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_restore, 0, 3, _IS_B
|
||||
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, timeout, IS_LONG, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "NULL")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_Redis_role arginfo_class_Redis_getAuth
|
||||
|
||||
+1
-2
@@ -1418,8 +1418,7 @@ PHP_METHOD(RedisCluster, pfmerge) {
|
||||
|
||||
/* {{{ proto boolean RedisCluster::restore(string key, long ttl, string val) */
|
||||
PHP_METHOD(RedisCluster, restore) {
|
||||
CLUSTER_PROCESS_KW_CMD("RESTORE", redis_key_long_str_cmd,
|
||||
cluster_bool_resp, 0);
|
||||
CLUSTER_PROCESS_CMD(restore, cluster_bool_resp, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ class RedisCluster {
|
||||
|
||||
public function renamenx(string $key, string $newkey): bool;
|
||||
|
||||
public function restore(string $key, int $timeout, string $value): bool;
|
||||
public function restore(string $key, int $timeout, string $value, ?array $options = NULL): bool;
|
||||
|
||||
public function role(string|array $key_or_address): mixed;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 75e03c96590793af52efbea1d6440d3daa57a5d8 */
|
||||
* Stub hash: 956f295e74025def86150d0acdf7a11594c72d47 */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster___construct, 0, 0, 1)
|
||||
ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 1)
|
||||
@@ -526,7 +526,12 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_RedisCluster_renamenx arginfo_class_RedisCluster_rename
|
||||
|
||||
#define arginfo_class_RedisCluster_restore arginfo_class_RedisCluster_psetex
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_RedisCluster_restore, 0, 3, _IS_BOOL, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, timeout, IS_LONG, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "NULL")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_RedisCluster_role, 0, 1, IS_MIXED, 0)
|
||||
ZEND_ARG_TYPE_MASK(0, key_or_address, MAY_BE_STRING|MAY_BE_ARRAY, NULL)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 75e03c96590793af52efbea1d6440d3daa57a5d8 */
|
||||
* Stub hash: 956f295e74025def86150d0acdf7a11594c72d47 */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster___construct, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, name)
|
||||
@@ -459,7 +459,12 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_RedisCluster_renamenx arginfo_class_RedisCluster_rename
|
||||
|
||||
#define arginfo_class_RedisCluster_restore arginfo_class_RedisCluster_psetex
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_restore, 0, 0, 3)
|
||||
ZEND_ARG_INFO(0, key)
|
||||
ZEND_ARG_INFO(0, timeout)
|
||||
ZEND_ARG_INFO(0, value)
|
||||
ZEND_ARG_INFO(0, options)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_RedisCluster_role arginfo_class_RedisCluster_bgrewriteaof
|
||||
|
||||
|
||||
@@ -65,6 +65,13 @@ typedef struct redisLcsOptions {
|
||||
zend_bool withmatchlen;
|
||||
} redisLcsOptions;
|
||||
|
||||
typedef struct redisRestoreOptions {
|
||||
zend_bool replace;
|
||||
zend_bool absttl;
|
||||
zend_long idletime;
|
||||
zend_long freq;
|
||||
} redisRestoreOptions;
|
||||
|
||||
/* Local passthrough macro for command construction. Given that these methods
|
||||
* are generic (so they work whether the caller is Redis or RedisCluster) we
|
||||
* will always have redis_sock, slot*, and */
|
||||
@@ -2411,6 +2418,100 @@ int redis_lcs_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void redis_get_restore_options(redisRestoreOptions *dst, HashTable *ht) {
|
||||
zend_string *key;
|
||||
zend_long lval;
|
||||
zval *zv;
|
||||
|
||||
ZEND_ASSERT(dst != NULL);
|
||||
|
||||
memset(dst, 0, sizeof(*dst));
|
||||
dst->idletime = dst->freq = -1;
|
||||
|
||||
if (ht == NULL)
|
||||
return;
|
||||
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, zv) {
|
||||
ZVAL_DEREF(zv);
|
||||
|
||||
if (key) {
|
||||
if (zend_string_equals_literal_ci(key, "IDLETIME")) {
|
||||
lval = zval_get_long(zv);
|
||||
if (lval < 0) {
|
||||
php_error_docref(NULL, E_WARNING, "IDLETIME must be >= 0");
|
||||
} else {
|
||||
dst->idletime = lval;
|
||||
dst->freq = -1;
|
||||
}
|
||||
} else if (zend_string_equals_literal_ci(key, "FREQ")) {
|
||||
lval = zval_get_long(zv);
|
||||
if (lval < 0 || lval > 255) {
|
||||
php_error_docref(NULL, E_WARNING, "FREQ must be >= 0 and <= 255");
|
||||
} else {
|
||||
dst->freq = lval;
|
||||
dst->idletime = -1;
|
||||
}
|
||||
} else {
|
||||
php_error_docref(NULL, E_WARNING, "Unknown RESTORE option '%s'", ZSTR_VAL(key));
|
||||
}
|
||||
} else if (Z_TYPE_P(zv) == IS_STRING) {
|
||||
if (zend_string_equals_literal_ci(Z_STR_P(zv), "REPLACE")) {
|
||||
dst->replace = 1;
|
||||
} else if (zend_string_equals_literal_ci(Z_STR_P(zv), "ABSTTL")) {
|
||||
dst->absttl = 1;
|
||||
} else {
|
||||
php_error_docref(NULL, E_WARNING, "Unknown RESTORE option '%s'", Z_STRVAL_P(zv));
|
||||
}
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
|
||||
/* RESTORE */
|
||||
int redis_restore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx)
|
||||
{
|
||||
zend_string *key, *value = NULL;
|
||||
smart_string cmdstr = {0};
|
||||
HashTable *options = NULL;
|
||||
redisRestoreOptions opt;
|
||||
zend_long timeout = 0;
|
||||
int argc;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(3, 4) {
|
||||
Z_PARAM_STR(key)
|
||||
Z_PARAM_LONG(timeout)
|
||||
Z_PARAM_STR(value)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_ARRAY_HT_OR_NULL(options)
|
||||
} ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
|
||||
|
||||
redis_get_restore_options(&opt, options);
|
||||
|
||||
argc = 3 + (opt.idletime>-1?2:0) + (opt.freq>-1?2:0) + !!opt.absttl + !!opt.replace;
|
||||
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, argc, "RESTORE");
|
||||
|
||||
redis_cmd_append_sstr_key(&cmdstr, ZSTR_VAL(key), ZSTR_LEN(key), redis_sock, slot);
|
||||
redis_cmd_append_sstr_long(&cmdstr, timeout);
|
||||
redis_cmd_append_sstr_zstr(&cmdstr, value);
|
||||
|
||||
REDIS_CMD_APPEND_SSTR_OPT_STATIC(&cmdstr, opt.replace, "REPLACE");
|
||||
REDIS_CMD_APPEND_SSTR_OPT_STATIC(&cmdstr, opt.absttl, "ABSTTL");
|
||||
|
||||
if (opt.idletime > -1) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "IDLETIME");
|
||||
redis_cmd_append_sstr_long(&cmdstr, opt.idletime);
|
||||
}
|
||||
|
||||
if (opt.freq > -1) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "FREQ");
|
||||
redis_cmd_append_sstr_long(&cmdstr, opt.freq);
|
||||
}
|
||||
|
||||
*cmd = cmdstr.c;
|
||||
*cmd_len = cmdstr.len;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* BITPOS */
|
||||
int redis_bitpos_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
|
||||
@@ -135,6 +135,9 @@ int redis_lcs_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
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_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: f547b5f24c4d373043c89dab57d450d27f959b08 */
|
||||
* Stub hash: 2c4ee6dc4a5aa66b1700df8859233c349aa00519 */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
|
||||
ZEND_ARG_INFO(0, options)
|
||||
@@ -552,6 +552,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_restore, 0, 0, 3)
|
||||
ZEND_ARG_INFO(0, key)
|
||||
ZEND_ARG_INFO(0, timeout)
|
||||
ZEND_ARG_INFO(0, value)
|
||||
ZEND_ARG_INFO(0, options)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_Redis_role arginfo_class_Redis___destruct
|
||||
|
||||
@@ -5096,6 +5096,22 @@ class Redis_Test extends TestSuite
|
||||
$this->assertTrue($this->redis->get('foo') === 'this-is-bar');
|
||||
$this->assertTrue($this->redis->get('bar') === 'this-is-foo');
|
||||
|
||||
/* Test that we can REPLACE a key */
|
||||
$this->assertTrue($this->redis->set('foo', 'some-value'));
|
||||
$this->assertTrue($this->redis->restore('foo', 0, $d_bar, ['REPLACE']));
|
||||
|
||||
/* Ensure we can set an absolute TTL */
|
||||
$this->assertTrue($this->redis->restore('foo', time() + 10, $d_bar, ['REPLACE', 'ABSTTL']));
|
||||
$this->assertTrue($this->redis->ttl('foo') <= 10);
|
||||
|
||||
/* Ensure we can set an IDLETIME */
|
||||
$this->assertTrue($this->redis->restore('foo', 0, $d_bar, ['REPLACE', 'IDLETIME' => 200]));
|
||||
$this->assertTrue($this->redis->object('idletime', 'foo') > 100);
|
||||
|
||||
/* We can't neccissarily check this depending on LRU policy, but at least attempt to use
|
||||
the FREQ option */
|
||||
$this->assertTrue($this->redis->restore('foo', 0, $d_bar, ['REPLACE', 'FREQ' => 200]));
|
||||
|
||||
$this->redis->del('foo');
|
||||
$this->redis->del('bar');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user