Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2470ba2

Browse files
Implemented SENTINEL commands
This is the initial commit for the SENTINEL command, allowing phpredis to communicate with a redis-server started in --sentinel mode. It doesn't provide functionality to direct phpredis connections but can be used to configure/execute commands against the sentinel. Addresses phpredis#449
1 parent 02a67d5 commit 2470ba2

File tree

7 files changed

+755
-1
lines changed

7 files changed

+755
-1
lines changed

common.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,25 @@ typedef enum _REDIS_SCAN_TYPE {
4545
TYPE_ZSCAN
4646
} REDIS_SCAN_TYPE;
4747

48+
/* SENTINEL subcommands */
49+
typedef enum _SENTINEL_CMD {
50+
/* Standard directives */
51+
SENTINEL_MASTERS,
52+
SENTINEL_MASTER,
53+
SENTINEL_SLAVES,
54+
SENTINEL_MASTER_BY_NAME,
55+
SENTINEL_RESET,
56+
SENTINEL_FAILOVER,
57+
58+
/* Monitoring/Configuration */
59+
SENTINEL_MONITOR,
60+
SENTINEL_REMOVE,
61+
SENTINEL_SET,
62+
63+
/* invalid/unknown */
64+
SENTINEL_UNKNOWN
65+
} SENTINEL_CMD;
66+
4867
/* PUBSUB subcommands */
4968
typedef enum _PUBSUB_TYPE {
5069
PUBSUB_CHANNELS,

library.c

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,126 @@ PHPAPI int redis_check_eof(RedisSock *redis_sock TSRMLS_DC)
100100
return 0;
101101
}
102102

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+
}
103223

104224
PHPAPI int
105225
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
17091829
return 0;
17101830
}
17111831

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+
17121850
PHPAPI int
17131851
redis_read_reply_type(RedisSock *redis_sock, REDIS_REPLY_TYPE *reply_type, int *reply_info TSRMLS_DC) {
17141852
// Make sure we haven't lost the connection, even trying to reconnect

library.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,15 @@ redis_key_prefix(RedisSock *redis_sock, char **key, int *key_len TSRMLS_DC);
5353
PHPAPI int
5454
redis_unserialize(RedisSock *redis_sock, const char *val, int val_len, zval **return_value TSRMLS_DC);
5555

56+
/* Sentinel command handlers */
57+
PHPAPI int redis_sock_read_sentinel_servers_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab);
58+
PHPAPI int redis_sock_read_sentinel_server_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab);
5659

5760
/*
5861
* Variant Read methods, mostly to implement eval
5962
*/
6063

64+
const char *redis_reply_type_str(REDIS_REPLY_TYPE reply_type);
6165
PHPAPI int redis_read_reply_type(RedisSock *redis_sock, REDIS_REPLY_TYPE *reply_type, int *reply_info TSRMLS_DC);
6266
PHPAPI int redis_read_variant_line(RedisSock *redis_sock, REDIS_REPLY_TYPE reply_type, zval **z_ret TSRMLS_DC);
6367
PHPAPI int redis_read_variant_bulk(RedisSock *redis_sock, int size, zval **z_ret TSRMLS_DC);

php_redis.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ PHP_METHOD(Redis, config);
186186
PHP_METHOD(Redis, slowlog);
187187
PHP_METHOD(Redis, wait);
188188
PHP_METHOD(Redis, pubsub);
189+
PHP_METHOD(Redis, sentinel);
189190

190191
PHP_METHOD(Redis, client);
191192

0 commit comments

Comments
 (0)