From b7e8b3b64edbfc6583f551a22c9d2186625e19c9 Mon Sep 17 00:00:00 2001 From: vostok4 Date: Thu, 10 Oct 2013 13:07:01 +0200 Subject: [PATCH 1/5] Fix compilation errors on Win32 with VC11 This brings the W32 compilation fixes done by @char101 up to date and allows building of php_redis.dll with VC11 on Win32 (allows for a php5.5 version). --- config.w32 | 12 ++++-- library.c | 104 +++++++++++++++++++++++++-------------------- library.h | 75 ++++++++++++++++---------------- php_redis.h | 36 ++++++++-------- redis.c | 95 +++++++++++++++++++++-------------------- redis_array.c | 9 ++-- redis_array_impl.c | 5 ++- redis_session.c | 14 +++--- 8 files changed, 185 insertions(+), 165 deletions(-) diff --git a/config.w32 b/config.w32 index 8b39af90..6926a027 100644 --- a/config.w32 +++ b/config.w32 @@ -2,14 +2,20 @@ ARG_ENABLE("redis", "whether to enable redis support", "yes"); 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 library.c igbinary\\igbinary.c igbinary\\hash_si.c igbinary\\hash_function.c"; + var sources = "redis.c library.c redis_array.c redis_array_impl.c"; if (PHP_REDIS_SESSION != "no") { AC_DEFINE('PHP_SESSION', 1); sources += " redis_session.c"; } - - AC_DEFINE("PHP_EXPORTS", 1); + + if (PHP_REDIS_IGBINARY != "no") { + CHECK_HEADER_ADD_INCLUDE("igbinary.h", "CFLAGS_REDIS", "ext\\igbinary"); + AC_DEFINE('HAVE_REDIS_IGBINARY', 1); + ADD_EXTENSION_DEP('redis', 'igbinary'); + } + EXTENSION("redis", sources); } diff --git a/library.c b/library.c index 7e7dc072..7db595b8 100644 --- a/library.c +++ b/library.c @@ -18,6 +18,12 @@ #include "library.h" #include +#ifdef _MSC_VER +#define atoll _atoi64 +#define random rand +#define usleep Sleep +#endif + #define UNSERIALIZE_ONLY_VALUES 0 #define UNSERIALIZE_ALL 1 @@ -25,7 +31,7 @@ extern zend_class_entry *redis_ce; extern zend_class_entry *redis_exception_ce; extern zend_class_entry *spl_ce_RuntimeException; -PHPAPI void redis_stream_close(RedisSock *redis_sock TSRMLS_DC) { +PHP_REDIS_API void redis_stream_close(RedisSock *redis_sock TSRMLS_DC) { if (!redis_sock->persistent) { php_stream_close(redis_sock->stream); } else { @@ -33,7 +39,7 @@ PHPAPI void redis_stream_close(RedisSock *redis_sock TSRMLS_DC) { } } -PHPAPI int redis_check_eof(RedisSock *redis_sock TSRMLS_DC) +PHP_REDIS_API int redis_check_eof(RedisSock *redis_sock TSRMLS_DC) { int eof; int count = 0; @@ -100,7 +106,7 @@ PHPAPI int redis_check_eof(RedisSock *redis_sock TSRMLS_DC) return 0; } -PHPAPI zval *redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock) { +PHP_REDIS_API zval *redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock) { char inbuf[1024]; int numElems; zval *z_tab; @@ -135,7 +141,7 @@ PHPAPI zval *redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAMETERS, /** * redis_sock_read_bulk_reply */ -PHPAPI char *redis_sock_read_bulk_reply(RedisSock *redis_sock, int bytes TSRMLS_DC) +PHP_REDIS_API char *redis_sock_read_bulk_reply(RedisSock *redis_sock, int bytes TSRMLS_DC) { int offset = 0; size_t got; @@ -175,7 +181,7 @@ PHPAPI char *redis_sock_read_bulk_reply(RedisSock *redis_sock, int bytes TSRMLS_ /** * redis_sock_read */ -PHPAPI char *redis_sock_read(RedisSock *redis_sock, int *buf_len TSRMLS_DC) +PHP_REDIS_API char *redis_sock_read(RedisSock *redis_sock, int *buf_len TSRMLS_DC) { char inbuf[1024]; char *resp = NULL; @@ -298,6 +304,7 @@ redis_cmd_format_static(char **ret, char *keyword, char *format, ...) { smart_str buf = {0}; int l = strlen(keyword); char *dbl_str; + char dbl_decsep; int dbl_len; va_start(ap, format); @@ -379,6 +386,7 @@ redis_cmd_format(char **ret, char *format, ...) { va_list ap; char *p = format; char *dbl_str; + char dbl_decsep; int dbl_len; va_start(ap, format); @@ -508,12 +516,14 @@ int redis_cmd_append_sstr_long(smart_str *str, long append) { int redis_cmd_append_sstr_dbl(smart_str *str, double value) { char *dbl_str; int dbl_len; + char dbl_decsep; + int retval; /// Convert to double REDIS_DOUBLE_TO_STRING(dbl_str, dbl_len, value); // Append the string - int retval = redis_cmd_append_sstr(str, dbl_str, dbl_len); + retval = redis_cmd_append_sstr(str, dbl_str, dbl_len); // Free our double string efree(dbl_str); @@ -535,7 +545,7 @@ int redis_cmd_append_int(char **cmd, int cmd_len, int append) { return redis_cmd_append_str(cmd, cmd_len, int_buf, int_len); } -PHPAPI void redis_bulk_double_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { +PHP_REDIS_API void redis_bulk_double_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { char *response; int response_len; @@ -559,7 +569,7 @@ PHPAPI void redis_bulk_double_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock * } } -PHPAPI void redis_type_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { +PHP_REDIS_API void redis_type_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { char *response; int response_len; long l; @@ -594,7 +604,7 @@ PHPAPI void redis_type_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s } } -PHPAPI void redis_info_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { +PHP_REDIS_API void redis_info_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { char *response; int response_len; char *pos, *cur; @@ -673,11 +683,17 @@ PHPAPI void redis_info_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s * Specialized handling of the CLIENT LIST output so it comes out in a simple way for PHP userland code * to handle. */ -PHPAPI void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab) { +PHP_REDIS_API void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab) { char *resp; int resp_len; zval *z_result, *z_sub_result; - + + // Pointers for parsing + char *p = resp, *lpos = resp, *kpos = NULL, *vpos = NULL, *p2, *key, *value; + + // Key length, done flag + int klen, done = 0, is_numeric; + // Make sure we can read a response from Redis if((resp = redis_sock_read(redis_sock, &resp_len TSRMLS_CC)) == NULL) { RETURN_FALSE; @@ -691,12 +707,6 @@ PHPAPI void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *red ALLOC_INIT_ZVAL(z_sub_result); array_init(z_sub_result); - // Pointers for parsing - char *p = resp, *lpos = resp, *kpos = NULL, *vpos = NULL, *p2, *key, *value; - - // Key length, done flag - int klen, done = 0, is_numeric; - // While we've got more to parse while(!done) { // What character are we on @@ -791,7 +801,7 @@ PHPAPI void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *red } } -PHPAPI void redis_boolean_response_impl(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx, SuccessCallback success_callback) { +PHP_REDIS_API void redis_boolean_response_impl(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx, SuccessCallback success_callback) { char *response; int response_len; @@ -828,11 +838,11 @@ PHPAPI void redis_boolean_response_impl(INTERNAL_FUNCTION_PARAMETERS, RedisSock } } -PHPAPI void redis_boolean_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { +PHP_REDIS_API void redis_boolean_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { redis_boolean_response_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, ctx, NULL); } -PHPAPI void redis_long_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval * z_tab, void *ctx) { +PHP_REDIS_API void redis_long_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval * z_tab, void *ctx) { char *response; int response_len; @@ -875,7 +885,7 @@ PHPAPI void redis_long_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s -PHPAPI int redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, int flag) { +PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, int flag) { /* int ret = redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab TSRMLS_CC); @@ -928,16 +938,16 @@ PHPAPI int redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNCTION_PA return 0; } -PHPAPI int redis_sock_read_multibulk_reply_zipped(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { +PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { return redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, 1); } -PHPAPI int redis_sock_read_multibulk_reply_zipped_strings(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { +PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped_strings(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { return redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, 0); } -PHPAPI void redis_1_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { +PHP_REDIS_API void redis_1_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { char *response; int response_len; @@ -969,7 +979,7 @@ PHPAPI void redis_1_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock } } -PHPAPI void redis_string_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { +PHP_REDIS_API void redis_string_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { char *response; int response_len; @@ -999,7 +1009,7 @@ PHPAPI void redis_string_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis } /* like string response, but never unserialized. */ -PHPAPI void redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { +PHP_REDIS_API void redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { char *response; int response_len; @@ -1022,7 +1032,7 @@ PHPAPI void redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s /** * redis_sock_create */ -PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short port, +PHP_REDIS_API RedisSock* redis_sock_create(char *host, int host_len, unsigned short port, double timeout, int persistent, char *persistent_id, long retry_interval, zend_bool lazy_connect) @@ -1070,7 +1080,7 @@ PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short por /** * redis_sock_connect */ -PHPAPI int redis_sock_connect(RedisSock *redis_sock TSRMLS_DC) +PHP_REDIS_API int redis_sock_connect(RedisSock *redis_sock TSRMLS_DC) { struct timeval tv, read_tv, *tv_ptr = NULL; char *host = NULL, *persistent_id = NULL, *errstr = NULL; @@ -1146,7 +1156,7 @@ PHPAPI int redis_sock_connect(RedisSock *redis_sock TSRMLS_DC) /** * redis_sock_server_open */ -PHPAPI int redis_sock_server_open(RedisSock *redis_sock, int force_connect TSRMLS_DC) +PHP_REDIS_API int redis_sock_server_open(RedisSock *redis_sock, int force_connect TSRMLS_DC) { int res = -1; @@ -1173,7 +1183,7 @@ PHPAPI int redis_sock_server_open(RedisSock *redis_sock, int force_connect TSRML /** * redis_sock_disconnect */ -PHPAPI int redis_sock_disconnect(RedisSock *redis_sock TSRMLS_DC) +PHP_REDIS_API int redis_sock_disconnect(RedisSock *redis_sock TSRMLS_DC) { if (redis_sock == NULL) { return 1; @@ -1198,7 +1208,7 @@ PHPAPI int redis_sock_disconnect(RedisSock *redis_sock TSRMLS_DC) return 0; } -PHPAPI void redis_send_discard(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock) +PHP_REDIS_API void redis_send_discard(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock) { char *cmd; int response_len, cmd_len; @@ -1225,7 +1235,7 @@ PHPAPI void redis_send_discard(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_so /** * redis_sock_set_err */ -PHPAPI int redis_sock_set_err(RedisSock *redis_sock, const char *msg, int msg_len) { +PHP_REDIS_API int redis_sock_set_err(RedisSock *redis_sock, const char *msg, int msg_len) { // Allocate/Reallocate our last error member if(msg != NULL && msg_len > 0) { if(redis_sock->err == NULL) { @@ -1256,7 +1266,7 @@ PHPAPI int redis_sock_set_err(RedisSock *redis_sock, const char *msg, int msg_le /** * redis_sock_read_multibulk_reply */ -PHPAPI 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, void *ctx) { char inbuf[1024]; int numElems; @@ -1303,7 +1313,7 @@ PHPAPI int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSo /** * Like multibulk reply, but don't touch the values, they won't be compressed. (this is used by HKEYS). */ -PHPAPI int redis_sock_read_multibulk_reply_raw(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) +PHP_REDIS_API int redis_sock_read_multibulk_reply_raw(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { char inbuf[1024]; int numElems; @@ -1347,7 +1357,7 @@ PHPAPI int redis_sock_read_multibulk_reply_raw(INTERNAL_FUNCTION_PARAMETERS, Red return 0; } -PHPAPI int +PHP_REDIS_API int redis_sock_read_multibulk_reply_loop(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, int numElems, int unwrap_key, int unserialize_even_only) { @@ -1379,7 +1389,7 @@ redis_sock_read_multibulk_reply_loop(INTERNAL_FUNCTION_PARAMETERS, RedisSock *re /** * redis_sock_read_multibulk_reply_assoc */ -PHPAPI int redis_sock_read_multibulk_reply_assoc(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) +PHP_REDIS_API int redis_sock_read_multibulk_reply_assoc(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { char inbuf[1024], *response; int response_len; @@ -1446,7 +1456,7 @@ PHPAPI int redis_sock_read_multibulk_reply_assoc(INTERNAL_FUNCTION_PARAMETERS, R /** * redis_sock_write */ -PHPAPI int redis_sock_write(RedisSock *redis_sock, char *cmd, size_t sz TSRMLS_DC) +PHP_REDIS_API int redis_sock_write(RedisSock *redis_sock, char *cmd, size_t sz TSRMLS_DC) { if(redis_sock && redis_sock->status == REDIS_SOCK_STATUS_DISCONNECTED) { zend_throw_exception(redis_exception_ce, "Connection closed", 0 TSRMLS_CC); @@ -1461,7 +1471,7 @@ PHPAPI int redis_sock_write(RedisSock *redis_sock, char *cmd, size_t sz TSRMLS_D /** * redis_free_socket */ -PHPAPI void redis_free_socket(RedisSock *redis_sock) +PHP_REDIS_API void redis_free_socket(RedisSock *redis_sock) { if(redis_sock->prefix) { efree(redis_sock->prefix); @@ -1479,7 +1489,7 @@ PHPAPI void redis_free_socket(RedisSock *redis_sock) efree(redis_sock); } -PHPAPI int +PHP_REDIS_API int redis_serialize(RedisSock *redis_sock, zval *z, char **val, int *val_len TSRMLS_DC) { #if ZEND_MODULE_API_NO >= 20100000 php_serialize_data_t ht; @@ -1555,7 +1565,7 @@ redis_serialize(RedisSock *redis_sock, zval *z, char **val, int *val_len TSRMLS_ return 0; } -PHPAPI int +PHP_REDIS_API int redis_unserialize(RedisSock *redis_sock, const char *val, int val_len, zval **return_value TSRMLS_DC) { php_unserialize_data_t var_hash; @@ -1606,7 +1616,7 @@ redis_unserialize(RedisSock *redis_sock, const char *val, int val_len, zval **re return 0; } -PHPAPI int +PHP_REDIS_API int redis_key_prefix(RedisSock *redis_sock, char **key, int *key_len TSRMLS_DC) { int ret_len; char *ret; @@ -1629,7 +1639,7 @@ redis_key_prefix(RedisSock *redis_sock, char **key, int *key_len TSRMLS_DC) { * Processing for variant reply types (think EVAL) */ -PHPAPI int +PHP_REDIS_API int redis_sock_gets(RedisSock *redis_sock, char *buf, int buf_size, size_t *line_size TSRMLS_DC) { // Handle EOF if(-1 == redis_check_eof(redis_sock TSRMLS_CC)) { @@ -1657,7 +1667,7 @@ redis_sock_gets(RedisSock *redis_sock, char *buf, int buf_size, size_t *line_siz return 0; } -PHPAPI int +PHP_REDIS_API int redis_read_reply_type(RedisSock *redis_sock, REDIS_REPLY_TYPE *reply_type, int *reply_info TSRMLS_DC) { // Make sure we haven't lost the connection, even trying to reconnect if(-1 == redis_check_eof(redis_sock TSRMLS_CC)) { @@ -1691,7 +1701,7 @@ redis_read_reply_type(RedisSock *redis_sock, REDIS_REPLY_TYPE *reply_type, int * /* * Read a single line response, having already consumed the reply-type byte */ -PHPAPI int +PHP_REDIS_API int redis_read_variant_line(RedisSock *redis_sock, REDIS_REPLY_TYPE reply_type, zval **z_ret TSRMLS_DC) { // Buffer to read our single line reply char inbuf[1024]; @@ -1721,7 +1731,7 @@ redis_read_variant_line(RedisSock *redis_sock, REDIS_REPLY_TYPE reply_type, zval return 0; } -PHPAPI int +PHP_REDIS_API int redis_read_variant_bulk(RedisSock *redis_sock, int size, zval **z_ret TSRMLS_DC) { // Attempt to read the bulk reply char *bulk_resp = redis_sock_read_bulk_reply(redis_sock, size TSRMLS_CC); @@ -1736,7 +1746,7 @@ redis_read_variant_bulk(RedisSock *redis_sock, int size, zval **z_ret TSRMLS_DC) } } -PHPAPI int +PHP_REDIS_API int redis_read_multibulk_recursive(RedisSock *redis_sock, int elements, zval **z_ret TSRMLS_DC) { int reply_info; REDIS_REPLY_TYPE reply_type; @@ -1784,7 +1794,7 @@ redis_read_multibulk_recursive(RedisSock *redis_sock, int elements, zval **z_ret return 0; } -PHPAPI int +PHP_REDIS_API int redis_read_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab) { // Reply type, and reply size vars REDIS_REPLY_TYPE reply_type; diff --git a/library.h b/library.h index 7b1d0383..ec34987c 100644 --- a/library.h +++ b/library.h @@ -11,44 +11,44 @@ int redis_cmd_append_sstr_long(smart_str *str, long append); int redis_cmd_append_int(char **cmd, int cmd_len, int append); int redis_cmd_append_sstr_dbl(smart_str *str, double value); -PHPAPI char * redis_sock_read(RedisSock *redis_sock, int *buf_len TSRMLS_DC); +PHP_REDIS_API char * redis_sock_read(RedisSock *redis_sock, int *buf_len TSRMLS_DC); -PHPAPI void redis_1_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); -PHPAPI void redis_long_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval* z_tab, void *ctx); +PHP_REDIS_API void redis_1_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); +PHP_REDIS_API void redis_long_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval* z_tab, void *ctx); typedef void (*SuccessCallback)(RedisSock *redis_sock); -PHPAPI void redis_boolean_response_impl(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx, SuccessCallback success_callback); -PHPAPI void redis_boolean_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); -PHPAPI void redis_bulk_double_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); -PHPAPI void redis_string_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); -PHPAPI void redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); -PHPAPI void redis_info_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); -PHPAPI void redis_type_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); -PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short port, double timeout, int persistent, char *persistent_id, long retry_interval, zend_bool lazy_connect); -PHPAPI int redis_sock_connect(RedisSock *redis_sock TSRMLS_DC); -PHPAPI int redis_sock_server_open(RedisSock *redis_sock, int force_connect TSRMLS_DC); -PHPAPI int redis_sock_disconnect(RedisSock *redis_sock TSRMLS_DC); -PHPAPI zval *redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock); -PHPAPI char *redis_sock_read_bulk_reply(RedisSock *redis_sock, int bytes TSRMLS_DC); -PHPAPI int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *_z_tab, void *ctx); -PHPAPI int redis_sock_read_multibulk_reply_raw(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); -PHPAPI int redis_sock_read_multibulk_reply_loop(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, int numElems, int unwrap_key, int unserialize_even_only); -PHPAPI int redis_sock_read_multibulk_reply_zipped(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); -PHPAPI int redis_sock_read_multibulk_reply_zipped_strings(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); -PHPAPI int redis_sock_read_multibulk_reply_assoc(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); -PHPAPI int redis_sock_write(RedisSock *redis_sock, char *cmd, size_t sz TSRMLS_DC); -PHPAPI void redis_stream_close(RedisSock *redis_sock TSRMLS_DC); -PHPAPI int redis_check_eof(RedisSock *redis_sock TSRMLS_DC); +PHP_REDIS_API void redis_boolean_response_impl(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx, SuccessCallback success_callback); +PHP_REDIS_API void redis_boolean_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); +PHP_REDIS_API void redis_bulk_double_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); +PHP_REDIS_API void redis_string_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); +PHP_REDIS_API void redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); +PHP_REDIS_API void redis_info_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); +PHP_REDIS_API void 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, unsigned short port, double timeout, int persistent, char *persistent_id, long retry_interval, zend_bool lazy_connect); +PHP_REDIS_API int redis_sock_connect(RedisSock *redis_sock TSRMLS_DC); +PHP_REDIS_API int redis_sock_server_open(RedisSock *redis_sock, int force_connect TSRMLS_DC); +PHP_REDIS_API int redis_sock_disconnect(RedisSock *redis_sock TSRMLS_DC); +PHP_REDIS_API zval *redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock); +PHP_REDIS_API char *redis_sock_read_bulk_reply(RedisSock *redis_sock, int bytes TSRMLS_DC); +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_raw(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); +PHP_REDIS_API int redis_sock_read_multibulk_reply_loop(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, int numElems, int unwrap_key, int unserialize_even_only); +PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); +PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped_strings(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); +PHP_REDIS_API int redis_sock_read_multibulk_reply_assoc(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); +PHP_REDIS_API int redis_sock_write(RedisSock *redis_sock, char *cmd, size_t sz TSRMLS_DC); +PHP_REDIS_API void redis_stream_close(RedisSock *redis_sock TSRMLS_DC); +PHP_REDIS_API int redis_check_eof(RedisSock *redis_sock TSRMLS_DC); //PHPAPI int redis_sock_get(zval *id, RedisSock **redis_sock TSRMLS_DC); -PHPAPI void redis_free_socket(RedisSock *redis_sock); -PHPAPI void redis_send_discard(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock); -PHPAPI int redis_sock_set_err(RedisSock *redis_sock, const char *msg, int msg_len); +PHP_REDIS_API void redis_free_socket(RedisSock *redis_sock); +PHP_REDIS_API void redis_send_discard(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock); +PHP_REDIS_API int redis_sock_set_err(RedisSock *redis_sock, const char *msg, int msg_len); -PHPAPI int +PHP_REDIS_API int redis_serialize(RedisSock *redis_sock, zval *z, char **val, int *val_len TSRMLS_DC); -PHPAPI int +PHP_REDIS_API int redis_key_prefix(RedisSock *redis_sock, char **key, int *key_len TSRMLS_DC); -PHPAPI int +PHP_REDIS_API int redis_unserialize(RedisSock *redis_sock, const char *val, int val_len, zval **return_value TSRMLS_DC); @@ -56,17 +56,16 @@ redis_unserialize(RedisSock *redis_sock, const char *val, int val_len, zval **re * Variant Read methods, mostly to implement eval */ -PHPAPI int redis_read_reply_type(RedisSock *redis_sock, REDIS_REPLY_TYPE *reply_type, int *reply_info TSRMLS_DC); -PHPAPI int redis_read_variant_line(RedisSock *redis_sock, REDIS_REPLY_TYPE reply_type, zval **z_ret TSRMLS_DC); -PHPAPI int redis_read_variant_bulk(RedisSock *redis_sock, int size, zval **z_ret TSRMLS_DC); -PHPAPI int redis_read_multibulk_recursive(RedisSock *redis_sock, int elements, zval **z_ret TSRMLS_DC); -PHPAPI int redis_read_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab); +PHP_REDIS_API int redis_read_reply_type(RedisSock *redis_sock, REDIS_REPLY_TYPE *reply_type, int *reply_info TSRMLS_DC); +PHP_REDIS_API int redis_read_variant_line(RedisSock *redis_sock, REDIS_REPLY_TYPE reply_type, zval **z_ret TSRMLS_DC); +PHP_REDIS_API int redis_read_variant_bulk(RedisSock *redis_sock, int size, zval **z_ret TSRMLS_DC); +PHP_REDIS_API int redis_read_multibulk_recursive(RedisSock *redis_sock, int elements, zval **z_ret TSRMLS_DC); +PHP_REDIS_API int redis_read_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab); -PHPAPI void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab); +PHP_REDIS_API void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab); #if ZEND_MODULE_API_NO >= 20100000 #define REDIS_DOUBLE_TO_STRING(dbl_str, dbl_len, dbl) \ - char dbl_decsep; \ dbl_decsep = '.'; \ dbl_str = _php_math_number_format_ex(dbl, 16, &dbl_decsep, 1, NULL, 0); \ dbl_len = strlen(dbl_str); diff --git a/php_redis.h b/php_redis.h index 879503aa..905c7b3b 100644 --- a/php_redis.h +++ b/php_redis.h @@ -209,32 +209,32 @@ PHP_RINIT_FUNCTION(redis); PHP_RSHUTDOWN_FUNCTION(redis); PHP_MINFO_FUNCTION(redis); -PHPAPI int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent); -PHPAPI void redis_atomic_increment(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int count); -PHPAPI int generic_multiple_args_cmd(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len, +PHP_REDIS_API int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent); +PHP_REDIS_API void redis_atomic_increment(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int count); +PHP_REDIS_API int generic_multiple_args_cmd(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len, int min_argc, RedisSock **redis_sock, int has_timeout, int all_keys, int can_serialize); -PHPAPI void generic_sort_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sort, int use_alpha); +PHP_REDIS_API void generic_sort_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sort, int use_alpha); typedef void (*ResultCallback)(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); -PHPAPI void generic_empty_cmd_impl(INTERNAL_FUNCTION_PARAMETERS, char *cmd, int cmd_len, ResultCallback result_callback); -PHPAPI void generic_empty_cmd(INTERNAL_FUNCTION_PARAMETERS, char *cmd, int cmd_len, ...); -PHPAPI void generic_empty_long_cmd(INTERNAL_FUNCTION_PARAMETERS, char *cmd, int cmd_len, ...); +PHP_REDIS_API void generic_empty_cmd_impl(INTERNAL_FUNCTION_PARAMETERS, char *cmd, int cmd_len, ResultCallback result_callback); +PHP_REDIS_API void generic_empty_cmd(INTERNAL_FUNCTION_PARAMETERS, char *cmd, int cmd_len, ...); +PHP_REDIS_API void generic_empty_long_cmd(INTERNAL_FUNCTION_PARAMETERS, char *cmd, int cmd_len, ...); -PHPAPI void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub_cmd); -PHPAPI void generic_unsubscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *unsub_cmd); +PHP_REDIS_API void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub_cmd); +PHP_REDIS_API void generic_unsubscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *unsub_cmd); -PHPAPI void array_zip_values_and_scores(RedisSock *redis_sock, zval *z_tab, int use_atof TSRMLS_DC); -PHPAPI int redis_response_enqueued(RedisSock *redis_sock TSRMLS_DC); +PHP_REDIS_API void array_zip_values_and_scores(RedisSock *redis_sock, zval *z_tab, int use_atof TSRMLS_DC); +PHP_REDIS_API int redis_response_enqueued(RedisSock *redis_sock TSRMLS_DC); -PHPAPI int get_flag(zval *object TSRMLS_DC); -PHPAPI void set_flag(zval *object, int new_flag TSRMLS_DC); +PHP_REDIS_API int get_flag(zval *object TSRMLS_DC); +PHP_REDIS_API void set_flag(zval *object, int new_flag TSRMLS_DC); -PHPAPI int redis_sock_read_multibulk_multi_reply_loop(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, int numElems); +PHP_REDIS_API int redis_sock_read_multibulk_multi_reply_loop(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, int numElems); /* pipeline */ -PHPAPI request_item* get_pipeline_head(zval *object); -PHPAPI void set_pipeline_head(zval *object, request_item *head); -PHPAPI request_item* get_pipeline_current(zval *object); -PHPAPI void set_pipeline_current(zval *object, request_item *current); +PHP_REDIS_API request_item* get_pipeline_head(zval *object); +PHP_REDIS_API void set_pipeline_head(zval *object, request_item *head); +PHP_REDIS_API request_item* get_pipeline_current(zval *object); +PHP_REDIS_API void set_pipeline_current(zval *object, request_item *current); #ifndef _MSC_VER ZEND_BEGIN_MODULE_GLOBALS(redis) diff --git a/redis.c b/redis.c index ed4ec9d9..f869d001 100644 --- a/redis.c +++ b/redis.c @@ -69,7 +69,9 @@ PHP_INI_BEGIN() PHP_INI_ENTRY("redis.arrays.autorehash", "", PHP_INI_ALL, NULL) PHP_INI_END() +#ifdef ZTS ZEND_DECLARE_MODULE_GLOBALS(redis) +#endif static zend_function_entry redis_functions[] = { PHP_ME(Redis, __construct, NULL, ZEND_ACC_CTOR | ZEND_ACC_PUBLIC) @@ -307,7 +309,7 @@ zend_module_entry redis_module_entry = { ZEND_GET_MODULE(redis) #endif -PHPAPI zend_class_entry *redis_get_exception_base(int root TSRMLS_DC) +PHP_REDIS_API zend_class_entry *redis_get_exception_base(int root TSRMLS_DC) { #if HAVE_SPL if (!root) { @@ -373,7 +375,7 @@ static void redis_destructor_redis_sock(zend_rsrc_list_entry * rsrc TSRMLS_DC) /** * redis_sock_get */ -PHPAPI int redis_sock_get(zval *id, RedisSock **redis_sock TSRMLS_DC, int no_throw) +PHP_REDIS_API int redis_sock_get(zval *id, RedisSock **redis_sock TSRMLS_DC, int no_throw) { zval **socket; @@ -412,7 +414,7 @@ PHPAPI int redis_sock_get(zval *id, RedisSock **redis_sock TSRMLS_DC, int no_thr * redis_sock_get_direct * Returns our attached RedisSock pointer if we're connected */ -PHPAPI RedisSock *redis_sock_get_connected(INTERNAL_FUNCTION_PARAMETERS) { +PHP_REDIS_API RedisSock *redis_sock_get_connected(INTERNAL_FUNCTION_PARAMETERS) { zval *object; RedisSock *redis_sock; @@ -550,12 +552,13 @@ PHP_METHOD(Redis, __construct) Public Destructor */ PHP_METHOD(Redis,__destruct) { + RedisSock *redis_sock; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { RETURN_FALSE; } // Grab our socket - RedisSock *redis_sock; if (redis_sock_get(getThis(), &redis_sock TSRMLS_CC, 1) < 0) { RETURN_FALSE; } @@ -598,7 +601,7 @@ PHP_METHOD(Redis, pconnect) } /* }}} */ -PHPAPI int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) { +PHP_REDIS_API int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) { zval *object; zval **socket; int host_len, id; @@ -910,7 +913,7 @@ PHP_METHOD(Redis, set) { REDIS_PROCESS_RESPONSE(redis_boolean_response); } -PHPAPI void redis_generic_setex(INTERNAL_FUNCTION_PARAMETERS, char *keyword) { +PHP_REDIS_API void redis_generic_setex(INTERNAL_FUNCTION_PARAMETERS, char *keyword) { zval *object; RedisSock *redis_sock; @@ -1231,7 +1234,7 @@ PHP_METHOD(Redis, ping) } /* }}} */ -PHPAPI void redis_atomic_increment(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int count) { +PHP_REDIS_API void redis_atomic_increment(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int count) { zval *object; RedisSock *redis_sock; @@ -1523,12 +1526,12 @@ PHP_METHOD(Redis, delete) } /* }}} */ -PHPAPI void redis_set_watch(RedisSock *redis_sock) +PHP_REDIS_API void redis_set_watch(RedisSock *redis_sock) { redis_sock->watching = 1; } -PHPAPI void redis_watch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) +PHP_REDIS_API void redis_watch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { redis_boolean_response_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, ctx, redis_set_watch); } @@ -1551,12 +1554,12 @@ PHP_METHOD(Redis, watch) } /* }}} */ -PHPAPI void redis_clear_watch(RedisSock *redis_sock) +PHP_REDIS_API void redis_clear_watch(RedisSock *redis_sock) { redis_sock->watching = 0; } -PHPAPI void redis_unwatch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) +PHP_REDIS_API void redis_unwatch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) { redis_boolean_response_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, ctx, redis_clear_watch); } @@ -1808,7 +1811,7 @@ PHP_METHOD(Redis, strlen) REDIS_PROCESS_RESPONSE(redis_long_response); } -PHPAPI void +PHP_REDIS_API void generic_push_function(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len) { zval *object; RedisSock *redis_sock; @@ -1931,7 +1934,7 @@ PHP_METHOD(Redis, rPushx) generic_push_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "RPUSHX", sizeof("RPUSHX")-1); } -PHPAPI void +PHP_REDIS_API void generic_pop_function(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len) { zval *object; @@ -2426,7 +2429,7 @@ PHP_METHOD(Redis, sMembers) } /* }}} */ -PHPAPI int generic_multiple_args_cmd(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len, +PHP_REDIS_API int generic_multiple_args_cmd(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len, int min_argc, RedisSock **out_sock, int has_timeout, int all_keys, int can_serialize) { zval **z_args, *z_array; @@ -2959,7 +2962,7 @@ PHP_METHOD(Redis, sort) { } } -PHPAPI void generic_sort_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sort, int use_alpha) { +PHP_REDIS_API void generic_sort_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sort, int use_alpha) { zval *object; RedisSock *redis_sock; @@ -3170,7 +3173,7 @@ PHP_METHOD(Redis, sortDescAlpha) } /* }}} */ -PHPAPI void generic_expire_cmd(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len) { +PHP_REDIS_API void generic_expire_cmd(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len) { zval *object; RedisSock *redis_sock; char *key = NULL, *cmd, *t; @@ -3266,7 +3269,7 @@ PHP_METHOD(Redis, lSet) { } /* }}} */ -PHPAPI void generic_empty_cmd_impl(INTERNAL_FUNCTION_PARAMETERS, char *cmd, int cmd_len, ResultCallback result_callback) { +PHP_REDIS_API void generic_empty_cmd_impl(INTERNAL_FUNCTION_PARAMETERS, char *cmd, int cmd_len, ResultCallback result_callback) { zval *object; RedisSock *redis_sock; @@ -3286,7 +3289,7 @@ PHPAPI void generic_empty_cmd_impl(INTERNAL_FUNCTION_PARAMETERS, char *cmd, int REDIS_PROCESS_RESPONSE(result_callback); } -PHPAPI void generic_empty_cmd(INTERNAL_FUNCTION_PARAMETERS, char *cmd, int cmd_len, ...) { +PHP_REDIS_API void generic_empty_cmd(INTERNAL_FUNCTION_PARAMETERS, char *cmd, int cmd_len, ...) { generic_empty_cmd_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, cmd, cmd_len, redis_boolean_response); } @@ -3312,7 +3315,7 @@ PHP_METHOD(Redis, bgSave) } /* }}} */ -PHPAPI void generic_empty_long_cmd(INTERNAL_FUNCTION_PARAMETERS, char *cmd, int cmd_len, ...) { +PHP_REDIS_API void generic_empty_long_cmd(INTERNAL_FUNCTION_PARAMETERS, char *cmd, int cmd_len, ...) { zval *object; RedisSock *redis_sock; @@ -3438,7 +3441,7 @@ PHP_METHOD(Redis, persist) { } /* }}} */ -PHPAPI void generic_ttl(INTERNAL_FUNCTION_PARAMETERS, char *keyword) { +PHP_REDIS_API void generic_ttl(INTERNAL_FUNCTION_PARAMETERS, char *keyword) { zval *object; RedisSock *redis_sock; @@ -3588,7 +3591,7 @@ PHP_METHOD(Redis, move) { } /* }}} */ -PHPAPI void +PHP_REDIS_API void generic_mset(INTERNAL_FUNCTION_PARAMETERS, char *kw, void (*fun)(INTERNAL_FUNCTION_PARAMETERS, RedisSock *, zval *, void *)) { zval *object; @@ -3703,7 +3706,7 @@ PHP_METHOD(Redis, msetnx) { } /* }}} */ -PHPAPI void common_rpoplpush(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, +PHP_REDIS_API void common_rpoplpush(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *srckey, int srckey_len, char *dstkey, int dstkey_len, int timeout) { char *cmd; @@ -3786,7 +3789,9 @@ PHP_METHOD(Redis, zAdd) { char *key, *val; int val_free, key_free = 0; char *dbl_str; + char dbl_decsep; int dbl_len; + smart_str buf = {0}; zval **z_args; int argc = ZEND_NUM_ARGS(), i; @@ -3817,7 +3822,6 @@ PHP_METHOD(Redis, zAdd) { key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); /* start building the command */ - smart_str buf = {0}; smart_str_appendc(&buf, '*'); smart_str_append_long(&buf, argc + 1); /* +1 for ZADD command */ smart_str_appendl(&buf, _NL, sizeof(_NL) - 1); @@ -4053,7 +4057,7 @@ PHP_METHOD(Redis, zReverseRange) } /* }}} */ -PHPAPI void +PHP_REDIS_API void redis_generic_zrange_by_score(INTERNAL_FUNCTION_PARAMETERS, char *keyword) { zval *object, *z_options = NULL, **z_limit_val_pp = NULL, **z_withscores_val_pp = NULL; @@ -4266,7 +4270,7 @@ PHP_METHOD(Redis, zScore) /* }}} */ -PHPAPI void generic_rank_method(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len) { +PHP_REDIS_API void generic_rank_method(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len) { zval *object; RedisSock *redis_sock; char *key = NULL, *val = NULL, *cmd; @@ -4314,7 +4318,7 @@ PHP_METHOD(Redis, zRevRank) { } /* }}} */ -PHPAPI void generic_incrby_method(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len) { +PHP_REDIS_API void generic_incrby_method(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len) { zval *object; RedisSock *redis_sock; @@ -4356,14 +4360,14 @@ PHP_METHOD(Redis, zIncrBy) } /* }}} */ -PHPAPI void generic_z_command(INTERNAL_FUNCTION_PARAMETERS, char *command, int command_len) { +PHP_REDIS_API void generic_z_command(INTERNAL_FUNCTION_PARAMETERS, char *command, int command_len) { zval *object, *z_keys, *z_weights = NULL, **z_data; HashTable *ht_keys, *ht_weights = NULL; RedisSock *redis_sock; smart_str cmd = {0}; HashPosition ptr; char *store_key, *agg_op = NULL; - int cmd_arg_count = 2, store_key_len, agg_op_len = 0, keys_count; + int cmd_arg_count = 2, store_key_len, agg_op_len = 0, keys_count, key_free; // Grab our parameters if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Osa|a!s", @@ -4422,7 +4426,7 @@ PHPAPI void generic_z_command(INTERNAL_FUNCTION_PARAMETERS, char *command, int c redis_cmd_init_sstr(&cmd, cmd_arg_count, command, command_len); // Prefix our key if necessary and add the output key - int key_free = redis_key_prefix(redis_sock, &store_key, &store_key_len TSRMLS_CC); + key_free = redis_key_prefix(redis_sock, &store_key, &store_key_len TSRMLS_CC); redis_cmd_append_sstr(&cmd, store_key, store_key_len); if(key_free) efree(store_key); @@ -4530,7 +4534,7 @@ PHP_METHOD(Redis, zUnion) { /* hashes */ -PHPAPI void +PHP_REDIS_API void generic_hset(INTERNAL_FUNCTION_PARAMETERS, char *kw, void (*fun)(INTERNAL_FUNCTION_PARAMETERS, RedisSock *, zval *, void *)) { zval *object; RedisSock *redis_sock; @@ -4636,7 +4640,7 @@ PHP_METHOD(Redis, hLen) } /* }}} */ -PHPAPI RedisSock* +PHP_REDIS_API RedisSock* generic_hash_command_2(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len, char **out_cmd, int *out_len) { zval *object; @@ -4697,7 +4701,7 @@ PHP_METHOD(Redis, hExists) } -PHPAPI RedisSock* +PHP_REDIS_API RedisSock* generic_hash_command_1(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len) { zval *object; @@ -4785,7 +4789,7 @@ PHP_METHOD(Redis, hGetAll) { REDIS_PROCESS_RESPONSE(redis_sock_read_multibulk_reply_zipped_strings); } -PHPAPI void array_zip_values_and_scores(RedisSock *redis_sock, zval *z_tab, int use_atof TSRMLS_DC) { +PHP_REDIS_API void array_zip_values_and_scores(RedisSock *redis_sock, zval *z_tab, int use_atof TSRMLS_DC) { zval *z_ret; HashTable *keytable; @@ -5091,7 +5095,7 @@ PHP_METHOD(Redis, hMset) } -PHPAPI int redis_response_enqueued(RedisSock *redis_sock TSRMLS_DC) { +PHP_REDIS_API int redis_response_enqueued(RedisSock *redis_sock TSRMLS_DC) { char *response; int response_len, ret = 0; @@ -5183,7 +5187,7 @@ PHP_METHOD(Redis, discard) redis_send_discard(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock); } -PHPAPI int redis_sock_read_multibulk_pipeline_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock) +PHP_REDIS_API int redis_sock_read_multibulk_pipeline_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock) { zval *z_tab; MAKE_STD_ZVAL(z_tab); @@ -5202,7 +5206,7 @@ PHPAPI int redis_sock_read_multibulk_pipeline_reply(INTERNAL_FUNCTION_PARAMETERS } /* redis_sock_read_multibulk_multi_reply */ -PHPAPI int redis_sock_read_multibulk_multi_reply(INTERNAL_FUNCTION_PARAMETERS, +PHP_REDIS_API int redis_sock_read_multibulk_multi_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock) { @@ -5348,11 +5352,11 @@ PHP_METHOD(Redis, exec) } } -PHPAPI void fold_this_item(INTERNAL_FUNCTION_PARAMETERS, fold_item *item, RedisSock *redis_sock, zval *z_tab) { +PHP_REDIS_API void fold_this_item(INTERNAL_FUNCTION_PARAMETERS, fold_item *item, RedisSock *redis_sock, zval *z_tab) { item->fun(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, item->ctx TSRMLS_CC); } -PHPAPI int redis_sock_read_multibulk_multi_reply_loop(INTERNAL_FUNCTION_PARAMETERS, +PHP_REDIS_API int redis_sock_read_multibulk_multi_reply_loop(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, int numElems) { @@ -5423,7 +5427,7 @@ PHP_METHOD(Redis, publish) REDIS_PROCESS_RESPONSE(redis_long_response); } -PHPAPI void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub_cmd) +PHP_REDIS_API void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub_cmd) { zval *object, *array, **data; HashTable *arr_hash; @@ -5433,7 +5437,8 @@ PHPAPI void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub_cmd) int cmd_len, array_count, key_len, key_free; zval *z_tab, **tmp; char *type_response; - + int is_pmsg, tab_idx; + // Function call information zend_fcall_info z_callback; zend_fcall_info_cache z_callback_cache; @@ -5525,8 +5530,8 @@ PHPAPI void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub_cmd) /* call the callback with this z_tab in argument */ zval **type, **channel, **pattern, **data; z_tab = redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock); - int is_pmsg, tab_idx = 1; - + tab_idx = 1; + if(z_tab == NULL || Z_TYPE_P(z_tab) != IS_ARRAY) { //ERROR break; @@ -5615,7 +5620,7 @@ PHP_METHOD(Redis, subscribe) { * ); **/ -PHPAPI void generic_unsubscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *unsub_cmd) +PHP_REDIS_API void generic_unsubscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *unsub_cmd) { zval *object, *array, **data; HashTable *arr_hash; @@ -5988,7 +5993,7 @@ PHP_METHOD(Redis, slowlog) { } // Construct an EVAL or EVALSHA command, with option argument array and number of arguments that are keys parameter -PHPAPI int +PHP_REDIS_API int redis_build_eval_cmd(RedisSock *redis_sock, char **ret, char *keyword, char *value, int val_len, zval *args, int keys_count TSRMLS_DC) { zval **elem; HashTable *args_hash; @@ -6130,7 +6135,7 @@ PHP_METHOD(Redis, eval) REDIS_PROCESS_RESPONSE(redis_read_variant_reply); } -PHPAPI int +PHP_REDIS_API int redis_build_script_exists_cmd(char **ret, zval **argv, int argc) { // Our command length and iterator int cmd_len = 0, i; diff --git a/redis_array.c b/redis_array.c index ecc158ea..12fe9830 100644 --- a/redis_array.c +++ b/redis_array.c @@ -116,7 +116,7 @@ void redis_destructor_redis_array(zend_rsrc_list_entry * rsrc TSRMLS_DC) /** * redis_array_get */ -PHPAPI int redis_array_get(zval *id, RedisArray **ra TSRMLS_DC) +PHP_REDIS_API int redis_array_get(zval *id, RedisArray **ra TSRMLS_DC) { zval **socket; @@ -198,6 +198,7 @@ PHP_METHOD(RedisArray, __construct) HashTable *hPrev = NULL, *hOpts = NULL; long l_retry_interval = 0; zend_bool b_lazy_connect = 0; + zval **z_retry_interval_pp; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &z0, &z_opts) == FAILURE) { RETURN_FALSE; @@ -245,7 +246,6 @@ PHP_METHOD(RedisArray, __construct) } /* extract retry_interval option. */ - zval **z_retry_interval_pp; if (FAILURE != zend_hash_find(hOpts, "retry_interval", sizeof("retry_interval"), (void**)&z_retry_interval_pp)) { if (Z_TYPE_PP(z_retry_interval_pp) == IS_LONG || Z_TYPE_PP(z_retry_interval_pp) == IS_STRING) { if (Z_TYPE_PP(z_retry_interval_pp) == IS_LONG) { @@ -961,6 +961,8 @@ PHP_METHOD(RedisArray, mset) unsigned int key_len, free_idx = 0; int type, *key_lens; unsigned long idx; + int found; + zval *z_tmp; /* Multi/exec support */ HANDLE_MULTI_EXEC("MSET"); @@ -1028,13 +1030,12 @@ PHP_METHOD(RedisArray, mset) redis_inst = ra->redis[n]; /* copy args */ - int found = 0; + found = 0; MAKE_STD_ZVAL(z_argarray); array_init(z_argarray); for(i = 0; i < argc; ++i) { if(pos[i] != n) continue; - zval *z_tmp; ALLOC_ZVAL(z_tmp); *z_tmp = *argv[i]; zval_copy_ctor(z_tmp); diff --git a/redis_array_impl.c b/redis_array_impl.c index c3a1f365..65ccd61f 100644 --- a/redis_array_impl.c +++ b/redis_array_impl.c @@ -430,6 +430,7 @@ zval * ra_find_node(RedisArray *ra, const char *key, int key_len, int *out_pos TSRMLS_DC) { uint32_t hash; + uint64_t h64; char *out; int pos, out_len; @@ -449,7 +450,7 @@ ra_find_node(RedisArray *ra, const char *key, int key_len, int *out_pos TSRMLS_D efree(out); /* get position on ring */ - uint64_t h64 = hash; + h64 = hash; h64 *= ra->count; h64 /= 0xffffffff; pos = (int)h64; @@ -544,13 +545,13 @@ ra_index_keys(zval *z_pairs, zval *z_redis TSRMLS_DC) { /* Initialize key array */ zval *z_keys, **z_entry_pp; + HashPosition pos; MAKE_STD_ZVAL(z_keys); #if PHP_VERSION_ID > 50300 array_init_size(z_keys, zend_hash_num_elements(Z_ARRVAL_P(z_pairs))); #else array_init(z_keys); #endif - HashPosition pos; /* Go through input array and add values to the key array */ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(z_pairs), &pos); diff --git a/redis_session.c b/redis_session.c index 591f07b8..e1d107f2 100644 --- a/redis_session.c +++ b/redis_session.c @@ -70,12 +70,12 @@ typedef struct { } redis_pool; -PHPAPI redis_pool* +PHP_REDIS_API redis_pool* redis_pool_new(TSRMLS_D) { return ecalloc(1, sizeof(redis_pool)); } -PHPAPI void +PHP_REDIS_API void redis_pool_add(redis_pool *pool, RedisSock *redis_sock, int weight, int database, char *prefix, char *auth TSRMLS_DC) { @@ -96,7 +96,7 @@ redis_pool_add(redis_pool *pool, RedisSock *redis_sock, int weight, pool->totalWeight += weight; } -PHPAPI void +PHP_REDIS_API void redis_pool_free(redis_pool *pool TSRMLS_DC) { redis_pool_member *rpm, *next; @@ -148,15 +148,13 @@ redis_pool_member_select(redis_pool_member *rpm TSRMLS_DC) { efree(cmd); } -PHPAPI redis_pool_member * +PHP_REDIS_API redis_pool_member * redis_pool_get_sock(redis_pool *pool, const char *key TSRMLS_DC) { - + redis_pool_member *rpm = pool->head; unsigned int pos, i; memcpy(&pos, key, sizeof(pos)); pos %= pool->totalWeight; - redis_pool_member *rpm = pool->head; - for(i = 0; i < pool->totalWeight;) { if(pos >= i && pos < i + rpm->weight) { int needs_auth = 0; @@ -188,6 +186,7 @@ PS_OPEN_FUNC(redis) php_url *url; zval *params, **param; int i, j, path_len; + RedisSock *redis_sock; redis_pool *pool = redis_pool_new(TSRMLS_C); @@ -276,7 +275,6 @@ PS_OPEN_FUNC(redis) return FAILURE; } - RedisSock *redis_sock; if(url->host) { redis_sock = redis_sock_create(url->host, strlen(url->host), url->port, timeout, persistent, persistent_id, retry_interval, 0); } else { /* unix */ From 5655f0574e1df30c7c39d67dea40fb9fece334f4 Mon Sep 17 00:00:00 2001 From: vostok4 Date: Wed, 16 Oct 2013 11:39:51 +0200 Subject: [PATCH 2/5] Last fix for win32 compiles This fixes the rc command using <> characters which breaks it. --- CREDITS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CREDITS b/CREDITS index 59596599..c501060a 100644 --- a/CREDITS +++ b/CREDITS @@ -1,4 +1,4 @@ Redis client extension for PHP -Alfonso Jimenez -Nasreddine Bouafif -Nicolas Favre-Felix +Alfonso Jimenez (yo@alfonsojimenez.com) +Nasreddine Bouafif (n.bouafif@owlient.eu) +Nicolas Favre-Felix (n.favre-felix@owlient.eu) From 978fbcf6fc355fcd344feb76ab4b7d6b77e9f7c1 Mon Sep 17 00:00:00 2001 From: vostok4 Date: Fri, 18 Oct 2013 14:37:06 +0200 Subject: [PATCH 3/5] Further fixes for building on VC9 Win32, C89 compliance Include win32/php_stdint.h on Win32 (fixes compilation on VC9) Change C++ comments to C89 style (to adhere to PHP project) --- library.c | 188 ++++++++++++++++++++++----------------------- library.h | 2 +- redis_array.c | 24 +++--- redis_array.h | 7 +- redis_array_impl.c | 28 +++---- redis_array_impl.h | 5 ++ 6 files changed, 132 insertions(+), 122 deletions(-) diff --git a/library.c b/library.c index 7db595b8..4fd523de 100644 --- a/library.c +++ b/library.c @@ -67,9 +67,9 @@ PHP_REDIS_API int redis_check_eof(RedisSock *redis_sock TSRMLS_DC) redis_sock->mode = ATOMIC; redis_sock->watching = 0; } - // Wait for a while before trying to reconnect + /* Wait for a while before trying to reconnect */ if (redis_sock->retry_interval) { - // Random factor to avoid having several (or many) concurrent connections trying to reconnect at the same time + /* Random factor to avoid having several (or many) concurrent connections trying to reconnect at the same time */ long retry_interval = (count ? redis_sock->retry_interval : (random() % redis_sock->retry_interval)); usleep(retry_interval); } @@ -79,7 +79,7 @@ PHP_REDIS_API int redis_check_eof(RedisSock *redis_sock TSRMLS_DC) } } - // Reselect the DB. + /* Reselect the DB. */ if (count && redis_sock->dbNumber) { char *cmd, *response; int cmd_len, response_len; @@ -157,7 +157,7 @@ PHP_REDIS_API char *redis_sock_read_bulk_reply(RedisSock *redis_sock, int bytes } else { char c; int i; - + reply = emalloc(bytes+1); while(offset < bytes) { @@ -225,7 +225,7 @@ PHP_REDIS_API char *redis_sock_read(RedisSock *redis_sock, int *buf_len TSRMLS_D case '+': case ':': - // Single Line Reply + /* Single Line Reply */ /* :123\r\n */ *buf_len = strlen(inbuf) - 2; if(*buf_len >= 2) { @@ -274,10 +274,10 @@ integer_length(int i) { int redis_cmd_format_header(char **ret, char *keyword, int arg_count) { - // Our return buffer + /* Our return buffer */ smart_str buf = {0}; - // Keyword length + /* Keyword length */ int l = strlen(keyword); smart_str_appendc(&buf, '*'); @@ -289,10 +289,10 @@ redis_cmd_format_header(char **ret, char *keyword, int arg_count) { smart_str_appendl(&buf, keyword, l); smart_str_appendl(&buf, _NL, sizeof(_NL) - 1); - // Set our return pointer + /* Set our return pointer */ *ret = buf.c; - // Return the length + /* Return the length */ return buf.len; } @@ -439,26 +439,26 @@ redis_cmd_format(char **ret, char *format, ...) { * Append a command sequence to a Redis command */ int redis_cmd_append_str(char **cmd, int cmd_len, char *append, int append_len) { - // Smart string buffer + /* Smart string buffer */ smart_str buf = {0}; - // Append the current command to our smart_str + /* Append the current command to our smart_str */ smart_str_appendl(&buf, *cmd, cmd_len); - // Append our new command sequence + /* Append our new command sequence */ smart_str_appendc(&buf, '$'); smart_str_append_long(&buf, append_len); smart_str_appendl(&buf, _NL, sizeof(_NL) -1); smart_str_appendl(&buf, append, append_len); smart_str_appendl(&buf, _NL, sizeof(_NL) -1); - // Free our old command + /* Free our old command */ efree(*cmd); - // Set our return pointer + /* Set our return pointer */ *cmd = buf.c; - // Return new command length + /* Return new command length */ return buf.len; } @@ -488,7 +488,7 @@ int redis_cmd_append_sstr(smart_str *str, char *append, int append_len) { smart_str_appendl(str, append, append_len); smart_str_appendl(str, _NL, sizeof(_NL) - 1); - // Return our new length + /* Return our new length */ return str->len; } @@ -519,16 +519,16 @@ int redis_cmd_append_sstr_dbl(smart_str *str, double value) { char dbl_decsep; int retval; - /// Convert to double + /* Convert to double */ REDIS_DOUBLE_TO_STRING(dbl_str, dbl_len, value); - // Append the string + /* Append the string */ retval = redis_cmd_append_sstr(str, dbl_str, dbl_len); - // Free our double string + /* Free our double string */ efree(dbl_str); - // Return new length + /* Return new length */ return retval; } @@ -538,10 +538,10 @@ int redis_cmd_append_sstr_dbl(smart_str *str, double value) { int redis_cmd_append_int(char **cmd, int cmd_len, int append) { char int_buf[32]; - // Conver to an int, capture length + /* Conver to an int, capture length */ int int_len = snprintf(int_buf, sizeof(int_buf), "%d", append); - // Return the new length + /* Return the new length */ return redis_cmd_append_str(cmd, cmd_len, int_buf, int_len); } @@ -688,28 +688,28 @@ PHP_REDIS_API void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSo int resp_len; zval *z_result, *z_sub_result; - // Pointers for parsing + /* Pointers for parsing */ char *p = resp, *lpos = resp, *kpos = NULL, *vpos = NULL, *p2, *key, *value; - // Key length, done flag + /* Key length, done flag */ int klen, done = 0, is_numeric; - // Make sure we can read a response from Redis + /* Make sure we can read a response from Redis */ if((resp = redis_sock_read(redis_sock, &resp_len TSRMLS_CC)) == NULL) { RETURN_FALSE; } - // Allocate memory for our response + /* Allocate memory for our response */ MAKE_STD_ZVAL(z_result); array_init(z_result); - // Allocate memory for one user (there should be at least one, namely us!) + /* Allocate memory for one user (there should be at least one, namely us!) */ ALLOC_INIT_ZVAL(z_sub_result); array_init(z_sub_result); - // While we've got more to parse + /* While we've got more to parse */ while(!done) { - // What character are we on + /* What character are we on */ switch(*p) { /* We're done */ case '\0': @@ -718,23 +718,23 @@ PHP_REDIS_API void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSo /* \n, ' ' mean we can pull a k/v pair */ case '\n': case ' ': - // Grab our value + /* Grab our value */ vpos = lpos; - // There is some communication error or Redis bug if we don't - // have a key and value, but check anyway. + /* There is some communication error or Redis bug if we don't + have a key and value, but check anyway. */ if(kpos && vpos) { - // Allocate, copy in our key + /* Allocate, copy in our key */ key = emalloc(klen + 1); strncpy(key, kpos, klen); key[klen] = 0; - // Allocate, copy in our value + /* Allocate, copy in our value */ value = emalloc(p-lpos+1); strncpy(value,lpos,p-lpos+1); value[p-lpos]=0; - // Treat numbers as numbers, strings as strings + /* Treat numbers as numbers, strings as strings */ is_numeric = 1; for(p2 = value; *p; ++p) { if(*p < '0' || *p > '9') { @@ -743,7 +743,7 @@ PHP_REDIS_API void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSo } } - // Add as a long or string, depending + /* Add as a long or string, depending */ if(is_numeric == 1) { add_assoc_long(z_sub_result, key, atol(value)); efree(value); @@ -751,50 +751,50 @@ PHP_REDIS_API void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSo add_assoc_string(z_sub_result, key, value, 0); } - // If we hit a '\n', then we can add this user to our list + /* If we hit a '\n', then we can add this user to our list */ if(*p == '\n') { - // Add our user + /* Add our user */ add_next_index_zval(z_result, z_sub_result); - // If we have another user, make another one + /* If we have another user, make another one */ if(*(p+1) != '\0') { ALLOC_INIT_ZVAL(z_sub_result); array_init(z_sub_result); } } - - // Free our key + + /* Free our key */ efree(key); } else { - // Something is wrong + /* Something is wrong */ efree(resp); RETURN_FALSE; } - // Move forward + /* Move forward */ lpos = p + 1; break; /* We can pull the key and null terminate at our sep */ case '=': - // Key, key length + /* Key, key length */ kpos = lpos; klen = p - lpos; - // Move forward + /* Move forward */ lpos = p + 1; break; } - // Increment + /* Increment */ p++; } - // Free our respoonse + /* Free our respoonse */ efree(resp); - IF_MULTI_OR_PIPELINE() { + IF_MULTI_OR_PIPELINE() { add_next_index_zval(z_tab, z_result); } else { RETVAL_ZVAL(z_result, 0, 1); @@ -1236,7 +1236,7 @@ PHP_REDIS_API void redis_send_discard(INTERNAL_FUNCTION_PARAMETERS, RedisSock *r * redis_sock_set_err */ PHP_REDIS_API int redis_sock_set_err(RedisSock *redis_sock, const char *msg, int msg_len) { - // Allocate/Reallocate our last error member + /* Allocate/Reallocate our last error member */ if(msg != NULL && msg_len > 0) { if(redis_sock->err == NULL) { redis_sock->err = emalloc(msg_len + 1); @@ -1244,22 +1244,22 @@ PHP_REDIS_API int redis_sock_set_err(RedisSock *redis_sock, const char *msg, int redis_sock->err = erealloc(redis_sock->err, msg_len +1); } - // Copy in our new error message, set new length, and null terminate + /* Copy in our new error message, set new length, and null terminate */ memcpy(redis_sock->err, msg, msg_len); redis_sock->err[msg_len] = '\0'; redis_sock->err_len = msg_len; } else { - // Free our last error + /* Free our last error */ if(redis_sock->err != NULL) { efree(redis_sock->err); } - // Set to null, with zero length + /* Set to null, with zero length */ redis_sock->err = NULL; redis_sock->err_len = 0; } - // Success + /* Success */ return 0; } @@ -1306,7 +1306,7 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS, *return_value = *z_multi_result; efree(z_multi_result); } - //zval_copy_ctor(return_value); + /*zval_copy_ctor(return_value); */ return 0; } @@ -1353,7 +1353,7 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_raw(INTERNAL_FUNCTION_PARAMETE *return_value = *z_multi_result; efree(z_multi_result); } - //zval_copy_ctor(return_value); + /*zval_copy_ctor(return_value); */ return 0; } @@ -1620,7 +1620,7 @@ PHP_REDIS_API int redis_key_prefix(RedisSock *redis_sock, char **key, int *key_len TSRMLS_DC) { int ret_len; char *ret; - + if(redis_sock->prefix == NULL || redis_sock->prefix_len == 0) { return 0; } @@ -1641,60 +1641,60 @@ redis_key_prefix(RedisSock *redis_sock, char **key, int *key_len TSRMLS_DC) { PHP_REDIS_API int redis_sock_gets(RedisSock *redis_sock, char *buf, int buf_size, size_t *line_size TSRMLS_DC) { - // Handle EOF + /* Handle EOF */ if(-1 == redis_check_eof(redis_sock TSRMLS_CC)) { return -1; } if(php_stream_get_line(redis_sock->stream, buf, buf_size, line_size) == NULL) { - // Close, put our socket state into error + /* Close, put our socket state into error */ redis_stream_close(redis_sock TSRMLS_CC); redis_sock->stream = NULL; redis_sock->status = REDIS_SOCK_STATUS_FAILED; redis_sock->mode = ATOMIC; redis_sock->watching = 0; - // Throw a read error exception + /* Throw a read error exception */ zend_throw_exception(redis_exception_ce, "read error on connection", 0 TSRMLS_CC); } - // We don't need \r\n + /* We don't need \r\n */ *line_size-=2; buf[*line_size]='\0'; - // Success! + /* Success! */ return 0; } PHP_REDIS_API int redis_read_reply_type(RedisSock *redis_sock, REDIS_REPLY_TYPE *reply_type, int *reply_info TSRMLS_DC) { - // Make sure we haven't lost the connection, even trying to reconnect + /* Make sure we haven't lost the connection, even trying to reconnect */ if(-1 == redis_check_eof(redis_sock TSRMLS_CC)) { - // Failure + /* Failure */ return -1; } - // Attempt to read the reply-type byte + /* Attempt to read the reply-type byte */ if((*reply_type = php_stream_getc(redis_sock->stream)) == EOF) { zend_throw_exception(redis_exception_ce, "socket error on read socket", 0 TSRMLS_CC); } - // If this is a BULK, MULTI BULK, or simply an INTEGER response, we can extract the value or size info here + /* If this is a BULK, MULTI BULK, or simply an INTEGER response, we can extract the value or size info here */ if(*reply_type == TYPE_INT || *reply_type == TYPE_BULK || *reply_type == TYPE_MULTIBULK) { - // Buffer to hold size information + /* Buffer to hold size information */ char inbuf[255]; - // Read up to our newline + /* Read up to our newline */ if(php_stream_gets(redis_sock->stream, inbuf, sizeof(inbuf)) < 0) { return -1; } - // Set our size response + /* Set our size response */ *reply_info = atoi(inbuf); } - // Success! + /* Success! */ return 0; } @@ -1703,28 +1703,28 @@ redis_read_reply_type(RedisSock *redis_sock, REDIS_REPLY_TYPE *reply_type, int * */ PHP_REDIS_API int redis_read_variant_line(RedisSock *redis_sock, REDIS_REPLY_TYPE reply_type, zval **z_ret TSRMLS_DC) { - // Buffer to read our single line reply + /* Buffer to read our single line reply */ char inbuf[1024]; size_t line_size; - // Attempt to read our single line reply + /* Attempt to read our single line reply */ if(redis_sock_gets(redis_sock, inbuf, sizeof(inbuf), &line_size TSRMLS_CC) < 0) { return -1; } - // If this is an error response, check if it is a SYNC error, and throw in that case + /* If this is an error response, check if it is a SYNC error, and throw in that case */ if(reply_type == TYPE_ERR) { if(memcmp(inbuf, "ERR SYNC", 9) == 0) { zend_throw_exception(redis_exception_ce, "SYNC with master in progress", 0 TSRMLS_CC); } - // Set our last error + /* Set our last error */ redis_sock_set_err(redis_sock, inbuf, line_size); - // Set our response to FALSE + /* Set our response to FALSE */ ZVAL_FALSE(*z_ret); } else { - // Set our response to TRUE + /* Set our response to TRUE */ ZVAL_TRUE(*z_ret); } @@ -1733,10 +1733,10 @@ redis_read_variant_line(RedisSock *redis_sock, REDIS_REPLY_TYPE reply_type, zval PHP_REDIS_API int redis_read_variant_bulk(RedisSock *redis_sock, int size, zval **z_ret TSRMLS_DC) { - // Attempt to read the bulk reply + /* Attempt to read the bulk reply */ char *bulk_resp = redis_sock_read_bulk_reply(redis_sock, size TSRMLS_CC); - // Set our reply to FALSE on failure, and the string on success + /* Set our reply to FALSE on failure, and the string on success */ if(bulk_resp == NULL) { ZVAL_FALSE(*z_ret); return -1; @@ -1752,15 +1752,15 @@ redis_read_multibulk_recursive(RedisSock *redis_sock, int elements, zval **z_ret REDIS_REPLY_TYPE reply_type; zval *z_subelem; - // Iterate while we have elements + /* Iterate while we have elements */ while(elements > 0) { - // Attempt to read our reply type + /* Attempt to read our reply type */ if(redis_read_reply_type(redis_sock, &reply_type, &reply_info TSRMLS_CC) < 0) { zend_throw_exception_ex(redis_exception_ce, 0 TSRMLS_CC, "protocol error, couldn't parse MULTI-BULK response\n", reply_type); return -1; } - // Switch on our reply-type byte + /* Switch on our reply-type byte */ switch(reply_type) { case TYPE_ERR: case TYPE_LINE: @@ -1769,17 +1769,17 @@ redis_read_multibulk_recursive(RedisSock *redis_sock, int elements, zval **z_ret add_next_index_zval(*z_ret, z_subelem); break; case TYPE_INT: - // Add our long value + /* Add our long value */ add_next_index_long(*z_ret, reply_info); break; case TYPE_BULK: - // Init a zval for our bulk response, read and add it + /* Init a zval for our bulk response, read and add it */ ALLOC_INIT_ZVAL(z_subelem); redis_read_variant_bulk(redis_sock, reply_info, &z_subelem TSRMLS_CC); add_next_index_zval(*z_ret, z_subelem); break; case TYPE_MULTIBULK: - // Construct an array for our sub element, and add it, and recurse + /* Construct an array for our sub element, and add it, and recurse */ ALLOC_INIT_ZVAL(z_subelem); array_init(z_subelem); add_next_index_zval(*z_ret, z_subelem); @@ -1787,7 +1787,7 @@ redis_read_multibulk_recursive(RedisSock *redis_sock, int elements, zval **z_ret break; } - // Decrement our element counter + /* Decrement our element counter */ elements--; } @@ -1796,21 +1796,21 @@ redis_read_multibulk_recursive(RedisSock *redis_sock, int elements, zval **z_ret PHP_REDIS_API int redis_read_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab) { - // Reply type, and reply size vars + /* Reply type, and reply size vars */ REDIS_REPLY_TYPE reply_type; int reply_info; - //char *bulk_resp; + /*char *bulk_resp; */ zval *z_ret; - // Attempt to read our header + /* Attempt to read our header */ if(redis_read_reply_type(redis_sock, &reply_type, &reply_info TSRMLS_CC) < 0) { return -1; } - // Our return ZVAL + /* Our return ZVAL */ MAKE_STD_ZVAL(z_ret); - // Switch based on our top level reply type + /* Switch based on our top level reply type */ switch(reply_type) { case TYPE_ERR: case TYPE_LINE: @@ -1823,16 +1823,16 @@ redis_read_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zv redis_read_variant_bulk(redis_sock, reply_info, &z_ret TSRMLS_CC); break; case TYPE_MULTIBULK: - // Initialize an array for our multi-bulk response + /* Initialize an array for our multi-bulk response */ array_init(z_ret); - // If we've got more than zero elements, parse our multi bulk respoinse recursively + /* If we've got more than zero elements, parse our multi bulk respoinse recursively */ if(reply_info > -1) { redis_read_multibulk_recursive(redis_sock, reply_info, &z_ret TSRMLS_CC); } break; default: - // Protocol error + /* Protocol error */ zend_throw_exception_ex(redis_exception_ce, 0 TSRMLS_CC, "protocol error, got '%c' as reply-type byte\n", reply_type); break; } @@ -1840,14 +1840,14 @@ redis_read_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zv IF_MULTI_OR_PIPELINE() { add_next_index_zval(z_tab, z_ret); } else { - // Set our return value + /* Set our return value */ *return_value = *z_ret; zval_copy_ctor(return_value); zval_dtor(z_ret); efree(z_ret); } - // Success + /* Success */ return 0; } diff --git a/library.h b/library.h index ec34987c..b749cf63 100644 --- a/library.h +++ b/library.h @@ -38,7 +38,7 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_assoc(INTERNAL_FUNCTION_PARAME PHP_REDIS_API int redis_sock_write(RedisSock *redis_sock, char *cmd, size_t sz TSRMLS_DC); PHP_REDIS_API void redis_stream_close(RedisSock *redis_sock TSRMLS_DC); PHP_REDIS_API int redis_check_eof(RedisSock *redis_sock TSRMLS_DC); -//PHPAPI int redis_sock_get(zval *id, RedisSock **redis_sock TSRMLS_DC); +/* PHPAPI int redis_sock_get(zval *id, RedisSock **redis_sock TSRMLS_DC); */ PHP_REDIS_API void redis_free_socket(RedisSock *redis_sock); PHP_REDIS_API void redis_send_discard(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock); PHP_REDIS_API int redis_sock_set_err(RedisSock *redis_sock, const char *msg, int msg_len); diff --git a/redis_array.c b/redis_array.c index 12fe9830..60d1022b 100644 --- a/redis_array.c +++ b/redis_array.c @@ -293,7 +293,7 @@ static void ra_forward_call(INTERNAL_FUNCTION_PARAMETERS, RedisArray *ra, const char *cmd, int cmd_len, zval *z_args, zval *z_new_target) { zval **zp_tmp, z_tmp; - char *key = NULL; // set to avoid "unused-but-set-variable" + char *key = NULL; /* set to avoid "unused-but-set-variable" */ int key_len; int i; zval *redis_inst; @@ -607,41 +607,41 @@ PHP_METHOD(RedisArray, keys) char *pattern; int pattern_len, i; - // Make sure the prototype is correct + /* Make sure the prototype is correct */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &object, redis_array_ce, &pattern, &pattern_len) == FAILURE) { RETURN_FALSE; } - // Make sure we can grab our RedisArray object + /* Make sure we can grab our RedisArray object */ if(redis_array_get(object, &ra TSRMLS_CC) < 0) { RETURN_FALSE; } - // Set up our function call (KEYS) + /* Set up our function call (KEYS) */ ZVAL_STRING(&z_fun, "KEYS", 0); - // We will be passing with one string argument (the pattern) + /* We will be passing with one string argument (the pattern) */ MAKE_STD_ZVAL(z_args[0]); ZVAL_STRINGL(z_args[0], pattern, pattern_len, 0); - // Init our array return + /* Init our array return */ array_init(return_value); - // Iterate our RedisArray nodes + /* Iterate our RedisArray nodes */ for(i=0; icount; ++i) { - // Return for this node + /* Return for this node */ MAKE_STD_ZVAL(z_tmp); - // Call KEYS on each node + /* Call KEYS on each node */ call_user_function(&redis_ce->function_table, &ra->redis[i], &z_fun, z_tmp, 1, z_args TSRMLS_CC); - // Add the result for this host + /* Add the result for this host */ add_assoc_zval(return_value, ra->hosts[i], z_tmp); } - // Free arg array + /* Free arg array */ efree(z_args[0]); } @@ -1186,7 +1186,7 @@ PHP_METHOD(RedisArray, del) found++; } - if(!found) { // don't run empty DELs + if(!found) { /* don't run empty DELs */ zval_dtor(z_argarray); efree(z_argarray); continue; diff --git a/redis_array.h b/redis_array.h index 652b5aef..3b1163bf 100644 --- a/redis_array.h +++ b/redis_array.h @@ -1,7 +1,12 @@ #ifndef REDIS_ARRAY_H #define REDIS_ARRAY_H +#ifdef PHP_WIN32 +#include "win32/php_stdint.h" +#else #include +#endif + #include "common.h" void redis_destructor_redis_array(zend_rsrc_list_entry * rsrc TSRMLS_DC); @@ -34,7 +39,7 @@ PHP_METHOD(RedisArray, unwatch); typedef struct RedisArray_ { - + int count; char **hosts; /* array of host:port strings */ zval **redis; /* array of Redis instances */ diff --git a/redis_array_impl.c b/redis_array_impl.c index 65ccd61f..10c7dc81 100644 --- a/redis_array_impl.c +++ b/redis_array_impl.c @@ -348,7 +348,7 @@ ra_call_extractor(RedisArray *ra, const char *key, int key_len, int *out_len TSR php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not call extractor function"); return NULL; } - //convert_to_string(ra->z_fun); + /* convert_to_string(ra->z_fun); */ /* call extraction function */ MAKE_STD_ZVAL(z_argv0); @@ -408,7 +408,7 @@ ra_call_distributor(RedisArray *ra, const char *key, int key_len, int *pos TSRML php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not call distributor function"); return 0; } - //convert_to_string(ra->z_fun); + /* convert_to_string(ra->z_fun); */ /* call extraction function */ MAKE_STD_ZVAL(z_argv0); @@ -448,7 +448,7 @@ ra_find_node(RedisArray *ra, const char *key, int key_len, int *out_pos TSRMLS_D /* hash */ hash = rcrc32(out, out_len); efree(out); - + /* get position on ring */ h64 = hash; h64 *= ra->count; @@ -502,7 +502,7 @@ ra_index_multi(zval *z_redis, long multi_value TSRMLS_DC) { ZVAL_LONG(z_args[0], multi_value); call_user_function(&redis_ce->function_table, &z_redis, &z_fun_multi, &z_ret, 1, z_args TSRMLS_CC); efree(z_args[0]); - //zval_dtor(&z_ret); + /* zval_dtor(&z_ret); */ } static void @@ -630,8 +630,8 @@ ra_index_exec(zval *z_redis, zval *return_value, int keep_all TSRMLS_DC) { zval_dtor(&z_ret); } - //zval *zptr = &z_ret; - //php_var_dump(&zptr, 0 TSRMLS_CC); + /* zval *zptr = &z_ret; */ + /* php_var_dump(&zptr, 0 TSRMLS_CC); */ } void @@ -773,7 +773,7 @@ ra_get_key_type(zval *z_redis, const char *key, int key_len, zval *z_from, long if(zend_hash_get_current_data(retHash, (void**)&z_data) == FAILURE) { success = 0; break; - } + } if(Z_TYPE_PP(z_data) != IS_LONG) { success = 0; break; @@ -865,7 +865,7 @@ ra_move_zset(const char *key, int key_len, zval *z_from, zval *z_to, long ttl TS unsigned int val_len; int i; unsigned long idx; - + /* run ZRANGE key 0 -1 WITHSCORES on source */ ZVAL_STRINGL(&z_fun_zrange, "ZRANGE", 6, 0); for(i = 0; i < 4; ++i) { @@ -917,7 +917,7 @@ ra_move_zset(const char *key, int key_len, zval *z_from, zval *z_to, long ttl TS ZVAL_LONG(z_zadd_args[i+1], (long)idx); break; default: - return -1; // Todo: log error + return -1; /* Todo: log error */ break; } i += 2; @@ -1123,23 +1123,23 @@ ra_move_key(const char *key, int key_len, zval *z_from, zval *z_to TSRMLS_DC) { case REDIS_STRING: success = ra_move_string(key, key_len, z_from, z_to, ttl TSRMLS_CC); break; - + case REDIS_SET: success = ra_move_set(key, key_len, z_from, z_to, ttl TSRMLS_CC); break; - + case REDIS_LIST: success = ra_move_list(key, key_len, z_from, z_to, ttl TSRMLS_CC); break; - + case REDIS_ZSET: success = ra_move_zset(key, key_len, z_from, z_to, ttl TSRMLS_CC); break; - + case REDIS_HASH: success = ra_move_hash(key, key_len, z_from, z_to, ttl TSRMLS_CC); break; - + default: /* TODO: report? */ break; diff --git a/redis_array_impl.h b/redis_array_impl.h index 10f8512a..8f106542 100644 --- a/redis_array_impl.h +++ b/redis_array_impl.h @@ -1,7 +1,12 @@ #ifndef REDIS_ARRAY_IMPL_H #define REDIS_ARRAY_IMPL_H +#ifdef PHP_WIN32 +#include "win32/php_stdint.h" +#else #include +#endif + #include "common.h" #include "redis_array.h" From 9c12c40a66cbd76f5efa053b1718fa936320400b Mon Sep 17 00:00:00 2001 From: vostok4 Date: Wed, 9 Apr 2014 11:14:45 +0200 Subject: [PATCH 4/5] Merge nicolasff:b9a16b5ad5 in, fixing for Win32 Now we should be up to master with upstream for an easier merge. --- CREDITS | 1 + README.markdown | 177 ++++++++++++- common.h | 28 ++ library.c | 54 +++- library.h | 2 + package.xml | 92 ++++++- php_redis.h | 14 +- redis.c | 609 +++++++++++++++++++++++++++++++++++++++++--- redis_array.c | 72 ++++-- redis_array.h | 1 + redis_array_impl.c | 40 ++- redis_array_impl.h | 2 +- rpm/php-redis.spec | 2 +- tests/TestRedis.php | 344 +++++++++++++++++++++++++ 14 files changed, 1352 insertions(+), 86 deletions(-) diff --git a/CREDITS b/CREDITS index c501060a..53010079 100644 --- a/CREDITS +++ b/CREDITS @@ -2,3 +2,4 @@ Redis client extension for PHP Alfonso Jimenez (yo@alfonsojimenez.com) Nasreddine Bouafif (n.bouafif@owlient.eu) Nicolas Favre-Felix (n.favre-felix@owlient.eu) +Michael Grunder (michael.grunder@gmail.com) \ No newline at end of file diff --git a/README.markdown b/README.markdown index 7d5d2dc8..91d09f19 100644 --- a/README.markdown +++ b/README.markdown @@ -3,7 +3,7 @@ The phpredis extension provides an API for communicating with the [Redis](http://redis.io/) key-value store. It is released under the [PHP License, version 3.01](http://www.php.net/license/3_01.txt). This code has been developed and maintained by Owlient from November 2009 to March 2011. -You can send comments, patches, questions [here on github](https://github.com/nicolasff/phpredis/issues) or to n.favrefelix@gmail.com ([@yowgi](http://twitter.com/yowgi)). +You can send comments, patches, questions [here on github](https://github.com/nicolasff/phpredis/issues), to n.favrefelix@gmail.com ([@yowgi](http://twitter.com/yowgi)), or to michael.grunder@gmail.com ([@grumi78](http://twitter.com/grumi78)). # Table of contents @@ -69,6 +69,10 @@ Taken from [Compiling phpredis on Zend Server CE/OSX ](http://www.tumblr.com/tag See also: [Install Redis & PHP Extension PHPRedis with Macports](http://www.lecloud.net/post/3378834922/install-redis-php-extension-phpredis-with-macports). +You can install install it using Homebrew: + +- [Get homebrew-php](https://github.com/josegonzalez/homebrew-php) +- `brew install php55-redis` (or php53-redis, php54-redis) ## PHP Session handler @@ -268,6 +272,15 @@ $redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP); // use built-in $redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_IGBINARY); // use igBinary serialize/unserialize $redis->setOption(Redis::OPT_PREFIX, 'myAppName:'); // use custom prefix on all keys + +/* Options for the SCAN family of commands, indicating whether to abstract + empty results from the user. If set to SCAN_NORETRY (the default), phpredis + will just issue one SCAN command at a time, sometimes returning an empty + array of results. If set to SCAN_RETRY, phpredis will retry the scan command + until keys come back OR Redis returns an iterator of zero +*/ +$redis->setOption(Redis::OPT_SCAN, Redis::SCAN_NORETRY); +$redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); ~~~ @@ -607,6 +620,7 @@ $redis->slowlog('len'); * [expire, setTimeout, pexpire](#expire-settimeout-pexpire) - Set a key's time to live in seconds * [expireAt, pexpireAt](#expireat-pexpireat) - Set the expiration for a key as a UNIX timestamp * [keys, getKeys](#keys-getkeys) - Find all keys matching the given pattern +* [scan](#scan) - Scan for keys in the keyspace (Redis >= 2.8.0) * [migrate](#migrate) - Atomically transfer a key from a Redis instance to another one * [move](#move) - Move a key to another database * [object](#object) - Inspect the internals of Redis objects @@ -658,10 +672,10 @@ $redis->set('key', 'value'); $redis->set('key','value', 10); // Will set the key, if it doesn't exist, with a ttl of 10 seconds -$redis->set('key', 'value', Array('nx', 'ex'=>10); +$redis->set('key', 'value', Array('nx', 'ex'=>10)); // Will set a key, if it does exist, with a ttl of 1000 miliseconds -$redis->set('key', 'value', Array('xx', 'px'=>1000); +$redis->set('key', 'value', Array('xx', 'px'=>1000)); ~~~ @@ -780,7 +794,7 @@ $redis->incrByFloat('key1', 1.5); /* key1 didn't exist, so it will now be 1.5 */ $redis->incrByFloat('key1', 1.5); /* 3 */ $redis->incrByFloat('key1', -1.5); /* 1.5 */ -$redis->incrByFloat('key1', 2.5); /* 3.5 */ +$redis->incrByFloat('key1', 2.5); /* 4 */ ~~~ ### decr, decrBy @@ -953,7 +967,29 @@ $allKeys = $redis->keys('*'); // all keys will match this. $keyWithUserPrefix = $redis->keys('user*'); ~~~ +### scan +----- +_**Description**_: Scan the keyspace for keys +##### *Parameters* +*LONG (reference)*: Iterator, initialized to NULL +*STRING, Optional*: Pattern to match +*LONG, Optional*: Count of keys per iteration (only a suggestion to Redis) + +##### *Return value* +*Array, boolean*: This function will return an array of keys or FALSE if there are no more keys + +##### *Example* +~~~ +$it = NULL; /* Initialize our iterator to NULL */ +$redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); /* retry when we get no keys back */ +while($arr_keys = $redis->scan($it)) { + foreach($arr_keys as $str_key) { + echo "Here is a key: $str_key\n"; + } + echo "No more keys to scan!\n"; +} +~~~ ### object ----- @@ -1261,9 +1297,13 @@ _**Description**_: Migrates a key to a different Redis instance. *key* string. The key to migrate. *destination-db* integer. The target DB. *timeout* integer. The maximum amount of time given to this transfer. +*copy* boolean, optional. Should we send the COPY flag to redis +*replace* boolean, optional. Should we send the REPLACE flag to redis ##### *Examples* ~~~ $redis->migrate('backup', 6379, 'foo', 0, 3600); +$redis->migrate('backup', 6379, 'foo', 0, 3600, true, true); /* copy and replace */ +$redis->migrate('backup', 6379, 'foo', 0, 3600, false, true); /* just REPLACE flag */ ~~~ @@ -1283,6 +1323,7 @@ $redis->migrate('backup', 6379, 'foo', 0, 3600); * [hSet](#hset) - Set the string value of a hash field * [hSetNx](#hsetnx) - Set the value of a hash field, only if the field does not exist * [hVals](#hvals) - Get all the values in a hash +* [hScan](#hscan) - Scan a hash key for members ### hSet ----- @@ -1542,7 +1583,28 @@ $redis->hSet('h', 'field2', 'value2'); $redis->hmGet('h', array('field1', 'field2')); /* returns array('field1' => 'value1', 'field2' => 'value2') */ ~~~ +### hScan +----- +_**Description**_: Scan a HASH value for members, with an optional pattern and count +##### *Parameters* +*key*: String +*iterator*: Long (reference) +*pattern*: Optional pattern to match against +*count*: How many keys to return in a go (only a sugestion to Redis) +##### *Return value* +*Array* An array of members that match our pattern +##### *Examples* +~~~ +$it = NULL; +/* Don't ever return an empty array until we're done iterating */ +$redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); +while($arr_keys = $redis->hscan('hash', $it)) { + foreach($arr_keys as $str_field => $str_value) { + echo "$str_field => $str_value\n"; /* Print the hash member and value */ + } +} +~~~ ## Lists @@ -1981,6 +2043,7 @@ $redis->lSize('key1');/* 2 */ * [sRem, sRemove](#srem-sremove) - Remove one or more members from a set * [sUnion](#sunion) - Add multiple sets * [sUnionStore](#sunionstore) - Add multiple sets and store the resulting set in a key +* [sScan](#sscan) - Scan a set for members ### sAdd ----- @@ -2380,6 +2443,41 @@ array(4) { } ~~~ +### sScan +----- +_**Description**_: Scan a set for members + +##### *Parameters* +*Key*: The set to search +*iterator*: LONG (reference) to the iterator as we go +*pattern*: String, optional pattern to match against +*count*: How many members to return at a time (Redis might return a different amount) + +##### *Return value* +*Array, boolean*: PHPRedis will return an array of keys or FALSE when we're done iterating + +##### *Example* +~~~ +$it = NULL; +$redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); /* don't return empty results until we're done */ +while($arr_mems = $redis->sscan('set', $it, "*pattern*")) { + foreach($arr_mems as $str_mem) { + echo "Member: $str_mem\n"; + } +} + +$it = NULL; +$redis->setOption(Redis::OPT_SCAN, Redis::SCAN_NORETRY); /* return after each iteration, even if empty */ +while(($arr_mems = $redis->sscan('set', $it, "*pattern*"))!==FALSE) { + if(count($arr_mems) > 0) { + foreach($arr_mems as $str_mem) { + echo "Member found: $str_mem\n"; + } + } else { + echo "No members in this iteration, iterator value: $it\n"; + } +} +~~~ ## Sorted sets @@ -2397,6 +2495,7 @@ array(4) { * [zRevRange](#zrevrange) - Return a range of members in a sorted set, by index, with scores ordered from high to low * [zScore](#zscore) - Get the score associated with the given member in a sorted set * [zUnion](#zunion) - Add multiple sorted sets and store the resulting sorted set in a new key +* [zScan](#zscan) - Scan a sorted set for members ### zAdd ----- @@ -2736,11 +2835,36 @@ $redis->zUnion('ko2', array('k1', 'k2'), array(1, 1)); /* 4, 'ko2' => array('val $redis->zUnion('ko3', array('k1', 'k2'), array(5, 1)); /* 4, 'ko3' => array('val0', 'val2', 'val3', 'val1') */ ~~~ +### zScan +----- +_**Description**_: Scan a sorted set for members, with optional pattern and count + +##### *Parameters* +*key*: String, the set to scan +*iterator*: Long (reference), initialized to NULL +*pattern*: String (optional), the pattern to match +*count*: How many keys to return per iteration (Redis might return a different number) + +##### *Return value* +*Array, boolean* PHPRedis will return matching keys from Redis, or FALSE when iteration is complete + +##### *Example* +~~~ +$it = NULL; +$redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); +while($arr_matches = $redis->zscan('zset', $it, '*pattern*')) { + foreach($arr_matches as $str_mem => $f_score) { + echo "Key: $str_mem, Score: $f_score\n"; + } +} +~~~ + ## Pub/sub * [psubscribe](#psubscribe) - Subscribe to channels by pattern * [publish](#publish) - Post a message to a channel * [subscribe](#subscribe) - Subscribe to channels +* [pubsub](#pubsub) - Introspection into the pub/sub subsystem ### psubscribe ----- @@ -2801,6 +2925,26 @@ function f($redis, $chan, $msg) { $redis->subscribe(array('chan-1', 'chan-2', 'chan-3'), 'f'); // subscribe to 3 chans ~~~ +### pubsub +----- +_**Description**_: A command allowing you to get information on the Redis pub/sub system. + +##### *Parameters* +*keyword*: String, which can be: "channels", "numsub", or "numpat" +*argument*: Optional, variant. For the "channels" subcommand, you can pass a string pattern. For "numsub" an array of channel names. + +##### *Return value* +*CHANNELS*: Returns an array where the members are the matching channels. +*NUMSUB*: Returns a key/value array where the keys are channel names and values are their counts. +*NUMPAT*: Integer return containing the number active pattern subscriptions + +##### *Example* +~~~ +$redis->pubsub("channels"); /*All channels */ +$redis->pubsub("channels", "*pattern*"); /* Just channels matching your pattern */ +$redis->pubsub("numsub", Array("chan1", "chan2")); /*Get subscriber counts for 'chan1' and 'chan2'*/ +$redsi->pubsub("numpat"); /* Get the number of pattern subscribers */ +``` ## Transactions @@ -2867,6 +3011,7 @@ $ret = FALSE if x has been modified between the call to WATCH and the call to EX * [clearLastError](#) - Clear the last error message * [_prefix](#) - A utility method to prefix the value with the prefix setting for phpredis * [_unserialize](#) - A utility method to unserialize data with whatever serializer is set up +* [_serialize](#) - A utility method to serialize data with whatever serializer is set up ### eval ----- @@ -3016,6 +3161,28 @@ $redis->setOption(Redis::OPT_PREFIX, 'my-prefix:'); $redis->_prefix('my-value'); // Will return 'my-prefix:my-value' ~~~ +### _serialize +----- +_**Description**_: A utility method to serialize values manually. + +This method allows you to serialize a value with whatever serializer is configured, manually. +This can be useful for serialization/unserialization of data going in and out of EVAL commands +as phpredis can't automatically do this itself. Note that if no serializer is set, phpredis +will change Array values to 'Array', and Objects to 'Object'. + +##### *Parameters* +*value*: Mixed. The value to be serialized + +##### *Examples* +~~~ +$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE); +$redis->_serialize("foo"); // returns "foo" +$redis->_serialize(Array()); // Returns "Array" +$redis->_serialize(new stdClass()); // Returns "Object" + +$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP); +$redis->_serialize("foo"); // Returns 's:3:"foo";' + ### _unserialize ----- _**Description**_: A utility method to unserialize data with whatever serializer is set up. @@ -3080,7 +3247,7 @@ None ### GetTimeout ----- -_**Description**_: Get the (write) timeout in use for phpreids +_**Description**_: Get the (write) timeout in use for phpredis ##### *Parameters* None diff --git a/common.h b/common.h index 63b1d9ee..a0623fbd 100644 --- a/common.h +++ b/common.h @@ -37,22 +37,48 @@ typedef enum _REDIS_REPLY_TYPE { TYPE_MULTIBULK = '*' } REDIS_REPLY_TYPE; +/* SCAN variants */ +typedef enum _REDIS_SCAN_TYPE { + TYPE_SCAN, + TYPE_SSCAN, + TYPE_HSCAN, + TYPE_ZSCAN +} REDIS_SCAN_TYPE; + +/* PUBSUB subcommands */ +typedef enum _PUBSUB_TYPE { + PUBSUB_CHANNELS, + PUBSUB_NUMSUB, + PUBSUB_NUMPAT +} PUBSUB_TYPE; + /* options */ #define REDIS_OPT_SERIALIZER 1 #define REDIS_OPT_PREFIX 2 #define REDIS_OPT_READ_TIMEOUT 3 +#define REDIS_OPT_SCAN 4 /* serializers */ #define REDIS_SERIALIZER_NONE 0 #define REDIS_SERIALIZER_PHP 1 #define REDIS_SERIALIZER_IGBINARY 2 +/* SCAN options */ + +#define REDIS_SCAN_NORETRY 0 +#define REDIS_SCAN_RETRY 1 + +/* GETBIT/SETBIT offset range limits */ +#define BITOP_MIN_OFFSET 0 +#define BITOP_MAX_OFFSET 4294967295 + #define IF_MULTI() if(redis_sock->mode == MULTI) #define IF_MULTI_OR_ATOMIC() if(redis_sock->mode == MULTI || redis_sock->mode == ATOMIC)\ #define IF_MULTI_OR_PIPELINE() if(redis_sock->mode == MULTI || redis_sock->mode == PIPELINE) #define IF_PIPELINE() if(redis_sock->mode == PIPELINE) #define IF_NOT_MULTI() if(redis_sock->mode != MULTI) +#define IF_NOT_ATOMIC() if(redis_sock->mode != ATOMIC) #define IF_ATOMIC() if(redis_sock->mode == ATOMIC) #define ELSE_IF_MULTI() else if(redis_sock->mode == MULTI) { \ if(redis_response_enqueued(redis_sock TSRMLS_CC) == 1) {\ @@ -197,6 +223,8 @@ typedef struct { char *err; int err_len; zend_bool lazy_connect; + + int scan; } RedisSock; /* }}} */ diff --git a/library.c b/library.c index 4fd523de..c368d3a3 100644 --- a/library.c +++ b/library.c @@ -106,6 +106,54 @@ PHP_REDIS_API int redis_check_eof(RedisSock *redis_sock TSRMLS_DC) return 0; } + +PHP_REDIS_API int +redis_sock_read_scan_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, + REDIS_SCAN_TYPE type, long *iter) +{ + REDIS_REPLY_TYPE reply_type; + int reply_info; + char *p_iter; + + /* Our response should have two multibulk replies */ + if(redis_read_reply_type(redis_sock, &reply_type, &reply_info TSRMLS_CC)<0 + || reply_type != TYPE_MULTIBULK || reply_info != 2) + { + return -1; + } + + /* The BULK response iterator */ + if(redis_read_reply_type(redis_sock, &reply_type, &reply_info TSRMLS_CC)<0 + || reply_type != TYPE_BULK) + { + return -1; + } + + /* Attempt to read the iterator */ + if(!(p_iter = redis_sock_read_bulk_reply(redis_sock, reply_info TSRMLS_CC))) { + return -1; + } + + /* Push the iterator out to the caller */ + *iter = atol(p_iter); + efree(p_iter); + + /* Read our actual keys/members/etc differently depending on what kind of + scan command this is. They all come back in slightly different ways */ + switch(type) { + case TYPE_SCAN: + return redis_sock_read_multibulk_reply_raw(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL); + case TYPE_SSCAN: + return redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL); + case TYPE_ZSCAN: + return redis_sock_read_multibulk_reply_zipped(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL); + case TYPE_HSCAN: + return redis_sock_read_multibulk_reply_zipped_strings(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL); + default: + return -1; + } +} + PHP_REDIS_API zval *redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock) { char inbuf[1024]; int numElems; @@ -1074,6 +1122,8 @@ PHP_REDIS_API RedisSock* redis_sock_create(char *host, int host_len, unsigned sh redis_sock->err = NULL; redis_sock->err_len = 0; + redis_sock->scan = REDIS_SCAN_NORETRY; + return redis_sock; } @@ -1498,8 +1548,10 @@ redis_serialize(RedisSock *redis_sock, zval *z, char **val, int *val_len TSRMLS_ #endif smart_str sstr = {0}; zval *z_copy; +#ifdef HAVE_REDIS_IGBINARY size_t sz; uint8_t *val8; +#endif switch(redis_sock->serializer) { case REDIS_SERIALIZER_NONE: @@ -1834,7 +1886,7 @@ redis_read_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zv default: /* Protocol error */ zend_throw_exception_ex(redis_exception_ce, 0 TSRMLS_CC, "protocol error, got '%c' as reply-type byte\n", reply_type); - break; + return FAILURE; } IF_MULTI_OR_PIPELINE() { diff --git a/library.h b/library.h index b749cf63..4813b126 100644 --- a/library.h +++ b/library.h @@ -35,6 +35,8 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_loop(INTERNAL_FUNCTION_PARAMET PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped_strings(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); PHP_REDIS_API int redis_sock_read_multibulk_reply_assoc(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); +PHP_REDIS_API int redis_sock_read_scan_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, REDIS_SCAN_TYPE type, long *iter); + PHP_REDIS_API int redis_sock_write(RedisSock *redis_sock, char *cmd, size_t sz TSRMLS_DC); PHP_REDIS_API void redis_stream_close(RedisSock *redis_sock TSRMLS_DC); PHP_REDIS_API int redis_check_eof(RedisSock *redis_sock TSRMLS_DC); diff --git a/package.xml b/package.xml index dd97ad77..f3b82d4f 100644 --- a/package.xml +++ b/package.xml @@ -21,10 +21,10 @@ http://pear.php.net/dtd/package-2.0.xsd"> michael.grunder@gmail.com yes - 2013-09-01 + 2014-03-15 - 2.2.4 - 2.2.4 + 2.2.5 + 2.2.5 stable @@ -32,7 +32,25 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP - First public release + phpredis 2.2.5 + + This is a minor release with several bug fixes as well as additions to support + new commands that have been introduced to Redis since our last release. + + A special thanks to everyone who helps the project by commenting on issues and + submitting pull requests! :) + + [NEW] Support for the BITPOS command + [NEW] Connection timeout option for RedisArray (@MikeToString) + [NEW] A _serialize method, to complement our existing _unserialize method + [NEW] Support for the PUBSUB command + [NEW] Support for SCAN, SSCAN, HSCAN, and ZSCAN + [NEW] Support for the WAIT command + + [FIX] Handle the COPY and REPLACE arguments for the MIGRATE command + + [DOC] Fix syntax error in documentation for the SET command (@mithunsatheesh) + [DOC] Homebrew documentation instructions (@mathias) @@ -53,6 +71,13 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + + + + + + @@ -70,12 +95,69 @@ http://pear.php.net/dtd/package-2.0.xsd"> redis + + stablestable + 2.2.52.2.5 + 2014-03-15 + + phpredis 2.2.5 + + This is a minor release with several bug fixes as well as additions to support + new commands that have been introduced to Redis since our last release. + + A special thanks to everyone who helps the project by commenting on issues and + submitting pull requests! :) + + [NEW] Support for the BITPOS command + [NEW] Connection timeout option for RedisArray (@MikeToString) + [NEW] A _serialize method, to complement our existing _unserialize method + [NEW] Support for the PUBSUB command + [NEW] Support for SCAN, SSCAN, HSCAN, and ZSCAN + [NEW] Support for the WAIT command + + [FIX] Handle the COPY and REPLACE arguments for the MIGRATE command + + [DOC] Fix syntax error in documentation for the SET command (@mithunsatheesh) + [DOC] Homebrew documentation instructions (@mathias) + + + stablestable 2.2.42.2.4 2013-09-01 - See GitHub for release notes + ** + ** Features / Improvements + ** + + * Randomized reconnect delay for RedisArray @mobli + This feature adds an optional parameter when constructing a RedisArray object + such that a random delay will be introduced if reconnections are made, + mitigating any 'thundering herd' type problems. + + * Lazy connections to RedisArray servers @mobli + By default, RedisArray will attempt to connect to each server you pass in + the ring on construction. This feature lets you specify that you would + rather have RedisArray only attempt a connection when it needs to get data + from a particular node (throughput/performance improvement). + + * Allow LONG and STRING keys in MGET/MSET + * Extended SET options for Redis >= 2.6.12 + * Persistent connections and UNIX SOCKET support for RedisArray + * Allow aggregates for ZUNION/ZINTER without weights @mheijkoop + * Support for SLOWLOG command + * Reworked MGET algorithm to run in linear time regardless of key count. + * Reworked ZINTERSTORE/ZUNIONSTORE algorithm to run in linear time + + ** + ** Bug fixes + ** + + * C99 Compliance (or rather lack thereof) fix @mobli + * Added ZEND_ACC_CTOR and ZEND_ACC_DTOR @euskadi31 + * Stop throwing and clearing an exception on connect failure @matmoi + * Fix a false positive unit test failure having to do with TTL returns diff --git a/php_redis.h b/php_redis.h index 905c7b3b..ccc2e724 100644 --- a/php_redis.h +++ b/php_redis.h @@ -14,6 +14,7 @@ +----------------------------------------------------------------------+ | Original author: Alfonso Jimenez | | Maintainer: Nicolas Favre-Felix | + | Maintainer: Michael Grunder | | Maintainer: Nasreddine Bouafif | +----------------------------------------------------------------------+ */ @@ -128,6 +129,7 @@ PHP_METHOD(Redis, slaveof); PHP_METHOD(Redis, object); PHP_METHOD(Redis, bitop); PHP_METHOD(Redis, bitcount); +PHP_METHOD(Redis, bitpos); PHP_METHOD(Redis, eval); PHP_METHOD(Redis, evalsha); @@ -141,6 +143,7 @@ PHP_METHOD(Redis, time); PHP_METHOD(Redis, getLastError); PHP_METHOD(Redis, clearLastError); PHP_METHOD(Redis, _prefix); +PHP_METHOD(Redis, _serialize); PHP_METHOD(Redis, _unserialize); PHP_METHOD(Redis, mset); @@ -181,9 +184,18 @@ PHP_METHOD(Redis, setOption); PHP_METHOD(Redis, config); PHP_METHOD(Redis, slowlog); +PHP_METHOD(Redis, wait); +PHP_METHOD(Redis, pubsub); PHP_METHOD(Redis, client); +/* SCAN and friends */ +PHP_METHOD(Redis, scan); +PHP_METHOD(Redis, hscan); +PHP_METHOD(Redis, sscan); +PHP_METHOD(Redis, zscan); + +/* Reflection */ PHP_METHOD(Redis, getHost); PHP_METHOD(Redis, getPort); PHP_METHOD(Redis, getDBNum); @@ -257,7 +269,7 @@ extern zend_module_entry redis_module_entry; #define phpext_redis_ptr redis_module_ptr -#define PHP_REDIS_VERSION "2.2.4" +#define PHP_REDIS_VERSION "2.2.5" #endif diff --git a/redis.c b/redis.c index f869d001..b565069d 100644 --- a/redis.c +++ b/redis.c @@ -69,6 +69,25 @@ PHP_INI_BEGIN() PHP_INI_ENTRY("redis.arrays.autorehash", "", PHP_INI_ALL, NULL) PHP_INI_END() +/** + * Argument info for the SCAN proper + */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_scan, 0, 0, 1) + ZEND_ARG_INFO(1, i_iterator) + ZEND_ARG_INFO(0, str_pattern) + ZEND_ARG_INFO(0, i_count) +ZEND_END_ARG_INFO(); + +/** + * Argument info for key scanning + */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_kscan, 0, 0, 2) + ZEND_ARG_INFO(0, str_key) + ZEND_ARG_INFO(1, i_iterator) + ZEND_ARG_INFO(0, str_pattern) + ZEND_ARG_INFO(0, i_count) +ZEND_END_ARG_INFO(); + #ifdef ZTS ZEND_DECLARE_MODULE_GLOBALS(redis) #endif @@ -160,6 +179,7 @@ static zend_function_entry redis_functions[] = { PHP_ME(Redis, object, NULL, ZEND_ACC_PUBLIC) PHP_ME(Redis, bitop, NULL, ZEND_ACC_PUBLIC) PHP_ME(Redis, bitcount, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Redis, bitpos, NULL, ZEND_ACC_PUBLIC) /* 1.1 */ PHP_ME(Redis, mset, NULL, ZEND_ACC_PUBLIC) @@ -228,10 +248,17 @@ static zend_function_entry redis_functions[] = { PHP_ME(Redis, clearLastError, NULL, ZEND_ACC_PUBLIC) PHP_ME(Redis, _prefix, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Redis, _serialize, NULL, ZEND_ACC_PUBLIC) PHP_ME(Redis, _unserialize, NULL, ZEND_ACC_PUBLIC) PHP_ME(Redis, client, NULL, ZEND_ACC_PUBLIC) + /* SCAN and friends */ + PHP_ME(Redis, scan, arginfo_scan, ZEND_ACC_PUBLIC) + PHP_ME(Redis, hscan, arginfo_kscan, ZEND_ACC_PUBLIC) + PHP_ME(Redis, zscan, arginfo_kscan, ZEND_ACC_PUBLIC) + PHP_ME(Redis, sscan, arginfo_kscan, ZEND_ACC_PUBLIC) + /* options */ PHP_ME(Redis, getOption, NULL, ZEND_ACC_PUBLIC) PHP_ME(Redis, setOption, NULL, ZEND_ACC_PUBLIC) @@ -252,6 +279,9 @@ static zend_function_entry redis_functions[] = { PHP_ME(Redis, getAuth, NULL, ZEND_ACC_PUBLIC) PHP_ME(Redis, isConnected, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Redis, wait, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Redis, pubsub, NULL, ZEND_ACC_PUBLIC) + /* aliases */ PHP_MALIAS(Redis, open, connect, NULL, ZEND_ACC_PUBLIC) PHP_MALIAS(Redis, popen, pconnect, NULL, ZEND_ACC_PUBLIC) @@ -488,6 +518,11 @@ PHP_MINIT_FUNCTION(redis) /* serializer */ add_constant_long(redis_ce, "SERIALIZER_NONE", REDIS_SERIALIZER_NONE); add_constant_long(redis_ce, "SERIALIZER_PHP", REDIS_SERIALIZER_PHP); + + /* scan options*/ + add_constant_long(redis_ce, "OPT_SCAN", REDIS_OPT_SCAN); + add_constant_long(redis_ce, "SCAN_RETRY", REDIS_SCAN_RETRY); + add_constant_long(redis_ce, "SCAN_NORETRY", REDIS_SCAN_NORETRY); #ifdef HAVE_REDIS_IGBINARY add_constant_long(redis_ce, "SERIALIZER_IGBINARY", REDIS_SERIALIZER_IGBINARY); #endif @@ -790,6 +825,59 @@ PHP_METHOD(Redis, bitcount) } /* }}} */ +/* {{{ proto integer Redis::bitpos(string key, int bit, [int start], [int end]) */ +PHP_METHOD(Redis, bitpos) +{ + zval *object; + RedisSock *redis_sock; + char *key, *cmd; + int key_len, cmd_len, argc, key_free=0; + long bit, start, end; + + argc = ZEND_NUM_ARGS(); + + if(zend_parse_method_parameters(argc TSRMLS_CC, getThis(), "Osl|ll", + &object, redis_ce, &key, &key_len, &bit, + &start, &end)==FAILURE) + { + RETURN_FALSE; + } + + if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { + RETURN_FALSE; + } + + // We can prevalidate the first argument + if(bit != 0 && bit != 1) { + RETURN_FALSE; + } + + // Prefix our key + key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); + + // Various command semantics + if(argc == 2) { + cmd_len = redis_cmd_format_static(&cmd, "BITPOS", "sd", key, key_len, + bit); + } else if(argc == 3) { + cmd_len = redis_cmd_format_static(&cmd, "BITPOS", "sdd", key, key_len, + bit, start); + } else { + cmd_len = redis_cmd_format_static(&cmd, "BITPOS", "sddd", key, key_len, + bit, start, end); + } + + // Free our key if it was prefixed + if(key_free) efree(key); + + REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); + IF_ATOMIC() { + redis_long_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL); + } + REDIS_PROCESS_RESPONSE(redis_long_response); +} +/* }}} */ + /* {{{ proto boolean Redis::close() */ PHP_METHOD(Redis, close) @@ -839,7 +927,9 @@ PHP_METHOD(Redis, set) { /* Our optional argument can either be a long (to support legacy SETEX */ /* redirection), or an array with Redis >= 2.6.12 set options */ - if(z_opts && Z_TYPE_P(z_opts) != IS_LONG && Z_TYPE_P(z_opts) != IS_ARRAY) { + if(z_opts && Z_TYPE_P(z_opts) != IS_LONG && Z_TYPE_P(z_opts) != IS_ARRAY + && Z_TYPE_P(z_opts) != IS_NULL) + { RETURN_FALSE; } @@ -903,7 +993,7 @@ PHP_METHOD(Redis, set) { /* Free our key or value if we prefixed/serialized */ if(key_free) efree(key); - if(val_free) efree(val); + if(val_free) STR_FREE(val); /* Kick off the command */ REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -936,7 +1026,7 @@ PHP_REDIS_API void redis_generic_setex(INTERNAL_FUNCTION_PARAMETERS, char *keywo val_free = redis_serialize(redis_sock, z_value, &val, &val_len TSRMLS_CC); key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, keyword, "sls", key, key_len, expire, val, val_len); - if(val_free) efree(val); + if(val_free) STR_FREE(val); if(key_free) efree(key); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -985,7 +1075,7 @@ PHP_METHOD(Redis, setnx) val_free = redis_serialize(redis_sock, z_value, &val, &val_len TSRMLS_CC); key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, "SETNX", "ss", key, key_len, val, val_len); - if(val_free) efree(val); + if(val_free) STR_FREE(val); if(key_free) efree(key); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -1023,7 +1113,7 @@ PHP_METHOD(Redis, getSet) val_free = redis_serialize(redis_sock, z_value, &val, &val_len TSRMLS_CC); key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, "GETSET", "ss", key, key_len, val, val_len); - if(val_free) efree(val); + if(val_free) STR_FREE(val); if(key_free) efree(key); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -1331,12 +1421,10 @@ PHP_METHOD(Redis, incrByFloat) { RETURN_FALSE; } - // Prefix our key, free it if we have + // Prefix key, format command, free old key if necissary key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); - if(key_free) efree(key); - - // Format our INCRBYFLOAT command cmd_len = redis_cmd_format_static(&cmd, "INCRBYFLOAT", "sf", key, key_len, val); + if(key_free) efree(key); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); IF_ATOMIC() { @@ -1742,6 +1830,11 @@ PHP_METHOD(Redis, getBit) RETURN_FALSE; } + // GETBIT and SETBIT only work for 0 - 2^32-1 + if(offset < BITOP_MIN_OFFSET || offset > BITOP_MAX_OFFSET) { + RETURN_FALSE; + } + key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, "GETBIT", "sd", key, key_len, (int)offset); if(key_free) efree(key); @@ -1771,6 +1864,11 @@ PHP_METHOD(Redis, setBit) RETURN_FALSE; } + // GETBIT and SETBIT only work for 0 - 2^32-1 + if(offset < BITOP_MIN_OFFSET || offset > BITOP_MAX_OFFSET) { + RETURN_FALSE; + } + key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, "SETBIT", "sdd", key, key_len, (int)offset, (int)val); if(key_free) efree(key); @@ -1833,7 +1931,7 @@ generic_push_function(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_l val_free = redis_serialize(redis_sock, z_value, &val, &val_len TSRMLS_CC); key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, keyword, "ss", key, key_len, val, val_len); - if(val_free) efree(val); + if(val_free) STR_FREE(val); if(key_free) efree(key); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -1909,9 +2007,9 @@ PHP_METHOD(Redis, lInsert) val_free = redis_serialize(redis_sock, z_value, &val, &val_len TSRMLS_CC); pivot_free = redis_serialize(redis_sock, z_pivot, &pivot, &pivot_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, "LINSERT", "ssss", key, key_len, position, position_len, pivot, pivot_len, val, val_len); - if(val_free) efree(val); + if(val_free) STR_FREE(val); if(key_free) efree(key); - if(pivot_free) efree(pivot); + if(pivot_free) STR_FREE(pivot); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); IF_ATOMIC() { @@ -2083,7 +2181,7 @@ PHP_METHOD(Redis, lRemove) val_free = redis_serialize(redis_sock, z_value, &val, &val_len TSRMLS_CC); key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, "LREM", "sds", key, key_len, count, val, val_len); - if(val_free) efree(val); + if(val_free) STR_FREE(val); if(key_free) efree(key); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -2287,7 +2385,7 @@ PHP_METHOD(Redis, sMove) src_free = redis_key_prefix(redis_sock, &src, &src_len TSRMLS_CC); dst_free = redis_key_prefix(redis_sock, &dst, &dst_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, "SMOVE", "sss", src, src_len, dst, dst_len, val, val_len); - if(val_free) efree(val); + if(val_free) STR_FREE(val); if(src_free) efree(src); if(dst_free) efree(dst); @@ -2349,14 +2447,23 @@ PHP_METHOD(Redis, sRandMember) // Process our command REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); - // Process our reply + // Either bulk or multi-bulk depending on argument count + if(ZEND_NUM_ARGS() == 2) { IF_ATOMIC() { - // This will be bulk or multi-bulk depending if we passed the optional [COUNT] argument - if(redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL) < 0) { + if(redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, + redis_sock, NULL, NULL) < 0) + { RETURN_FALSE; } } - REDIS_PROCESS_RESPONSE(redis_read_variant_reply); + REDIS_PROCESS_RESPONSE(redis_sock_read_multibulk_reply); + } else { + IF_ATOMIC() { + redis_string_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, + NULL, NULL); + } + REDIS_PROCESS_RESPONSE(redis_string_response); + } } /* }}} */ @@ -2384,7 +2491,7 @@ PHP_METHOD(Redis, sContains) val_free = redis_serialize(redis_sock, z_value, &val, &val_len TSRMLS_CC); key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, "SISMEMBER", "ss", key, key_len, val, val_len); - if(val_free) efree(val); + if(val_free) STR_FREE(val); if(key_free) efree(key); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -2612,7 +2719,7 @@ PHP_REDIS_API int generic_multiple_args_cmd(INTERNAL_FUNCTION_PARAMETERS, char * /* cleanup prefixed keys. */ for(i = 0; i < real_argc + (has_timeout?-1:0); ++i) { if(keys_to_free[i]) - efree(keys[i]); + STR_FREE(keys[i]); } if(single_array && has_timeout) { /* cleanup string created to contain timeout value */ efree(keys[real_argc-1]); @@ -3258,7 +3365,7 @@ PHP_METHOD(Redis, lSet) { val_free = redis_serialize(redis_sock, z_value, &val, &val_len TSRMLS_CC); key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, "LSET", "sds", key, key_len, index, val, val_len); - if(val_free) efree(val); + if(val_free) STR_FREE(val); if(key_free) efree(key); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -3678,7 +3785,7 @@ generic_mset(INTERNAL_FUNCTION_PARAMETERS, char *kw, void (*fun)(INTERNAL_FUNCTI memcpy(p, _NL, 2); p += 2; } - if(val_free) efree(val); + if(val_free) STR_FREE(val); if(key_free) efree(key); } } @@ -3861,7 +3968,7 @@ PHP_METHOD(Redis, zAdd) { smart_str_appendl(&buf, val, val_len); smart_str_appendl(&buf, _NL, sizeof(_NL) - 1); - if(val_free) efree(val); + if(val_free) STR_FREE(val); } /* end string */ @@ -4258,7 +4365,7 @@ PHP_METHOD(Redis, zScore) val_free = redis_serialize(redis_sock, z_value, &val, &val_len TSRMLS_CC); key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, "ZSCORE", "ss", key, key_len, val, val_len); - if(val_free) efree(val); + if(val_free) STR_FREE(val); if(key_free) efree(key); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -4291,7 +4398,7 @@ PHP_REDIS_API void generic_rank_method(INTERNAL_FUNCTION_PARAMETERS, char *keywo val_free = redis_serialize(redis_sock, z_value, &val, &val_len TSRMLS_CC); key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, keyword, "ss", key, key_len, val, val_len); - if(val_free) efree(val); + if(val_free) STR_FREE(val); if(key_free) efree(key); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -4341,7 +4448,7 @@ PHP_REDIS_API void generic_incrby_method(INTERNAL_FUNCTION_PARAMETERS, char *key val_free = redis_serialize(redis_sock, z_value, &val, &val_len TSRMLS_CC); key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, keyword, "sfs", key, key_len, add, val, val_len); - if(val_free) efree(val); + if(val_free) STR_FREE(val); if(key_free) efree(key); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -4556,7 +4663,7 @@ generic_hset(INTERNAL_FUNCTION_PARAMETERS, char *kw, void (*fun)(INTERNAL_FUNCTI val_free = redis_serialize(redis_sock, z_value, &val, &val_len TSRMLS_CC); key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, kw, "sss", key, key_len, member, member_len, val, val_len); - if(val_free) efree(val); + if(val_free) STR_FREE(val); if(key_free) efree(key); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -5076,7 +5183,7 @@ PHP_METHOD(Redis, hMset) redis_cmd_append_sstr(&set_cmds, hkey, hkey_len - 1); redis_cmd_append_sstr(&set_cmds, hval, hval_len); - if(hval_free) efree(hval); + if(hval_free) STR_FREE(hval); } // Now construct the entire command @@ -5804,22 +5911,19 @@ PHP_METHOD(Redis, getOption) { } switch(option) { - case REDIS_OPT_SERIALIZER: RETURN_LONG(redis_sock->serializer); - case REDIS_OPT_PREFIX: if(redis_sock->prefix) { RETURN_STRINGL(redis_sock->prefix, redis_sock->prefix_len, 1); } RETURN_NULL(); - case REDIS_OPT_READ_TIMEOUT: RETURN_DOUBLE(redis_sock->read_timeout); - + case REDIS_OPT_SCAN: + RETURN_LONG(redis_sock->scan); default: RETURN_FALSE; - } } /* }}} */ @@ -5857,7 +5961,6 @@ PHP_METHOD(Redis, setOption) { RETURN_FALSE; } break; - case REDIS_OPT_PREFIX: if(redis_sock->prefix) { efree(redis_sock->prefix); @@ -5871,17 +5974,22 @@ PHP_METHOD(Redis, setOption) { memcpy(redis_sock->prefix, val_str, val_len); } RETURN_TRUE; - case REDIS_OPT_READ_TIMEOUT: redis_sock->read_timeout = atof(val_str); if(redis_sock->stream) { read_tv.tv_sec = (time_t)redis_sock->read_timeout; read_tv.tv_usec = (int)((redis_sock->read_timeout - read_tv.tv_sec) * 1000000); - php_stream_set_option(redis_sock->stream, PHP_STREAM_OPTION_READ_TIMEOUT, - 0, &read_tv); + php_stream_set_option(redis_sock->stream, PHP_STREAM_OPTION_READ_TIMEOUT,0, &read_tv); } RETURN_TRUE; - + case REDIS_OPT_SCAN: + val_long = atol(val_str); + if(val_long == REDIS_SCAN_NORETRY || val_long == REDIS_SCAN_RETRY) { + redis_sock->scan = val_long; + RETURN_TRUE; + } + RETURN_FALSE; + break; default: RETURN_FALSE; } @@ -5992,6 +6100,207 @@ PHP_METHOD(Redis, slowlog) { REDIS_PROCESS_RESPONSE(redis_read_variant_reply); } +/* {{{ proto Redis::wait(int num_slaves, int ms) }}} + */ +PHP_METHOD(Redis, wait) { + zval *object; + RedisSock *redis_sock; + long num_slaves, timeout; + char *cmd; + int cmd_len; + + // Make sure arguments are valid + if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll", + &object, redis_ce, &num_slaves, &timeout) + ==FAILURE) + { + RETURN_FALSE; + } + + // Don't even send this to Redis if our args are negative + if(num_slaves < 0 || timeout < 0) { + RETURN_FALSE; + } + + // Grab our socket + if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0)<0) { + RETURN_FALSE; + } + + // Construct the command + cmd_len = redis_cmd_format_static(&cmd, "WAIT", "ll", num_slaves, timeout); + + // Kick it off + REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); + IF_ATOMIC() { + redis_long_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL); + } + REDIS_PROCESS_RESPONSE(redis_long_response); +} + +/* + * Construct a PUBSUB command + */ +PHP_REDIS_API int +redis_build_pubsub_cmd(RedisSock *redis_sock, char **ret, PUBSUB_TYPE type, + zval *arg TSRMLS_DC) +{ + HashTable *ht_chan; + HashPosition ptr; + zval **z_ele; + char *key; + int cmd_len, key_len, key_free; + smart_str cmd = {0}; + + if(type == PUBSUB_CHANNELS) { + if(arg) { + // Get string argument and length. + key = Z_STRVAL_P(arg); + key_len = Z_STRLEN_P(arg); + + // Prefix if necissary + key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); + + // With a pattern + cmd_len = redis_cmd_format_static(ret, "PUBSUB", "ss", "CHANNELS", sizeof("CHANNELS")-1, + key, key_len); + + // Free the channel name if we prefixed it + if(key_free) efree(key); + + // Return command length + return cmd_len; + } else { + // No pattern + return redis_cmd_format_static(ret, "PUBSUB", "s", "CHANNELS", sizeof("CHANNELS")-1); + } + } else if(type == PUBSUB_NUMSUB) { + ht_chan = Z_ARRVAL_P(arg); + + // Add PUBSUB and NUMSUB bits + redis_cmd_init_sstr(&cmd, zend_hash_num_elements(ht_chan)+1, "PUBSUB", sizeof("PUBSUB")-1); + redis_cmd_append_sstr(&cmd, "NUMSUB", sizeof("NUMSUB")-1); + + // Iterate our elements + for(zend_hash_internal_pointer_reset_ex(ht_chan, &ptr); + zend_hash_get_current_data_ex(ht_chan, (void**)&z_ele, &ptr)==SUCCESS; + zend_hash_move_forward_ex(ht_chan, &ptr)) + { + char *key; + int key_len, key_free; + zval *z_tmp = NULL; + + if(Z_TYPE_PP(z_ele) == IS_STRING) { + key = Z_STRVAL_PP(z_ele); + key_len = Z_STRLEN_PP(z_ele); + } else { + MAKE_STD_ZVAL(z_tmp); + *z_tmp = **z_ele; + zval_copy_ctor(z_tmp); + convert_to_string(z_tmp); + + key = Z_STRVAL_P(z_tmp); + key_len = Z_STRLEN_P(z_tmp); + } + + // Apply prefix if required + key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); + + // Append this channel + redis_cmd_append_sstr(&cmd, key, key_len); + + // Free key if prefixed + if(key_free) efree(key); + + // Free our temp var if we converted from something other than a string + if(z_tmp) { + zval_dtor(z_tmp); + efree(z_tmp); + z_tmp = NULL; + } + } + + // Set return + *ret = cmd.c; + return cmd.len; + } else if(type == PUBSUB_NUMPAT) { + return redis_cmd_format_static(ret, "PUBSUB", "s", "NUMPAT", sizeof("NUMPAT")-1); + } + + // Shouldn't ever happen + return -1; +} + +/* + * {{{ proto Redis::pubsub("channels", pattern); + * proto Redis::pubsub("numsub", Array channels); + * proto Redis::pubsub("numpat"); }}} + */ +PHP_METHOD(Redis, pubsub) { + zval *object; + RedisSock *redis_sock; + char *keyword, *cmd; + int kw_len, cmd_len; + PUBSUB_TYPE type; + zval *arg=NULL; + + // Parse arguments + if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|z", + &object, redis_ce, &keyword, &kw_len, &arg) + ==FAILURE) + { + RETURN_FALSE; + } + + // Validate our sub command keyword, and that we've got proper arguments + if(!strncasecmp(keyword, "channels", sizeof("channels"))) { + // One (optional) string argument + if(arg && Z_TYPE_P(arg) != IS_STRING) { + RETURN_FALSE; + } + type = PUBSUB_CHANNELS; + } else if(!strncasecmp(keyword, "numsub", sizeof("numsub"))) { + // One array argument + if(ZEND_NUM_ARGS() < 2 || Z_TYPE_P(arg) != IS_ARRAY || + zend_hash_num_elements(Z_ARRVAL_P(arg))==0) + { + RETURN_FALSE; + } + type = PUBSUB_NUMSUB; + } else if(!strncasecmp(keyword, "numpat", sizeof("numpat"))) { + type = PUBSUB_NUMPAT; + } else { + // Invalid keyword + RETURN_FALSE; + } + + // Grab our socket context object + if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0)<0) { + RETURN_FALSE; + } + + // Construct our "PUBSUB" command + cmd_len = redis_build_pubsub_cmd(redis_sock, &cmd, type, arg TSRMLS_CC); + + REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); + + if(type == PUBSUB_NUMSUB) { + IF_ATOMIC() { + if(redis_sock_read_multibulk_reply_zipped(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL)<0) { + RETURN_FALSE; + } + } + REDIS_PROCESS_RESPONSE(redis_sock_read_multibulk_reply_zipped); + } else { + IF_ATOMIC() { + if(redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL)<0) { + RETURN_FALSE; + } + } + REDIS_PROCESS_RESPONSE(redis_read_variant_reply); + } +} + // Construct an EVAL or EVALSHA command, with option argument array and number of arguments that are keys parameter PHP_REDIS_API int redis_build_eval_cmd(RedisSock *redis_sock, char **ret, char *keyword, char *value, int val_len, zval *args, int keys_count TSRMLS_DC) { @@ -6291,18 +6600,20 @@ PHP_METHOD(Redis, restore) { } /* - * {{{ proto Redis::migrate(host port key dest-db timeout) + * {{{ proto Redis::migrate(host port key dest-db timeout [bool copy, bool replace]) */ PHP_METHOD(Redis, migrate) { zval *object; RedisSock *redis_sock; char *cmd, *host, *key; int cmd_len, host_len, key_len, key_free; + zend_bool copy=0, replace=0; long port, dest_db, timeout; // Parse arguments - if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oslsll", &object, redis_ce, - &host, &host_len, &port, &key, &key_len, &dest_db, &timeout) == FAILURE) { + if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oslsll|bb", &object, redis_ce, + &host, &host_len, &port, &key, &key_len, &dest_db, &timeout, + ©, &replace) == FAILURE) { RETURN_FALSE; } @@ -6313,7 +6624,26 @@ PHP_METHOD(Redis, migrate) { // Prefix our key if we need to, build our command key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); - cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsdd", host, host_len, port, key, key_len, dest_db, timeout); + + // Construct our command + if(copy && replace) { + cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsddss", host, host_len, port, + key, key_len, dest_db, timeout, "COPY", + sizeof("COPY")-1, "REPLACE", sizeof("REPLACE")-1); + } else if(copy) { + cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsdds", host, host_len, port, + key, key_len, dest_db, timeout, "COPY", + sizeof("COPY")-1); + } else if(replace) { + cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsdds", host, host_len, port, + key, key_len, dest_db, timeout, "REPLACE", + sizeof("REPLACE")-1); + } else { + cmd_len = redis_cmd_format_static(&cmd, "MIGRATE", "sdsdd", host, host_len, port, + key, key_len, dest_db, timeout); + } + + // Free our key if we prefixed it if(key_free) efree(key); // Kick off our MIGRATE request @@ -6352,6 +6682,36 @@ PHP_METHOD(Redis, _prefix) { } } +/* + * {{{ proto Redis::_serialize(value) + */ +PHP_METHOD(Redis, _serialize) { + zval *object; + RedisSock *redis_sock; + zval *z_val; + char *val; + int val_len; + + // Parse arguments + if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz", + &object, redis_ce, &z_val) == FAILURE) + { + RETURN_FALSE; + } + + // Grab socket + if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { + RETURN_FALSE; + } + + // Serialize, which will return a value even if no serializer is set + redis_serialize(redis_sock, z_val, &val, &val_len TSRMLS_CC); + + // Return serialized value. Tell PHP to make a copy as some can be interned. + RETVAL_STRINGL(val, val_len, 1); + STR_FREE(val); +} + /* * {{{ proto Redis::_unserialize(value) */ @@ -6634,4 +6994,169 @@ PHP_METHOD(Redis, client) { } } +/** + * Helper to format any combination of SCAN arguments + */ +PHP_REDIS_API int +redis_build_scan_cmd(char **cmd, REDIS_SCAN_TYPE type, char *key, int key_len, + int iter, char *pattern, int pattern_len, int count) +{ + char *keyword; + int arg_count, cmd_len; + + // 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. + arg_count = 1 + (key_len>0) + (pattern_len>0?2:0) + (count>0?2:0); + + // Turn our type into a keyword + switch(type) { + case TYPE_SCAN: + keyword = "SCAN"; + break; + case TYPE_SSCAN: + keyword = "SSCAN"; + break; + case TYPE_HSCAN: + keyword = "HSCAN"; + break; + case TYPE_ZSCAN: + default: + keyword = "ZSCAN"; + break; + } + + // Start the command + cmd_len = redis_cmd_format_header(cmd, keyword, arg_count); + + // Add the key in question if we have one + if(key_len) { + cmd_len = redis_cmd_append_str(cmd, cmd_len, key, key_len); + } + + // Add our iterator + cmd_len = redis_cmd_append_int(cmd, cmd_len, iter); + + // Append COUNT if we've got it + if(count) { + cmd_len = redis_cmd_append_str(cmd, cmd_len, "COUNT", sizeof("COUNT")-1); + cmd_len = redis_cmd_append_int(cmd, cmd_len, count); + } + + // Append MATCH if we've got it + if(pattern_len) { + cmd_len = redis_cmd_append_str(cmd, cmd_len, "MATCH", sizeof("MATCH")-1); + cmd_len = redis_cmd_append_str(cmd, cmd_len, pattern, pattern_len); + } + + // Return our command length + return cmd_len; +} + +/** + * {{{ proto redis::scan(&$iterator, [pattern, [count]]) + */ +PHP_REDIS_API void +generic_scan_cmd(INTERNAL_FUNCTION_PARAMETERS, REDIS_SCAN_TYPE type) { + zval *object, *z_iter; + RedisSock *redis_sock; + HashTable *hash; + char *pattern=NULL, *cmd, *key=NULL; + int cmd_len, key_len=0, pattern_len=0, num_elements, key_free=0; + long count=0, iter; + + // 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() TSRMLS_CC, getThis(), "Osz/|s!l", + &object, redis_ce, &key, &key_len, &z_iter, + &pattern, &pattern_len, &count)==FAILURE) + { + RETURN_FALSE; + } + } else { + // Doesn't require a key + if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz/|s!l", + &object, redis_ce, &z_iter, &pattern, &pattern_len, + &count) == FAILURE) + { + RETURN_FALSE; + } + } + + // Grab our socket + if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { + RETURN_FALSE; + } + + // Calling this in a pipeline makes no sense + IF_NOT_ATOMIC() { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can't call SCAN commands in multi or pipeline mode!"); + RETURN_FALSE; + } + + // The iterator should be passed in as NULL for the first iteration, but we can treat + // any NON LONG value as NULL for these purposes as we've seperated the variable anyway. + if(Z_TYPE_P(z_iter) != IS_LONG || Z_LVAL_P(z_iter)<0) { + // Convert to long + convert_to_long(z_iter); + iter = 0; + } else if(Z_LVAL_P(z_iter)!=0) { + // Update our iterator value for the next passthru + iter = Z_LVAL_P(z_iter); + } else { + // We're done, back to iterator zero + 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 TSRMLS_CC); + } + + /** + * Redis can return to us empty keys, especially in the case where there are a large + * number of keys to scan, and we're matching against a pattern. PHPRedis can be set + * up to abstract this from the user, by setting OPT_SCAN to REDIS_SCAN_RETRY. Otherwise + * we will return empty keys and the user will need to make subsequent calls with + * an updated iterator. + */ + do { + // Format our SCAN command + cmd_len = redis_build_scan_cmd(&cmd, type, key, key_len, (int)iter, + pattern, pattern_len, count); + + // Execute our command getting our new iterator value + REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); + if(redis_sock_read_scan_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, + redis_sock,type,&iter)<0) + { + if(key_free) efree(key); + RETURN_FALSE; + } + + // Get the number of elements + hash = Z_ARRVAL_P(return_value); + num_elements = zend_hash_num_elements(hash); + } while(redis_sock->scan == REDIS_SCAN_RETRY && iter != 0 && num_elements == 0); + + // Free our key if it was prefixed + if(key_free) efree(key); + + // Update our iterator reference + Z_LVAL_P(z_iter) = iter; +} + +PHP_METHOD(Redis, scan) { + generic_scan_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, TYPE_SCAN); +} +PHP_METHOD(Redis, hscan) { + generic_scan_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, TYPE_HSCAN); +} +PHP_METHOD(Redis, sscan) { + generic_scan_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, TYPE_SSCAN); +} +PHP_METHOD(Redis, zscan) { + generic_scan_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, TYPE_ZSCAN); +} + /* vim: set tabstop=4 softtabstops=4 noexpandtab shiftwidth=4: */ diff --git a/redis_array.c b/redis_array.c index 60d1022b..e9a56e7a 100644 --- a/redis_array.c +++ b/redis_array.c @@ -32,6 +32,12 @@ #include "redis_array.h" #include "redis_array_impl.h" +/* Simple macro to detect failure in a RedisArray call */ +#define RA_CALL_FAILED(rv, cmd) \ + ((Z_TYPE_P(rv) == IS_BOOL && Z_BVAL_P(rv) == 0) || \ + (Z_TYPE_P(rv) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(rv)) == 0) || \ + (Z_TYPE_P(rv) == IS_LONG && Z_LVAL_P(rv) == 0 && !strcasecmp(cmd, "TYPE"))) \ + extern zend_class_entry *redis_ce; zend_class_entry *redis_array_ce; @@ -76,43 +82,50 @@ zend_function_entry redis_array_functions[] = { {NULL, NULL, NULL} }; -int le_redis_array; -void redis_destructor_redis_array(zend_rsrc_list_entry * rsrc TSRMLS_DC) -{ +static void redis_array_free(RedisArray *ra) { int i; - RedisArray *ra = (RedisArray*)rsrc->ptr; - /* delete Redis objects */ - for(i = 0; i < ra->count; ++i) { + // Redis objects + for(i=0;icount;i++) { zval_dtor(ra->redis[i]); efree(ra->redis[i]); - - /* remove host too */ efree(ra->hosts[i]); } efree(ra->redis); efree(ra->hosts); - /* delete function */ + /* delete hash function */ if(ra->z_fun) { zval_dtor(ra->z_fun); efree(ra->z_fun); } - /* delete distributor */ + /* Distributor */ if(ra->z_dist) { zval_dtor(ra->z_dist); efree(ra->z_dist); } - /* delete list of pure commands */ + /* Delete pur commands */ zval_dtor(ra->z_pure_cmds); efree(ra->z_pure_cmds); - /* free container */ + // Free structure itself efree(ra); } +int le_redis_array; +void redis_destructor_redis_array(zend_rsrc_list_entry * rsrc TSRMLS_DC) +{ + RedisArray *ra = (RedisArray*)rsrc->ptr; + + /* Free previous ring if it's set */ + if(ra->prev) redis_array_free(ra->prev); + + /* Free parent array */ + redis_array_free(ra); +} + /** * redis_array_get */ @@ -199,6 +212,8 @@ PHP_METHOD(RedisArray, __construct) long l_retry_interval = 0; zend_bool b_lazy_connect = 0; zval **z_retry_interval_pp; + double d_connect_timeout = 0; + zval **z_connect_timeout_pp; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &z0, &z_opts) == FAILURE) { RETURN_FALSE; @@ -261,6 +276,18 @@ PHP_METHOD(RedisArray, __construct) if(FAILURE != zend_hash_find(hOpts, "lazy_connect", sizeof("lazy_connect"), (void**)&zpData) && Z_TYPE_PP(zpData) == IS_BOOL) { b_lazy_connect = Z_BVAL_PP(zpData); } + + /* extract connect_timeout option */ + if (FAILURE != zend_hash_find(hOpts, "connect_timeout", sizeof("connect_timeout"), (void**)&z_connect_timeout_pp)) { + if (Z_TYPE_PP(z_connect_timeout_pp) == IS_DOUBLE || Z_TYPE_PP(z_connect_timeout_pp) == IS_STRING) { + if (Z_TYPE_PP(z_connect_timeout_pp) == IS_DOUBLE) { + d_connect_timeout = Z_DVAL_PP(z_connect_timeout_pp); + } + else { + d_connect_timeout = atof(Z_STRVAL_PP(z_connect_timeout_pp)); + } + } + } } /* extract either name of list of hosts from z0 */ @@ -270,7 +297,7 @@ PHP_METHOD(RedisArray, __construct) break; case IS_ARRAY: - ra = ra_make_array(Z_ARRVAL_P(z0), z_fun, z_dist, hPrev, b_index, b_pconnect, l_retry_interval, b_lazy_connect TSRMLS_CC); + ra = ra_make_array(Z_ARRVAL_P(z0), z_fun, z_dist, hPrev, b_index, b_pconnect, l_retry_interval, b_lazy_connect, d_connect_timeout TSRMLS_CC); break; default: @@ -280,6 +307,8 @@ PHP_METHOD(RedisArray, __construct) if(ra) { ra->auto_rehash = b_autorehash; + ra->connect_timeout = d_connect_timeout; + if(ra->prev) ra->prev->auto_rehash = b_autorehash; #if PHP_VERSION_ID >= 50400 id = zend_list_insert(ra, le_redis_array TSRMLS_CC); #else @@ -366,22 +395,14 @@ ra_forward_call(INTERNAL_FUNCTION_PARAMETERS, RedisArray *ra, const char *cmd, i } else { /* call directly through. */ call_user_function(&redis_ce->function_table, &redis_inst, &z_fun, return_value, argc, z_callargs TSRMLS_CC); - failed = 0; - if((Z_TYPE_P(return_value) == IS_BOOL && Z_BVAL_P(return_value) == 0) || - (Z_TYPE_P(return_value) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(return_value)) == 0) || - (Z_TYPE_P(return_value) == IS_LONG && Z_LVAL_P(return_value) == 0 && !strcasecmp(cmd, "TYPE"))) - - { - failed = 1; - } - /* check if we have an error. */ - if(failed && ra->prev && !b_write_cmd) { /* there was an error reading, try with prev ring. */ + if(RA_CALL_FAILED(return_value,cmd) && ra->prev && !b_write_cmd) { /* there was an error reading, try with prev ring. */ /* ERROR, FALLBACK TO PREVIOUS RING and forward a reference to the first redis instance we were looking at. */ ra_forward_call(INTERNAL_FUNCTION_PARAM_PASSTHRU, ra->prev, cmd, cmd_len, z_args, z_new_target?z_new_target:redis_inst); } - if(!failed && !b_write_cmd && z_new_target && ra->auto_rehash) { /* move key from old ring to new ring */ + /* Autorehash if the key was found on the previous node if this is a read command and auto rehashing is on */ + if(!RA_CALL_FAILED(return_value,cmd) && !b_write_cmd && z_new_target && ra->auto_rehash) { /* move key from old ring to new ring */ ra_move_key(key, key_len, redis_inst, z_new_target TSRMLS_CC); } } @@ -876,6 +897,9 @@ PHP_METHOD(RedisArray, mget) /* calls */ for(n = 0; n < ra->count; ++n) { /* for each node */ + /* We don't even need to make a call to this node if no keys go there */ + if(!argc_each[n]) continue; + /* copy args for MGET call on node. */ MAKE_STD_ZVAL(z_argarray); array_init(z_argarray); diff --git a/redis_array.h b/redis_array.h index 3b1163bf..2a8baf44 100644 --- a/redis_array.h +++ b/redis_array.h @@ -50,6 +50,7 @@ typedef struct RedisArray_ { zval *z_fun; /* key extractor, callable */ zval *z_dist; /* key distributor, callable */ zval *z_pure_cmds; /* hash table */ + double connect_timeout; /* socket connect timeout */ struct RedisArray_ *prev; } RedisArray; diff --git a/redis_array_impl.c b/redis_array_impl.c index 10c7dc81..ef499e1a 100644 --- a/redis_array_impl.c +++ b/redis_array_impl.c @@ -44,7 +44,9 @@ ra_load_hosts(RedisArray *ra, HashTable *hosts, long retry_interval, zend_bool b /* init connections */ for(i = 0; i < count; ++i) { - if(FAILURE == zend_hash_quick_find(hosts, NULL, 0, i, (void**)&zpData)) { + if(FAILURE == zend_hash_quick_find(hosts, NULL, 0, i, (void**)&zpData) || + Z_TYPE_PP(zpData) != IS_STRING) + { efree(ra); return NULL; } @@ -70,7 +72,7 @@ ra_load_hosts(RedisArray *ra, HashTable *hosts, long retry_interval, zend_bool b call_user_function(&redis_ce->function_table, &ra->redis[i], &z_cons, &z_ret, 0, NULL TSRMLS_CC); /* create socket */ - redis_sock = redis_sock_create(host, host_len, port, 0, ra->pconnect, NULL, retry_interval, b_lazy_connect); + redis_sock = redis_sock_create(host, host_len, port, ra->connect_timeout, ra->pconnect, NULL, retry_interval, b_lazy_connect); if (!b_lazy_connect) { @@ -166,12 +168,14 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) { zval *z_params_autorehash; zval *z_params_retry_interval; zval *z_params_pconnect; + zval *z_params_connect_timeout; zval *z_params_lazy_connect; RedisArray *ra = NULL; zend_bool b_index = 0, b_autorehash = 0, b_pconnect = 0; long l_retry_interval = 0; zend_bool b_lazy_connect = 0; + double d_connect_timeout = 0; HashTable *hHosts = NULL, *hPrev = NULL; /* find entry */ @@ -258,7 +262,8 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) { b_pconnect = 1; } } - /* find retry interval option */ + + /* find lazy connect option */ MAKE_STD_ZVAL(z_params_lazy_connect); array_init(z_params_lazy_connect); sapi_module.treat_data(PARSE_STRING, estrdup(INI_STR("redis.arrays.lazyconnect")), z_params_lazy_connect TSRMLS_CC); @@ -268,9 +273,25 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) { } } + /* find connect timeout option */ + MAKE_STD_ZVAL(z_params_connect_timeout); + array_init(z_params_connect_timeout); + sapi_module.treat_data(PARSE_STRING, estrdup(INI_STR("redis.arrays.connecttimeout")), z_params_connect_timeout TSRMLS_CC); + if (zend_hash_find(Z_ARRVAL_P(z_params_connect_timeout), name, strlen(name) + 1, (void **) &z_data_pp) != FAILURE) { + if (Z_TYPE_PP(z_data_pp) == IS_DOUBLE || Z_TYPE_PP(z_data_pp) == IS_STRING) { + if (Z_TYPE_PP(z_data_pp) == IS_DOUBLE) { + d_connect_timeout = Z_DVAL_PP(z_data_pp); + } + else { + d_connect_timeout = atof(Z_STRVAL_PP(z_data_pp)); + } + } + } + /* create RedisArray object */ - ra = ra_make_array(hHosts, z_fun, z_dist, hPrev, b_index, b_pconnect, l_retry_interval, b_lazy_connect TSRMLS_CC); + ra = ra_make_array(hHosts, z_fun, z_dist, hPrev, b_index, b_pconnect, l_retry_interval, b_lazy_connect, d_connect_timeout TSRMLS_CC); ra->auto_rehash = b_autorehash; + if(ra->prev) ra->prev->auto_rehash = b_autorehash; /* cleanup */ zval_dtor(z_params_hosts); @@ -287,6 +308,8 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) { efree(z_params_retry_interval); zval_dtor(z_params_pconnect); efree(z_params_pconnect); + zval_dtor(z_params_connect_timeout); + efree(z_params_connect_timeout); zval_dtor(z_params_lazy_connect); efree(z_params_lazy_connect); @@ -294,7 +317,7 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) { } RedisArray * -ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index, zend_bool b_pconnect, long retry_interval, zend_bool b_lazy_connect TSRMLS_DC) { +ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index, zend_bool b_pconnect, long retry_interval, zend_bool b_lazy_connect, double connect_timeout TSRMLS_DC) { int count = zend_hash_num_elements(hosts); @@ -308,6 +331,8 @@ ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev ra->z_multi_exec = NULL; ra->index = b_index; ra->auto_rehash = 0; + ra->pconnect = b_pconnect; + ra->connect_timeout = connect_timeout; /* init array data structures */ ra_init_function_table(ra); @@ -315,7 +340,7 @@ ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev if(NULL == ra_load_hosts(ra, hosts, retry_interval, b_lazy_connect TSRMLS_CC)) { return NULL; } - ra->prev = hosts_prev ? ra_make_array(hosts_prev, z_fun, z_dist, NULL, b_index, b_pconnect, retry_interval, b_lazy_connect TSRMLS_CC) : NULL; + ra->prev = hosts_prev ? ra_make_array(hosts_prev, z_fun, z_dist, NULL, b_index, b_pconnect, retry_interval, b_lazy_connect, connect_timeout TSRMLS_CC) : NULL; /* copy function if provided */ if(z_fun) { @@ -603,6 +628,7 @@ ra_index_key(const char *key, int key_len, zval *z_redis TSRMLS_DC) { /* don't dtor z_ret, since we're returning z_redis */ efree(z_args[0]); + zval_dtor(z_args[1]); efree(z_args[1]); } @@ -965,6 +991,7 @@ ra_move_string(const char *key, int key_len, zval *z_from, zval *z_to, long ttl ZVAL_STRINGL(z_args[0], key, key_len, 0); ZVAL_LONG(z_args[1], ttl); ZVAL_STRINGL(z_args[2], Z_STRVAL(z_ret), Z_STRLEN(z_ret), 1); /* copy z_ret to arg 1 */ + zval_dtor(&z_ret); /* free memory from our previous call */ call_user_function(&redis_ce->function_table, &z_to, &z_fun_set, &z_ret, 3, z_args TSRMLS_CC); /* cleanup */ efree(z_args[1]); @@ -975,6 +1002,7 @@ ra_move_string(const char *key, int key_len, zval *z_from, zval *z_to, long ttl ZVAL_STRINGL(&z_fun_set, "SET", 3, 0); ZVAL_STRINGL(z_args[0], key, key_len, 0); ZVAL_STRINGL(z_args[1], Z_STRVAL(z_ret), Z_STRLEN(z_ret), 1); /* copy z_ret to arg 1 */ + zval_dtor(&z_ret); /* free memory from our previous return value */ call_user_function(&redis_ce->function_table, &z_to, &z_fun_set, &z_ret, 2, z_args TSRMLS_CC); /* cleanup */ zval_dtor(z_args[1]); diff --git a/redis_array_impl.h b/redis_array_impl.h index 8f106542..06b5332a 100644 --- a/redis_array_impl.h +++ b/redis_array_impl.h @@ -12,7 +12,7 @@ RedisArray *ra_load_hosts(RedisArray *ra, HashTable *hosts, long retry_interval, zend_bool b_lazy_connect TSRMLS_DC); RedisArray *ra_load_array(const char *name TSRMLS_DC); -RedisArray *ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index, zend_bool b_pconnect, long retry_interval, zend_bool b_lazy_connect TSRMLS_DC); +RedisArray *ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index, zend_bool b_pconnect, long retry_interval, zend_bool b_lazy_connect, double connect_timeout TSRMLS_DC); zval *ra_find_node_by_name(RedisArray *ra, const char *host, int host_len TSRMLS_DC); zval *ra_find_node(RedisArray *ra, const char *key, int key_len, int *out_pos TSRMLS_DC); void ra_init_function_table(RedisArray *ra); diff --git a/rpm/php-redis.spec b/rpm/php-redis.spec index 4f04fb18..5363d1ee 100644 --- a/rpm/php-redis.spec +++ b/rpm/php-redis.spec @@ -3,7 +3,7 @@ %global php_version %(php-config --version 2>/dev/null || echo 0) Name: php-redis -Version: 2.2.4 +Version: 2.2.5 Release: 1%{?dist} Summary: The phpredis extension provides an API for communicating with the Redis key-value store. diff --git a/tests/TestRedis.php b/tests/TestRedis.php index 2a684754..ad577202 100644 --- a/tests/TestRedis.php +++ b/tests/TestRedis.php @@ -72,6 +72,47 @@ class Redis_Test extends TestSuite $this->assertTrue(is_array($ret) && count($ret) === 1 && $ret[0] >= 0); } + // Run some simple tests against the PUBSUB command. This is problematic, as we + // can't be sure what's going on in the instance, but we can do some things. + public function testPubSub() { + // Only available since 2.8.0 + if(version_compare($this->version, "2.8.0", "lt")) { + $this->markTestSkipped(); + return; + } + + // PUBSUB CHANNELS ... + $result = $this->redis->pubsub("channels", "*"); + $this->assertTrue(is_array($result)); + $result = $this->redis->pubsub("channels"); + $this->assertTrue(is_array($result)); + + // PUBSUB NUMSUB + + $c1 = uniqid() . '-' . rand(1,100); + $c2 = uniqid() . '-' . rand(1,100); + + $result = $this->redis->pubsub("numsub", Array($c1, $c2)); + + // Should get an array back, with two elements + $this->assertTrue(is_array($result)); + $this->assertEquals(count($result), 2); + + // Make sure the elements are correct, and have zero counts + foreach(Array($c1,$c2) as $channel) { + $this->assertTrue(isset($result[$channel])); + $this->assertEquals($result[$channel], "0"); + } + + // PUBSUB NUMPAT + $result = $this->redis->pubsub("numpat"); + $this->assertTrue(is_int($result)); + + // Invalid calls + $this->assertFalse($this->redis->pubsub("notacommand")); + $this->assertFalse($this->redis->pubsub("numsub", "not-an-array")); + } + public function testBitsets() { $this->redis->delete('key'); @@ -110,6 +151,31 @@ class Redis_Test extends TestSuite // values above 1 are changed to 1 but don't overflow on bits to the right. $this->assertTrue(0 === $this->redis->setBit('key', 0, 0xff)); $this->assertTrue("\x9f" === $this->redis->get('key')); + + // Verify valid offset ranges + $this->assertFalse($this->redis->getBit('key', -1)); + $this->assertFalse($this->redis->getBit('key', 4294967296)); + $this->assertFalse($this->redis->setBit('key', -1, 1)); + $this->assertFalse($this->redis->setBit('key', 4294967296, 1)); + } + + public function testBitPos() { + if(version_compare($this->version, "2.8.7", "lt")) { + $this->MarkTestSkipped(); + return; + } + + $this->redis->del('bpkey'); + + $this->redis->set('bpkey', "\xff\xf0\x00"); + $this->assertEquals($this->redis->bitpos('bpkey', 0), 12); + + $this->redis->set('bpkey', "\x00\xff\xf0"); + $this->assertEquals($this->redis->bitpos('bpkey', 1, 0), 8); + $this->assertEquals($this->redis->bitpos('bpkey', 1, 1), 8); + + $this->redis->set('bpkey', "\x00\x00\x00"); + $this->assertEquals($this->redis->bitpos('bpkey', 1), -1); } public function test1000() { @@ -258,6 +324,12 @@ class Redis_Test extends TestSuite $this->assertTrue($this->redis->set('foo','barbaz', Array('not-valid','nx','invalid','ex'=>200))); $this->assertEquals($this->redis->ttl('foo'), 200); $this->assertEquals($this->redis->get('foo'), 'barbaz'); + + /* Pass NULL as the optional arguments which should be ignored */ + $this->redis->del('foo'); + $this->redis->set('foo','bar', NULL); + $this->assertEquals($this->redis->get('foo'), 'bar'); + $this->assertTrue($this->redis->ttl('foo')<0); } public function testGetSet() { @@ -475,6 +547,16 @@ class Redis_Test extends TestSuite $this->redis->incrbyfloat('key', -1.5); $this->assertTrue("abc" === $this->redis->get('key')); + + // Test with prefixing + $this->redis->setOption(Redis::OPT_PREFIX, 'someprefix:'); + $this->redis->del('key'); + $this->redis->incrbyfloat('key',1.8); + $this->assertEquals('1.8', $this->redis->get('key')); + $this->redis->setOption(Redis::OPT_PREFIX, ''); + $this->assertTrue($this->redis->exists('someprefix:key')); + $this->redis->del('someprefix:key'); + } public function testDecr() @@ -1144,6 +1226,28 @@ class Redis_Test extends TestSuite break; } } + + // + // With and without count, while serializing + // + + $this->redis->delete('set0'); + $this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP); + for($i=0;$i<5;$i++) { + $member = "member:$i"; + $this->redis->sAdd('set0', $member); + $mems[] = $member; + } + + $member = $this->redis->srandmember('set0'); + $this->assertTrue(in_array($member, $mems)); + + $rmembers = $this->redis->srandmember('set0', $i); + foreach($rmembers as $reply_mem) { + $this->assertTrue(in_array($reply_mem, $mems)); + } + + $this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE); } public function testSRandMemberWithCount() { @@ -1759,6 +1863,34 @@ class Redis_Test extends TestSuite $this->assertFalse($this->redis->slowlog('notvalid')); } + public function testWait() { + // Closest we can check based on redis commmit history + if(version_compare($this->version, '2.9.11', 'lt')) { + $this->markTestSkipped(); + return; + } + + // We could have slaves here, so determine that + $arr_slaves = $this->redis->info(); + $i_slaves = $arr_slaves['connected_slaves']; + + // Send a couple commands + $this->redis->set('wait-foo', 'over9000'); + $this->redis->set('wait-bar', 'revo9000'); + + // Make sure we get the right replication count + $this->assertEquals($this->redis->wait($i_slaves, 100), $i_slaves); + + // Pass more slaves than are connected + $this->redis->set('wait-foo','over9000'); + $this->redis->set('wait-bar','revo9000'); + $this->assertTrue($this->redis->wait($i_slaves+1, 100) < $i_slaves+1); + + // Make sure when we pass with bad arguments we just get back false + $this->assertFalse($this->redis->wait(-1, -1)); + $this->assertFalse($this->redis->wait(-1, 20)); + } + public function testinfo() { $info = $this->redis->info(); @@ -4356,6 +4488,34 @@ class Redis_Test extends TestSuite $this->assertTrue(1 === $this->redis->evalsha($sha)); } + public function testSerialize() { + $vals = Array(1, 1.5, 'one', Array('here','is','an','array')); + + // Test with no serialization at all + $this->assertTrue($this->redis->_serialize('test') === 'test'); + $this->assertTrue($this->redis->_serialize(1) === '1'); + $this->assertTrue($this->redis->_serialize(Array()) === 'Array'); + $this->assertTrue($this->redis->_serialize(new stdClass) === 'Object'); + + $arr_serializers = Array(Redis::SERIALIZER_PHP); + if(defined('Redis::SERIALIZER_IGBINARY')) { + $arr_serializers[] = Redis::SERIALIZER_IGBINARY; + } + + foreach($arr_serializers as $mode) { + $arr_enc = Array(); + $arr_dec = Array(); + + foreach($vals as $k => $v) { + $enc = $this->redis->_serialize($v); + $dec = $this->redis->_unserialize($enc); + + // They should be the same + $this->assertTrue($enc == $dec); + } + } + } + public function testUnserialize() { $vals = Array( 1,1.5,'one',Array('this','is','an','array') @@ -4462,6 +4622,190 @@ class Redis_Test extends TestSuite $this->assertTrue($this->redis->getAuth() === self::AUTH); } + /** + * Scan and variants + */ + + protected function get_keyspace_count($str_db) { + $arr_info = $this->redis->info(); + $arr_info = $arr_info[$str_db]; + $arr_info = explode(',', $arr_info); + $arr_info = explode('=', $arr_info[0]); + return $arr_info[1]; + } + + public function testScan() { + if(version_compare($this->version, "2.8.0", "lt")) { + $this->markTestSkipped(); + return; + } + + // Key count + $i_key_count = $this->get_keyspace_count('db0'); + + // Have scan retry + $this->redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); + + // Scan them all + $it = NULL; + while($arr_keys = $this->redis->scan($it)) { + $i_key_count -= count($arr_keys); + } + // Should have iterated all keys + $this->assertEquals(0, $i_key_count); + + // Unique keys, for pattern matching + $str_uniq = uniqid() . '-' . uniqid(); + for($i=0;$i<10;$i++) { + $this->redis->set($str_uniq . "::$i", "bar::$i"); + } + + // Scan just these keys using a pattern match + $it = NULL; + while($arr_keys = $this->redis->scan($it, "*$str_uniq*")) { + $i -= count($arr_keys); + } + $this->assertEquals(0, $i); + } + + public function testHScan() { + if(version_compare($this->version, "2.8.0", "lt")) { + $this->markTestSkipped(); + return; + } + + // Never get empty sets + $this->redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); + + $this->redis->del('hash'); + $i_foo_mems = 0; + + for($i=0;$i<100;$i++) { + if($i>3) { + $this->redis->hset('hash', "member:$i", "value:$i"); + } else { + $this->redis->hset('hash', "foomember:$i", "value:$i"); + $i_foo_mems++; + } + } + + // Scan all of them + $it = NULL; + while($arr_keys = $this->redis->hscan('hash', $it)) { + $i -= count($arr_keys); + } + $this->assertEquals(0, $i); + + // Scan just *foomem* (should be 4) + $it = NULL; + while($arr_keys = $this->redis->hscan('hash', $it, '*foomember*')) { + $i_foo_mems -= count($arr_keys); + foreach($arr_keys as $str_mem => $str_val) { + $this->assertTrue(strpos($str_mem, 'member')!==FALSE); + $this->assertTrue(strpos($str_val, 'value')!==FALSE); + } + } + $this->assertEquals(0, $i_foo_mems); + } + + public function testSScan() { + if(version_compare($this->version, "2.8.0", "lt")) { + $this->markTestSkipped(); + return; + } + + $this->redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); + + $this->redis->del('set'); + for($i=0;$i<100;$i++) { + $this->redis->sadd('set', "member:$i"); + } + + // Scan all of them + $it = NULL; + while($arr_keys = $this->redis->sscan('set', $it)) { + $i -= count($arr_keys); + foreach($arr_keys as $str_mem) { + $this->assertTrue(strpos($str_mem,'member')!==FALSE); + } + } + $this->assertEquals(0, $i); + + // Scan just ones with zero in them (0, 10, 20, 30, 40, 50, 60, 70, 80, 90) + $it = NULL; + $i_w_zero = 0; + while($arr_keys = $this->redis->sscan('set', $it, '*0*')) { + $i_w_zero += count($arr_keys); + } + $this->assertEquals(10, $i_w_zero); + } + + public function testZScan() { + if(version_compare($this->version, "2.8.0", "lt")) { + $this->markTestSkipped(); + return; + } + + $this->redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); + + $this->redis->del('zset'); + $i_tot_score = 0; + $i_p_score = 0; + $i_p_count = 0; + for($i=0;$i<2000;$i++) { + if($i<10) { + $this->redis->zadd('zset', $i, "pmem:$i"); + $i_p_score += $i; + $i_p_count += 1; + } else { + $this->redis->zadd('zset', $i, "mem:$i"); + } + + $i_tot_score += $i; + } + + // Scan them all + $it = NULL; + while($arr_keys = $this->redis->zscan('zset', $it)) { + foreach($arr_keys as $str_mem => $f_score) { + $i_tot_score -= $f_score; + $i--; + } + } + $this->assertEquals(0, $i); + $this->assertEquals(0, $i_tot_score); + + // Just scan "pmem" members + $it = NULL; + $i_p_score_old = $i_p_score; + $i_p_count_old = $i_p_count; + while($arr_keys = $this->redis->zscan('zset', $it, "*pmem*")) { + foreach($arr_keys as $str_mem => $f_score) { + $i_p_score -= $f_score; + $i_p_count -= 1; + } + } + $this->assertEquals(0, $i_p_score); + $this->assertEquals(0, $i_p_count); + + // Turn off retrying and we should get some empty results + $this->redis->setOption(Redis::OPT_SCAN, Redis::SCAN_NORETRY); + $i_skips = 0; + $i_p_score = $i_p_score_old; + $i_p_count = $i_p_count_old; + $it = NULL; + while(($arr_keys = $this->redis->zscan('zset', $it, "*pmem*")) !== FALSE) { + if(count($arr_keys) == 0) $i_skips++; + foreach($arr_keys as $str_mem => $f_score) { + $i_p_score -= $f_score; + $i_p_count -= 1; + } + } + // We should still get all the keys, just with several empty results + $this->assertTrue($i_skips > 0); + $this->assertEquals(0, $i_p_score); + $this->assertEquals(0, $i_p_count); + } } exit(TestSuite::run("Redis_Test")); From 566d673f83170e9f5a49d8f072c8e5e0a1c8d6b1 Mon Sep 17 00:00:00 2001 From: vostok4 Date: Wed, 9 Apr 2014 11:21:32 +0200 Subject: [PATCH 5/5] Fix comments for C89 compatibility --- redis.c | 538 +++++++++++++++++++++++++------------------------- redis_array.c | 4 +- 2 files changed, 271 insertions(+), 271 deletions(-) diff --git a/redis.c b/redis.c index b565069d..1158e2a2 100644 --- a/redis.c +++ b/redis.c @@ -413,7 +413,7 @@ PHP_REDIS_API int redis_sock_get(zval *id, RedisSock **redis_sock TSRMLS_DC, int if (Z_TYPE_P(id) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(id), "socket", sizeof("socket"), (void **) &socket) == FAILURE) { - // Throw an exception unless we've been requested not to + /* Throw an exception unless we've been requested not to */ if(!no_throw) { zend_throw_exception(redis_exception_ce, "Redis server went away", 0 TSRMLS_CC); } @@ -423,7 +423,7 @@ PHP_REDIS_API int redis_sock_get(zval *id, RedisSock **redis_sock TSRMLS_DC, int *redis_sock = (RedisSock *) zend_list_find(Z_LVAL_PP(socket), &resource_type); if (!*redis_sock || resource_type != le_redis_sock) { - // Throw an exception unless we've been requested not to + /* Throw an exception unless we've been requested not to */ if(!no_throw) { zend_throw_exception(redis_exception_ce, "Redis server went away", 0 TSRMLS_CC); } @@ -448,14 +448,14 @@ PHP_REDIS_API RedisSock *redis_sock_get_connected(INTERNAL_FUNCTION_PARAMETERS) zval *object; RedisSock *redis_sock; - // If we can't grab our object, or get a socket, or we're not connected, return NULL + /* If we can't grab our object, or get a socket, or we're not connected, return NULL */ if((zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, redis_ce) == FAILURE) || (redis_sock_get(object, &redis_sock TSRMLS_CC, 1) < 0) || redis_sock->status != REDIS_SOCK_STATUS_CONNECTED) { return NULL; } - // Return our socket + /* Return our socket */ return redis_sock; } @@ -593,14 +593,14 @@ PHP_METHOD(Redis,__destruct) { RETURN_FALSE; } - // Grab our socket + /* Grab our socket */ if (redis_sock_get(getThis(), &redis_sock TSRMLS_CC, 1) < 0) { RETURN_FALSE; } - // If we think we're in MULTI mode, send a discard + /* If we think we're in MULTI mode, send a discard */ if(redis_sock->mode == MULTI) { - // Discard any multi commands, and free any callbacks that have been queued + /* Discard any multi commands, and free any callbacks that have been queued */ send_discard_static(redis_sock TSRMLS_CC); free_reply_callbacks(getThis(), redis_sock); } @@ -847,15 +847,15 @@ PHP_METHOD(Redis, bitpos) RETURN_FALSE; } - // We can prevalidate the first argument + /* We can prevalidate the first argument */ if(bit != 0 && bit != 1) { RETURN_FALSE; } - // Prefix our key + /* Prefix our key */ key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); - // Various command semantics + /* Various command semantics */ if(argc == 2) { cmd_len = redis_cmd_format_static(&cmd, "BITPOS", "sd", key, key_len, bit); @@ -867,7 +867,7 @@ PHP_METHOD(Redis, bitpos) bit, start, end); } - // Free our key if it was prefixed + /* Free our key if it was prefixed */ if(key_free) efree(key); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -912,7 +912,7 @@ PHP_METHOD(Redis, set) { int val_free = 0, key_free = 0; zval *z_value, *z_opts = NULL; - // Make sure the arguments are correct + /* Make sure the arguments are correct */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Osz|z", &object, redis_ce, &key, &key_len, &z_value, &z_opts) == FAILURE) @@ -920,7 +920,7 @@ PHP_METHOD(Redis, set) { RETURN_FALSE; } - // Ensure we can grab our redis socket + /* Ensure we can grab our redis socket */ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } @@ -950,7 +950,7 @@ PHP_METHOD(Redis, set) { zend_hash_has_more_elements(kt) == SUCCESS; zend_hash_move_forward(kt)) { - // Grab key and value + /* Grab key and value */ type = zend_hash_get_current_key_ex(kt, &k, &ht_key_len, &idx, 0, NULL); zend_hash_get_current_data(kt, (void**)&v); @@ -1421,7 +1421,7 @@ PHP_METHOD(Redis, incrByFloat) { RETURN_FALSE; } - // Prefix key, format command, free old key if necissary + /* Prefix key, format command, free old key if necissary */ key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); cmd_len = redis_cmd_format_static(&cmd, "INCRBYFLOAT", "sf", key, key_len, val); if(key_free) efree(key); @@ -1490,29 +1490,29 @@ PHP_METHOD(Redis, getMultiple) smart_str cmd = {0}; int arg_count; - // Make sure we have proper arguments + /* Make sure we have proper arguments */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oa", &object, redis_ce, &z_args) == FAILURE) { RETURN_FALSE; } - // We'll need the socket + /* We'll need the socket */ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } - // Grab our array + /* Grab our array */ hash = Z_ARRVAL_P(z_args); - // We don't need to do anything if there aren't any keys + /* We don't need to do anything if there aren't any keys */ if((arg_count = zend_hash_num_elements(hash)) == 0) { RETURN_FALSE; } - // Build our command header + /* Build our command header */ redis_cmd_init_sstr(&cmd, arg_count, "MGET", 4); - // Iterate through and grab our keys + /* Iterate through and grab our keys */ for(zend_hash_internal_pointer_reset_ex(hash, &ptr); zend_hash_get_current_data_ex(hash, (void**)&z_ele, &ptr) == SUCCESS; zend_hash_move_forward_ex(hash, &ptr)) @@ -1521,7 +1521,7 @@ PHP_METHOD(Redis, getMultiple) int key_len, key_free; zval *z_tmp = NULL; - // If the key isn't a string, turn it into one + /* If the key isn't a string, turn it into one */ if(Z_TYPE_PP(z_ele) == IS_STRING) { key = Z_STRVAL_PP(z_ele); key_len = Z_STRLEN_PP(z_ele); @@ -1535,16 +1535,16 @@ PHP_METHOD(Redis, getMultiple) key_len = Z_STRLEN_P(z_tmp); } - // Apply key prefix if necissary + /* Apply key prefix if necissary */ key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); - // Append this key to our command + /* Append this key to our command */ redis_cmd_append_sstr(&cmd, key, key_len); - // Free our key if it was prefixed + /* Free our key if it was prefixed */ if(key_free) efree(key); - // Free oour temporary ZVAL if we converted from a non-string + /* Free oour temporary ZVAL if we converted from a non-string */ if(z_tmp) { zval_dtor(z_tmp); efree(z_tmp); @@ -1552,7 +1552,7 @@ PHP_METHOD(Redis, getMultiple) } } - // Kick off our command + /* Kick off our command */ REDIS_PROCESS_REQUEST(redis_sock, cmd.c, cmd.len); IF_ATOMIC() { if(redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, @@ -1830,7 +1830,7 @@ PHP_METHOD(Redis, getBit) RETURN_FALSE; } - // GETBIT and SETBIT only work for 0 - 2^32-1 + /* GETBIT and SETBIT only work for 0 - 2^32-1 */ if(offset < BITOP_MIN_OFFSET || offset > BITOP_MAX_OFFSET) { RETURN_FALSE; } @@ -1864,7 +1864,7 @@ PHP_METHOD(Redis, setBit) RETURN_FALSE; } - // GETBIT and SETBIT only work for 0 - 2^32-1 + /* GETBIT and SETBIT only work for 0 - 2^32-1 */ if(offset < BITOP_MIN_OFFSET || offset > BITOP_MAX_OFFSET) { RETURN_FALSE; } @@ -2417,37 +2417,37 @@ PHP_METHOD(Redis, sRandMember) int key_len, cmd_len, key_free = 0; long count; - // Parse our params + /* Parse our params */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|l", &object, redis_ce, &key, &key_len, &count) == FAILURE) { RETURN_FALSE; } - // Get our redis socket + /* Get our redis socket */ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } - // Prefix our key if necissary + /* Prefix our key if necissary */ key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); - // If we have two arguments, we're running with an optional COUNT, which will return - // a multibulk reply. Without the argument we'll return a string response + /* If we have two arguments, we're running with an optional COUNT, which will return */ + /* a multibulk reply. Without the argument we'll return a string response */ if(ZEND_NUM_ARGS() == 2) { - // Construct our command with count + /* Construct our command with count */ cmd_len = redis_cmd_format_static(&cmd, "SRANDMEMBER", "sl", key, key_len, count); } else { - // Construct our command + /* Construct our command */ cmd_len = redis_cmd_format_static(&cmd, "SRANDMEMBER", "s", key, key_len); } - // Free our key if we prefixed it + /* Free our key if we prefixed it */ if(key_free) efree(key); - // Process our command + /* Process our command */ REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); - // Either bulk or multi-bulk depending on argument count + /* Either bulk or multi-bulk depending on argument count */ if(ZEND_NUM_ARGS() == 2) { IF_ATOMIC() { if(redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, @@ -2655,7 +2655,7 @@ PHP_REDIS_API int generic_multiple_args_cmd(INTERNAL_FUNCTION_PARAMETERS, char * } if(has_timeout) { keys_len[j] = spprintf(&keys[j], 0, "%d", timeout); - cmd_len += 1 + integer_length(keys_len[j]) + 2 + keys_len[j] + 2; // $ + size + NL + string + NL + cmd_len += 1 + integer_length(keys_len[j]) + 2 + keys_len[j] + 2; /* $ + size + NL + string + NL */ j++; real_argc++; } @@ -2685,7 +2685,7 @@ PHP_REDIS_API int generic_multiple_args_cmd(INTERNAL_FUNCTION_PARAMETERS, char * keys[j] = Z_STRVAL_P(z_args[i]); keys_len[j] = Z_STRLEN_P(z_args[i]); - // If we have a timeout it should be the last argument, which we do not want to prefix + /* If we have a timeout it should be the last argument, which we do not want to prefix */ if(!has_timeout || i < argc-1) { keys_to_free[j] = redis_key_prefix(redis_sock, &keys[j], &keys_len[j] TSRMLS_CC); /* add optional prefix TSRMLS_CC*/ } @@ -2697,7 +2697,7 @@ PHP_REDIS_API int generic_multiple_args_cmd(INTERNAL_FUNCTION_PARAMETERS, char * } } - cmd_len += 1 + integer_length(real_argc+1) + 2; // *count NL + cmd_len += 1 + integer_length(real_argc+1) + 2; /* *count NL */ cmd = emalloc(cmd_len+1); sprintf(cmd, "*%d" _NL "$%d" _NL "%s" _NL, 1+real_argc, keyword_len, keyword); @@ -2708,7 +2708,7 @@ PHP_REDIS_API int generic_multiple_args_cmd(INTERNAL_FUNCTION_PARAMETERS, char * /* copy each key to its destination */ for(i = 0; i < real_argc; ++i) { - sprintf(cmd + pos, "$%d" _NL, keys_len[i]); // size + sprintf(cmd + pos, "$%d" _NL, keys_len[i]); /* size */ pos += 1 + integer_length(keys_len[i]) + 2; memcpy(cmd + pos, keys[i], keys_len[i]); pos += keys_len[i]; @@ -2953,7 +2953,7 @@ PHP_METHOD(Redis, sort) { , Z_STRLEN_PP(z_cur), Z_STRVAL_PP(z_cur), Z_STRLEN_PP(z_cur)); elements += 2; efree(old_cmd); - } else if(Z_TYPE_PP(z_cur) == IS_ARRAY) { // loop over the strings in that array and add them as patterns + } else if(Z_TYPE_PP(z_cur) == IS_ARRAY) { /* loop over the strings in that array and add them as patterns */ HashTable *keytable = Z_ARRVAL_PP(z_cur); for(zend_hash_internal_pointer_reset(keytable); @@ -3005,7 +3005,7 @@ PHP_METHOD(Redis, sort) { if(zend_hash_num_elements(Z_ARRVAL_PP(z_cur)) == 2) { zval **z_offset_pp, **z_count_pp; - // get the two values from the table, check that they are indeed of LONG type + /* get the two values from the table, check that they are indeed of LONG type */ if(SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(z_cur), 0, (void**)&z_offset_pp) && SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(z_cur), 1, (void**)&z_count_pp)) { @@ -3105,7 +3105,7 @@ PHP_REDIS_API void generic_sort_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sort, in cmd_lines[2] = estrdup("SORT"); cmd_sizes[2] = 4; - // Prefix our key if we need to + /* Prefix our key if we need to */ key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); /* second line, key */ @@ -3115,7 +3115,7 @@ PHP_REDIS_API void generic_sort_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sort, in cmd_lines[4][key_len] = 0; cmd_sizes[4] = key_len; - // If we prefixed our key, free it + /* If we prefixed our key, free it */ if(key_free) efree(key); cmd_elements = 5; @@ -3505,7 +3505,7 @@ PHP_METHOD(Redis, auth) { cmd_len = redis_cmd_format_static(&cmd, "AUTH", "s", password, password_len); - // Free previously stored auth if we have one, and store this password + /* Free previously stored auth if we have one, and store this password */ if(redis_sock->auth) efree(redis_sock->auth); redis_sock->auth = estrndup(password, password_len); @@ -3607,7 +3607,7 @@ PHP_METHOD(Redis, info) { RETURN_FALSE; } - // Build a standalone INFO command or one with an option + /* Build a standalone INFO command or one with an option */ if(opt != NULL) { cmd_len = redis_cmd_format_static(&cmd, "INFO", "s", opt, opt_len); } else { @@ -3706,7 +3706,7 @@ generic_mset(INTERNAL_FUNCTION_PARAMETERS, char *kw, void (*fun)(INTERNAL_FUNCTI char *cmd = NULL, *p = NULL; int cmd_len = 0, argc = 0, kw_len = strlen(kw); - int step = 0; // 0: compute size; 1: copy strings. + int step = 0; /* 0: compute size; 1: copy strings. */ zval *z_array; HashTable *keytable; @@ -3753,14 +3753,14 @@ generic_mset(INTERNAL_FUNCTION_PARAMETERS, char *kw, void (*fun)(INTERNAL_FUNCTI continue; /* this should never happen, according to the PHP people. */ } - // If the key isn't a string, use the index value returned when grabbing the - // key. We typecast to long, because they could actually be negative. + /* If the key isn't a string, use the index value returned when grabbing the */ + /* key. We typecast to long, because they could actually be negative. */ if(type != HASH_KEY_IS_STRING) { - // Create string representation of our index + /* Create string representation of our index */ key_len = snprintf(buf, sizeof(buf), "%ld", (long)idx); key = (char*)buf; } else if(key_len > 0) { - // When not an integer key, the length will include the \0 + /* When not an integer key, the length will include the \0 */ key_len--; } @@ -3916,7 +3916,7 @@ PHP_METHOD(Redis, zAdd) { /* need key, score, value, [score, value...] */ if(argc > 1) { - convert_to_string(z_args[0]); // required string + convert_to_string(z_args[0]); /* required string */ } if(argc < 3 || Z_TYPE_P(z_args[0]) != IS_STRING || (argc-1) % 2 != 0) { efree(z_args); @@ -3948,8 +3948,8 @@ PHP_METHOD(Redis, zAdd) { smart_str_appendl(&buf, _NL, sizeof(_NL) - 1); for(i = 1; i < argc; i +=2) { - convert_to_double(z_args[i]); // convert score to double - val_free = redis_serialize(redis_sock, z_args[i+1], &val, &val_len TSRMLS_CC); // possibly serialize value. + convert_to_double(z_args[i]); /* convert score to double */ + val_free = redis_serialize(redis_sock, z_args[i+1], &val, &val_len TSRMLS_CC); /* possibly serialize value. */ /* add score */ score = Z_DVAL_P(z_args[i]); @@ -4203,7 +4203,7 @@ redis_generic_zrange_by_score(INTERNAL_FUNCTION_PARAMETERS, char *keyword) { if(zend_hash_find(Z_ARRVAL_P(z_options), "limit", sizeof("limit"), (void**)&z_limit_val_pp)== SUCCESS) {; if(zend_hash_num_elements(Z_ARRVAL_PP(z_limit_val_pp)) == 2) { zval **z_offset_pp, **z_count_pp; - // get the two values from the table, check that they are indeed of LONG type + /* get the two values from the table, check that they are indeed of LONG type */ if(SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(z_limit_val_pp), 0, (void**)&z_offset_pp) && SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(z_limit_val_pp), 1, (void**)&z_count_pp) && Z_TYPE_PP(z_offset_pp) == IS_LONG && @@ -4476,7 +4476,7 @@ PHP_REDIS_API void generic_z_command(INTERNAL_FUNCTION_PARAMETERS, char *command char *store_key, *agg_op = NULL; int cmd_arg_count = 2, store_key_len, agg_op_len = 0, keys_count, key_free; - // Grab our parameters + /* Grab our parameters */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Osa|a!s", &object, redis_ce, &store_key, &store_key_len, &z_keys, &z_weights, &agg_op, &agg_op_len) == FAILURE) @@ -4484,40 +4484,40 @@ PHP_REDIS_API void generic_z_command(INTERNAL_FUNCTION_PARAMETERS, char *command RETURN_FALSE; } - // We'll need our socket + /* We'll need our socket */ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } - // Grab our keys argument as an array + /* Grab our keys argument as an array */ ht_keys = Z_ARRVAL_P(z_keys); - // Nothing to do if there aren't any keys + /* Nothing to do if there aren't any keys */ if((keys_count = zend_hash_num_elements(ht_keys)) == 0) { RETURN_FALSE; } else { - // Increment our overall argument count + /* Increment our overall argument count */ cmd_arg_count += keys_count; } - // Grab and validate our weights array + /* Grab and validate our weights array */ if(z_weights != NULL) { ht_weights = Z_ARRVAL_P(z_weights); - // This command is invalid if the weights array isn't the same size - // as our keys array. + /* This command is invalid if the weights array isn't the same size */ + /* as our keys array. */ if(zend_hash_num_elements(ht_weights) != keys_count) { RETURN_FALSE; } - // Increment our overall argument count by the number of keys - // plus one, for the "WEIGHTS" argument itself + /* Increment our overall argument count by the number of keys */ + /* plus one, for the "WEIGHTS" argument itself */ cmd_arg_count += keys_count + 1; } - // AGGREGATE option + /* AGGREGATE option */ if(agg_op_len != 0) { - // Verify our aggregation option + /* Verify our aggregation option */ if(strncasecmp(agg_op, "SUM", sizeof("SUM")) && strncasecmp(agg_op, "MIN", sizeof("MIN")) && strncasecmp(agg_op, "MAX", sizeof("MAX"))) @@ -4525,22 +4525,22 @@ PHP_REDIS_API void generic_z_command(INTERNAL_FUNCTION_PARAMETERS, char *command RETURN_FALSE; } - // Two more arguments: "AGGREGATE" and agg_op + /* Two more arguments: "AGGREGATE" and agg_op */ cmd_arg_count += 2; } - // Command header + /* Command header */ redis_cmd_init_sstr(&cmd, cmd_arg_count, command, command_len); - // Prefix our key if necessary and add the output key + /* Prefix our key if necessary and add the output key */ key_free = redis_key_prefix(redis_sock, &store_key, &store_key_len TSRMLS_CC); redis_cmd_append_sstr(&cmd, store_key, store_key_len); if(key_free) efree(store_key); - // Number of input keys argument + /* Number of input keys argument */ redis_cmd_append_sstr_int(&cmd, keys_count); - // Process input keys + /* Process input keys */ for(zend_hash_internal_pointer_reset_ex(ht_keys, &ptr); zend_hash_get_current_data_ex(ht_keys, (void**)&z_data, &ptr)==SUCCESS; zend_hash_move_forward_ex(ht_keys, &ptr)) @@ -4561,16 +4561,16 @@ PHP_REDIS_API void generic_z_command(INTERNAL_FUNCTION_PARAMETERS, char *command key_len = Z_STRLEN_P(z_tmp); } - // Apply key prefix if necessary + /* Apply key prefix if necessary */ key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); - // Append this input set + /* Append this input set */ redis_cmd_append_sstr(&cmd, key, key_len); - // Free our key if it was prefixed + /* Free our key if it was prefixed */ if(key_free) efree(key); - // Free our temporary z_val if it was converted + /* Free our temporary z_val if it was converted */ if(z_tmp) { zval_dtor(z_tmp); efree(z_tmp); @@ -4578,29 +4578,29 @@ PHP_REDIS_API void generic_z_command(INTERNAL_FUNCTION_PARAMETERS, char *command } } - // Weights + /* Weights */ if(ht_weights != NULL) { - // Append "WEIGHTS" argument + /* Append "WEIGHTS" argument */ redis_cmd_append_sstr(&cmd, "WEIGHTS", sizeof("WEIGHTS") - 1); - // Process weights + /* Process weights */ for(zend_hash_internal_pointer_reset_ex(ht_weights, &ptr); zend_hash_get_current_data_ex(ht_weights, (void**)&z_data, &ptr)==SUCCESS; zend_hash_move_forward_ex(ht_weights, &ptr)) { - // Ignore non numeric arguments, unless they're special Redis numbers + /* Ignore non numeric arguments, unless they're special Redis numbers */ if (Z_TYPE_PP(z_data) != IS_LONG && Z_TYPE_PP(z_data) != IS_DOUBLE && strncasecmp(Z_STRVAL_PP(z_data), "inf", sizeof("inf")) != 0 && strncasecmp(Z_STRVAL_PP(z_data), "-inf", sizeof("-inf")) != 0 && strncasecmp(Z_STRVAL_PP(z_data), "+inf", sizeof("+inf")) != 0) { - // We should abort if we have an invalid weight, rather than pass - // a different number of weights than the user is expecting + /* We should abort if we have an invalid weight, rather than pass */ + /* a different number of weights than the user is expecting */ efree(cmd.c); RETURN_FALSE; } - // Append the weight based on the input type + /* Append the weight based on the input type */ switch(Z_TYPE_PP(z_data)) { case IS_LONG: redis_cmd_append_sstr_long(&cmd, Z_LVAL_PP(z_data)); @@ -4615,13 +4615,13 @@ PHP_REDIS_API void generic_z_command(INTERNAL_FUNCTION_PARAMETERS, char *command } } - // Aggregation options, if we have them + /* Aggregation options, if we have them */ if(agg_op_len != 0) { redis_cmd_append_sstr(&cmd, "AGGREGATE", sizeof("AGGREGATE") - 1); redis_cmd_append_sstr(&cmd, agg_op, agg_op_len); } - // Kick off our request + /* Kick off our request */ REDIS_PROCESS_REQUEST(redis_sock, cmd.c, cmd.len); IF_ATOMIC() { redis_long_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL); @@ -4964,14 +4964,14 @@ PHP_METHOD(Redis, hIncrByFloat) int key_len, member_len, cmd_len, key_free; double val; - // Validate we have the right number of arguments + /* Validate we have the right number of arguments */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ossd", &object, redis_ce, &key, &key_len, &member, &member_len, &val) == FAILURE) { RETURN_FALSE; } - // Grab our socket + /* Grab our socket */ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } @@ -5040,7 +5040,7 @@ PHP_METHOD(Redis, hMget) { HashPosition ptr; smart_str cmd = {0}; - // Make sure we can grab our arguments properly + /* Make sure we can grab our arguments properly */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Osa", &object, redis_ce, &key, &key_len, &z_array) == FAILURE) @@ -5048,68 +5048,68 @@ PHP_METHOD(Redis, hMget) { RETURN_FALSE; } - // We'll need our socket + /* We'll need our socket */ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } - // Grab member count and abort if we don't have any + /* Grab member count and abort if we don't have any */ if((field_count = zend_hash_num_elements(Z_ARRVAL_P(z_array))) == 0) { RETURN_FALSE; } - // Prefix our key if we need to + /* Prefix our key if we need to */ key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); - // Allocate enough memory for the number of keys being requested + /* Allocate enough memory for the number of keys being requested */ z_keys = ecalloc(field_count, sizeof(zval *)); - // Grab our HashTable + /* Grab our HashTable */ ht_array = Z_ARRVAL_P(z_array); - // Iterate through our keys, grabbing members that are valid + /* Iterate through our keys, grabbing members that are valid */ for(valid=0, zend_hash_internal_pointer_reset_ex(ht_array, &ptr); zend_hash_get_current_data_ex(ht_array, (void**)&data, &ptr)==SUCCESS; zend_hash_move_forward_ex(ht_array, &ptr)) { - // Make sure the data is a long or string, and if it's a string that - // it isn't empty. There is no reason to send empty length members. + /* Make sure the data is a long or string, and if it's a string that */ + /* it isn't empty. There is no reason to send empty length members. */ if((Z_TYPE_PP(data) == IS_STRING && Z_STRLEN_PP(data)>0) || Z_TYPE_PP(data) == IS_LONG) { - // This is a key we can ask for, copy it and set it in our array + /* This is a key we can ask for, copy it and set it in our array */ MAKE_STD_ZVAL(z_keys[valid]); *z_keys[valid] = **data; zval_copy_ctor(z_keys[valid]); convert_to_string(z_keys[valid]); - // Increment the number of valid keys we've encountered + /* Increment the number of valid keys we've encountered */ valid++; } } - // If we don't have any valid keys, we can abort here + /* If we don't have any valid keys, we can abort here */ if(valid == 0) { if(key_free) efree(key); efree(z_keys); RETURN_FALSE; } - // Build command header. One extra argument for the hash key itself + /* Build command header. One extra argument for the hash key itself */ redis_cmd_init_sstr(&cmd, valid+1, "HMGET", sizeof("HMGET")-1); - // Add the hash key + /* Add the hash key */ redis_cmd_append_sstr(&cmd, key, key_len); - // Free key memory if it was prefixed + /* Free key memory if it was prefixed */ if(key_free) efree(key); - // Iterate our keys, appending them as arguments + /* Iterate our keys, appending them as arguments */ for(i=0;i 0) { - // Header for our EVAL command + /* Header for our EVAL command */ cmd_len = redis_cmd_format_header(ret, keyword, eval_cmd_count + args_count); - // Now append the script itself, and the number of arguments to treat as keys + /* Now append the script itself, and the number of arguments to treat as keys */ cmd_len = redis_cmd_append_str(ret, cmd_len, value, val_len); cmd_len = redis_cmd_append_int(ret, cmd_len, keys_count); - // Iterate the values in our "keys" array + /* Iterate the values in our "keys" array */ for(zend_hash_internal_pointer_reset_ex(args_hash, &hash_pos); zend_hash_get_current_data_ex(args_hash, (void **)&elem, &hash_pos) == SUCCESS; zend_hash_move_forward_ex(args_hash, &hash_pos)) @@ -6338,7 +6338,7 @@ redis_build_eval_cmd(RedisSock *redis_sock, char **ret, char *keyword, char *val key = Z_STRVAL_PP(elem); key_len = Z_STRLEN_PP(elem); } else { - // Convert it to a string + /* Convert it to a string */ MAKE_STD_ZVAL(z_tmp); *z_tmp = **elem; zval_copy_ctor(z_tmp); @@ -6348,20 +6348,20 @@ redis_build_eval_cmd(RedisSock *redis_sock, char **ret, char *keyword, char *val key_len = Z_STRLEN_P(z_tmp); } - // Keep track of the old command pointer + /* Keep track of the old command pointer */ old_cmd = *ret; - // If this is still a key argument, prefix it if we've been set up to prefix keys + /* If this is still a key argument, prefix it if we've been set up to prefix keys */ key_free = keys_count-- > 0 ? redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC) : 0; - // Append this key to our EVAL command, free our old command + /* Append this key to our EVAL command, free our old command */ cmd_len = redis_cmd_format(ret, "%s$%d" _NL "%s" _NL, *ret, cmd_len, key_len, key, key_len); efree(old_cmd); - // Free our key, old command if we need to + /* Free our key, old command if we need to */ if(key_free) efree(key); - // Free our temporary zval (converted from non string) if we've got one + /* Free our temporary zval (converted from non string) if we've got one */ if(z_tmp) { zval_dtor(z_tmp); efree(z_tmp); @@ -6370,12 +6370,12 @@ redis_build_eval_cmd(RedisSock *redis_sock, char **ret, char *keyword, char *val } } - // If there weren't any arguments (none passed, or an empty array), construct a standard no args command + /* If there weren't any arguments (none passed, or an empty array), construct a standard no args command */ if(args_count < 1) { cmd_len = redis_cmd_format_static(ret, keyword, "sd", value, val_len, 0); } - // Return our command length + /* Return our command length */ return cmd_len; } @@ -6394,12 +6394,12 @@ PHP_METHOD(Redis, evalsha) RETURN_FALSE; } - // Attempt to grab socket + /* Attempt to grab socket */ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } - // Construct our EVALSHA command + /* Construct our EVALSHA command */ cmd_len = redis_build_eval_cmd(redis_sock, &cmd, "EVALSHA", sha, sha_len, args, keys_count TSRMLS_CC); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -6421,18 +6421,18 @@ PHP_METHOD(Redis, eval) int script_len, cmd_len; long keys_count = 0; - // Attempt to parse parameters + /* Attempt to parse parameters */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|al", &object, redis_ce, &script, &script_len, &args, &keys_count) == FAILURE) { RETURN_FALSE; } - // Attempt to grab socket + /* Attempt to grab socket */ if (redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } - // Construct our EVAL command + /* Construct our EVAL command */ cmd_len = redis_build_eval_cmd(redis_sock, &cmd, "EVAL", script, script_len, args, keys_count TSRMLS_CC); REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); @@ -6446,23 +6446,23 @@ PHP_METHOD(Redis, eval) PHP_REDIS_API int redis_build_script_exists_cmd(char **ret, zval **argv, int argc) { - // Our command length and iterator + /* Our command length and iterator */ int cmd_len = 0, i; - // Start building our command - cmd_len = redis_cmd_format_header(ret, "SCRIPT", argc + 1); // +1 for "EXISTS" + /* Start building our command */ + cmd_len = redis_cmd_format_header(ret, "SCRIPT", argc + 1); /* +1 for "EXISTS" */ cmd_len = redis_cmd_append_str(ret, cmd_len, "EXISTS", 6); - // Iterate our arguments + /* Iterate our arguments */ for(i=0;iprefix != NULL && redis_sock->prefix_len > 0) { redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); RETURN_STRINGL(key, key_len, 0); @@ -6692,22 +6692,22 @@ PHP_METHOD(Redis, _serialize) { char *val; int val_len; - // Parse arguments + /* Parse arguments */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz", &object, redis_ce, &z_val) == FAILURE) { RETURN_FALSE; } - // Grab socket + /* Grab socket */ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } - // Serialize, which will return a value even if no serializer is set + /* Serialize, which will return a value even if no serializer is set */ redis_serialize(redis_sock, z_val, &val, &val_len TSRMLS_CC); - // Return serialized value. Tell PHP to make a copy as some can be interned. + /* Return serialized value. Tell PHP to make a copy as some can be interned. */ RETVAL_STRINGL(val, val_len, 1); STR_FREE(val); } @@ -6721,27 +6721,27 @@ PHP_METHOD(Redis, _unserialize) { char *value; int value_len; - // Parse our arguments + /* Parse our arguments */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &object, redis_ce, &value, &value_len) == FAILURE) { RETURN_FALSE; } - // Grab socket + /* Grab socket */ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } - // We only need to attempt unserialization if we have a serializer running + /* We only need to attempt unserialization if we have a serializer running */ if(redis_sock->serializer != REDIS_SERIALIZER_NONE) { zval *z_ret = NULL; if(redis_unserialize(redis_sock, value, value_len, &z_ret TSRMLS_CC) == 0) { - // Badly formed input, throw an execption + /* Badly formed input, throw an execption */ zend_throw_exception(redis_exception_ce, "Invalid serialized data, or unserialization error", 0 TSRMLS_CC); RETURN_FALSE; } RETURN_ZVAL(z_ret, 0, 1); } else { - // Just return the value that was passed to us + /* Just return the value that was passed to us */ RETURN_STRINGL(value, value_len, 1); } } @@ -6753,16 +6753,16 @@ PHP_METHOD(Redis, getLastError) { zval *object; RedisSock *redis_sock; - // Grab our object + /* Grab our object */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, redis_ce) == FAILURE) { RETURN_FALSE; } - // Grab socket + /* Grab socket */ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } - // Return our last error or NULL if we don't have one + /* Return our last error or NULL if we don't have one */ if(redis_sock->err != NULL && redis_sock->err_len > 0) { RETURN_STRINGL(redis_sock->err, redis_sock->err_len, 1); } else { @@ -6777,16 +6777,16 @@ PHP_METHOD(Redis, clearLastError) { zval *object; RedisSock *redis_sock; - // Grab our object + /* Grab our object */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, redis_ce) == FAILURE) { RETURN_FALSE; } - // Grab socket + /* Grab socket */ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } - // Clear error message + /* Clear error message */ if(redis_sock->err) { efree(redis_sock->err); } @@ -6805,19 +6805,19 @@ PHP_METHOD(Redis, time) { char *cmd; int cmd_len; - // Grab our object + /* Grab our object */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, redis_ce) == FAILURE) { RETURN_FALSE; } - // Grab socket + /* Grab socket */ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } - // Build TIME command + /* Build TIME command */ cmd_len = redis_cmd_format_static(&cmd, "TIME", ""); - // Execute or queue command + /* Execute or queue command */ REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); IF_ATOMIC() { if(redis_sock_read_multibulk_reply_raw(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL) < 0) { @@ -6864,7 +6864,7 @@ PHP_METHOD(Redis, getPort) { RedisSock *redis_sock; if((redis_sock = redis_sock_get_connected(INTERNAL_FUNCTION_PARAM_PASSTHRU))) { - // Return our port + /* Return our port */ RETURN_LONG(redis_sock->port); } else { RETURN_FALSE; @@ -6878,7 +6878,7 @@ PHP_METHOD(Redis, getDBNum) { RedisSock *redis_sock; if((redis_sock = redis_sock_get_connected(INTERNAL_FUNCTION_PARAM_PASSTHRU))) { - // Return our db number + /* Return our db number */ RETURN_LONG(redis_sock->dbNumber); } else { RETURN_FALSE; @@ -6957,19 +6957,19 @@ PHP_METHOD(Redis, client) { char *cmd, *opt=NULL, *arg=NULL; int cmd_len, opt_len, arg_len; - // Parse our method parameters + /* Parse our method parameters */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|s", &object, redis_ce, &opt, &opt_len, &arg, &arg_len) == FAILURE) { RETURN_FALSE; } - // Grab our socket + /* Grab our socket */ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } - // Build our CLIENT command + /* Build our CLIENT command */ if(ZEND_NUM_ARGS() == 2) { cmd_len = redis_cmd_format_static(&cmd, "CLIENT", "ss", opt, opt_len, arg, arg_len); @@ -6977,10 +6977,10 @@ PHP_METHOD(Redis, client) { cmd_len = redis_cmd_format_static(&cmd, "CLIENT", "s", opt, opt_len); } - // Execute our queue command + /* Execute our queue command */ REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); - // We handle CLIENT LIST with a custom response function + /* We handle CLIENT LIST with a custom response function */ if(!strncasecmp(opt, "list", 4)) { IF_ATOMIC() { redis_client_list_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,redis_sock,NULL); @@ -7004,11 +7004,11 @@ redis_build_scan_cmd(char **cmd, REDIS_SCAN_TYPE type, char *key, int key_len, char *keyword; int arg_count, cmd_len; - // 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. + /* 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. */ arg_count = 1 + (key_len>0) + (pattern_len>0?2:0) + (count>0?2:0); - // Turn our type into a keyword + /* Turn our type into a keyword */ switch(type) { case TYPE_SCAN: keyword = "SCAN"; @@ -7025,30 +7025,30 @@ redis_build_scan_cmd(char **cmd, REDIS_SCAN_TYPE type, char *key, int key_len, break; } - // Start the command + /* Start the command */ cmd_len = redis_cmd_format_header(cmd, keyword, arg_count); - // Add the key in question if we have one + /* Add the key in question if we have one */ if(key_len) { cmd_len = redis_cmd_append_str(cmd, cmd_len, key, key_len); } - // Add our iterator + /* Add our iterator */ cmd_len = redis_cmd_append_int(cmd, cmd_len, iter); - // Append COUNT if we've got it + /* Append COUNT if we've got it */ if(count) { cmd_len = redis_cmd_append_str(cmd, cmd_len, "COUNT", sizeof("COUNT")-1); cmd_len = redis_cmd_append_int(cmd, cmd_len, count); } - // Append MATCH if we've got it + /* Append MATCH if we've got it */ if(pattern_len) { cmd_len = redis_cmd_append_str(cmd, cmd_len, "MATCH", sizeof("MATCH")-1); cmd_len = redis_cmd_append_str(cmd, cmd_len, pattern, pattern_len); } - // Return our command length + /* Return our command length */ return cmd_len; } @@ -7064,9 +7064,9 @@ generic_scan_cmd(INTERNAL_FUNCTION_PARAMETERS, REDIS_SCAN_TYPE type) { int cmd_len, key_len=0, pattern_len=0, num_elements, key_free=0; long count=0, iter; - // Different prototype depending on if this is a key based scan + /* Different prototype depending on if this is a key based scan */ if(type != TYPE_SCAN) { - // Requires a key + /* Requires a key */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Osz/|s!l", &object, redis_ce, &key, &key_len, &z_iter, &pattern, &pattern_len, &count)==FAILURE) @@ -7074,7 +7074,7 @@ generic_scan_cmd(INTERNAL_FUNCTION_PARAMETERS, REDIS_SCAN_TYPE type) { RETURN_FALSE; } } else { - // Doesn't require a key + /* Doesn't require a key */ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz/|s!l", &object, redis_ce, &z_iter, &pattern, &pattern_len, &count) == FAILURE) @@ -7083,32 +7083,32 @@ generic_scan_cmd(INTERNAL_FUNCTION_PARAMETERS, REDIS_SCAN_TYPE type) { } } - // Grab our socket + /* Grab our socket */ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { RETURN_FALSE; } - // Calling this in a pipeline makes no sense + /* Calling this in a pipeline makes no sense */ IF_NOT_ATOMIC() { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can't call SCAN commands in multi or pipeline mode!"); RETURN_FALSE; } - // The iterator should be passed in as NULL for the first iteration, but we can treat - // any NON LONG value as NULL for these purposes as we've seperated the variable anyway. + /* The iterator should be passed in as NULL for the first iteration, but we can treat */ + /* any NON LONG value as NULL for these purposes as we've seperated the variable anyway. */ if(Z_TYPE_P(z_iter) != IS_LONG || Z_LVAL_P(z_iter)<0) { - // Convert to long + /* Convert to long */ convert_to_long(z_iter); iter = 0; } else if(Z_LVAL_P(z_iter)!=0) { - // Update our iterator value for the next passthru + /* Update our iterator value for the next passthru */ iter = Z_LVAL_P(z_iter); } else { - // We're done, back to iterator zero + /* We're done, back to iterator zero */ RETURN_FALSE; } - // Prefix our key if we've got one and we have a prefix set + /* 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 TSRMLS_CC); } @@ -7121,11 +7121,11 @@ generic_scan_cmd(INTERNAL_FUNCTION_PARAMETERS, REDIS_SCAN_TYPE type) { * an updated iterator. */ do { - // Format our SCAN command + /* Format our SCAN command */ cmd_len = redis_build_scan_cmd(&cmd, type, key, key_len, (int)iter, pattern, pattern_len, count); - // Execute our command getting our new iterator value + /* Execute our command getting our new iterator value */ REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); if(redis_sock_read_scan_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,type,&iter)<0) @@ -7134,15 +7134,15 @@ generic_scan_cmd(INTERNAL_FUNCTION_PARAMETERS, REDIS_SCAN_TYPE type) { RETURN_FALSE; } - // Get the number of elements + /* Get the number of elements */ hash = Z_ARRVAL_P(return_value); num_elements = zend_hash_num_elements(hash); } while(redis_sock->scan == REDIS_SCAN_RETRY && iter != 0 && num_elements == 0); - // Free our key if it was prefixed + /* Free our key if it was prefixed */ if(key_free) efree(key); - // Update our iterator reference + /* Update our iterator reference */ Z_LVAL_P(z_iter) = iter; } diff --git a/redis_array.c b/redis_array.c index e9a56e7a..05f0c2e4 100644 --- a/redis_array.c +++ b/redis_array.c @@ -85,7 +85,7 @@ zend_function_entry redis_array_functions[] = { static void redis_array_free(RedisArray *ra) { int i; - // Redis objects + /* Redis objects */ for(i=0;icount;i++) { zval_dtor(ra->redis[i]); efree(ra->redis[i]); @@ -110,7 +110,7 @@ static void redis_array_free(RedisArray *ra) { zval_dtor(ra->z_pure_cmds); efree(ra->z_pure_cmds); - // Free structure itself + /* Free structure itself */ efree(ra); }