diff options
-rw-r--r-- | common.h | 12 | ||||
-rw-r--r-- | redis.c | 145 | ||||
-rw-r--r-- | redis_array_impl.c | 27 | ||||
-rw-r--r-- | redis_array_impl.h | 1 |
4 files changed, 110 insertions, 75 deletions
@@ -680,6 +680,18 @@ typedef struct { } RedisSock; /* }}} */ +#if (PHP_MAJOR_VERSION < 7) +typedef struct { + zend_object std; + RedisSock *sock; +} redis_object; +#else +typedef struct { + RedisSock *sock; + zend_object std; +} redis_object; +#endif + void free_reply_callbacks(zval *z_this, RedisSock *redis_sock); @@ -42,8 +42,6 @@ #define R_SUB_CALLBACK_FT_TYPE 2 #define R_SUB_CLOSURE_TYPE 3 -int le_redis_sock; - #ifdef PHP_SESSION extern ps_module ps_mod_redis; extern ps_module ps_mod_redis_cluster; @@ -426,36 +424,90 @@ static int send_discard_static(RedisSock *redis_sock TSRMLS_DC) { return result; } -/** - * redis_destructor_redis_sock - */ -static void redis_destructor_redis_sock(zend_resource * rsrc TSRMLS_DC) +#if (PHP_MAJOR_VERSION < 7) +void +free_redis_object(void *object TSRMLS_DC) +{ + redis_object *redis = (redis_object *)object; + + zend_object_std_dtor(&redis->std TSRMLS_CC); + if (redis->sock) { + redis_sock_disconnect(redis->sock TSRMLS_CC); + redis_free_socket(redis->sock); + } + efree(redis); +} + +zend_object_value +create_redis_object(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + redis_object *redis = ecalloc(1, sizeof(redis_object)); + + memset(redis, 0, sizeof(redis_object)); + zend_object_std_init(&redis->std, ce TSRMLS_CC); + +#if PHP_VERSION_ID < 50399 + zval *tmp; + zend_hash_copy(redis->std.properties, &ce->default_properties, + (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *)); +#endif + + retval.handle = zend_objects_store_put(redis, + (zend_objects_store_dtor_t)zend_objects_destroy_object, + (zend_objects_free_object_storage_t)free_redis_object, + NULL TSRMLS_CC); + retval.handlers = zend_get_std_object_handlers(); + + return retval; +} +#else +zend_object_handlers redis_object_handlers; + +void +free_redis_object(zend_object *object) +{ + redis_object *redis = (redis_object *)((char *)(object) - XtOffsetOf(redis_object, std)); + + zend_object_std_dtor(&redis->std TSRMLS_CC); + if (redis->sock) { + redis_sock_disconnect(redis->sock TSRMLS_CC); + redis_free_socket(redis->sock); + } +} + +zend_object * +create_redis_object(zend_class_entry *ce TSRMLS_DC) { - RedisSock *redis_sock = (RedisSock *) rsrc->ptr; - redis_sock_disconnect(redis_sock TSRMLS_CC); - redis_free_socket(redis_sock); + redis_object *redis = ecalloc(1, sizeof(redis_object) + zend_object_properties_size(ce)); + + redis->sock = NULL; + + zend_object_std_init(&redis->std, ce TSRMLS_CC); + object_properties_init(&redis->std, ce); + + memcpy(&redis_object_handlers, zend_get_std_object_handlers(), sizeof(redis_object_handlers)); + redis_object_handlers.offset = XtOffsetOf(redis_object, std); + redis_object_handlers.free_obj = free_redis_object; + redis->std.handlers = &redis_object_handlers; + + return &redis->std; } +#endif static zend_always_inline int redis_sock_get_instance(zval *id, RedisSock **redis_sock TSRMLS_DC, int no_throw) { - zval *socket; - int resource_type = 0; + redis_object *redis; - if (Z_TYPE_P(id) == IS_OBJECT && - (socket = zend_hash_str_find(Z_OBJPROP_P(id), "socket", sizeof("socket") - 1)) != NULL - ) { + if (Z_TYPE_P(id) == IS_OBJECT) { #if (PHP_MAJOR_VERSION < 7) - *redis_sock = (RedisSock *)zend_list_find(Z_LVAL_P(socket), &resource_type); + redis = (redis_object *)zend_objects_get_address(id TSRMLS_CC); #else - *redis_sock = NULL; - - if (Z_RES_P(socket) != NULL) { - *redis_sock = (RedisSock *)Z_RES_P(socket)->ptr; - resource_type = Z_RES_P(socket)->type; - } + redis = (redis_object *)((char *)Z_OBJ_P(id) - XtOffsetOf(redis_object, std)); #endif - if (*redis_sock && resource_type == le_redis_sock) { + if (redis->sock) { + *redis_sock = redis->sock; return 0; } } @@ -580,6 +632,7 @@ PHP_MINIT_FUNCTION(redis) /* Redis class */ INIT_CLASS_ENTRY(redis_class_entry, "Redis", redis_functions); redis_ce = zend_register_internal_class(&redis_class_entry TSRMLS_CC); + redis_ce->create_object = create_redis_object; /* RedisArray class */ INIT_CLASS_ENTRY(redis_array_class_entry, "RedisArray", redis_array_functions); @@ -616,12 +669,6 @@ PHP_MINIT_FUNCTION(redis) #endif ); - le_redis_sock = zend_register_list_destructors_ex( - redis_destructor_redis_sock, - NULL, - redis_sock_name, module_number - ); - /* Add shared class constants to Redis and RedisCluster objects */ add_class_constants(redis_ce, 0 TSRMLS_CC); add_class_constants(redis_cluster_ce, 1 TSRMLS_CC); @@ -737,13 +784,15 @@ PHP_METHOD(Redis, pconnect) } /* }}} */ -PHP_REDIS_API int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) { - zval *object, *socket; +PHP_REDIS_API int +redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) +{ + zval *object; char *host = NULL, *persistent_id = NULL; zend_long port = -1, retry_interval = 0; strlen_t host_len, persistent_id_len; double timeout = 0.0; - RedisSock *redis_sock = NULL; + redis_object *redis; #ifdef ZTS /* not sure how in threaded mode this works so disabled persistence at @@ -779,40 +828,24 @@ PHP_REDIS_API int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) { port = 6379; } - /* if there is a redis sock already we have to remove it from the list */ - if (redis_sock_get(object, &redis_sock TSRMLS_CC, 1) >= 0) { - if ((socket = zend_hash_str_find(Z_OBJPROP_P(object), "socket", sizeof("socket") - 1)) == NULL) - { - /* maybe there is a socket but the id isn't known.. what to do? */ - } else { - /* The refcount should be decreased and destructor invoked */ #if (PHP_MAJOR_VERSION < 7) - zend_list_delete(Z_LVAL_P(socket)); + redis = (redis_object *)zend_objects_get_address(object TSRMLS_CC); #else - zend_list_close(Z_RES_P(socket)); + redis = (redis_object *)((char *)Z_OBJ_P(object) - XtOffsetOf(redis_object, std)); #endif - } + /* if there is a redis sock already we have to remove it */ + if (redis->sock) { + redis_sock_disconnect(redis->sock TSRMLS_CC); + redis_free_socket(redis->sock); } - redis_sock = redis_sock_create(host, host_len, port, timeout, persistent, + redis->sock = redis_sock_create(host, host_len, port, timeout, persistent, persistent_id, retry_interval, 0); - if (redis_sock_server_open(redis_sock, 1 TSRMLS_CC) < 0) { - redis_free_socket(redis_sock); + if (redis_sock_server_open(redis->sock, 1 TSRMLS_CC) < 0) { + redis_free_socket(redis->sock); return FAILURE; } -#if (PHP_MAJOR_VERSION < 7) - int id; -#if PHP_VERSION_ID >= 50400 - id = zend_list_insert(redis_sock, le_redis_sock TSRMLS_CC); -#else - id = zend_list_insert(redis_sock, le_redis_sock); -#endif - add_property_resource(object, "socket", id); -#else - zval *id = zend_list_insert(redis_sock, le_redis_sock TSRMLS_CC); - add_property_resource(object, "socket", Z_RES_P(id)); -#endif return SUCCESS; } diff --git a/redis_array_impl.c b/redis_array_impl.c index 860b44a8..01f586ca 100644 --- a/redis_array_impl.c +++ b/redis_array_impl.c @@ -26,7 +26,6 @@ #define PHPREDIS_INDEX_NAME "__phpredis_array_index__" -extern int le_redis_sock; extern zend_class_entry *redis_ce; RedisArray* @@ -36,7 +35,7 @@ ra_load_hosts(RedisArray *ra, HashTable *hosts, long retry_interval, zend_bool b char *host, *p; short port; zval *zpData, z_cons, z_ret; - RedisSock *redis_sock = NULL; + redis_object *redis; /* function calls on the Redis object */ ZVAL_STRINGL(&z_cons, "__construct", 11); @@ -72,29 +71,21 @@ 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); zval_dtor(&z_ret); +#if (PHP_MAJOR_VERSION < 7) + redis = (redis_object *)zend_objects_get_address(&ra->redis[i] TSRMLS_CC); +#else + redis = (redis_object *)((char *)Z_OBJ_P(&ra->redis[i]) - XtOffsetOf(redis_object, std)); +#endif + /* create socket */ - redis_sock = redis_sock_create(host, host_len, port, ra->connect_timeout, 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) { /* connect */ - redis_sock_server_open(redis_sock, 1 TSRMLS_CC); + redis_sock_server_open(redis->sock, 1 TSRMLS_CC); } - /* attach */ -#if (PHP_MAJOR_VERSION < 7) - int id; -#if PHP_VERSION_ID >= 50400 - id = zend_list_insert(redis_sock, le_redis_sock TSRMLS_CC); -#else - id = zend_list_insert(redis_sock, le_redis_sock); -#endif - add_property_resource(&ra->redis[i], "socket", id); -#else - zval *id = zend_list_insert(redis_sock, le_redis_sock TSRMLS_CC); - add_property_resource(&ra->redis[i], "socket", Z_RES_P(id)); -#endif - ra->count = ++i; } diff --git a/redis_array_impl.h b/redis_array_impl.h index db8d7aff..b3859869 100644 --- a/redis_array_impl.h +++ b/redis_array_impl.h @@ -7,7 +7,6 @@ #include <stdint.h> #endif -#include "common.h" #include "redis_array.h" RedisArray *ra_load_hosts(RedisArray *ra, HashTable *hosts, long retry_interval, zend_bool b_lazy_connect TSRMLS_DC); |