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/**
@@ -295,6 +308,7 @@ PHP_METHOD(RedisArray, __construct)
295308 if (ra ) {
296309 ra -> auto_rehash = b_autorehash ;
297310 ra -> connect_timeout = d_connect_timeout ;
311+ if (ra -> prev ) ra -> prev -> auto_rehash = b_autorehash ;
298312#if PHP_VERSION_ID >= 50400
299313 id = zend_list_insert (ra , le_redis_array TSRMLS_CC );
300314#else
@@ -317,7 +331,6 @@ ra_forward_call(INTERNAL_FUNCTION_PARAMETERS, RedisArray *ra, const char *cmd, i
317331 HashTable * h_args ;
318332
319333 int argc ;
320- int failed ;
321334 zend_bool b_write_cmd = 0 ;
322335
323336 h_args = Z_ARRVAL_P (z_args );
@@ -381,23 +394,15 @@ ra_forward_call(INTERNAL_FUNCTION_PARAMETERS, RedisArray *ra, const char *cmd, i
381394 } else { /* call directly through. */
382395 call_user_function (& redis_ce -> function_table , & redis_inst , & z_fun , return_value , argc , z_callargs TSRMLS_CC );
383396
384- failed = 0 ;
385- if ((Z_TYPE_P (return_value ) == IS_BOOL && Z_BVAL_P (return_value ) == 0 ) ||
386- (Z_TYPE_P (return_value ) == IS_ARRAY && zend_hash_num_elements (Z_ARRVAL_P (return_value )) == 0 ) ||
387- (Z_TYPE_P (return_value ) == IS_LONG && Z_LVAL_P (return_value ) == 0 && !strcasecmp (cmd , "TYPE" )))
388-
389- {
390- failed = 1 ;
391- }
392-
393397 /* check if we have an error. */
394- if (failed && ra -> prev && !b_write_cmd ) { /* there was an error reading, try with prev ring. */
395- /* ERROR, FALLBACK TO PREVIOUS RING and forward a reference to the first redis instance we were looking at. */
398+ if (RA_CALL_FAILED ( return_value , cmd ) && ra -> prev && !b_write_cmd ) { /* there was an error reading, try with prev ring. */
399+ /* ERROR, FALLBACK TO PREVIOUS RING and forward a reference to the first redis instance we were looking at. */
396400 ra_forward_call (INTERNAL_FUNCTION_PARAM_PASSTHRU , ra -> prev , cmd , cmd_len , z_args , z_new_target ?z_new_target :redis_inst );
397401 }
398402
399- if (!failed && !b_write_cmd && z_new_target && ra -> auto_rehash ) { /* move key from old ring to new ring */
400- ra_move_key (key , key_len , redis_inst , z_new_target TSRMLS_CC );
403+ /* Autorehash if the key was found on the previous node if this is a read command and auto rehashing is on */
404+ if (!RA_CALL_FAILED (return_value ,cmd ) && !b_write_cmd && z_new_target && ra -> auto_rehash ) { /* move key from old ring to new ring */
405+ ra_move_key (key , key_len , redis_inst , z_new_target TSRMLS_CC );
401406 }
402407 }
403408
0 commit comments