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