Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/phpredis/phpredis.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cluster_library.c30
-rw-r--r--cluster_library.h11
-rw-r--r--redis_cluster.c12
3 files changed, 45 insertions, 8 deletions
diff --git a/cluster_library.c b/cluster_library.c
index 09b34fc3..ee2a61aa 100644
--- a/cluster_library.c
+++ b/cluster_library.c
@@ -430,6 +430,18 @@ unsigned short cluster_hash_key(const char *key, int len) {
return crc16((char*)key+s+1,e-s-1) & REDIS_CLUSTER_MOD;
}
+/* Grab the current time in milliseconds */
+long long mstime(void) {
+ struct timeval tv;
+ long long mst;
+
+ gettimeofday(&tv, NULL);
+ mst = ((long long)tv.tv_sec)*1000;
+ mst += tv.tv_usec/1000;
+
+ return mst;
+}
+
/* Hash a key from a ZVAL */
unsigned short cluster_hash_key_zval(zval *z_key) {
const char *kptr;
@@ -1260,9 +1272,15 @@ PHPAPI int cluster_send_slot(redisCluster *c, short slot, char *cmd,
PHPAPI short cluster_send_command(redisCluster *c, short slot, const char *cmd,
int cmd_len TSRMLS_DC)
{
- int resp;
+ int resp, timedout=0;
+ long msstart;
- // Issue commands until we find the right node or fail
+ /* Grab the current time in milliseconds */
+ msstart = mstime();
+
+ /* Our main cluster request/reply loop. This loop runs until we're able
+ * to get a valid reply from a node, hit our "request" timeout, or encounter
+ * a CLUSTERDOWN state from Redis cluster. */
do {
// Send MULTI to the node if we haven't yet.
if(c->flags->mode == MULTI && SLOT_SOCK(c,slot)->mode != MULTI) {
@@ -1309,13 +1327,19 @@ PHPAPI short cluster_send_command(redisCluster *c, short slot, const char *cmd,
}
slot = c->redir_slot;
}
- } while(resp != 0 && !c->clusterdown);
+
+ /* If we didn't get a valid response and we do have a timeout check it */
+ timedout = resp && c->waitms ? mstime() - msstart >= c->waitms : 0;
+ } while(resp != 0 && !c->clusterdown && !timedout);
// If we've detected the cluster is down, throw an exception
if(c->clusterdown) {
zend_throw_exception(redis_cluster_exception_ce,
"The Redis Cluster is down (CLUSTERDOWN)", 0 TSRMLS_CC);
return -1;
+ } else if (timedout) {
+ zend_throw_exception(redis_cluster_exception_ce,
+ "Timed out attempting to find data in the correct node!", 0 TSRMLS_CC);
}
// Inform the cluster where to read the rest of our response,
diff --git a/cluster_library.h b/cluster_library.h
index 98ee305c..162b0d30 100644
--- a/cluster_library.h
+++ b/cluster_library.h
@@ -178,10 +178,13 @@ typedef struct redisCluster {
/* Object reference for Zend */
zend_object std;
- /* Timeout and read timeout */
+ /* Timeout and read timeout (for normal operations) */
double timeout;
double read_timeout;
+ /* How long in milliseconds should we wait when being bounced around */
+ long waitms;
+
/* Hash table of seed host/ports */
HashTable *seeds;
@@ -214,9 +217,6 @@ typedef struct redisCluster {
/* One RedisSock* struct for serialization and prefix information */
RedisSock *flags;
- /* Cluster distribution mode (speed, vs. maintaining order of execution) */
- short dist_mode;
-
/* The first line of our last reply, not including our reply type byte
* or the trailing \r\n */
char line_reply[1024];
@@ -330,6 +330,9 @@ void cluster_multi_fini(clusterMultiCmd *mc);
unsigned short cluster_hash_key_zval(zval *key);
unsigned short cluster_hash_key(const char *key, int len);
+/* Get the current time in miliseconds */
+long long mstime(void);
+
PHPAPI short cluster_send_command(redisCluster *c, short slot, const char *cmd,
int cmd_len TSRMLS_DC);
diff --git a/redis_cluster.c b/redis_cluster.c
index 47229370..7d077d96 100644
--- a/redis_cluster.c
+++ b/redis_cluster.c
@@ -333,7 +333,7 @@ void free_cluster_context(void *object TSRMLS_DC) {
PHP_METHOD(RedisCluster, __construct) {
zval *object, *z_seeds=NULL;
char *name;
- long name_len;
+ long name_len, tmsec;
double timeout = 0.0, read_timeout = 0.0;
redisCluster *context = GET_CONTEXT();
@@ -374,6 +374,16 @@ PHP_METHOD(RedisCluster, __construct) {
RETURN_FALSE;
}
+ /* Set our timeout and read_timeout which we'll pass through to the
+ * socket type operations */
+ context->timeout = timeout;
+ context->read_timeout = read_timeout;
+
+ /* Calculate the number of miliseconds we will wait when bouncing around,
+ * (e.g. a node goes down), which is not the same as a standard timeout. */
+ tmsec = (long)timeout * 1000;
+ context->waitms = tmsec + ((timeout-(long)timeout) * 1000);
+
// Initialize our RedisSock "seed" objects
cluster_init_seeds(context, Z_ARRVAL_P(z_seeds));