@@ -32,8 +32,14 @@ PHPAPI int usleep(unsigned int useconds);
32
32
#define usleep Sleep
33
33
#endif
34
34
35
- #define UNSERIALIZE_ONLY_VALUES 0
36
- #define UNSERIALIZE_ALL 1
35
+ #define UNSERIALIZE_NONE 0
36
+ #define UNSERIALIZE_KEYS 1
37
+ #define UNSERIALIZE_VALS 2
38
+ #define UNSERIALIZE_ALL 3
39
+
40
+ #define SCORE_DECODE_NONE 0
41
+ #define SCORE_DECODE_INT 1
42
+ #define SCORE_DECODE_DOUBLE 2
37
43
38
44
extern zend_class_entry * redis_ce ;
39
45
extern zend_class_entry * redis_exception_ce ;
@@ -229,13 +235,13 @@ redis_sock_read_scan_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
229
235
scan command this is. They all come back in slightly different ways */
230
236
switch (type ) {
231
237
case TYPE_SCAN :
232
- return redis_sock_read_multibulk_reply_raw (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
238
+ return redis_mbulk_reply_raw (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
233
239
case TYPE_SSCAN :
234
240
return redis_sock_read_multibulk_reply (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
235
241
case TYPE_ZSCAN :
236
- return redis_sock_read_multibulk_reply_zipped (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
242
+ return redis_mbulk_reply_zipped_keys_dbl (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
237
243
case TYPE_HSCAN :
238
- return redis_sock_read_multibulk_reply_zipped_strings (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
244
+ return redis_mbulk_reply_zipped_vals (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
239
245
default :
240
246
return -1 ;
241
247
}
@@ -268,9 +274,10 @@ PHP_REDIS_API zval *redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAM
268
274
MAKE_STD_ZVAL (z_tab );
269
275
array_init (z_tab );
270
276
271
- redis_sock_read_multibulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU ,
272
- redis_sock , z_tab , numElems , 1 , UNSERIALIZE_ALL );
273
- return z_tab ;
277
+ redis_mbulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , z_tab ,
278
+ numElems , UNSERIALIZE_ALL );
279
+
280
+ return z_tab ;
274
281
}
275
282
276
283
/**
@@ -1023,15 +1030,79 @@ PHP_REDIS_API void redis_long_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *
1023
1030
}
1024
1031
}
1025
1032
1033
+ /* Helper method to convert [key, value, key, value] into [key => value,
1034
+ * key => value] when returning data to the caller. Depending on our decode
1035
+ * flag we'll convert the value data types */
1036
+ static void array_zip_values_and_scores (RedisSock * redis_sock , zval * z_tab ,
1037
+ int decode TSRMLS_DC )
1038
+ {
1039
+
1040
+ zval * z_ret ;
1041
+ HashTable * keytable ;
1042
+
1043
+ MAKE_STD_ZVAL (z_ret );
1044
+ array_init (z_ret );
1045
+ keytable = Z_ARRVAL_P (z_tab );
1046
+
1047
+ for (zend_hash_internal_pointer_reset (keytable );
1048
+ zend_hash_has_more_elements (keytable ) == SUCCESS ;
1049
+ zend_hash_move_forward (keytable )) {
1050
+
1051
+ char * tablekey , * hkey , * hval ;
1052
+ unsigned int tablekey_len ;
1053
+ int hkey_len ;
1054
+ unsigned long idx ;
1055
+ zval * * z_key_pp , * * z_value_pp ;
1026
1056
1057
+ zend_hash_get_current_key_ex (keytable , & tablekey , & tablekey_len , & idx , 0 , NULL );
1058
+ if (zend_hash_get_current_data (keytable , (void * * )& z_key_pp ) == FAILURE ) {
1059
+ continue ; /* this should never happen, according to the PHP people. */
1060
+ }
1061
+
1062
+ /* get current value, a key */
1063
+ convert_to_string (* z_key_pp );
1064
+ hkey = Z_STRVAL_PP (z_key_pp );
1065
+ hkey_len = Z_STRLEN_PP (z_key_pp );
1027
1066
1028
- PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped_with_flag (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , int flag ) {
1067
+ /* move forward */
1068
+ zend_hash_move_forward (keytable );
1069
+
1070
+ /* fetch again */
1071
+ zend_hash_get_current_key_ex (keytable , & tablekey , & tablekey_len , & idx , 0 , NULL );
1072
+ if (zend_hash_get_current_data (keytable , (void * * )& z_value_pp ) == FAILURE ) {
1073
+ continue ; /* this should never happen, according to the PHP people. */
1074
+ }
1029
1075
1030
- /*
1031
- int ret = redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab TSRMLS_CC);
1032
- array_zip_values_and_scores(return_value, 0);
1033
- */
1076
+ /* get current value, a hash value now. */
1077
+ hval = Z_STRVAL_PP (z_value_pp );
1034
1078
1079
+ /* Decode the score depending on flag */
1080
+ if (decode == SCORE_DECODE_INT && Z_STRLEN_PP (z_value_pp ) > 0 ) {
1081
+ add_assoc_long_ex (z_ret , hkey , 1 + hkey_len , atoi (hval + 1 ));
1082
+ } else if (decode == SCORE_DECODE_DOUBLE ) {
1083
+ add_assoc_double_ex (z_ret , hkey , 1 + hkey_len , atof (hval ));
1084
+ } else {
1085
+ zval * z = NULL ;
1086
+ MAKE_STD_ZVAL (z );
1087
+ * z = * * z_value_pp ;
1088
+ zval_copy_ctor (z );
1089
+ add_assoc_zval_ex (z_ret , hkey , 1 + hkey_len , z );
1090
+ }
1091
+ }
1092
+
1093
+ /* replace */
1094
+ zval_dtor (z_tab );
1095
+ * z_tab = * z_ret ;
1096
+ zval_copy_ctor (z_tab );
1097
+ zval_dtor (z_ret );
1098
+
1099
+ efree (z_ret );
1100
+ }
1101
+
1102
+ static int
1103
+ redis_mbulk_reply_zipped (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
1104
+ zval * z_tab , int unserialize , int decode )
1105
+ {
1035
1106
char inbuf [1024 ];
1036
1107
int numElems ;
1037
1108
zval * z_multi_result ;
@@ -1061,10 +1132,12 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNC
1061
1132
MAKE_STD_ZVAL (z_multi_result );
1062
1133
array_init (z_multi_result ); /* pre-allocate array for multi's results. */
1063
1134
1064
- redis_sock_read_multibulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1065
- redis_sock , z_multi_result , numElems , 1 , flag ? UNSERIALIZE_ALL : UNSERIALIZE_ONLY_VALUES );
1135
+ /* Grab our key, value, key, value array */
1136
+ redis_mbulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1137
+ z_multi_result , numElems , unserialize );
1066
1138
1067
- array_zip_values_and_scores (redis_sock , z_multi_result , 0 TSRMLS_CC );
1139
+ /* Zip keys and values */
1140
+ array_zip_values_and_scores (redis_sock , z_multi_result , decode TSRMLS_CC );
1068
1141
1069
1142
IF_MULTI_OR_PIPELINE () {
1070
1143
add_next_index_zval (z_tab , z_multi_result );
@@ -1078,13 +1151,35 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNC
1078
1151
return 0 ;
1079
1152
}
1080
1153
1081
- PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx ) {
1154
+ /* Zipped key => value reply but we don't touch anything (e.g. CONFIG GET) */
1155
+ PHP_REDIS_API int redis_mbulk_reply_zipped_raw (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx )
1156
+ {
1157
+ return redis_mbulk_reply_zipped (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1158
+ z_tab , UNSERIALIZE_NONE , SCORE_DECODE_NONE );
1159
+ }
1082
1160
1083
- return redis_sock_read_multibulk_reply_zipped_with_flag (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , z_tab , 1 );
1161
+ /* Zipped key => value reply unserializing keys and decoding the score as an integer (PUBSUB) */
1162
+ PHP_REDIS_API int redis_mbulk_reply_zipped_keys_int (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
1163
+ zval * z_tab , void * ctx )
1164
+ {
1165
+ return redis_mbulk_reply_zipped (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1166
+ z_tab , UNSERIALIZE_KEYS , SCORE_DECODE_INT );
1084
1167
}
1085
1168
1086
- PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped_strings (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx ) {
1087
- return redis_sock_read_multibulk_reply_zipped_with_flag (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , z_tab , 0 );
1169
+ /* Zipped key => value reply unserializing keys and decoding the score as a double (ZSET commands) */
1170
+ PHP_REDIS_API int redis_mbulk_reply_zipped_keys_dbl (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
1171
+ zval * z_tab , void * ctx )
1172
+ {
1173
+ return redis_mbulk_reply_zipped (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1174
+ z_tab , UNSERIALIZE_KEYS , SCORE_DECODE_DOUBLE );
1175
+ }
1176
+
1177
+ /* Zipped key => value reply where only the values are unserialized (e.g. HMGET) */
1178
+ PHP_REDIS_API int redis_mbulk_reply_zipped_vals (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
1179
+ zval * z_tab , void * ctx )
1180
+ {
1181
+ return redis_mbulk_reply_zipped (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1182
+ z_tab , UNSERIALIZE_VALS , SCORE_DECODE_NONE );
1088
1183
}
1089
1184
1090
1185
PHP_REDIS_API void redis_1_response (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx ) {
@@ -1500,8 +1595,8 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS,
1500
1595
MAKE_STD_ZVAL (z_multi_result );
1501
1596
array_init (z_multi_result ); /* pre-allocate array for multi's results. */
1502
1597
1503
- redis_sock_read_multibulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1504
- redis_sock , z_multi_result , numElems , 1 , UNSERIALIZE_ALL );
1598
+ redis_mbulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1599
+ z_multi_result , numElems , UNSERIALIZE_ALL );
1505
1600
1506
1601
IF_MULTI_OR_PIPELINE () {
1507
1602
add_next_index_zval (z_tab , z_multi_result );
@@ -1516,7 +1611,7 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS,
1516
1611
/**
1517
1612
* Like multibulk reply, but don't touch the values, they won't be compressed. (this is used by HKEYS).
1518
1613
*/
1519
- PHP_REDIS_API int redis_sock_read_multibulk_reply_raw (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx )
1614
+ PHP_REDIS_API int redis_mbulk_reply_raw (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx )
1520
1615
{
1521
1616
char inbuf [1024 ];
1522
1617
int numElems ;
@@ -1547,8 +1642,8 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_raw(INTERNAL_FUNCTION_PARAMETE
1547
1642
MAKE_STD_ZVAL (z_multi_result );
1548
1643
array_init (z_multi_result ); /* pre-allocate array for multi's results. */
1549
1644
1550
- redis_sock_read_multibulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1551
- redis_sock , z_multi_result , numElems , 0 , UNSERIALIZE_ALL );
1645
+ redis_mbulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1646
+ z_multi_result , numElems , UNSERIALIZE_NONE );
1552
1647
1553
1648
IF_MULTI_OR_PIPELINE () {
1554
1649
add_next_index_zval (z_tab , z_multi_result );
@@ -1560,6 +1655,42 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_raw(INTERNAL_FUNCTION_PARAMETE
1560
1655
return 0 ;
1561
1656
}
1562
1657
1658
+ PHP_REDIS_API void
1659
+ redis_mbulk_reply_loop (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
1660
+ zval * z_tab , int count , int unserialize )
1661
+ {
1662
+ char * line ;
1663
+ int len ;
1664
+
1665
+ while (count > 0 ) {
1666
+ line = redis_sock_read (redis_sock , & len TSRMLS_CC );
1667
+ if (line != NULL ) {
1668
+ zval * z = NULL ;
1669
+ int unwrap ;
1670
+
1671
+ /* We will attempt unserialization, if we're unserializing everything,
1672
+ * or if we're unserializing keys and we're on a key, or we're
1673
+ * unserializing values and we're on a value! */
1674
+ unwrap = unserialize == UNSERIALIZE_ALL ||
1675
+ (unserialize == UNSERIALIZE_KEYS && count % 2 == 0 ) ||
1676
+ (unserialize == UNSERIALIZE_VALS && count % 2 != 0 );
1677
+
1678
+ if (unwrap && redis_unserialize (redis_sock , line , len , & z TSRMLS_CC )) {
1679
+ efree (line );
1680
+ add_next_index_zval (z_tab , z );
1681
+ } else {
1682
+ add_next_index_stringl (z_tab , line , len , 0 );
1683
+ }
1684
+ } else {
1685
+ add_next_index_bool (z_tab , 0 );
1686
+ }
1687
+
1688
+ count -- ;
1689
+ }
1690
+ }
1691
+
1692
+
1693
+ /*
1563
1694
PHP_REDIS_API int
1564
1695
redis_sock_read_multibulk_reply_loop(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
1565
1696
zval *z_tab, int numElems, int unwrap_key, int unserialize_even_only)
@@ -1588,24 +1719,24 @@ redis_sock_read_multibulk_reply_loop(INTERNAL_FUNCTION_PARAMETERS, RedisSock *re
1588
1719
}
1589
1720
return 0;
1590
1721
}
1722
+ */
1591
1723
1592
- /**
1593
- * redis_sock_read_multibulk_reply_assoc
1594
- */
1595
- PHP_REDIS_API int redis_sock_read_multibulk_reply_assoc (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx )
1724
+ /* Specialized multibulk processing for HMGET where we need to pair requested
1725
+ * keys with their returned values */
1726
+ PHP_REDIS_API int redis_mbulk_reply_assoc (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx )
1596
1727
{
1597
1728
char inbuf [1024 ], * response ;
1598
1729
int response_len ;
1599
- int i , numElems ;
1600
- zval * z_multi_result ;
1730
+ int i , numElems ;
1731
+ zval * z_multi_result ;
1601
1732
1602
1733
zval * * z_keys = ctx ;
1603
1734
1604
1735
if (-1 == redis_check_eof (redis_sock TSRMLS_CC )) {
1605
1736
return -1 ;
1606
1737
}
1607
1738
if (php_stream_gets (redis_sock -> stream , inbuf , 1024 ) == NULL ) {
1608
- redis_stream_close (redis_sock TSRMLS_CC );
1739
+ redis_stream_close (redis_sock TSRMLS_CC );
1609
1740
redis_sock -> stream = NULL ;
1610
1741
redis_sock -> status = REDIS_SOCK_STATUS_FAILED ;
1611
1742
redis_sock -> mode = ATOMIC ;
@@ -1629,30 +1760,30 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_assoc(INTERNAL_FUNCTION_PARAME
1629
1760
for (i = 0 ; i < numElems ; ++ i ) {
1630
1761
response = redis_sock_read (redis_sock , & response_len TSRMLS_CC );
1631
1762
if (response != NULL ) {
1632
- zval * z = NULL ;
1633
- if (redis_unserialize (redis_sock , response , response_len , & z TSRMLS_CC ) == 1 ) {
1634
- efree (response );
1635
- add_assoc_zval_ex (z_multi_result , Z_STRVAL_P (z_keys [i ]), 1 + Z_STRLEN_P (z_keys [i ]), z );
1636
- } else {
1637
- add_assoc_stringl_ex (z_multi_result , Z_STRVAL_P (z_keys [i ]), 1 + Z_STRLEN_P (z_keys [i ]), response , response_len , 0 );
1638
- }
1639
- } else {
1640
- add_assoc_bool_ex (z_multi_result , Z_STRVAL_P (z_keys [i ]), 1 + Z_STRLEN_P (z_keys [i ]), 0 );
1641
- }
1642
- zval_dtor (z_keys [i ]);
1643
- efree (z_keys [i ]);
1763
+ zval * z = NULL ;
1764
+ if (redis_unserialize (redis_sock , response , response_len , & z TSRMLS_CC ) == 1 ) {
1765
+ efree (response );
1766
+ add_assoc_zval_ex (z_multi_result , Z_STRVAL_P (z_keys [i ]), 1 + Z_STRLEN_P (z_keys [i ]), z );
1767
+ } else {
1768
+ add_assoc_stringl_ex (z_multi_result , Z_STRVAL_P (z_keys [i ]), 1 + Z_STRLEN_P (z_keys [i ]), response , response_len , 0 );
1769
+ }
1770
+ } else {
1771
+ add_assoc_bool_ex (z_multi_result , Z_STRVAL_P (z_keys [i ]), 1 + Z_STRLEN_P (z_keys [i ]), 0 );
1772
+ }
1773
+ zval_dtor (z_keys [i ]);
1774
+ efree (z_keys [i ]);
1644
1775
}
1645
1776
efree (z_keys );
1646
1777
1647
1778
IF_MULTI_OR_PIPELINE () {
1648
1779
add_next_index_zval (z_tab , z_multi_result );
1649
1780
} else {
1650
- * return_value = * z_multi_result ;
1651
- zval_copy_ctor (return_value );
1652
- INIT_PZVAL (return_value );
1653
- zval_dtor (z_multi_result );
1654
- efree (z_multi_result );
1655
- }
1781
+ * return_value = * z_multi_result ;
1782
+ zval_copy_ctor (return_value );
1783
+ INIT_PZVAL (return_value );
1784
+ zval_dtor (z_multi_result );
1785
+ efree (z_multi_result );
1786
+ }
1656
1787
return 0 ;
1657
1788
}
1658
1789
0 commit comments