Synchronize Redis and RedisSentinel constructors

This commit is contained in:
Pavlo Yatsukhnenko
2023-02-12 22:33:45 +02:00
parent e571a81f8d
commit ebb2386e52
9 changed files with 103 additions and 152 deletions

View File

@@ -2749,6 +2749,80 @@ PHP_REDIS_API void redis_debug_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock
}
}
PHP_REDIS_API int
redis_sock_configure(RedisSock *redis_sock, HashTable *opts)
{
zend_string *zkey;
zval *val;
ZEND_HASH_FOREACH_STR_KEY_VAL(opts, zkey, val) {
if (zkey == NULL) {
continue;
}
ZVAL_DEREF(val);
if (zend_string_equals_literal_ci(zkey, "host")) {
if (Z_TYPE_P(val) != IS_STRING) {
REDIS_VALUE_EXCEPTION("Invalid host");
return FAILURE;
}
if (redis_sock->host) zend_string_release(redis_sock->host);
redis_sock->host = zval_get_string(val);
} else if (zend_string_equals_literal_ci(zkey, "port")) {
if (Z_TYPE_P(val) != IS_LONG) {
REDIS_VALUE_EXCEPTION("Invalid port");
return FAILURE;
}
redis_sock->port = zval_get_long(val);
} else if (zend_string_equals_literal_ci(zkey, "connectTimeout")) {
if (Z_TYPE_P(val) != IS_LONG && Z_TYPE_P(val) != IS_DOUBLE) {
REDIS_VALUE_EXCEPTION("Invalid connect timeout");
return FAILURE;
}
redis_sock->timeout = zval_get_double(val);
} else if (zend_string_equals_literal_ci(zkey, "readTimeout")) {
if (Z_TYPE_P(val) != IS_LONG && Z_TYPE_P(val) != IS_DOUBLE) {
REDIS_VALUE_EXCEPTION("Invalid read timeout");
return FAILURE;
}
redis_sock->read_timeout = zval_get_double(val);
} else if (zend_string_equals_literal_ci(zkey, "persistent")) {
if (Z_TYPE_P(val) == IS_STRING) {
if (redis_sock->persistent_id) zend_string_release(redis_sock->persistent_id);
redis_sock->persistent_id = zval_get_string(val);
redis_sock->persistent = 1;
} else {
redis_sock->persistent = zval_is_true(val);
}
} else if (zend_string_equals_literal_ci(zkey, "retryInterval")) {
if (Z_TYPE_P(val) != IS_LONG && Z_TYPE_P(val) != IS_DOUBLE) {
REDIS_VALUE_EXCEPTION("Invalid retry interval");
return FAILURE;
}
redis_sock->retry_interval = zval_get_long(val);
} else if (zend_string_equals_literal_ci(zkey, "ssl")) {
if (redis_sock_set_stream_context(redis_sock, val) != SUCCESS) {
REDIS_VALUE_EXCEPTION("Invalid SSL context options");
return FAILURE;
}
} else if (zend_string_equals_literal_ci(zkey, "auth")) {
if (Z_TYPE_P(val) != IS_STRING && Z_TYPE_P(val) != IS_ARRAY) {
REDIS_VALUE_EXCEPTION("Invalid auth credentials");
return FAILURE;
}
redis_sock_set_auth_zval(redis_sock, val);
} else if (zend_string_equals_literal_ci(zkey, "backoff")) {
if (redis_sock_set_backoff(redis_sock, val) != SUCCESS) {
REDIS_VALUE_EXCEPTION("Invalid backoff options");
return FAILURE;
}
} else {
php_error_docref(NULL, E_WARNING, "Skip unknown option '%s'", ZSTR_VAL(zkey));
}
} ZEND_HASH_FOREACH_END();
return SUCCESS;
}
/**
* redis_sock_create
*/

View File

@@ -75,6 +75,7 @@ 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_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);

82
redis.c
View File

