Skip to content

Commit db3c3c5

Browse files
committed
Added SELECT after reconnect
This prevents the DB number from being reset to zero after a timeout and subsequent automatic reconnect.
1 parent ad7de59 commit db3c3c5

4 files changed

Lines changed: 60 additions & 2 deletions

File tree

common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ typedef struct {
154154
char *persistent_id;
155155

156156
int serializer;
157+
long dbNumber;
157158

158159
char *prefix;
159160
int prefix_len;

library.c

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ PHPAPI int redis_check_eof(RedisSock *redis_sock TSRMLS_DC)
3838
return -1;
3939

4040
eof = php_stream_eof(redis_sock->stream);
41-
while(eof) {
42-
if((MULTI == redis_sock->mode) || redis_sock->watching || count++ == 10) { /* too many failures */
41+
for (; eof; count++) {
42+
if((MULTI == redis_sock->mode) || redis_sock->watching || count == 10) { /* too many failures */
4343
if(redis_sock->stream) { /* close stream if still here */
4444
php_stream_close(redis_sock->stream);
4545
redis_sock->stream = NULL;
@@ -61,6 +61,31 @@ PHPAPI int redis_check_eof(RedisSock *redis_sock TSRMLS_DC)
6161
eof = php_stream_eof(redis_sock->stream);
6262
}
6363
}
64+
65+
// Reselect the DB.
66+
if (count && redis_sock->dbNumber) {
67+
char *cmd, *response;
68+
int cmd_len, response_len;
69+
70+
cmd_len = redis_cmd_format_static(&cmd, "SELECT", "d", redis_sock->dbNumber);
71+
72+
if (redis_sock_write(redis_sock, cmd, cmd_len TSRMLS_CC) < 0) {
73+
efree(cmd);
74+
return -1;
75+
}
76+
efree(cmd);
77+
78+
if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC)) == NULL) {
79+
return -1;
80+
}
81+
82+
if (strncmp(response, "+OK", 3)) {
83+
efree(response);
84+
return -1;
85+
}
86+
efree(response);
87+
}
88+
6489
return 0;
6590
}
6691

@@ -731,6 +756,7 @@ PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short por
731756
redis_sock->stream = NULL;
732757
redis_sock->status = REDIS_SOCK_STATUS_DISCONNECTED;
733758
redis_sock->watching = 0;
759+
redis_sock->dbNumber = 0;
734760

735761
redis_sock->persistent = persistent;
736762

redis.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3233,6 +3233,8 @@ PHP_METHOD(Redis, select) {
32333233
RETURN_FALSE;
32343234
}
32353235

3236+
redis_sock->dbNumber = dbNumber;
3237+
32363238
cmd_len = redis_cmd_format_static(&cmd, "SELECT", "d", dbNumber);
32373239

32383240
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);

tests/TestRedis.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2877,6 +2877,35 @@ private function checkSerializer($mode) {
28772877
$this->assertTrue($this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE) === TRUE); // set ok
28782878
$this->assertTrue($this->redis->getOption(Redis::OPT_SERIALIZER) === Redis::SERIALIZER_NONE); // get ok
28792879
}
2880+
2881+
public function testReconnectSelect() {
2882+
$key = 'reconnect-select';
2883+
$value = 'Has been set!';
2884+
2885+
$original_cfg = $this->redis->config('GET', 'timeout');
2886+
2887+
// Make sure the default DB doesn't have the key.
2888+
$this->redis->select(0);
2889+
$this->redis->delete($key);
2890+
2891+
// Set the key on a different DB.
2892+
$this->redis->select(5);
2893+
$this->redis->set($key, $value);
2894+
2895+
// Time out after 1 second.
2896+
$this->redis->config('SET', 'timeout', '1');
2897+
2898+
// Wait for the timeout. With Redis 2.4, we have to wait up to 10 s
2899+
// for the server to close the connection, regardless of the timeout
2900+
// setting.
2901+
sleep(11);
2902+
2903+
// Make sure we're still using the same DB.
2904+
$this->assertEquals($value, $this->redis->get($key));
2905+
2906+
// Revert the setting.
2907+
$this->redis->config('SET', 'timeout', $original_cfg['timeout']);
2908+
}
28802909
}
28812910

28822911
TestSuite::run("Redis_Test");

0 commit comments

Comments
 (0)