99#ifdef HAVE_REDIS_IGBINARY
1010#include "igbinary/igbinary.h"
1111#endif
12+ #ifdef HAVE_REDIS_MSGPACK
13+ #include "msgpack/php_msgpack.h"
14+ #endif
1215
1316#ifdef HAVE_REDIS_LZF
1417#include <lzf.h>
@@ -1894,6 +1897,7 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS,
18941897 }
18951898 return -1 ;
18961899 }
1900+
18971901 numElems = atoi (inbuf + 1 );
18981902 zval z_multi_result ;
18991903 array_init (& z_multi_result ); /* pre-allocate array for multi's results. */
@@ -1910,6 +1914,67 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS,
19101914 return 0 ;
19111915}
19121916
1917+ /**
1918+ * redis_sock_read_multibulk_reply_vals
1919+ *
1920+ * This is identical to redis_sock_read_multibulk_reply except that it unserializes vals only, rather than rely on
1921+ * the chosen unserializer to silently return 0 after a failed attempt (which msgpack does not do).
1922+ *
1923+ * Perhaps not the optimal solution, but the easiest way to resolve the problem of failed attempts to
1924+ * unserialize a key that hadn't been serialized to begin with in blpop, brpop.
1925+ *
1926+ */
1927+ PHP_REDIS_API int redis_sock_read_multibulk_reply_vals (INTERNAL_FUNCTION_PARAMETERS ,
1928+ RedisSock * redis_sock , zval * z_tab ,
1929+ void * ctx )
1930+ {
1931+ char inbuf [1024 ];
1932+ int numElems , err_len ;
1933+
1934+ if (-1 == redis_check_eof (redis_sock , 0 TSRMLS_CC )) {
1935+ return -1 ;
1936+ }
1937+
1938+ if (php_stream_gets (redis_sock -> stream , inbuf , 1024 ) == NULL ) {
1939+ REDIS_STREAM_CLOSE_MARK_FAILED (redis_sock );
1940+ zend_throw_exception (redis_exception_ce , "read error on connection" , 0
1941+ TSRMLS_CC );
1942+ return -1 ;
1943+ }
1944+
1945+ if (inbuf [0 ] != '*' ) {
1946+ IF_MULTI_OR_PIPELINE () {
1947+ add_next_index_bool (z_tab , 0 );
1948+ } else {
1949+ if (inbuf [0 ] == '-' ) {
1950+ err_len = strlen (inbuf + 1 ) - 2 ;
1951+ redis_sock_set_err (redis_sock , inbuf + 1 , err_len );
1952+ }
1953+ RETVAL_FALSE ;
1954+ }
1955+ return -1 ;
1956+ }
1957+
1958+ numElems = atoi (inbuf + 1 );
1959+ zval zv , * z_multi_result = & zv ;
1960+ #if (PHP_MAJOR_VERSION < 7 )
1961+ MAKE_STD_ZVAL (z_multi_result );
1962+ #endif
1963+ array_init (z_multi_result ); /* pre-allocate array for multi's results. */
1964+
1965+ redis_mbulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1966+ z_multi_result , numElems , UNSERIALIZE_VALS );
1967+
1968+ IF_MULTI_OR_PIPELINE () {
1969+ add_next_index_zval (z_tab , z_multi_result );
1970+ } else {
1971+ RETVAL_ZVAL (z_multi_result , 0 , 1 );
1972+ }
1973+ /*zval_copy_ctor(return_value); */
1974+ return 0 ;
1975+ }
1976+
1977+
19131978/* Like multibulk reply, but don't touch the values, they won't be unserialized
19141979 * (this is used by HKEYS). */
19151980PHP_REDIS_API int
@@ -2195,6 +2260,17 @@ redis_serialize(RedisSock *redis_sock, zval *z, char **val, size_t *val_len
21952260 PHP_VAR_SERIALIZE_DESTROY (ht );
21962261
21972262 return 1 ;
2263+
2264+ case REDIS_SERIALIZER_MSGPACK :
2265+ #ifdef HAVE_REDIS_MSGPACK
2266+ php_msgpack_serialize (& sstr , z TSRMLS_CC );
2267+ * val = estrndup (sstr .s -> val , sstr .s -> len );
2268+ * val_len = sstr .s -> len ;
2269+ smart_str_free (& sstr );
2270+
2271+ return 1 ;
2272+ #endif
2273+ break ;
21982274 case REDIS_SERIALIZER_IGBINARY :
21992275#ifdef HAVE_REDIS_IGBINARY
22002276 if (igbinary_serialize (& val8 , (size_t * )& sz , z TSRMLS_CC ) == 0 ) {
@@ -2205,6 +2281,7 @@ redis_serialize(RedisSock *redis_sock, zval *z, char **val, size_t *val_len
22052281#endif
22062282 break ;
22072283 }
2284+
22082285 return 0 ;
22092286}
22102287
@@ -2227,6 +2304,19 @@ redis_unserialize(RedisSock* redis_sock, const char *val, int val_len,
22272304 PHP_VAR_UNSERIALIZE_DESTROY (var_hash );
22282305 break ;
22292306
2307+ case REDIS_SERIALIZER_MSGPACK :
2308+ #ifdef HAVE_REDIS_MSGPACK
2309+ /*
2310+ * Would like to be able to check to see if a string is msgpack'd (like with igbinary, below),
2311+ * but I don't believe there's an easy way to do that as there's no consistent header or
2312+ * other simple indication of packed-ness in msgpacked binary sequences, as far as I know.
2313+ */
2314+
2315+ php_msgpack_unserialize (z_ret , (char * )val , (size_t )val_len TSRMLS_CC );
2316+ ret = 1 ;
2317+ #endif
2318+ break ;
2319+
22302320 case REDIS_SERIALIZER_IGBINARY :
22312321#ifdef HAVE_REDIS_IGBINARY
22322322 /*
@@ -2257,6 +2347,7 @@ redis_unserialize(RedisSock* redis_sock, const char *val, int val_len,
22572347#endif
22582348 break ;
22592349 }
2350+
22602351 return ret ;
22612352}
22622353
0 commit comments