@@ -455,83 +455,19 @@ PHP_MINFO_FUNCTION(redis)
Public constructor */
PHP_METHOD(Redis, __construct)
{
HashTable *opts = NULL;
redis_object *redis;
zend_string *zkey;
zval *val, *opts = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a", &opts) == FAILURE) {
ZEND_PARSE_PARAMETERS_START(0, 1)
Z_PARAM_OPTIONAL
Z_PARAM_ARRAY_HT_OR_NULL(opts)
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);
if (opts != NULL && redis_sock_configure(redis->sock, opts) != SUCCESS) {
RETURN_THROWS();
}
if (opts != NULL) {
redis = PHPREDIS_ZVAL_GET_OBJECT(redis_object, getThis());
redis->sock = redis_sock_create("127.0.0.1", sizeof("127.0.0.1") - 1, 6379, 0, 0, 0, NULL, 0);
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(opts), zkey, val) {
if (zkey == NULL) {
continue;
}
ZVAL_DEREF(val);
if (zend_string_equals_literal_ci(zkey, "host")) {
if (Z_TYPE_P(val) != IS_STRING) {
REDIS_VALUE_EXCEPTION("Invalid host");
RETURN_THROWS();
}
zend_string_release(redis->sock->host);
redis->sock->host = zval_get_string(val);
} else if (zend_string_equals_literal_ci(zkey, "port")) {
if (Z_TYPE_P(val) != IS_LONG) {
REDIS_VALUE_EXCEPTION("Invalid port");
RETURN_THROWS();
}
redis->sock->port = zval_get_long(val);
} else if (zend_string_equals_literal_ci(zkey, "connectTimeout")) {
if (Z_TYPE_P(val) != IS_LONG && Z_TYPE_P(val) != IS_DOUBLE) {
REDIS_VALUE_EXCEPTION("Invalid connect timeout");
RETURN_THROWS();
}
redis->sock->timeout = zval_get_double(val);
} else if (zend_string_equals_literal_ci(zkey, "readTimeout")) {
if (Z_TYPE_P(val) != IS_LONG && Z_TYPE_P(val) != IS_DOUBLE) {
REDIS_VALUE_EXCEPTION("Invalid read timeout");
RETURN_THROWS();
}
redis->sock->read_timeout = zval_get_double(val);
} else if (zend_string_equals_literal_ci(zkey, "persistent")) {
if (Z_TYPE_P(val) == IS_STRING) {
if (redis->sock->persistent_id) zend_string_release(redis->sock->persistent_id);
redis->sock->persistent_id = zval_get_string(val);
redis->sock->persistent = 1;
} else {
redis->sock->persistent = zval_is_true(val);
}
} else if (zend_string_equals_literal_ci(zkey, "retryInterval")) {
if (Z_TYPE_P(val) != IS_LONG && Z_TYPE_P(val) != IS_DOUBLE) {
REDIS_VALUE_EXCEPTION("Invalid retry interval");
RETURN_THROWS();
}
redis->sock->retry_interval = zval_get_long(val);
} else if (zend_string_equals_literal_ci(zkey, "ssl")) {
if (redis_sock_set_stream_context(redis->sock, val) != SUCCESS) {
REDIS_VALUE_EXCEPTION("Invalid SSL context options");
RETURN_THROWS();
}
} else if (zend_string_equals_literal_ci(zkey, "auth")) {
if (Z_TYPE_P(val) != IS_STRING && Z_TYPE_P(val) != IS_ARRAY) {
REDIS_VALUE_EXCEPTION("Invalid auth credentials");
RETURN_THROWS();
}
redis_sock_set_auth_zval(redis->sock, val);
} else if (zend_string_equals_literal_ci(zkey, "backoff")) {
if (redis_sock_set_backoff(redis->sock, val) != SUCCESS) {
REDIS_VALUE_EXCEPTION("Invalid backoff options");
RETURN_THROWS();
}
} else {
php_error_docref(NULL, E_WARNING, "Skip unknown option '%s'", ZSTR_VAL(zkey));
}
} ZEND_HASH_FOREACH_END();
}
}
/* }}} */

View File

