@@ -1846,141 +1846,82 @@ int redis_vararg_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
18461846 * timeout value. This can handle various SUNION/SUNIONSTORE/BRPOP type
18471847 * commands. */
18481848static int gen_varkey_cmd (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
1849- char * kw , int kw_len , int min_argc , int has_timeout ,
1849+ char * kw , int kw_len , int min_argc , zend_bool has_timeout ,
18501850 char * * cmd , int * cmd_len , short * slot )
18511851{
1852- zval * z_args , * z_ele , ztimeout = {0 };
1853- HashTable * ht_arr ;
1854- char * key ;
1855- int key_free , i , tail ;
1856- size_t key_len ;
1857- int single_array = 0 , argc = ZEND_NUM_ARGS ();
1852+ zval * argv = NULL , ztimeout = {0 }, * zv ;
18581853 smart_string cmdstr = {0 };
18591854 short kslot = -1 ;
1860- zend_string * zstr ;
1855+ int single_array ;
1856+ int argc = 0 ;
18611857
1862- if (argc < min_argc ) {
1863- zend_wrong_param_count ();
1864- return FAILURE ;
1865- }
1858+ ZEND_PARSE_PARAMETERS_START (min_argc , -1 )
1859+ Z_PARAM_VARIADIC ('*' , argv , argc )
1860+ ZEND_PARSE_PARAMETERS_END_EX (return FAILURE );
18661861
1867- // Allocate args
1868- z_args = emalloc (argc * sizeof (zval ));
1869- if (zend_get_parameters_array (ht , argc , z_args ) == FAILURE ) {
1870- efree (z_args );
1871- return FAILURE ;
1872- }
1862+ single_array = argc == 1 + !!has_timeout && Z_TYPE (argv [0 ]) == IS_ARRAY ;
18731863
1874- // Handle our "single array" case
1875- if (has_timeout == 0 ) {
1876- single_array = argc == 1 && Z_TYPE (z_args [0 ]) == IS_ARRAY ;
1877- } else {
1878- single_array = argc == 2 && Z_TYPE (z_args [0 ]) == IS_ARRAY &&
1879- (Z_TYPE (z_args [1 ]) == IS_LONG || Z_TYPE (z_args [1 ]) == IS_DOUBLE );
1864+ if (has_timeout ) {
18801865 if (single_array )
1881- ZVAL_COPY_VALUE (& ztimeout , & z_args [1 ]);
1866+ ZVAL_COPY_VALUE (& ztimeout , & argv [1 ]);
1867+ else
1868+ ZVAL_COPY_VALUE (& ztimeout , & argv [argc - 1 ]);
1869+
1870+ if (Z_TYPE (ztimeout ) != IS_LONG && Z_TYPE (ztimeout ) != IS_DOUBLE ) {
1871+ php_error_docref (NULL , E_WARNING , "Timeout must be a long or double" );
1872+ return FAILURE ;
1873+ }
18821874 }
18831875
18841876 // If we're running a single array, rework args
18851877 if (single_array ) {
1886- ht_arr = Z_ARRVAL (z_args [0 ]);
1887- argc = zend_hash_num_elements (ht_arr );
1888- if (has_timeout ) argc ++ ;
1889- efree (z_args );
1890- z_args = NULL ;
1878+ /* Need at least one argument */
1879+ argc = zend_hash_num_elements (Z_ARRVAL (argv [0 ]));
1880+ if (argc == 0 )
1881+ return FAILURE ;
18911882
1892- /* If the array is empty, we can simply abort */
1893- if (argc == 0 ) return FAILURE ;
1883+ if (has_timeout ) argc ++ ;
18941884 }
18951885
18961886 // Begin construction of our command
18971887 redis_cmd_init_sstr (& cmdstr , argc , kw , kw_len );
18981888
18991889 if (single_array ) {
1900- ZEND_HASH_FOREACH_VAL (ht_arr , z_ele ) {
1901- zstr = zval_get_string (z_ele );
1902- key = ZSTR_VAL (zstr );
1903- key_len = ZSTR_LEN (zstr );
1904- key_free = redis_key_prefix (redis_sock , & key , & key_len );
1905-
1906- // Protect against CROSSLOT errors
1890+ ZEND_HASH_FOREACH_VAL (Z_ARRVAL (argv [0 ]), zv ) {
1891+ redis_cmd_append_sstr_key_zval (& cmdstr , zv , redis_sock , slot );
19071892 if (slot ) {
1908- if (kslot == -1 ) {
1909- kslot = cluster_hash_key (key , key_len );
1910- } else if (cluster_hash_key (key ,key_len )!= kslot ) {
1911- zend_string_release (zstr );
1912- if (key_free ) efree (key );
1913- php_error_docref (NULL , E_WARNING ,
1914- "Not all keys hash to the same slot!" );
1915- return FAILURE ;
1916- }
1893+ if (kslot != -1 && * slot != kslot )
1894+ goto cross_slot ;
1895+ kslot = * slot ;
19171896 }
1918-
1919- // Append this key, free it if we prefixed
1920- redis_cmd_append_sstr (& cmdstr , key , key_len );
1921- zend_string_release (zstr );
1922- if (key_free ) efree (key );
19231897 } ZEND_HASH_FOREACH_END ();
1924- if (Z_TYPE (ztimeout ) == IS_LONG ) {
1925- redis_cmd_append_sstr_long (& cmdstr , Z_LVAL (ztimeout ));
1926- } else if (Z_TYPE (ztimeout ) == IS_DOUBLE ) {
1927- redis_cmd_append_sstr_dbl (& cmdstr , Z_DVAL (ztimeout ));
1928- }
19291898 } else {
1930- if (has_timeout ) {
1931- zend_uchar type = Z_TYPE (z_args [argc - 1 ]);
1932- if (type == IS_LONG || type == IS_DOUBLE ) {
1933- ZVAL_COPY_VALUE (& ztimeout , & z_args [argc - 1 ]);
1934- } else {
1935- php_error_docref (NULL , E_ERROR , "Timeout value must be a long or double" );
1936- efree (z_args );
1937- return FAILURE ;
1938- }
1939- }
1940- tail = has_timeout ? argc - 1 : argc ;
1941- for (i = 0 ; i < tail ; i ++ ) {
1942- zstr = zval_get_string (& z_args [i ]);
1943- key = ZSTR_VAL (zstr );
1944- key_len = ZSTR_LEN (zstr );
1945-
1946- key_free = redis_key_prefix (redis_sock , & key , & key_len );
1947-
1948- /* Protect against CROSSSLOT errors if we've got a slot */
1899+ for (uint32_t i = 0 ; i < argc - !!has_timeout ; i ++ ) {
1900+ redis_cmd_append_sstr_key_zval (& cmdstr , & argv [i ], redis_sock , slot );
19491901 if (slot ) {
1950- if ( kslot == -1 ) {
1951- kslot = cluster_hash_key (key , key_len );
1952- } else if (cluster_hash_key (key ,key_len )!= kslot ) {
1953- php_error_docref (NULL , E_WARNING ,
1954- "Not all keys hash to the same slot" );
1955- zend_string_release (zstr );
1956- if (key_free ) efree (key );
1957- efree (z_args );
1958- return FAILURE ;
1959- }
1902+ if (kslot != -1 && * slot != kslot )
1903+ goto cross_slot ;
1904+ kslot = * slot ;
19601905 }
1961-
1962- // Append this key
1963- redis_cmd_append_sstr (& cmdstr , key , key_len );
1964- zend_string_release (zstr );
1965- if (key_free ) efree (key );
1966- }
1967-
1968- if (Z_TYPE (ztimeout ) == IS_DOUBLE ) {
1969- redis_cmd_append_sstr_dbl (& cmdstr , Z_DVAL (z_args [tail ]));
1970- } else if (Z_TYPE (ztimeout ) == IS_LONG ) {
1971- redis_cmd_append_sstr_long (& cmdstr , Z_LVAL (z_args [tail ]));
19721906 }
1907+ }
19731908
1974- // Cleanup args
1975- efree (z_args );
1909+ if (Z_TYPE (ztimeout ) == IS_DOUBLE ) {
1910+ redis_cmd_append_sstr_dbl (& cmdstr , Z_DVAL (ztimeout ));
1911+ } else if (Z_TYPE (ztimeout ) == IS_LONG ) {
1912+ redis_cmd_append_sstr_long (& cmdstr , Z_LVAL (ztimeout ));
19761913 }
19771914
19781915 // Push out parameters
1979- if (slot ) * slot = kslot ;
19801916 * cmd = cmdstr .c ;
19811917 * cmd_len = cmdstr .len ;
19821918
19831919 return SUCCESS ;
1920+
1921+ cross_slot :
1922+ efree (cmdstr .c );
1923+ php_error_docref (NULL , E_WARNING , "Not all keys hash to the same slot!" );
1924+ return FAILURE ;
19841925}
19851926
19861927int redis_mpop_cmd (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , char * kw ,
@@ -2075,7 +2016,7 @@ int redis_blocking_pop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
20752016 void * * ctx )
20762017{
20772018 return gen_varkey_cmd (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , kw ,
2078- strlen (kw ), 2 , 2 , cmd , cmd_len , slot );
2019+ strlen (kw ), 2 , 1 , cmd , cmd_len , slot );
20792020}
20802021
20812022/*
0 commit comments