3232#include "redis_array.h"
3333#include "redis_array_impl.h"
3434
35+ /* Simple macro to detect failure in a RedisArray call */
36+ #define RA_CALL_FAILED (rv , cmd ) \
37+ ((Z_TYPE_P(rv) == IS_BOOL && Z_BVAL_P(rv) == 0) || \
38+ (Z_TYPE_P(rv) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(rv)) == 0) || \
39+ (Z_TYPE_P(rv) == IS_LONG && Z_LVAL_P(rv) == 0 && !strcasecmp(cmd, "TYPE"))) \
40+
3541extern zend_class_entry * redis_ce ;
3642zend_class_entry * redis_array_ce ;
3743
@@ -76,41 +82,48 @@ zend_function_entry redis_array_functions[] = {
7682 {NULL , NULL , NULL }
7783};
7884
79- int le_redis_array ;
80- void redis_destructor_redis_array (zend_rsrc_list_entry * rsrc TSRMLS_DC )
81- {
82- int i ;
83- RedisArray * ra = (RedisArray * )rsrc -> ptr ;
85+ static void redis_array_free (RedisArray * ra ) {
86+ int i ;
8487
85- /* delete Redis objects */
86- for (i = 0 ; i < ra -> count ; ++ i ) {
87- zval_dtor (ra -> redis [i ]);
88- efree (ra -> redis [i ]);
88+ // Redis objects
89+ for (i = 0 ;i < ra -> count ;i ++ ) {
90+ zval_dtor (ra -> redis [i ]);
91+ efree (ra -> redis [i ]);
92+ efree (ra -> hosts [i ]);
93+ }
94+ efree (ra -> redis );
95+ efree (ra -> hosts );
8996
90- /* remove host too */
91- efree (ra -> hosts [ i ]);
92- }
93- efree (ra -> redis );
94- efree ( ra -> hosts );
97+ /* delete hash function */
98+ if (ra -> z_fun ) {
99+ zval_dtor ( ra -> z_fun );
100+ efree (ra -> z_fun );
101+ }
95102
96- /* delete function */
97- if (ra -> z_fun ) {
98- zval_dtor (ra -> z_fun );
99- efree (ra -> z_fun );
100- }
103+ /* Distributor */
104+ if (ra -> z_dist ) {
105+ zval_dtor (ra -> z_dist );
106+ efree (ra -> z_dist );
107+ }
101108
102- /* delete distributor */
103- if (ra -> z_dist ) {
104- zval_dtor (ra -> z_dist );
105- efree (ra -> z_dist );
106- }
109+ /* Delete pur commands */
110+ zval_dtor (ra -> z_pure_cmds );
111+ efree (ra -> z_pure_cmds );
112+
113+ // Free structure itself
114+ efree (ra );
115+ }
107116
108- /* delete list of pure commands */
109- zval_dtor (ra -> z_pure_cmds );
110- efree (ra -> z_pure_cmds );
117+ int le_redis_array ;
118+ void redis_destructor_redis_array (zend_rsrc_list_entry * rsrc TSRMLS_DC )
119+ {
120+ RedisArray * ra = (RedisArray * )rsrc -> ptr ;
111121
112- /* free container */
113- efree (ra );
122+ /* Free previous ring if it's set */
123+ if (ra -> prev ) redis_array_free (ra -> prev );
124+
125+ /* Free parent array */
126+ redis_array_free (ra );
114127}
115128
116129/**
@@ -280,6 +293,7 @@ PHP_METHOD(RedisArray, __construct)
280293
281294 if (ra ) {
282295 ra -> auto_rehash = b_autorehash ;
296+ if (ra -> prev ) ra -> prev -> auto_rehash = b_autorehash ;
283297#if PHP_VERSION_ID >= 50400
284298 id = zend_list_insert (ra , le_redis_array TSRMLS_CC );
285299#else
@@ -302,7 +316,6 @@ ra_forward_call(INTERNAL_FUNCTION_PARAMETERS, RedisArray *ra, const char *cmd, i
302316 HashTable * h_args ;
303317
304318 int argc ;
305- int failed ;
306319 zend_bool b_write_cmd = 0 ;
307320
308321 h_args = Z_ARRVAL_P (z_args );
@@ -366,23 +379,15 @@ ra_forward_call(INTERNAL_FUNCTION_PARAMETERS, RedisArray *ra, const char *cmd, i
366379 } else { /* call directly through. */
367380 call_user_function (& redis_ce -> function_table , & redis_inst , & z_fun , return_value , argc , z_callargs TSRMLS_CC );
368381
369- failed = 0 ;
370- if ((Z_TYPE_P (return_value ) == IS_BOOL && Z_BVAL_P (return_value ) == 0 ) ||
371- (Z_TYPE_P (return_value ) == IS_ARRAY && zend_hash_num_elements (Z_ARRVAL_P (return_value )) == 0 ) ||
372- (Z_TYPE_P (return_value ) == IS_LONG && Z_LVAL_P (return_value ) == 0 && !strcasecmp (cmd , "TYPE" )))
373-
374- {
375- failed = 1 ;
376- }
377-
378382 /* check if we have an error. */
379- if (failed && ra -> prev && !b_write_cmd ) { /* there was an error reading, try with prev ring. */
380- /* ERROR, FALLBACK TO PREVIOUS RING and forward a reference to the first redis instance we were looking at. */
383+ if (RA_CALL_FAILED ( return_value , cmd ) && ra -> prev && !b_write_cmd ) { /* there was an error reading, try with prev ring. */
384+ /* ERROR, FALLBACK TO PREVIOUS RING and forward a reference to the first redis instance we were looking at. */
381385 ra_forward_call (INTERNAL_FUNCTION_PARAM_PASSTHRU , ra -> prev , cmd , cmd_len , z_args , z_new_target ?z_new_target :redis_inst );
382386 }
383387
384- if (!failed && !b_write_cmd && z_new_target && ra -> auto_rehash ) { /* move key from old ring to new ring */
385- ra_move_key (key , key_len , redis_inst , z_new_target TSRMLS_CC );
388+ /* Autorehash if the key was found on the previous node if this is a read command and auto rehashing is on */
389+ if (!RA_CALL_FAILED (return_value ,cmd ) && !b_write_cmd && z_new_target && ra -> auto_rehash ) { /* move key from old ring to new ring */
390+ ra_move_key (key , key_len , redis_inst , z_new_target TSRMLS_CC );
386391 }
387392 }
388393
0 commit comments