@@ -41,61 +41,20 @@ PHP_MINIT_FUNCTION(redis_sentinel)
PHP_METHOD(RedisSentinel, __construct)
{
int persistent = 0;
char *persistent_id = NULL;
double timeout = 0.0, read_timeout = 0.0;
zend_long port = 26379, retry_interval = 0;
redis_sentinel_object *obj;
zend_string *host;
zval *auth = NULL, *context = NULL, *zv = NULL;
HashTable *opts = NULL;
redis_sentinel_object *sentinel;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|ldz!ldza",
&host, &port, &timeout, &zv,
&retry_interval, &read_timeout,
&auth, &context) == FAILURE) {
RETURN_FALSE;
}
ZEND_PARSE_PARAMETERS_START(0, 1)
Z_PARAM_OPTIONAL
Z_PARAM_ARRAY_HT_OR_NULL(opts)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_THROWS());
if (port < 0 || port > UINT16_MAX) {
REDIS_VALUE_EXCEPTION("Invalid port");
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);
if (opts != NULL && redis_sock_configure(sentinel->sock, opts) != SUCCESS) {
RETURN_THROWS();
}
if (timeout > INT_MAX) {
REDIS_VALUE_EXCEPTION("Invalid connect timeout");
RETURN_THROWS();
}
if (read_timeout > INT_MAX) {
REDIS_VALUE_EXCEPTION("Invalid read timeout");
RETURN_THROWS();
}
if (retry_interval < 0L || retry_interval > INT_MAX) {
REDIS_VALUE_EXCEPTION("Invalid retry interval");
RETURN_THROWS();
}
if (zv) {
ZVAL_DEREF(zv);
if (Z_TYPE_P(zv) == IS_STRING) {
persistent_id = Z_STRVAL_P(zv);
persistent = 1; /* even empty */
} else {
persistent = zval_is_true(zv);
}
}
obj = PHPREDIS_ZVAL_GET_OBJECT(redis_sentinel_object, getThis());
obj->sock = redis_sock_create(ZSTR_VAL(host), ZSTR_LEN(host), port,
timeout, read_timeout, persistent, persistent_id, retry_interval);
if (auth) {
redis_sock_set_auth_zval(obj->sock, auth);
}
if (context) {
redis_sock_set_stream_context(obj->sock, context);
}
obj->sock->sentinel = 1;
sentinel->sock->sentinel = 1;
}
PHP_METHOD(RedisSentinel, ckquorum)

View File

@@ -3,7 +3,7 @@
#include "sentinel_library.h"
#define PHP_REDIS_SENTINEL_VERSION "0.1"
#define PHP_REDIS_SENTINEL_VERSION "1.0"
extern zend_class_entry *redis_sentinel_ce;
extern PHP_MINIT_FUNCTION(redis_sentinel);

View File

@@ -8,7 +8,7 @@
class RedisSentinel {
public function __construct(string $host, int $port = 26379, float $timeout = 0, mixed $persistent = null, int $retry_interval = 0, float $read_timeout = 0, #[\SensitiveParameter] mixed $auth = null, array $context = null);
public function __construct(array $options = null);
/** @return bool|RedisSentinel */
public function ckquorum(string $master);

View File

@@ -1,15 +1,8 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 847c735dfbbb643366344acfe6e2c5e8b76d0520 */
* Stub hash: f1f746cc848b1debcdf88eae015732720ba206c8 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisSentinel___construct, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, host, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, port, IS_LONG, 0, "26379")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeout, IS_DOUBLE, 0, "0")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent, IS_MIXED, 0, "null")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, retry_interval, IS_LONG, 0, "0")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, read_timeout, IS_DOUBLE, 0, "0")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, auth, IS_MIXED, 0, "null")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, context, IS_ARRAY, 0, "null")
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisSentinel___construct, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "null")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisSentinel_ckquorum, 0, 0, 1)
@@ -77,11 +70,6 @@ static zend_class_entry *register_class_RedisSentinel(void)
INIT_CLASS_ENTRY(ce, "RedisSentinel", class_RedisSentinel_methods);
class_entry = zend_register_internal_class_ex(&ce, NULL);
#if (PHP_VERSION_ID >= 80200)
zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "__construct", sizeof("__construct") - 1), 6, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0);
#endif
return class_entry;
}

View File

@@ -1,15 +1,8 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 847c735dfbbb643366344acfe6e2c5e8b76d0520 */
* Stub hash: f1f746cc848b1debcdf88eae015732720ba206c8 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisSentinel___construct, 0, 0, 1)
ZEND_ARG_INFO(0, host)
ZEND_ARG_INFO(0, port)
ZEND_ARG_INFO(0, timeout)
ZEND_ARG_INFO(0, persistent)
ZEND_ARG_INFO(0, retry_interval)
ZEND_ARG_INFO(0, read_timeout)
ZEND_ARG_INFO(0, auth)
ZEND_ARG_INFO(0, context)
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisSentinel___construct, 0, 0, 0)
ZEND_ARG_INFO(0, options)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisSentinel_ckquorum, 0, 0, 1)

View File

@@ -30,7 +30,7 @@ class Redis_Sentinel_Test extends TestSuite
protected function newInstance()
{
return new RedisSentinel($this->getHost());
return new RedisSentinel(['host' => $this->getHost()]);
}
public function setUp()