|
|
@ -446,10 +446,10 @@ static int processMultiBulkItem(redisReader *r) {
|
|
|
|
long elements;
|
|
|
|
long elements;
|
|
|
|
int root = 0;
|
|
|
|
int root = 0;
|
|
|
|
|
|
|
|
|
|
|
|
/* Set error for nested multi bulks with depth > 2 */
|
|
|
|
/* Set error for nested multi bulks with depth > 7 */
|
|
|
|
if (r->ridx == 3) {
|
|
|
|
if (r->ridx == 8) {
|
|
|
|
__redisReaderSetError(r,REDIS_ERR_PROTOCOL,
|
|
|
|
__redisReaderSetError(r,REDIS_ERR_PROTOCOL,
|
|
|
|
"No support for nested multi bulk replies with depth > 2");
|
|
|
|
"No support for nested multi bulk replies with depth > 7");
|
|
|
|
return REDIS_ERR;
|
|
|
|
return REDIS_ERR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -564,6 +564,7 @@ redisReader *redisReaderCreate(void) {
|
|
|
|
r->errstr[0] = '\0';
|
|
|
|
r->errstr[0] = '\0';
|
|
|
|
r->fn = &defaultFunctions;
|
|
|
|
r->fn = &defaultFunctions;
|
|
|
|
r->buf = sdsempty();
|
|
|
|
r->buf = sdsempty();
|
|
|
|
|
|
|
|
r->maxbuf = REDIS_READER_MAX_BUF;
|
|
|
|
if (r->buf == NULL) {
|
|
|
|
if (r->buf == NULL) {
|
|
|
|
free(r);
|
|
|
|
free(r);
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
@ -591,7 +592,7 @@ int redisReaderFeed(redisReader *r, const char *buf, size_t len) {
|
|
|
|
/* Copy the provided buffer. */
|
|
|
|
/* Copy the provided buffer. */
|
|
|
|
if (buf != NULL && len >= 1) {
|
|
|
|
if (buf != NULL && len >= 1) {
|
|
|
|
/* Destroy internal buffer when it is empty and is quite large. */
|
|
|
|
/* Destroy internal buffer when it is empty and is quite large. */
|
|
|
|
if (r->len == 0 && sdsavail(r->buf) > 16*1024) {
|
|
|
|
if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) {
|
|
|
|
sdsfree(r->buf);
|
|
|
|
sdsfree(r->buf);
|
|
|
|
r->buf = sdsempty();
|
|
|
|
r->buf = sdsempty();
|
|
|
|
r->pos = 0;
|
|
|
|
r->pos = 0;
|
|
|
@ -1013,42 +1014,72 @@ void redisFree(redisContext *c) {
|
|
|
|
* context will be set to the return value of the error function.
|
|
|
|
* context will be set to the return value of the error function.
|
|
|
|
* When no set of reply functions is given, the default set will be used. */
|
|
|
|
* When no set of reply functions is given, the default set will be used. */
|
|
|
|
redisContext *redisConnect(const char *ip, int port) {
|
|
|
|
redisContext *redisConnect(const char *ip, int port) {
|
|
|
|
redisContext *c = redisContextInit();
|
|
|
|
redisContext *c;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
c = redisContextInit();
|
|
|
|
|
|
|
|
if (c == NULL)
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
c->flags |= REDIS_BLOCK;
|
|
|
|
c->flags |= REDIS_BLOCK;
|
|
|
|
redisContextConnectTcp(c,ip,port,NULL);
|
|
|
|
redisContextConnectTcp(c,ip,port,NULL);
|
|
|
|
return c;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv) {
|
|
|
|
redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv) {
|
|
|
|
redisContext *c = redisContextInit();
|
|
|
|
redisContext *c;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
c = redisContextInit();
|
|
|
|
|
|
|
|
if (c == NULL)
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
c->flags |= REDIS_BLOCK;
|
|
|
|
c->flags |= REDIS_BLOCK;
|
|
|
|
redisContextConnectTcp(c,ip,port,&tv);
|
|
|
|
redisContextConnectTcp(c,ip,port,&tv);
|
|
|
|
return c;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
redisContext *redisConnectNonBlock(const char *ip, int port) {
|
|
|
|
redisContext *redisConnectNonBlock(const char *ip, int port) {
|
|
|
|
redisContext *c = redisContextInit();
|
|
|
|
redisContext *c;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
c = redisContextInit();
|
|
|
|
|
|
|
|
if (c == NULL)
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
c->flags &= ~REDIS_BLOCK;
|
|
|
|
c->flags &= ~REDIS_BLOCK;
|
|
|
|
redisContextConnectTcp(c,ip,port,NULL);
|
|
|
|
redisContextConnectTcp(c,ip,port,NULL);
|
|
|
|
return c;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
redisContext *redisConnectUnix(const char *path) {
|
|
|
|
redisContext *redisConnectUnix(const char *path) {
|
|
|
|
redisContext *c = redisContextInit();
|
|
|
|
redisContext *c;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
c = redisContextInit();
|
|
|
|
|
|
|
|
if (c == NULL)
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
c->flags |= REDIS_BLOCK;
|
|
|
|
c->flags |= REDIS_BLOCK;
|
|
|
|
redisContextConnectUnix(c,path,NULL);
|
|
|
|
redisContextConnectUnix(c,path,NULL);
|
|
|
|
return c;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv) {
|
|
|
|
redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv) {
|
|
|
|
redisContext *c = redisContextInit();
|
|
|
|
redisContext *c;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
c = redisContextInit();
|
|
|
|
|
|
|
|
if (c == NULL)
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
c->flags |= REDIS_BLOCK;
|
|
|
|
c->flags |= REDIS_BLOCK;
|
|
|
|
redisContextConnectUnix(c,path,&tv);
|
|
|
|
redisContextConnectUnix(c,path,&tv);
|
|
|
|
return c;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
redisContext *redisConnectUnixNonBlock(const char *path) {
|
|
|
|
redisContext *redisConnectUnixNonBlock(const char *path) {
|
|
|
|
redisContext *c = redisContextInit();
|
|
|
|
redisContext *c;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
c = redisContextInit();
|
|
|
|
|
|
|
|
if (c == NULL)
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
c->flags &= ~REDIS_BLOCK;
|
|
|
|
c->flags &= ~REDIS_BLOCK;
|
|
|
|
redisContextConnectUnix(c,path,NULL);
|
|
|
|
redisContextConnectUnix(c,path,NULL);
|
|
|
|
return c;
|
|
|
|
return c;
|
|
|
@ -1067,7 +1098,7 @@ int redisSetTimeout(redisContext *c, struct timeval tv) {
|
|
|
|
* After this function is called, you may use redisContextReadReply to
|
|
|
|
* After this function is called, you may use redisContextReadReply to
|
|
|
|
* see if there is a reply available. */
|
|
|
|
* see if there is a reply available. */
|
|
|
|
int redisBufferRead(redisContext *c) {
|
|
|
|
int redisBufferRead(redisContext *c) {
|
|
|
|
char buf[2048];
|
|
|
|
char buf[1024*16];
|
|
|
|
int nread;
|
|
|
|
int nread;
|
|
|
|
|
|
|
|
|
|
|
|
/* Return early when the context has seen an error. */
|
|
|
|
/* Return early when the context has seen an error. */
|
|
|
@ -1076,7 +1107,7 @@ int redisBufferRead(redisContext *c) {
|
|
|
|
|
|
|
|
|
|
|
|
nread = read(c->fd,buf,sizeof(buf));
|
|
|
|
nread = read(c->fd,buf,sizeof(buf));
|
|
|
|
if (nread == -1) {
|
|
|
|
if (nread == -1) {
|
|
|
|
if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) {
|
|
|
|
if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {
|
|
|
|
/* Try again later */
|
|
|
|
/* Try again later */
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
__redisSetError(c,REDIS_ERR_IO,NULL);
|
|
|
|
__redisSetError(c,REDIS_ERR_IO,NULL);
|
|
|
@ -1113,7 +1144,7 @@ int redisBufferWrite(redisContext *c, int *done) {
|
|
|
|
if (sdslen(c->obuf) > 0) {
|
|
|
|
if (sdslen(c->obuf) > 0) {
|
|
|
|
nwritten = write(c->fd,c->obuf,sdslen(c->obuf));
|
|
|
|
nwritten = write(c->fd,c->obuf,sdslen(c->obuf));
|
|
|
|
if (nwritten == -1) {
|
|
|
|
if (nwritten == -1) {
|
|
|
|
if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) {
|
|
|
|
if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {
|
|
|
|
/* Try again later */
|
|
|
|
/* Try again later */
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
__redisSetError(c,REDIS_ERR_IO,NULL);
|
|
|
|
__redisSetError(c,REDIS_ERR_IO,NULL);
|
|
|
|