@@ -100,6 +100,126 @@ PHPAPI int redis_check_eof(RedisSock *redis_sock TSRMLS_DC)
100
100
return 0 ;
101
101
}
102
102
103
+ /* Inner MULTIBULK reply parser for SENTINEL MASTERS or SENTINEL SLAVE */
104
+ static zval *
105
+ read_sentinel_server_reply (RedisSock * redis_sock TSRMLS_DC )
106
+ {
107
+ char buf [1024 ], * resp ;
108
+ int count , resp_len ;
109
+ zval * z_ret ;
110
+
111
+ if (-1 == redis_check_eof (redis_sock TSRMLS_CC )) {
112
+ return NULL ;
113
+ }
114
+ if (php_stream_gets (redis_sock -> stream , buf , sizeof (buf )) == NULL ) {
115
+ redis_stream_close (redis_sock TSRMLS_CC );
116
+ redis_sock -> stream = NULL ;
117
+ redis_sock -> status = REDIS_SOCK_STATUS_FAILED ;
118
+ redis_sock -> mode = ATOMIC ;
119
+ redis_sock -> watching = 0 ;
120
+ zend_throw_exception (redis_exception_ce , "read error on connection" , 0 TSRMLS_CC );
121
+ return NULL ;
122
+ }
123
+
124
+ // Must be MULTIBULK
125
+ if (buf [0 ] != '*' ) {
126
+ // Set last error, if something is wrong with our command, otherwise
127
+ // throw an exception.
128
+ if (buf [0 ] == TYPE_ERR ) {
129
+ redis_sock_set_err (redis_sock , buf , strlen (buf ));
130
+ } else {
131
+ snprintf (buf , sizeof (buf ), "Protocol error: Expecting MULTIBULK but got %s" ,
132
+ redis_reply_type_str (buf [0 ]));
133
+ zend_throw_exception (redis_exception_ce , buf , 0 TSRMLS_CC );
134
+ }
135
+ return NULL ;
136
+ }
137
+
138
+ // Grab the number of MULTIBULK elements
139
+ count = atoi (buf + 1 );
140
+
141
+ // Crate our return array
142
+ MAKE_STD_ZVAL (z_ret );
143
+ array_init (z_ret );
144
+
145
+ // Read the values raw
146
+ while (count > 0 ) {
147
+ if ((resp = redis_sock_read (redis_sock , & resp_len TSRMLS_CC ))!= NULL ) {
148
+ add_next_index_stringl (z_ret , resp , resp_len , 0 );
149
+ }
150
+ count -- ;
151
+ }
152
+
153
+ // Turn k1,v1,k2,v2 into k1=>v1, k2=>v2
154
+ array_zip_values_and_scores (redis_sock , z_ret , 0 TSRMLS_CC );
155
+
156
+ // Return our value
157
+ return z_ret ;
158
+ }
159
+
160
+ /* Read one MULTIBULK server info response */
161
+ PHPAPI int
162
+ redis_sock_read_sentinel_server_reply (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
163
+ zval * z_tab )
164
+ {
165
+ zval * z_resp ;
166
+
167
+ // Grab the response in the form key1=>val1, key2=>val2
168
+ if ((z_resp = read_sentinel_server_reply (redis_sock TSRMLS_CC ))== NULL ) {
169
+ return -1 ;
170
+ }
171
+
172
+ // Set this as our return value, free contianer
173
+ * return_value = * z_resp ;
174
+ efree (z_resp );
175
+
176
+ // Success
177
+ return 0 ;
178
+ }
179
+
180
+ /* Nested MULTIBULK replies with N elements */
181
+ PHPAPI int
182
+ redis_sock_read_sentinel_servers_reply (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
183
+ zval * z_tab )
184
+ {
185
+ REDIS_REPLY_TYPE reply_type ;
186
+ int count ;
187
+ zval * z_ret , * z_sub ;
188
+
189
+ // Read our header
190
+ if (redis_read_reply_type (redis_sock , & reply_type , & count TSRMLS_CC ) < 0 ) {
191
+ return -1 ;
192
+ }
193
+
194
+ // Make sure we have an outer MULTIBULK reply
195
+ if (reply_type != TYPE_MULTIBULK ) {
196
+ return -1 ;
197
+ }
198
+
199
+ // Our return variable
200
+ MAKE_STD_ZVAL (z_ret );
201
+ array_init (z_ret );
202
+
203
+ // Read for each master reply
204
+ while (count > 0 ) {
205
+ // Grab our info for this master
206
+ if ((z_sub = read_sentinel_server_reply (redis_sock TSRMLS_CC ))== NULL ) {
207
+ return -1 ;
208
+ }
209
+ add_next_index_zval (z_ret , z_sub );
210
+ count -- ;
211
+ }
212
+
213
+ IF_MULTI_OR_PIPELINE () {
214
+ add_next_index_zval (z_tab , z_ret );
215
+ } else {
216
+ * return_value = * z_ret ;
217
+ efree (z_ret );
218
+ }
219
+
220
+ // Success!
221
+ return 0 ;
222
+ }
103
223
104
224
PHPAPI int
105
225
redis_sock_read_scan_reply (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
@@ -1709,6 +1829,24 @@ redis_sock_gets(RedisSock *redis_sock, char *buf, int buf_size, size_t *line_siz
1709
1829
return 0 ;
1710
1830
}
1711
1831
1832
+ /* Helper method to get the string representation of a REDIS_REPLY_TYPE */
1833
+ const char * redis_reply_type_str (REDIS_REPLY_TYPE reply_type ) {
1834
+ switch (reply_type ) {
1835
+ case TYPE_LINE :
1836
+ return "LINE" ;
1837
+ case TYPE_INT :
1838
+ return "INTEGER" ;
1839
+ case TYPE_ERR :
1840
+ return "ERROR" ;
1841
+ case TYPE_BULK :
1842
+ return "BULK" ;
1843
+ case TYPE_MULTIBULK :
1844
+ return "MULTIBULK" ;
1845
+ default :
1846
+ return "UNKNOWN" ;
1847
+ }
1848
+ }
1849
+
1712
1850
PHPAPI int
1713
1851
redis_read_reply_type (RedisSock * redis_sock , REDIS_REPLY_TYPE * reply_type , int * reply_info TSRMLS_DC ) {
1714
1852
// Make sure we haven't lost the connection, even trying to reconnect
0 commit comments